From 12fc6e6e3280757d4257bbf7cf5e5e3f56f6c577 Mon Sep 17 00:00:00 2001 From: mkljczk Date: Sun, 29 Dec 2024 23:46:42 +0100 Subject: [PATCH] =?UTF-8?q?pl-fe:=C2=A0cleanup=20interaction=20modals=20se?= =?UTF-8?q?ttings=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: mkljczk --- .../features/interaction-policies/index.tsx | 94 +++++++++++++------ 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/packages/pl-fe/src/features/interaction-policies/index.tsx b/packages/pl-fe/src/features/interaction-policies/index.tsx index 1fc672ee9..61e5aced7 100644 --- a/packages/pl-fe/src/features/interaction-policies/index.tsx +++ b/packages/pl-fe/src/features/interaction-policies/index.tsx @@ -1,3 +1,4 @@ +import { create } from 'mutative'; import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; @@ -14,6 +15,8 @@ import toast from 'pl-fe/toast'; import Warning from '../compose/components/warning'; +import type { InteractionPolicy } from 'pl-api'; + type Visibility = 'public' | 'unlisted' | 'private'; type Policy = 'can_favourite' | 'can_reblog' | 'can_reply'; type Rule = 'always' | 'with_approval'; @@ -56,6 +59,11 @@ const titleMessages = { can_reply: { id: 'interaction_policies.title.private.can_reply', defaultMessage: 'Who can reply to a followers-only post?' }, can_reblog: { id: 'interaction_policies.title.private.can_reblog', defaultMessage: 'Who can repost a followers-only post?' }, }), + single_post: defineMessages({ + can_favourite: { id: 'interaction_policies.title.single_post.can_favourite', defaultMessage: 'Who can like the post?' }, + can_reply: { id: 'interaction_policies.title.single_post.can_reply', defaultMessage: 'Who can reply to the post?' }, + can_reblog: { id: 'interaction_policies.title.single_post.can_reblog', defaultMessage: 'Who can repost the post?' }, + }), }; const options: Record>> = { @@ -76,44 +84,34 @@ const options: Record>> = { }, }; -const InteractionPolicies = () => { - const { interactionPolicies: initial, updateInteractionPolicies, isUpdating } = useInteractionPolicies(); +interface IInteractionPolicyConfig { + interactionPolicy: InteractionPolicy; + visibility: Visibility; + onChange: (policy: Policy, rule: Rule, value: Scope[]) => void; + singlePost?: boolean; + disabled?: boolean; +} + +const InteractionPolicyConfig: React.FC = ({ interactionPolicy, visibility, onChange, singlePost, disabled }) => { const intl = useIntl(); - const [interactionPolicies, setInteractionPolicies] = useState(initial); - const [visibility, setVisibility] = useState('public'); - useEffect(() => { - setInteractionPolicies(initial); - }, [initial]); + const getItems = (policy: Policy) => Object.fromEntries(options[visibility][policy].map(scope => [scope, intl.formatMessage(scopeMessages[scope])])) as Record; - const getItems = (visibility: Visibility, policy: Policy) => Object.fromEntries(options[visibility][policy].map(scope => [scope, intl.formatMessage(scopeMessages[scope])])) as Record; - - const handleChange = (visibility: Visibility, policy: Policy, rule: Rule) => (value: Array) => { - const newPolicies = { ...interactionPolicies }; - newPolicies[visibility][policy][rule] = value; - newPolicies[visibility][policy][rule === 'always' ? 'with_approval' : 'always'] = newPolicies[visibility][policy][rule === 'always' ? 'with_approval' : 'always'].filter(rule => !value.includes(rule as any)); - - setInteractionPolicies(newPolicies); + const handleChange = (policy: Policy, rule: Rule) => (value: Scope[]) => { + onChange(policy, rule, value); }; - const handleSubmit = () => { - updateInteractionPolicies(interactionPolicies, { - onSuccess: () => toast.success(messages.success), - onError: () => toast.success(messages.fail), - }); - }; - - const renderPolicy = (visibility: 'public' | 'unlisted' | 'private') => ( + return ( <> {policies.map((policy) => { - const items = getItems(visibility, policy); + const items = getItems(policy); if (!Object.keys(items).length) return null; return ( {policy === 'can_reply' && ( @@ -124,17 +122,17 @@ const InteractionPolicies = () => { items={items} - value={interactionPolicies[visibility][policy].always as Array} - onChange={handleChange(visibility, policy, 'always')} - disabled={isUpdating} + value={interactionPolicy[policy].always as Array} + onChange={handleChange(policy, 'always')} + disabled={disabled} /> } - onChange={handleChange(visibility, policy, 'with_approval')} - disabled={isUpdating} + value={interactionPolicy[policy].with_approval as Array} + onChange={handleChange(policy, 'with_approval')} + disabled={disabled} /> @@ -143,6 +141,40 @@ const InteractionPolicies = () => { })} ); +}; + +const InteractionPolicies = () => { + const { interactionPolicies: initial, updateInteractionPolicies, isUpdating } = useInteractionPolicies(); + const intl = useIntl(); + const [interactionPolicies, setInteractionPolicies] = useState(initial); + const [visibility, setVisibility] = useState('public'); + + useEffect(() => { + setInteractionPolicies(initial); + }, [initial]); + + const handleChange = (visibility: Visibility, policy: Policy, rule: Rule, value: Array) => { + setInteractionPolicies((policies) => create(policies, (draft) => { + draft[visibility][policy][rule] = value; + draft[visibility][policy][rule === 'always' ? 'with_approval' : 'always'] = draft[visibility][policy][rule === 'always' ? 'with_approval' : 'always'].filter(rule => !value.includes(rule as any)); + })); + }; + + const handleSubmit = () => { + updateInteractionPolicies(interactionPolicies, { + onSuccess: () => toast.success(messages.success), + onError: () => toast.success(messages.fail), + }); + }; + + const renderPolicy = (visibility: 'public' | 'unlisted' | 'private') => ( + handleChange(visibility, ...props)} + disabled={isUpdating} + /> + ); return (