pl-fe: WIP: Allow configuring url-purify

Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
mkljczk
2025-03-06 19:07:37 +01:00
parent 215eb39a8c
commit 076ff88f58
9 changed files with 172 additions and 36 deletions

View File

@@ -13,10 +13,12 @@ interface ISettingToggle {
settingPath: string[];
/** Callback when the setting is toggled. */
onChange: (settingPath: string[], checked: boolean) => void;
/** Whether the toggle is disabled. */
disabled?: boolean;
}
/** Stateful toggle to change user settings. */
const SettingToggle: React.FC<ISettingToggle> = ({ id, settings, settingPath, onChange }) => {
const SettingToggle: React.FC<ISettingToggle> = ({ id, settings, settingPath, onChange, disabled }) => {
const handleChange: React.ChangeEventHandler<HTMLInputElement> = ({ target }) => {
onChange(settingPath, target.checked);
@@ -27,6 +29,7 @@ const SettingToggle: React.FC<ISettingToggle> = ({ id, settings, settingPath, on
id={id}
checked={!!get(settings, settingPath)}
onChange={handleChange}
disabled={disabled}
/>
);
};

View File

@@ -42,6 +42,7 @@ const messages = defineMessages({
security: { id: 'settings.security', defaultMessage: 'Security' },
sessions: { id: 'settings.sessions', defaultMessage: 'Active sessions' },
settings: { id: 'settings.settings', defaultMessage: 'Settings' },
urlPrivacy: { id: 'settings.url_privacy', defaultMessage: 'URL privacy' },
});
/** User settings page. */
@@ -92,39 +93,31 @@ const Settings = () => {
</List>
</CardBody>
{any([
features.changeEmail,
features.changePassword,
features.manageMfa,
features.sessions,
]) && (
<>
<CardHeader>
<CardTitle title={intl.formatMessage(messages.security)} />
</CardHeader>
<CardHeader>
<CardTitle title={intl.formatMessage(messages.security)} />
</CardHeader>
<CardBody>
<List>
{features.changeEmail && <ListItem label={intl.formatMessage(messages.changeEmail)} to='/settings/email' />}
{features.changePassword && <ListItem label={intl.formatMessage(messages.changePassword)} to='/settings/password' />}
{features.manageMfa && (
<>
<ListItem label={intl.formatMessage(messages.configureMfa)} to='/settings/mfa'>
<span>
{isMfaEnabled ?
intl.formatMessage(messages.mfaEnabled) :
intl.formatMessage(messages.mfaDisabled)}
</span>
</ListItem>
</>
)}
{features.sessions && (
<ListItem label={intl.formatMessage(messages.sessions)} to='/settings/tokens' />
)}
</List>
</CardBody>
</>
)}
<CardBody>
<List>
{features.changeEmail && <ListItem label={intl.formatMessage(messages.changeEmail)} to='/settings/email' />}
{features.changePassword && <ListItem label={intl.formatMessage(messages.changePassword)} to='/settings/password' />}
{features.manageMfa && (
<>
<ListItem label={intl.formatMessage(messages.configureMfa)} to='/settings/mfa'>
<span>
{isMfaEnabled ?
intl.formatMessage(messages.mfaEnabled) :
intl.formatMessage(messages.mfaDisabled)}
</span>
</ListItem>
</>
)}
{features.sessions && (
<ListItem label={intl.formatMessage(messages.sessions)} to='/settings/tokens' />
)}
<ListItem label={intl.formatMessage(messages.urlPrivacy)} to='/settings/url_privacy' />
</List>
</CardBody>
{features.chats ? (
<>

View File

@@ -139,6 +139,7 @@ import {
StatusHoverCard,
TestTimeline,
ThemeEditor,
UrlPrivacy,
UserIndex,
} from './util/async-components';
import GlobalHotkeys from './util/global-hotkeys';
@@ -304,6 +305,7 @@ const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = React.memo(({ chil
<WrappedRoute path='/settings/mfa' layout={DefaultLayout} component={MfaForm} exact />
<WrappedRoute path='/settings/tokens' layout={DefaultLayout} component={AuthTokenList} content={children} />
{features.interactionRequests && <WrappedRoute path='/settings/interaction_policies' layout={DefaultLayout} component={InteractionPolicies} content={children} />}
<WrappedRoute path='/settings/url_privacy' layout={DefaultLayout} component={UrlPrivacy} content={children} />
<WrappedRoute path='/settings' layout={DefaultLayout} component={Settings} content={children} />
<WrappedRoute path='/pl-fe/config' adminOnly layout={DefaultLayout} component={PlFeConfig} content={children} />

View File

@@ -90,6 +90,7 @@ export const Share = lazy(() => import('pl-fe/features/share'));
export const Status = lazy(() => import('pl-fe/features/status'));
export const TestTimeline = lazy(() => import('pl-fe/features/test-timeline'));
export const ThemeEditor = lazy(() => import('pl-fe/features/theme-editor'));
export const UrlPrivacy = lazy(() => import('pl-fe/features/url-privacy'));
export const UserIndex = lazy(() => import('pl-fe/features/admin/user-index'));
// Panels

View File

@@ -0,0 +1,101 @@
import React, { useEffect } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { changeSetting } from 'pl-fe/actions/settings';
import List, { ListItem } from 'pl-fe/components/list';
import Button from 'pl-fe/components/ui/button';
import Card, { CardBody, CardHeader, CardTitle } from 'pl-fe/components/ui/card';
import Column from 'pl-fe/components/ui/column';
import Form from 'pl-fe/components/ui/form';
import FormActions from 'pl-fe/components/ui/form-actions';
import FormGroup from 'pl-fe/components/ui/form-group';
import Input from 'pl-fe/components/ui/input';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useSettings } from 'pl-fe/hooks/use-settings';
import SettingToggle from '../notifications/components/setting-toggle';
const messages = defineMessages({
urlPrivacy: { id: 'settings.url_privacy', defaultMessage: 'URL privacy' },
rulesUrlPlaceholder: { id: 'url_privacy.rules_url.placeholder', defaultMessage: 'Rules URL' },
hashUrlPlaceholder: { id: 'url_privacy.hash_url.placeholder', defaultMessage: 'Hash URL' },
});
const UrlPrivacy = () => {
const dispatch = useAppDispatch();
const intl = useIntl();
const settings = useSettings();
useEffect(() => {
}, [dispatch]);
const onToggleChange = (key: string[], checked: boolean) => {
dispatch(changeSetting(key, checked));
};
return (
<Column label={intl.formatMessage(messages.urlPrivacy)} transparent withHeader={false}>
<Card className='space-y-4' variant='rounded'>
<CardHeader backHref='/settings'>
<CardTitle title={intl.formatMessage(messages.urlPrivacy)} />
</CardHeader>
<CardBody>
<Form>
<List>
<ListItem label={<FormattedMessage id='url_privacy.clear_links_in_compose' defaultMessage='Suggest removing tracking parameters when composing a post' />}>
<SettingToggle settings={settings} settingPath={['urlPrivacy', 'clearLinksInCompose']} onChange={onToggleChange} />
</ListItem>
<ListItem label={<FormattedMessage id='url_privacy.clear_links_in_content' defaultMessage='Remove tracking parameters from displayed posts' />}>
<SettingToggle settings={settings} settingPath={['urlPrivacy', 'clearLinksInContent']} onChange={onToggleChange} />
</ListItem>
<ListItem label={<FormattedMessage id='url_privacy.allow_referral_marketing' defaultMessage='Make exception for referral marketing parameters' />}>
<SettingToggle
settings={settings}
settingPath={['urlPrivacy', 'allowReferralMarketing']}
onChange={onToggleChange}
disabled={!(settings.urlPrivacy.clearLinksInCompose || settings.urlPrivacy.clearLinksInContent)}
/>
</ListItem>
</List>
<FormGroup
labelText={<FormattedMessage id='url_privacy.rules_url.label' defaultMessage='URL cleaning rules database address' />}
hintText={<FormattedMessage id='url_privacy.rules_url.placeholder' defaultMessage='Rules database in ClearURLs-compatible format, eg. {url}' values={{ url: 'https://rules2.clearurls.xyz/data.minify.json' }} />}
>
<Input
type='text'
placeholder={intl.formatMessage(messages.rulesUrlPlaceholder)}
value={settings.urlPrivacy.rulesUrl}
// onChange={handleChange('tileServer', (e) => e.target.value)}
/>
</FormGroup>
<FormGroup
labelText={<FormattedMessage id='url_privacy.hash_url.label' defaultMessage='URL cleaning rules hash address (optional)' />}
hintText={<FormattedMessage id='url_privacy.hash_url.placeholder' defaultMessage='SHA256 hash of rules database, used to avoid unnecessary fetches, eg. {url}' values={{ url: 'https://rules2.clearurls.xyz/rules.minify.hash' }} />}
>
<Input
type='text'
placeholder={intl.formatMessage(messages.hashUrlPlaceholder)}
value={settings.urlPrivacy.rulesUrl}
// onChange={handleChange('tileServer', (e) => e.target.value)}
/>
</FormGroup>
<FormActions>
<Button type='submit'>
<FormattedMessage id='url_privacy.save' defaultMessage='Save' />
</Button>
</FormActions>
</Form>
</CardBody>
</Card>
</Column>
);
};
export { UrlPrivacy as default };