Merge branch 'groups-toggle' into 'develop'

Groups toggle

See merge request soapbox-pub/soapbox!2391
This commit is contained in:
Alex Gleason 2023-03-31 19:06:10 +00:00
commit 72b57d93da
17 changed files with 102 additions and 159 deletions

View file

@ -48,6 +48,7 @@ const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS'; const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO'; const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
const COMPOSE_GROUP_POST = 'COMPOSE_GROUP_POST'; 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_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR';
const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY'; const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY';
@ -292,7 +293,10 @@ const submitCompose = (composeId: string, routerHistory?: History, force = false
to, 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) { dispatch(createStatus(params, idempotencyKey, statusId)).then(function(data) {
if (!statusId && data.visibility === 'direct' && getState().conversations.mounted <= 0 && routerHistory) { 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) => { const clearComposeSuggestions = (composeId: string) => {
if (cancelFetchComposeSuggestionsAccounts) { if (cancelFetchComposeSuggestionsAccounts) {
cancelFetchComposeSuggestionsAccounts(); cancelFetchComposeSuggestionsAccounts();
@ -792,6 +802,7 @@ export {
COMPOSE_ADD_TO_MENTIONS, COMPOSE_ADD_TO_MENTIONS,
COMPOSE_REMOVE_FROM_MENTIONS, COMPOSE_REMOVE_FROM_MENTIONS,
COMPOSE_SET_STATUS, COMPOSE_SET_STATUS,
COMPOSE_SET_GROUP_TIMELINE_VISIBLE,
setComposeToStatus, setComposeToStatus,
changeCompose, changeCompose,
replyCompose, replyCompose,
@ -818,6 +829,7 @@ export {
uploadComposeFail, uploadComposeFail,
undoUploadCompose, undoUploadCompose,
groupCompose, groupCompose,
setGroupTimelineVisible,
clearComposeSuggestions, clearComposeSuggestions,
fetchComposeSuggestions, fetchComposeSuggestions,
readyComposeSuggestionsEmojis, readyComposeSuggestionsEmojis,

View file

@ -1,13 +1,52 @@
import React from 'react'; import clsx from 'clsx';
import ReactToggle, { ToggleProps } from 'react-toggle'; import React, { useRef } from 'react';
interface IToggle extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'id' | 'name' | 'checked' | 'onChange' | 'required' | 'disabled'> {
size?: 'sm' | 'md'
}
/** A glorified checkbox. */
const Toggle: React.FC<IToggle> = ({ id, size = 'md', name, checked, onChange, required, disabled }) => {
const input = useRef<HTMLInputElement>(null);
const handleClick: React.MouseEventHandler<HTMLButtonElement> = () => {
input.current?.focus();
input.current?.click();
};
/** A glorified checkbox. Wrapper around react-toggle. */
const Toggle: React.FC<ToggleProps> = ({ icons = false, ...rest }) => {
return ( return (
<ReactToggle <button
icons={icons} className={clsx('flex-none rounded-full', {
{...rest} 'bg-gray-500': !checked && !disabled,
/> 'bg-primary-600': checked && !disabled,
'bg-gray-200': !checked && disabled,
'bg-primary-200': checked && disabled,
'w-9 p-0.5': size === 'sm',
'w-11 p-0.5': size === 'md',
'cursor-default': disabled,
})}
onClick={handleClick}
>
<div className={clsx('rounded-full bg-white transition-transform', {
'h-4.5 w-4.5': size === 'sm',
'translate-x-3.5': size === 'sm' && checked,
'h-6 w-6': size === 'md',
'translate-x-4': size === 'md' && checked,
})}
/>
<input
id={id}
ref={input}
name={name}
type='checkbox'
className='sr-only'
checked={checked}
onChange={onChange}
required={required}
disabled={disabled}
/>
</button>
); );
}; };

View file

@ -63,9 +63,10 @@ interface IComposeForm<ID extends string> {
clickableAreaRef?: React.RefObject<HTMLDivElement> clickableAreaRef?: React.RefObject<HTMLDivElement>
event?: string event?: string
group?: string group?: string
extra?: React.ReactNode
} }
const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickableAreaRef, event, group }: IComposeForm<ID>) => { const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickableAreaRef, event, group, extra }: IComposeForm<ID>) => {
const history = useHistory(); const history = useHistory();
const intl = useIntl(); const intl = useIntl();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -333,6 +334,8 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
<QuotedStatusContainer composeId={id} /> <QuotedStatusContainer composeId={id} />
{extra && <div className={clsx({ 'hidden': condensed })}>{extra}</div>}
<div <div
className={clsx('flex flex-wrap items-center justify-between', { className={clsx('flex flex-wrap items-center justify-between', {
'hidden': condensed, 'hidden': condensed,

View file

@ -71,7 +71,6 @@ const FilterField: StreamfieldComponent<IFilterField> = ({ value, onChange }) =>
<Toggle <Toggle
checked={value.whole_word} checked={value.whole_word}
onChange={handleChange('whole_word')} onChange={handleChange('whole_word')}
icons={false}
/> />
<Text tag='span' theme='muted'> <Text tag='span' theme='muted'>
@ -212,28 +211,24 @@ const EditFilter: React.FC<IEditFilter> = ({ params }) => {
<List> <List>
<ListItem label={intl.formatMessage(messages.home_timeline)}> <ListItem label={intl.formatMessage(messages.home_timeline)}>
<Toggle <Toggle
name='home_timeline'
checked={homeTimeline} checked={homeTimeline}
onChange={({ target }) => setHomeTimeline(target.checked)} onChange={({ target }) => setHomeTimeline(target.checked)}
/> />
</ListItem> </ListItem>
<ListItem label={intl.formatMessage(messages.public_timeline)}> <ListItem label={intl.formatMessage(messages.public_timeline)}>
<Toggle <Toggle
name='public_timeline'
checked={publicTimeline} checked={publicTimeline}
onChange={({ target }) => setPublicTimeline(target.checked)} onChange={({ target }) => setPublicTimeline(target.checked)}
/> />
</ListItem> </ListItem>
<ListItem label={intl.formatMessage(messages.notifications)}> <ListItem label={intl.formatMessage(messages.notifications)}>
<Toggle <Toggle
name='notifications'
checked={notifications} checked={notifications}
onChange={({ target }) => setNotifications(target.checked)} onChange={({ target }) => setNotifications(target.checked)}
/> />
</ListItem> </ListItem>
<ListItem label={intl.formatMessage(messages.conversations)}> <ListItem label={intl.formatMessage(messages.conversations)}>
<Toggle <Toggle
name='conversations'
checked={conversations} checked={conversations}
onChange={({ target }) => setConversations(target.checked)} onChange={({ target }) => setConversations(target.checked)}
/> />
@ -241,7 +236,6 @@ const EditFilter: React.FC<IEditFilter> = ({ params }) => {
{features.filtersV2 && ( {features.filtersV2 && (
<ListItem label={intl.formatMessage(messages.accounts)}> <ListItem label={intl.formatMessage(messages.accounts)}>
<Toggle <Toggle
name='accounts'
checked={accounts} checked={accounts}
onChange={({ target }) => setAccounts(target.checked)} onChange={({ target }) => setAccounts(target.checked)}
/> />
@ -255,7 +249,6 @@ const EditFilter: React.FC<IEditFilter> = ({ params }) => {
hint={intl.formatMessage(features.filtersV2 ? messages.hide_hint : messages.drop_hint)} hint={intl.formatMessage(features.filtersV2 ? messages.hide_hint : messages.drop_hint)}
> >
<Toggle <Toggle
name='hide'
checked={hide} checked={hide}
onChange={({ target }) => setHide(target.checked)} onChange={({ target }) => setHide(target.checked)}
/> />

View file

@ -2,12 +2,12 @@ import React, { useEffect } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom'; 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 { connectGroupStream } from 'soapbox/actions/streaming';
import { expandGroupTimeline } from 'soapbox/actions/timelines'; 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 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 { useGroup } from 'soapbox/hooks/api';
import Timeline from '../ui/components/timeline'; import Timeline from '../ui/components/timeline';
@ -26,16 +26,21 @@ const GroupTimeline: React.FC<IGroupTimeline> = (props) => {
const { group } = useGroup(groupId); const { group } = useGroup(groupId);
const composeId = `group:${groupId}`;
const canComposeGroupStatus = !!account && group?.relationship?.member; const canComposeGroupStatus = !!account && group?.relationship?.member;
const groupTimelineVisible = useAppSelector((state) => !!state.compose.get(composeId)?.group_timeline_visible);
const handleLoadMore = (maxId: string) => { const handleLoadMore = (maxId: string) => {
dispatch(expandGroupTimeline(groupId, { maxId })); dispatch(expandGroupTimeline(groupId, { maxId }));
}; };
const handleToggleChange = () => {
dispatch(setGroupTimelineVisible(composeId, !groupTimelineVisible));
};
useEffect(() => { useEffect(() => {
dispatch(expandGroupTimeline(groupId)); dispatch(expandGroupTimeline(groupId));
dispatch(groupCompose(composeId, groupId));
dispatch(groupCompose(`group:${groupId}`, groupId));
const disconnect = dispatch(connectGroupStream(groupId)); const disconnect = dispatch(connectGroupStream(groupId));
@ -58,10 +63,25 @@ const GroupTimeline: React.FC<IGroupTimeline> = (props) => {
</Link> </Link>
<ComposeForm <ComposeForm
id={`group:${groupId}`} id={composeId}
shouldCondense shouldCondense
autoFocus={false} autoFocus={false}
group={groupId} group={groupId}
extra={!group.locked && (
<HStack alignItems='center' space={4}>
<label className='ml-auto cursor-pointer' htmlFor='group-timeline-visible'>
<Text theme='muted'>
<FormattedMessage id='compose_group.share_to_followers' defaultMessage='Share with my followers' />
</Text>
</label>
<Toggle
id='group-timeline-visible'
checked={groupTimelineVisible}
onChange={handleToggleChange}
size='sm'
/>
</HStack>
)}
/> />
</HStack> </HStack>
</div> </div>
@ -69,7 +89,7 @@ const GroupTimeline: React.FC<IGroupTimeline> = (props) => {
<Timeline <Timeline
scrollKey='group_timeline' scrollKey='group_timeline'
timelineId={`group:${groupId}`} timelineId={composeId}
onLoadMore={handleLoadMore} onLoadMore={handleLoadMore}
emptyMessage={ emptyMessage={
<Stack space={4} className='py-6' justifyContent='center' alignItems='center'> <Stack space={4} className='py-6' justifyContent='center' alignItems='center'>

View file

@ -1,9 +1,9 @@
import noop from 'lodash/noop'; import noop from 'lodash/noop';
import React from 'react'; import React from 'react';
import Toggle from 'react-toggle';
import { toggleStatusReport } from 'soapbox/actions/reports'; import { toggleStatusReport } from 'soapbox/actions/reports';
import StatusContent from 'soapbox/components/status-content'; import StatusContent from 'soapbox/components/status-content';
import { Toggle } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
import Bundle from '../../ui/components/bundle'; import Bundle from '../../ui/components/bundle';
@ -88,7 +88,7 @@ const StatusCheckBox: React.FC<IStatusCheckBox> = ({ id, disabled }) => {
</div> </div>
<div className='status-check-box-toggle'> <div className='status-check-box-toggle'>
<Toggle checked={checked} onChange={onToggle} disabled={disabled} icons={false} /> <Toggle checked={checked} onChange={onToggle} disabled={disabled} />
</div> </div>
</div> </div>
); );

View file

@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import Toggle from 'react-toggle';
import { import {
changeEditEventApprovalRequired, changeEditEventApprovalRequired,
@ -22,7 +21,7 @@ import { closeModal, openModal } from 'soapbox/actions/modals';
import { ADDRESS_ICONS } from 'soapbox/components/autosuggest-location'; import { ADDRESS_ICONS } from 'soapbox/components/autosuggest-location';
import LocationSearch from 'soapbox/components/location-search'; import LocationSearch from 'soapbox/components/location-search';
import { checkEventComposeContent } from 'soapbox/components/modal-root'; 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 AccountContainer from 'soapbox/containers/account-container';
import { isCurrentOrFutureDate } from 'soapbox/features/compose/components/schedule-form'; import { isCurrentOrFutureDate } from 'soapbox/features/compose/components/schedule-form';
import BundleContainer from 'soapbox/features/ui/containers/bundle-container'; import BundleContainer from 'soapbox/features/ui/containers/bundle-container';
@ -273,7 +272,6 @@ const ComposeEventModal: React.FC<IComposeEventModal> = ({ onClose }) => {
</FormGroup> </FormGroup>
<HStack alignItems='center' space={2}> <HStack alignItems='center' space={2}>
<Toggle <Toggle
icons={false}
checked={!!endTime} checked={!!endTime}
onChange={onChangeHasEndTime} onChange={onChangeHasEndTime}
/> />
@ -302,7 +300,6 @@ const ComposeEventModal: React.FC<IComposeEventModal> = ({ onClose }) => {
{!id && ( {!id && (
<HStack alignItems='center' space={2}> <HStack alignItems='center' space={2}>
<Toggle <Toggle
icons={false}
checked={approvalRequired} checked={approvalRequired}
onChange={onChangeApprovalRequired} onChange={onChangeApprovalRequired}
/> />

View file

@ -98,7 +98,6 @@ const EditAnnouncementModal: React.FC<IEditAnnouncementModal> = ({ onClose }) =>
</FormGroup> </FormGroup>
<HStack alignItems='center' space={2}> <HStack alignItems='center' space={2}>
<Toggle <Toggle
icons={false}
checked={allDay} checked={allDay}
onChange={onChangeAllDay} onChange={onChangeAllDay}
/> />

View file

@ -1,11 +1,10 @@
import { Map as ImmutableMap } from 'immutable'; import { Map as ImmutableMap } from 'immutable';
import React, { useState, useEffect, useCallback } from 'react'; import React, { useState, useEffect, useCallback } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import Toggle from 'react-toggle';
import { updateMrf } from 'soapbox/actions/mrf'; import { updateMrf } from 'soapbox/actions/mrf';
import List, { ListItem } from 'soapbox/components/list'; 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 { useAppSelector, useAppDispatch } from 'soapbox/hooks';
import { makeGetRemoteInstance } from 'soapbox/selectors'; import { makeGetRemoteInstance } from 'soapbox/selectors';
import toast from 'soapbox/toast'; import toast from 'soapbox/toast';
@ -86,7 +85,6 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
<Toggle <Toggle
checked={reject} checked={reject}
onChange={handleDataChange('reject')} onChange={handleDataChange('reject')}
icons={false}
id='reject' id='reject'
/> />
</ListItem> </ListItem>
@ -95,7 +93,6 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
<Toggle <Toggle
checked={fullMediaRemoval} checked={fullMediaRemoval}
onChange={handleMediaRemoval} onChange={handleMediaRemoval}
icons={false}
id='media_removal' id='media_removal'
disabled={reject} disabled={reject}
/> />
@ -105,7 +102,6 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
<Toggle <Toggle
checked={media_nsfw} checked={media_nsfw}
onChange={handleDataChange('media_nsfw')} onChange={handleDataChange('media_nsfw')}
icons={false}
id='media_nsfw' id='media_nsfw'
disabled={reject || media_removal} disabled={reject || media_removal}
/> />
@ -115,7 +111,6 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
<Toggle <Toggle
checked={followers_only} checked={followers_only}
onChange={handleDataChange('followers_only')} onChange={handleDataChange('followers_only')}
icons={false}
id='followers_only' id='followers_only'
disabled={reject} disabled={reject}
/> />
@ -125,7 +120,6 @@ const EditFederationModal: React.FC<IEditFederationModal> = ({ host, onClose })
<Toggle <Toggle
checked={federated_timeline_removal} checked={federated_timeline_removal}
onChange={handleDataChange('federated_timeline_removal')} onChange={handleDataChange('federated_timeline_removal')}
icons={false}
id='federated_timeline_removal' id='federated_timeline_removal'
disabled={reject || followers_only} disabled={reject || followers_only}
/> />

View file

@ -1,11 +1,10 @@
import React from 'react'; import React from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import Toggle from 'react-toggle';
import { muteAccount } from 'soapbox/actions/accounts'; import { muteAccount } from 'soapbox/actions/accounts';
import { closeModal } from 'soapbox/actions/modals'; import { closeModal } from 'soapbox/actions/modals';
import { toggleHideNotifications, changeMuteDuration } from 'soapbox/actions/mutes'; 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 DurationSelector from 'soapbox/features/compose/components/polls/duration-selector';
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
import { makeGetAccount } from 'soapbox/selectors'; import { makeGetAccount } from 'soapbox/selectors';
@ -74,7 +73,6 @@ const MuteModal = () => {
<Toggle <Toggle
checked={notifications} checked={notifications}
onChange={toggleNotifications} onChange={toggleNotifications}
icons={false}
/> />
</HStack> </HStack>
</label> </label>
@ -90,7 +88,6 @@ const MuteModal = () => {
<Toggle <Toggle
checked={duration !== 0} checked={duration !== 0}
onChange={toggleAutoExpire} onChange={toggleAutoExpire}
icons={false}
/> />
</HStack> </HStack>
</label> </label>

View file

@ -1,11 +1,10 @@
import { OrderedSet } from 'immutable'; import { OrderedSet } from 'immutable';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import Toggle from 'react-toggle';
import { changeReportBlock, changeReportForward } from 'soapbox/actions/reports'; import { changeReportBlock, changeReportForward } from 'soapbox/actions/reports';
import { fetchRules } from 'soapbox/actions/rules'; 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 StatusCheckBox from 'soapbox/features/report/components/status-check-box';
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks'; import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
import { isRemote, getDomain } from 'soapbox/utils/accounts'; import { isRemote, getDomain } from 'soapbox/utils/accounts';
@ -101,7 +100,6 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
<Toggle <Toggle
checked={isBlocked} checked={isBlocked}
onChange={handleBlockChange} onChange={handleBlockChange}
icons={false}
id='report-block' id='report-block'
/> />
@ -119,7 +117,6 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
<Toggle <Toggle
checked={isForward} checked={isForward}
onChange={handleForwardChange} onChange={handleForwardChange}
icons={false}
id='report-forward' id='report-forward'
disabled={isSubmitting} disabled={isSubmitting}
/> />

View file

@ -443,6 +443,7 @@
"compose_form.spoiler_placeholder": "Write your warning here (optional)", "compose_form.spoiler_placeholder": "Write your warning here (optional)",
"compose_form.spoiler_remove": "Remove sensitive", "compose_form.spoiler_remove": "Remove sensitive",
"compose_form.spoiler_title": "Sensitive content", "compose_form.spoiler_title": "Sensitive content",
"compose_group.share_to_followers": "Share with my followers",
"confirmation_modal.cancel": "Cancel", "confirmation_modal.cancel": "Cancel",
"confirmations.admin.deactivate_user.confirm": "Deactivate @{name}", "confirmations.admin.deactivate_user.confirm": "Deactivate @{name}",
"confirmations.admin.deactivate_user.heading": "Deactivate @{acct}", "confirmations.admin.deactivate_user.heading": "Deactivate @{acct}",

View file

@ -51,6 +51,7 @@ import {
COMPOSE_REMOVE_FROM_MENTIONS, COMPOSE_REMOVE_FROM_MENTIONS,
COMPOSE_SET_STATUS, COMPOSE_SET_STATUS,
COMPOSE_EVENT_REPLY, COMPOSE_EVENT_REPLY,
COMPOSE_SET_GROUP_TIMELINE_VISIBLE,
} from '../actions/compose'; } from '../actions/compose';
import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me'; import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS } from '../actions/me';
import { SETTING_CHANGE, FE_NAME } from '../actions/settings'; import { SETTING_CHANGE, FE_NAME } from '../actions/settings';
@ -103,6 +104,7 @@ export const ReducerCompose = ImmutableRecord({
tagHistory: ImmutableList<string>(), tagHistory: ImmutableList<string>(),
text: '', text: '',
to: ImmutableOrderedSet<string>(), to: ImmutableOrderedSet<string>(),
group_timeline_visible: false, // TruthSocial
}); });
type State = ImmutableMap<string, Compose>; type State = ImmutableMap<string, Compose>;
@ -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))); return updateCompose(state, action.id, compose => compose.update('to', mentions => mentions!.add(action.account)));
case COMPOSE_REMOVE_FROM_MENTIONS: case COMPOSE_REMOVE_FROM_MENTIONS:
return updateCompose(state, action.id, compose => compose.update('to', mentions => mentions!.delete(action.account))); 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: case ME_FETCH_SUCCESS:
return updateCompose(state, 'default', compose => importAccount(compose, action.me)); return updateCompose(state, 'default', compose => importAccount(compose, action.me));
case ME_PATCH_SUCCESS: case ME_PATCH_SUCCESS:

View file

@ -21,7 +21,6 @@
@import 'components/display-name'; @import 'components/display-name';
@import 'components/columns'; @import 'components/columns';
@import 'components/search'; @import 'components/search';
@import 'components/react-toggle';
@import 'components/video-player'; @import 'components/video-player';
@import 'components/audio-player'; @import 'components/audio-player';
@import 'components/crypto-donate'; @import 'components/crypto-donate';

View file

@ -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;
}

View file

@ -87,7 +87,6 @@
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"@types/react-sparklines": "^1.7.2", "@types/react-sparklines": "^1.7.2",
"@types/react-swipeable-views": "^0.13.1", "@types/react-swipeable-views": "^0.13.1",
"@types/react-toggle": "^4.0.3",
"@types/redux-mock-store": "^1.0.3", "@types/redux-mock-store": "^1.0.3",
"@types/seedrandom": "^3.0.2", "@types/seedrandom": "^3.0.2",
"@types/semver": "^7.3.9", "@types/semver": "^7.3.9",
@ -165,7 +164,6 @@
"react-sticky-box": "^2.0.0", "react-sticky-box": "^2.0.0",
"react-swipeable-views": "^0.14.0", "react-swipeable-views": "^0.14.0",
"react-textarea-autosize": "^8.3.4", "react-textarea-autosize": "^8.3.4",
"react-toggle": "^4.1.2",
"react-virtuoso": "^4.0.8", "react-virtuoso": "^4.0.8",
"redux": "^4.1.1", "redux": "^4.1.1",
"redux-immutable": "^4.0.0", "redux-immutable": "^4.0.0",

View file

@ -4497,13 +4497,6 @@
dependencies: dependencies:
"@types/react" "*" "@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": "@types/react@*", "@types/react@17", "@types/react@^18.0.26":
version "18.0.26" version "18.0.26"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" 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-composed-ref "^1.3.0"
use-latest "^1.2.1" 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: react-transition-group@^2.2.1:
version "2.9.0" version "2.9.0"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"