diff --git a/app/soapbox/actions/compose.ts b/app/soapbox/actions/compose.ts index 8be60bfc7..995f37c15 100644 --- a/app/soapbox/actions/compose.ts +++ b/app/soapbox/actions/compose.ts @@ -48,6 +48,7 @@ const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL'; const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS'; const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO'; const COMPOSE_GROUP_POST = 'COMPOSE_GROUP_POST'; +const COMPOSE_SET_GROUP_TIMELINE_VISIBLE = 'COMPOSE_SET_GROUP_TIMELINE_VISIBLE'; const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR'; const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY'; @@ -292,7 +293,10 @@ const submitCompose = (composeId: string, routerHistory?: History, force = false to, }; - if (compose.privacy === 'group') params.group_id = compose.group_id; + if (compose.privacy === 'group') { + params.group_id = compose.group_id; + params.group_timeline_visible = compose.group_timeline_visible; // Truth Social + } dispatch(createStatus(params, idempotencyKey, statusId)).then(function(data) { if (!statusId && data.visibility === 'direct' && getState().conversations.mounted <= 0 && routerHistory) { @@ -483,6 +487,12 @@ const groupCompose = (composeId: string, groupId: string) => }); }; +const setGroupTimelineVisible = (composeId: string, groupTimelineVisible: boolean) => ({ + type: COMPOSE_SET_GROUP_TIMELINE_VISIBLE, + id: composeId, + groupTimelineVisible, +}); + const clearComposeSuggestions = (composeId: string) => { if (cancelFetchComposeSuggestionsAccounts) { cancelFetchComposeSuggestionsAccounts(); @@ -792,6 +802,7 @@ export { COMPOSE_ADD_TO_MENTIONS, COMPOSE_REMOVE_FROM_MENTIONS, COMPOSE_SET_STATUS, + COMPOSE_SET_GROUP_TIMELINE_VISIBLE, setComposeToStatus, changeCompose, replyCompose, @@ -818,6 +829,7 @@ export { uploadComposeFail, undoUploadCompose, groupCompose, + setGroupTimelineVisible, clearComposeSuggestions, fetchComposeSuggestions, readyComposeSuggestionsEmojis, diff --git a/app/soapbox/components/ui/toggle/toggle.tsx b/app/soapbox/components/ui/toggle/toggle.tsx index 466a207f8..34651e98d 100644 --- a/app/soapbox/components/ui/toggle/toggle.tsx +++ b/app/soapbox/components/ui/toggle/toggle.tsx @@ -1,13 +1,52 @@ -import React from 'react'; -import ReactToggle, { ToggleProps } from 'react-toggle'; +import clsx from 'clsx'; +import React, { useRef } from 'react'; + +interface IToggle extends Pick, 'id' | 'name' | 'checked' | 'onChange' | 'required' | 'disabled'> { + size?: 'sm' | 'md' +} + +/** A glorified checkbox. */ +const Toggle: React.FC = ({ id, size = 'md', name, checked, onChange, required, disabled }) => { + const input = useRef(null); + + const handleClick: React.MouseEventHandler = () => { + input.current?.focus(); + input.current?.click(); + }; -/** A glorified checkbox. Wrapper around react-toggle. */ -const Toggle: React.FC = ({ icons = false, ...rest }) => { return ( - + ); }; diff --git a/app/soapbox/features/compose/components/compose-form.tsx b/app/soapbox/features/compose/components/compose-form.tsx index 00167886f..321b30aa2 100644 --- a/app/soapbox/features/compose/components/compose-form.tsx +++ b/app/soapbox/features/compose/components/compose-form.tsx @@ -63,9 +63,10 @@ interface IComposeForm { clickableAreaRef?: React.RefObject event?: string group?: string + extra?: React.ReactNode } -const ComposeForm = ({ id, shouldCondense, autoFocus, clickableAreaRef, event, group }: IComposeForm) => { +const ComposeForm = ({ id, shouldCondense, autoFocus, clickableAreaRef, event, group, extra }: IComposeForm) => { const history = useHistory(); const intl = useIntl(); const dispatch = useAppDispatch(); @@ -333,6 +334,8 @@ const ComposeForm = ({ id, shouldCondense, autoFocus, clickab + {extra &&
{extra}
} +
= ({ value, onChange }) => @@ -212,28 +211,24 @@ const EditFilter: React.FC = ({ params }) => { setHomeTimeline(target.checked)} /> setPublicTimeline(target.checked)} /> setNotifications(target.checked)} /> setConversations(target.checked)} /> @@ -241,7 +236,6 @@ const EditFilter: React.FC = ({ params }) => { {features.filtersV2 && ( setAccounts(target.checked)} /> @@ -255,7 +249,6 @@ const EditFilter: React.FC = ({ params }) => { hint={intl.formatMessage(features.filtersV2 ? messages.hide_hint : messages.drop_hint)} > setHide(target.checked)} /> diff --git a/app/soapbox/features/group/group-timeline.tsx b/app/soapbox/features/group/group-timeline.tsx index 9494b033e..f718b9c87 100644 --- a/app/soapbox/features/group/group-timeline.tsx +++ b/app/soapbox/features/group/group-timeline.tsx @@ -2,12 +2,12 @@ import React, { useEffect } from 'react'; import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router-dom'; -import { groupCompose } from 'soapbox/actions/compose'; +import { groupCompose, setGroupTimelineVisible } from 'soapbox/actions/compose'; import { connectGroupStream } from 'soapbox/actions/streaming'; import { expandGroupTimeline } from 'soapbox/actions/timelines'; -import { Avatar, HStack, Icon, Stack, Text } from 'soapbox/components/ui'; +import { Avatar, HStack, Icon, Stack, Text, Toggle } from 'soapbox/components/ui'; import ComposeForm from 'soapbox/features/compose/components/compose-form'; -import { useAppDispatch, useOwnAccount } from 'soapbox/hooks'; +import { useAppDispatch, useAppSelector, useOwnAccount } from 'soapbox/hooks'; import { useGroup } from 'soapbox/hooks/api'; import Timeline from '../ui/components/timeline'; @@ -26,16 +26,21 @@ const GroupTimeline: React.FC = (props) => { const { group } = useGroup(groupId); + const composeId = `group:${groupId}`; const canComposeGroupStatus = !!account && group?.relationship?.member; + const groupTimelineVisible = useAppSelector((state) => !!state.compose.get(composeId)?.group_timeline_visible); const handleLoadMore = (maxId: string) => { dispatch(expandGroupTimeline(groupId, { maxId })); }; + const handleToggleChange = () => { + dispatch(setGroupTimelineVisible(composeId, !groupTimelineVisible)); + }; + useEffect(() => { dispatch(expandGroupTimeline(groupId)); - - dispatch(groupCompose(`group:${groupId}`, groupId)); + dispatch(groupCompose(composeId, groupId)); const disconnect = dispatch(connectGroupStream(groupId)); @@ -58,10 +63,25 @@ const GroupTimeline: React.FC = (props) => { + + + + )} />
@@ -69,7 +89,7 @@ const GroupTimeline: React.FC = (props) => { diff --git a/app/soapbox/features/report/components/status-check-box.tsx b/app/soapbox/features/report/components/status-check-box.tsx index 9bb20dc77..78e3cbe79 100644 --- a/app/soapbox/features/report/components/status-check-box.tsx +++ b/app/soapbox/features/report/components/status-check-box.tsx @@ -1,9 +1,9 @@ import noop from 'lodash/noop'; import React from 'react'; -import Toggle from 'react-toggle'; import { toggleStatusReport } from 'soapbox/actions/reports'; import StatusContent from 'soapbox/components/status-content'; +import { Toggle } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import Bundle from '../../ui/components/bundle'; @@ -88,7 +88,7 @@ const StatusCheckBox: React.FC = ({ id, disabled }) => {
- +
); diff --git a/app/soapbox/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx b/app/soapbox/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx index 5aa862c28..bb5d7659e 100644 --- a/app/soapbox/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx +++ b/app/soapbox/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import Toggle from 'react-toggle'; import { changeEditEventApprovalRequired, @@ -22,7 +21,7 @@ import { closeModal, openModal } from 'soapbox/actions/modals'; import { ADDRESS_ICONS } from 'soapbox/components/autosuggest-location'; import LocationSearch from 'soapbox/components/location-search'; import { checkEventComposeContent } from 'soapbox/components/modal-root'; -import { Button, Form, FormGroup, HStack, Icon, IconButton, Input, Modal, Spinner, Stack, Tabs, Text, Textarea } from 'soapbox/components/ui'; +import { Button, Form, FormGroup, HStack, Icon, IconButton, Input, Modal, Spinner, Stack, Tabs, Text, Textarea, Toggle } from 'soapbox/components/ui'; import AccountContainer from 'soapbox/containers/account-container'; import { isCurrentOrFutureDate } from 'soapbox/features/compose/components/schedule-form'; import BundleContainer from 'soapbox/features/ui/containers/bundle-container'; @@ -273,7 +272,6 @@ const ComposeEventModal: React.FC = ({ onClose }) => { @@ -302,7 +300,6 @@ const ComposeEventModal: React.FC = ({ onClose }) => { {!id && ( diff --git a/app/soapbox/features/ui/components/modals/edit-announcement-modal.tsx b/app/soapbox/features/ui/components/modals/edit-announcement-modal.tsx index 183519817..3b8c7736f 100644 --- a/app/soapbox/features/ui/components/modals/edit-announcement-modal.tsx +++ b/app/soapbox/features/ui/components/modals/edit-announcement-modal.tsx @@ -98,7 +98,6 @@ const EditAnnouncementModal: React.FC = ({ onClose }) => diff --git a/app/soapbox/features/ui/components/modals/edit-federation-modal.tsx b/app/soapbox/features/ui/components/modals/edit-federation-modal.tsx index 59930e380..a8851420f 100644 --- a/app/soapbox/features/ui/components/modals/edit-federation-modal.tsx +++ b/app/soapbox/features/ui/components/modals/edit-federation-modal.tsx @@ -1,11 +1,10 @@ import { Map as ImmutableMap } from 'immutable'; import React, { useState, useEffect, useCallback } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import Toggle from 'react-toggle'; import { updateMrf } from 'soapbox/actions/mrf'; import List, { ListItem } from 'soapbox/components/list'; -import { Modal } from 'soapbox/components/ui'; +import { Modal, Toggle } from 'soapbox/components/ui'; import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; import { makeGetRemoteInstance } from 'soapbox/selectors'; import toast from 'soapbox/toast'; @@ -86,7 +85,6 @@ const EditFederationModal: React.FC = ({ host, onClose }) @@ -95,7 +93,6 @@ const EditFederationModal: React.FC = ({ host, onClose }) @@ -105,7 +102,6 @@ const EditFederationModal: React.FC = ({ host, onClose }) @@ -115,7 +111,6 @@ const EditFederationModal: React.FC = ({ host, onClose }) @@ -125,7 +120,6 @@ const EditFederationModal: React.FC = ({ host, onClose }) diff --git a/app/soapbox/features/ui/components/modals/mute-modal.tsx b/app/soapbox/features/ui/components/modals/mute-modal.tsx index 44ba725fe..5c8dd603e 100644 --- a/app/soapbox/features/ui/components/modals/mute-modal.tsx +++ b/app/soapbox/features/ui/components/modals/mute-modal.tsx @@ -1,11 +1,10 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; -import Toggle from 'react-toggle'; import { muteAccount } from 'soapbox/actions/accounts'; import { closeModal } from 'soapbox/actions/modals'; import { toggleHideNotifications, changeMuteDuration } from 'soapbox/actions/mutes'; -import { Modal, HStack, Stack, Text } from 'soapbox/components/ui'; +import { Modal, HStack, Stack, Text, Toggle } from 'soapbox/components/ui'; import DurationSelector from 'soapbox/features/compose/components/polls/duration-selector'; import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; @@ -74,7 +73,6 @@ const MuteModal = () => { @@ -90,7 +88,6 @@ const MuteModal = () => { diff --git a/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx b/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx index 8f58c4b35..55e435603 100644 --- a/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx +++ b/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx @@ -1,11 +1,10 @@ import { OrderedSet } from 'immutable'; import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import Toggle from 'react-toggle'; import { changeReportBlock, changeReportForward } from 'soapbox/actions/reports'; import { fetchRules } from 'soapbox/actions/rules'; -import { Button, FormGroup, HStack, Stack, Text } from 'soapbox/components/ui'; +import { Button, FormGroup, HStack, Stack, Text, Toggle } from 'soapbox/components/ui'; import StatusCheckBox from 'soapbox/features/report/components/status-check-box'; import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks'; import { isRemote, getDomain } from 'soapbox/utils/accounts'; @@ -101,7 +100,6 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { @@ -119,7 +117,6 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { diff --git a/app/soapbox/locales/en.json b/app/soapbox/locales/en.json index 81a4ed1da..c819a1f22 100644 --- a/app/soapbox/locales/en.json +++ b/app/soapbox/locales/en.json @@ -443,6 +443,7 @@ "compose_form.spoiler_placeholder": "Write your warning here (optional)", "compose_form.spoiler_remove": "Remove sensitive", "compose_form.spoiler_title": "Sensitive content", + "compose_group.share_to_followers": "Share with my followers", "confirmation_modal.cancel": "Cancel", "confirmations.admin.deactivate_user.confirm": "Deactivate @{name}", "confirmations.admin.deactivate_user.heading": "Deactivate @{acct}", diff --git a/app/soapbox/reducers/compose.ts b/app/soapbox/reducers/compose.ts index 63bec8be6..cfce14a5a 100644 --- a/app/soapbox/reducers/compose.ts +++ b/app/soapbox/reducers/compose.ts @@ -51,6 +51,7 @@ import { COMPOSE_REMOVE_FROM_MENTIONS, COMPOSE_SET_STATUS, COMPOSE_EVENT_REPLY, + COMPOSE_SET_GROUP_TIMELINE_VISIBLE, } from '../actions/compose'; import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me'; import { SETTING_CHANGE, FE_NAME } from '../actions/settings'; @@ -103,6 +104,7 @@ export const ReducerCompose = ImmutableRecord({ tagHistory: ImmutableList(), text: '', to: ImmutableOrderedSet(), + group_timeline_visible: false, // TruthSocial }); type State = ImmutableMap; @@ -493,6 +495,8 @@ export default function compose(state = initialState, action: AnyAction) { return updateCompose(state, action.id, compose => compose.update('to', mentions => mentions!.add(action.account))); case COMPOSE_REMOVE_FROM_MENTIONS: return updateCompose(state, action.id, compose => compose.update('to', mentions => mentions!.delete(action.account))); + case COMPOSE_SET_GROUP_TIMELINE_VISIBLE: + return updateCompose(state, action.id, compose => compose.set('group_timeline_visible', action.groupTimelineVisible)); case ME_FETCH_SUCCESS: return updateCompose(state, 'default', compose => importAccount(compose, action.me)); case ME_PATCH_SUCCESS: diff --git a/app/styles/application.scss b/app/styles/application.scss index d54785550..f0a17c975 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -21,7 +21,6 @@ @import 'components/display-name'; @import 'components/columns'; @import 'components/search'; -@import 'components/react-toggle'; @import 'components/video-player'; @import 'components/audio-player'; @import 'components/crypto-donate'; diff --git a/app/styles/components/react-toggle.scss b/app/styles/components/react-toggle.scss deleted file mode 100644 index a56db522a..000000000 --- a/app/styles/components/react-toggle.scss +++ /dev/null @@ -1,96 +0,0 @@ -.react-toggle { - display: inline-block; - position: relative; - cursor: pointer; - background-color: transparent; - border: 0; - padding: 0; - user-select: none; - -webkit-tap-highlight-color: #0000; - -webkit-tap-highlight-color: transparent; - - &:focus-within .react-toggle-track { - @apply ring-2 ring-offset-2 ring-primary-500; - } -} - -.react-toggle-screenreader-only { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.react-toggle--disabled { - cursor: not-allowed; - opacity: 0.5; - transition: opacity 0.25s; -} - -.react-toggle-track { - @apply bg-gray-500 dark:bg-gray-700 h-[30px] w-[50px] p-0 rounded-full transition-colors; -} - -.react-toggle--checked .react-toggle-track { - @apply bg-primary-600 dark:bg-accent-blue; -} - -.react-toggle-track-check { - position: absolute; - width: 14px; - height: 10px; - top: 0; - bottom: 0; - margin-top: auto; - margin-bottom: auto; - line-height: 0; - left: 8px; - opacity: 0; - transition: opacity 0.25s ease; -} - -.react-toggle--checked .react-toggle-track-check { - opacity: 1; - transition: opacity 0.25s ease; -} - -.react-toggle-track-x { - position: absolute; - width: 10px; - height: 10px; - top: 0; - bottom: 0; - margin-top: auto; - margin-bottom: auto; - line-height: 0; - right: 10px; - opacity: 1; - transition: opacity 0.25s ease; -} - -.react-toggle--checked .react-toggle-track-x { - opacity: 0; -} - -.react-toggle-thumb { - position: absolute; - top: 1px; - left: 1px; - width: 28px; - height: 28px; - border: 1px solid #fff; - border-radius: 50%; - background-color: #fff; - box-sizing: border-box; - transition: all 0.25s ease; - transition-property: border-color, left; -} - -.react-toggle--checked .react-toggle-thumb { - @apply border-primary-600 dark:border-accent-blue; - left: 21px; -} diff --git a/package.json b/package.json index 079f2173f..f1d6bf54e 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,6 @@ "@types/react-router-dom": "^5.3.3", "@types/react-sparklines": "^1.7.2", "@types/react-swipeable-views": "^0.13.1", - "@types/react-toggle": "^4.0.3", "@types/redux-mock-store": "^1.0.3", "@types/seedrandom": "^3.0.2", "@types/semver": "^7.3.9", @@ -165,7 +164,6 @@ "react-sticky-box": "^2.0.0", "react-swipeable-views": "^0.14.0", "react-textarea-autosize": "^8.3.4", - "react-toggle": "^4.1.2", "react-virtuoso": "^4.0.8", "redux": "^4.1.1", "redux-immutable": "^4.0.0", diff --git a/yarn.lock b/yarn.lock index 12eb37b1c..4b51ca055 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4497,13 +4497,6 @@ dependencies: "@types/react" "*" -"@types/react-toggle@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/react-toggle/-/react-toggle-4.0.3.tgz#8db98ac8d2c5e8c03c2d3a42027555c1cd2289da" - integrity sha512-57QdMWeeQdRjM2/p+udgYerxUbSkmeUIW18kwUttcci6GHkgxoqCsDZfRtsCsAHcvvM5VBQdtDUEgLWo2e87mA== - dependencies: - "@types/react" "*" - "@types/react@*", "@types/react@17", "@types/react@^18.0.26": version "18.0.26" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" @@ -14819,13 +14812,6 @@ react-textarea-autosize@^8.3.4: use-composed-ref "^1.3.0" use-latest "^1.2.1" -react-toggle@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/react-toggle/-/react-toggle-4.1.2.tgz#b00500832f925ad524356d909821821ae39f6c52" - integrity sha512-4Ohw31TuYQdhWfA6qlKafeXx3IOH7t4ZHhmRdwsm1fQREwOBGxJT+I22sgHqR/w8JRdk+AeMCJXPImEFSrNXow== - dependencies: - classnames "^2.2.5" - react-transition-group@^2.2.1: version "2.9.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"