mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 19:52:24 -06:00 
			
		
		
		
	* [feature] Allow users to set default interaction policies * use vars for default policies * avoid some code repetition * unfuck form binding * avoid bonkers loop * beep boop * put policyValsToAPIPolicyVals in separate function * don't bother with slices.Grow * oops
		
			
				
	
	
		
			180 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/*
 | 
						|
	GoToSocial
 | 
						|
	Copyright (C) GoToSocial Authors admin@gotosocial.org
 | 
						|
	SPDX-License-Identifier: AGPL-3.0-or-later
 | 
						|
 | 
						|
	This program is free software: you can redistribute it and/or modify
 | 
						|
	it under the terms of the GNU Affero General Public License as published by
 | 
						|
	the Free Software Foundation, either version 3 of the License, or
 | 
						|
	(at your option) any later version.
 | 
						|
 | 
						|
	This program is distributed in the hope that it will be useful,
 | 
						|
	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
	GNU Affero General Public License for more details.
 | 
						|
 | 
						|
	You should have received a copy of the GNU Affero General Public License
 | 
						|
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
*/
 | 
						|
 | 
						|
import React, { useMemo } from "react";
 | 
						|
import {
 | 
						|
	InteractionPolicyValue,
 | 
						|
	PolicyValueAuthor,
 | 
						|
	PolicyValueFollowers,
 | 
						|
	PolicyValueMentioned,
 | 
						|
	PolicyValuePublic,
 | 
						|
} from "../../../../lib/types/interaction";
 | 
						|
import { useTextInput } from "../../../../lib/form";
 | 
						|
import { Action, BasicValue, PolicyFormSub, Visibility } from "./types";
 | 
						|
 | 
						|
// Based on the given visibility, action, and states,
 | 
						|
// derives what the initial basic Select value should be.
 | 
						|
function useBasicValue(
 | 
						|
	forVis: Visibility,
 | 
						|
	forAction: Action,
 | 
						|
	always: InteractionPolicyValue[],
 | 
						|
	withApproval: InteractionPolicyValue[],
 | 
						|
): BasicValue {
 | 
						|
	// Check if "always" value is just the author
 | 
						|
	// (and possibly mentioned accounts when dealing
 | 
						|
	// with replies -- still counts as "just_me").
 | 
						|
	const alwaysJustAuthor = useMemo(() => {
 | 
						|
		if (
 | 
						|
			always.length === 1 &&
 | 
						|
			always[0] === PolicyValueAuthor
 | 
						|
		) {
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		if (
 | 
						|
			forAction === "reply" &&
 | 
						|
			always.length === 2 &&
 | 
						|
			always.includes(PolicyValueAuthor) &&
 | 
						|
			always.includes(PolicyValueMentioned)
 | 
						|
		) {
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		return false;
 | 
						|
	}, [forAction, always]);
 | 
						|
 | 
						|
	// Check if "always" includes the widest
 | 
						|
	// possible audience for this visibility.
 | 
						|
	const alwaysWidestAudience = useMemo(() => {
 | 
						|
		return (
 | 
						|
			(forVis === "private" && always.includes(PolicyValueFollowers)) ||
 | 
						|
			always.includes(PolicyValuePublic)
 | 
						|
		);
 | 
						|
	}, [forVis, always]);
 | 
						|
 | 
						|
	// Check if "withApproval" includes the widest
 | 
						|
	// possible audience for this visibility.
 | 
						|
	const withApprovalWidestAudience = useMemo(() => {
 | 
						|
		return (
 | 
						|
			(forVis === "private" && withApproval.includes(PolicyValueFollowers)) ||
 | 
						|
			withApproval.includes(PolicyValuePublic)
 | 
						|
		);
 | 
						|
	}, [forVis, withApproval]);
 | 
						|
 | 
						|
	return useMemo(() => {
 | 
						|
		// Simplest case: if "always" includes the
 | 
						|
		// widest possible audience for this visibility,
 | 
						|
		// then we don't need to check anything else.
 | 
						|
		if (alwaysWidestAudience) {
 | 
						|
			return "anyone";
 | 
						|
		}
 | 
						|
 | 
						|
		// Next simplest case: there's no "with approval"
 | 
						|
		// URIs set, so check if it's always just author.
 | 
						|
		if (withApproval.length === 0 && alwaysJustAuthor) {
 | 
						|
			return "just_me";
 | 
						|
		}
 | 
						|
 | 
						|
		// Third simplest case: always is just us, and with
 | 
						|
		// approval is addressed to the widest possible audience.
 | 
						|
		if (alwaysJustAuthor && withApprovalWidestAudience) {
 | 
						|
			return "anyone_with_approval";
 | 
						|
		}
 | 
						|
 | 
						|
		// We've exhausted the
 | 
						|
		// simple possibilities.
 | 
						|
		return "something_else";
 | 
						|
	}, [
 | 
						|
		withApproval.length,
 | 
						|
		alwaysJustAuthor,
 | 
						|
		alwaysWidestAudience,
 | 
						|
		withApprovalWidestAudience,
 | 
						|
	]);
 | 
						|
}
 | 
						|
 | 
						|
// Derive wording for the basic label for 
 | 
						|
// whatever visibility and action we're handling.
 | 
						|
function useBasicLabel(visibility: Visibility, action: Action) {
 | 
						|
	return useMemo(() => {
 | 
						|
		let visPost = "";
 | 
						|
		switch (visibility) {
 | 
						|
			case "public":
 | 
						|
				visPost = "a public post";
 | 
						|
				break;
 | 
						|
			case "unlisted":
 | 
						|
				visPost = "an unlisted post";
 | 
						|
				break;
 | 
						|
			case "private":
 | 
						|
				visPost = "a followers-only post";
 | 
						|
				break;
 | 
						|
		}
 | 
						|
		
 | 
						|
		switch (action) {
 | 
						|
			case "favourite":
 | 
						|
				return "Who can like " + visPost + "?";
 | 
						|
			case "reply":
 | 
						|
				return "Who else can reply to " + visPost + "?";
 | 
						|
			case "reblog":
 | 
						|
				return "Who can boost " + visPost + "?";
 | 
						|
		}
 | 
						|
	}, [visibility, action]);
 | 
						|
}
 | 
						|
 | 
						|
// Return whatever the "basic" options should
 | 
						|
// be in the basic Select for this visibility.
 | 
						|
function useBasicOptions(visibility: Visibility) {
 | 
						|
	return useMemo(() => {
 | 
						|
		const audience = visibility === "private"
 | 
						|
			? "My followers"
 | 
						|
			: "Anyone";
 | 
						|
		
 | 
						|
		return (
 | 
						|
			<>
 | 
						|
				<option value="anyone">{audience}</option>
 | 
						|
				<option value="anyone_with_approval">{audience} (approval required)</option>
 | 
						|
				<option value="just_me">Just me</option>
 | 
						|
				{ visibility !== "private" &&
 | 
						|
					<option value="something_else">Something else...</option>
 | 
						|
				}
 | 
						|
			</>
 | 
						|
		);
 | 
						|
	}, [visibility]);
 | 
						|
}
 | 
						|
 | 
						|
export function useBasicFor(
 | 
						|
	forVis: Visibility,
 | 
						|
	forAction: Action,
 | 
						|
	currentAlways: InteractionPolicyValue[],
 | 
						|
	currentWithApproval: InteractionPolicyValue[],
 | 
						|
): PolicyFormSub {
 | 
						|
	// Determine who's currently *basically* allowed
 | 
						|
	// to do this action for this visibility.
 | 
						|
	const defaultValue = useBasicValue(
 | 
						|
		forVis,
 | 
						|
		forAction,
 | 
						|
		currentAlways,
 | 
						|
		currentWithApproval,
 | 
						|
	);
 | 
						|
 | 
						|
	return {
 | 
						|
		field: useTextInput("basic", { defaultValue: defaultValue }),
 | 
						|
		label: useBasicLabel(forVis, forAction),
 | 
						|
		options: useBasicOptions(forVis),
 | 
						|
	};
 | 
						|
}
 |