From c096b0698840e7d8ec26f8451434e984bd1af3ba Mon Sep 17 00:00:00 2001 From: askmeaboutloom Date: Sat, 27 Jan 2024 00:43:23 +0100 Subject: [PATCH] Make content warnings part of the default section Because I'm getting tired of repeating it for a bunch of sites. The content warning will automatically be applied to Itaku, Mastodon, Misskey, Pixelfed and Pleroma. They can also overwrite the default via toggle switch, similar to how it works for descriptions. Probably mostly necessary for Itaku with its dinky 30 character limit. The content warning can be included into the description using the {cw} shortcut. This is mostly useful for sites like Bluesky and Telegram, which support spoilers, but don't have a dedicated content warning field. Backward compatibility with existing posts should be preserved: if the overwrite option is undefined, it will be guessed by the presence of a non-empty content warning text. This also now consistently presents the field as "content warning" to the user, rather than revealing the internal "spoiler text" name. I've seen confused users on Mastodon thinking that PostyBirb didn't support content warnings because of the misnomer. --- .../submission/default-options.interface.ts | 1 + .../itaku/itaku.file.options.interface.ts | 1 + .../itaku.notification.options.interface.ts | 1 + .../mastodon.file.options.interface.ts | 1 + ...mastodon.notification.options.interface.ts | 1 + .../misskey/misskey.file.options.interface.ts | 1 + .../misskey.notification.options.interface.ts | 1 + .../pixelfed.file.options.interface.ts | 1 + .../pleroma/pleroma.file.options.interface.ts | 1 + .../pleroma.notification.options.interface.ts | 1 + commons/src/models/default-options.entity.ts | 4 + .../src/websites/itaku/itaku.file.options.ts | 5 ++ .../itaku/itaku.notification.options.ts | 7 +- .../mastodon/mastodon.file.options.ts | 5 ++ .../mastodon/mastodon.notification.options.ts | 5 ++ .../websites/misskey/misskey.file.options.ts | 5 ++ .../misskey/misskey.notification.options.ts | 5 ++ .../pixelfed/pixelfed.file.options.ts | 5 ++ .../websites/pleroma/pleroma.file.options.ts | 7 +- .../pleroma/pleroma.notification.options.ts | 5 ++ .../submission/parser/parser.service.ts | 17 +++++ .../section-parsers/description.parser.ts | 6 +- .../post/interfaces/post-data.interface.ts | 1 + .../src/server/utils/form-content.util.ts | 16 ++++ .../server/websites/itaku/itaku.service.ts | 11 ++- .../websites/megalodon/megalodon.service.ts | 8 +- .../websites/misskey/misskey.service.ts | 8 +- .../form-components/DescriptionInput.tsx | 7 ++ .../form-components/SpoilerTextInput.tsx | 74 +++++++++++++++++++ .../form-sections/DefaultFormSection.tsx | 3 + ui/src/websites/itaku/Itaku.tsx | 15 ++-- ui/src/websites/mastodon/Mastodon.tsx | 25 ++++--- ui/src/websites/misskey/MissKey.tsx | 25 ++++--- ui/src/websites/pixelfed/Pixelfed.tsx | 13 ++-- ui/src/websites/pleroma/Pleroma.tsx | 25 ++++--- 35 files changed, 254 insertions(+), 63 deletions(-) create mode 100644 ui/src/views/submissions/submission-forms/form-components/SpoilerTextInput.tsx diff --git a/commons/src/interfaces/submission/default-options.interface.ts b/commons/src/interfaces/submission/default-options.interface.ts index c46b577c..b9220ffb 100644 --- a/commons/src/interfaces/submission/default-options.interface.ts +++ b/commons/src/interfaces/submission/default-options.interface.ts @@ -7,6 +7,7 @@ export interface DefaultOptions { tags: TagData; description: DescriptionData; rating?: SubmissionRating | string; + spoilerText?: string; sources: string[]; } diff --git a/commons/src/interfaces/websites/itaku/itaku.file.options.interface.ts b/commons/src/interfaces/websites/itaku/itaku.file.options.interface.ts index 4ae6a4cc..8202d390 100644 --- a/commons/src/interfaces/websites/itaku/itaku.file.options.interface.ts +++ b/commons/src/interfaces/websites/itaku/itaku.file.options.interface.ts @@ -5,4 +5,5 @@ export interface ItakuFileOptions extends DefaultFileOptions { visibility: string; shareOnFeed: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; } diff --git a/commons/src/interfaces/websites/itaku/itaku.notification.options.interface.ts b/commons/src/interfaces/websites/itaku/itaku.notification.options.interface.ts index 0f5d9bf6..dad8447e 100644 --- a/commons/src/interfaces/websites/itaku/itaku.notification.options.interface.ts +++ b/commons/src/interfaces/websites/itaku/itaku.notification.options.interface.ts @@ -4,4 +4,5 @@ export interface ItakuNotificationOptions extends DefaultOptions { folders: string[]; visibility: string; spoilerText?: string; + spoilerTextOverwrite?: boolean; } diff --git a/commons/src/interfaces/websites/mastodon/mastodon.file.options.interface.ts b/commons/src/interfaces/websites/mastodon/mastodon.file.options.interface.ts index ecbe86a1..96354e72 100644 --- a/commons/src/interfaces/websites/mastodon/mastodon.file.options.interface.ts +++ b/commons/src/interfaces/websites/mastodon/mastodon.file.options.interface.ts @@ -3,6 +3,7 @@ import { DefaultFileOptions } from '../../submission/default-options.interface'; export interface MastodonFileOptions extends DefaultFileOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; altText?: string; replyToUrl?: string; diff --git a/commons/src/interfaces/websites/mastodon/mastodon.notification.options.interface.ts b/commons/src/interfaces/websites/mastodon/mastodon.notification.options.interface.ts index 610d083f..9cedf5f5 100644 --- a/commons/src/interfaces/websites/mastodon/mastodon.notification.options.interface.ts +++ b/commons/src/interfaces/websites/mastodon/mastodon.notification.options.interface.ts @@ -3,6 +3,7 @@ import { DefaultOptions } from '../../submission/default-options.interface'; export interface MastodonNotificationOptions extends DefaultOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; replyToUrl?: string; } diff --git a/commons/src/interfaces/websites/misskey/misskey.file.options.interface.ts b/commons/src/interfaces/websites/misskey/misskey.file.options.interface.ts index 184683ed..22abe618 100644 --- a/commons/src/interfaces/websites/misskey/misskey.file.options.interface.ts +++ b/commons/src/interfaces/websites/misskey/misskey.file.options.interface.ts @@ -3,6 +3,7 @@ import { DefaultFileOptions } from '../../submission/default-options.interface'; export interface MissKeyFileOptions extends DefaultFileOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; altText?: string; } diff --git a/commons/src/interfaces/websites/misskey/misskey.notification.options.interface.ts b/commons/src/interfaces/websites/misskey/misskey.notification.options.interface.ts index 34de52ca..791c2d6d 100644 --- a/commons/src/interfaces/websites/misskey/misskey.notification.options.interface.ts +++ b/commons/src/interfaces/websites/misskey/misskey.notification.options.interface.ts @@ -3,5 +3,6 @@ import { DefaultOptions } from '../../submission/default-options.interface'; export interface MissKeyNotificationOptions extends DefaultOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; } diff --git a/commons/src/interfaces/websites/pixelfed/pixelfed.file.options.interface.ts b/commons/src/interfaces/websites/pixelfed/pixelfed.file.options.interface.ts index e4bebe8a..d597b1c4 100644 --- a/commons/src/interfaces/websites/pixelfed/pixelfed.file.options.interface.ts +++ b/commons/src/interfaces/websites/pixelfed/pixelfed.file.options.interface.ts @@ -3,6 +3,7 @@ import { DefaultFileOptions } from '../../submission/default-options.interface'; export interface PixelfedFileOptions extends DefaultFileOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; altText?: string; } diff --git a/commons/src/interfaces/websites/pleroma/pleroma.file.options.interface.ts b/commons/src/interfaces/websites/pleroma/pleroma.file.options.interface.ts index dd4fe0ca..7362b99b 100644 --- a/commons/src/interfaces/websites/pleroma/pleroma.file.options.interface.ts +++ b/commons/src/interfaces/websites/pleroma/pleroma.file.options.interface.ts @@ -3,6 +3,7 @@ import { DefaultFileOptions } from '../../submission/default-options.interface'; export interface PleromaFileOptions extends DefaultFileOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; altText?: string; replyToUrl?: string; diff --git a/commons/src/interfaces/websites/pleroma/pleroma.notification.options.interface.ts b/commons/src/interfaces/websites/pleroma/pleroma.notification.options.interface.ts index a674afb0..746ca673 100644 --- a/commons/src/interfaces/websites/pleroma/pleroma.notification.options.interface.ts +++ b/commons/src/interfaces/websites/pleroma/pleroma.notification.options.interface.ts @@ -3,6 +3,7 @@ import { DefaultOptions } from '../../submission/default-options.interface'; export interface PleromaNotificationOptions extends DefaultOptions { useTitle: boolean; spoilerText?: string; + spoilerTextOverwrite?: boolean; visibility: string; replyToUrl?: string; } diff --git a/commons/src/models/default-options.entity.ts b/commons/src/models/default-options.entity.ts index 2a8f66c1..56c4b3a8 100644 --- a/commons/src/models/default-options.entity.ts +++ b/commons/src/models/default-options.entity.ts @@ -30,6 +30,10 @@ export class DefaultOptionsEntity implements DefaultOptions { @IsOptional() rating?: SubmissionRating | string; + @Expose() + @IsOptional() + spoilerText?: string; + @IsArray() sources: string[]; diff --git a/commons/src/websites/itaku/itaku.file.options.ts b/commons/src/websites/itaku/itaku.file.options.ts index cdc7d222..3e667912 100644 --- a/commons/src/websites/itaku/itaku.file.options.ts +++ b/commons/src/websites/itaku/itaku.file.options.ts @@ -26,6 +26,11 @@ export class ItakuFileOptionsEntity extends DefaultFileOptionsEntity implements @IsOptional() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + constructor(entity?: Partial) { super(entity as DefaultFileOptions); } diff --git a/commons/src/websites/itaku/itaku.notification.options.ts b/commons/src/websites/itaku/itaku.notification.options.ts index 040476ee..60bf93a3 100644 --- a/commons/src/websites/itaku/itaku.notification.options.ts +++ b/commons/src/websites/itaku/itaku.notification.options.ts @@ -1,5 +1,5 @@ import { Expose } from 'class-transformer'; -import { IsArray, IsString, IsOptional } from 'class-validator'; +import { IsArray, IsString, IsOptional, IsBoolean } from 'class-validator'; import { DefaultOptions } from '../../interfaces/submission/default-options.interface'; import { ItakuNotificationOptions } from '../../interfaces/websites/itaku/itaku.notification.options.interface'; import { DefaultValue } from '../../models/decorators/default-value.decorator'; @@ -24,6 +24,11 @@ export class ItakuNotificationOptionsEntity @IsOptional() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + constructor(entity?: Partial) { super(entity as DefaultOptions); } diff --git a/commons/src/websites/mastodon/mastodon.file.options.ts b/commons/src/websites/mastodon/mastodon.file.options.ts index 55eef672..08078468 100644 --- a/commons/src/websites/mastodon/mastodon.file.options.ts +++ b/commons/src/websites/mastodon/mastodon.file.options.ts @@ -19,6 +19,11 @@ export class MastodonFileOptionsEntity @IsString() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/commons/src/websites/mastodon/mastodon.notification.options.ts b/commons/src/websites/mastodon/mastodon.notification.options.ts index 485f3ba2..ded8441c 100644 --- a/commons/src/websites/mastodon/mastodon.notification.options.ts +++ b/commons/src/websites/mastodon/mastodon.notification.options.ts @@ -19,6 +19,11 @@ export class MastodonNotificationOptionsEntity @IsString() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/commons/src/websites/misskey/misskey.file.options.ts b/commons/src/websites/misskey/misskey.file.options.ts index f85e9465..76664b1c 100644 --- a/commons/src/websites/misskey/misskey.file.options.ts +++ b/commons/src/websites/misskey/misskey.file.options.ts @@ -19,6 +19,11 @@ export class MissKeyFileOptionsEntity @IsString() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/commons/src/websites/misskey/misskey.notification.options.ts b/commons/src/websites/misskey/misskey.notification.options.ts index 5c625f68..f6f18475 100644 --- a/commons/src/websites/misskey/misskey.notification.options.ts +++ b/commons/src/websites/misskey/misskey.notification.options.ts @@ -19,6 +19,11 @@ export class MissKeyNotificationOptionsEntity @IsString() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/commons/src/websites/pixelfed/pixelfed.file.options.ts b/commons/src/websites/pixelfed/pixelfed.file.options.ts index 800403f3..174a4269 100644 --- a/commons/src/websites/pixelfed/pixelfed.file.options.ts +++ b/commons/src/websites/pixelfed/pixelfed.file.options.ts @@ -19,6 +19,11 @@ export class PixelfedFileOptionsEntity @IsString() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/commons/src/websites/pleroma/pleroma.file.options.ts b/commons/src/websites/pleroma/pleroma.file.options.ts index 94d559db..761d0a74 100644 --- a/commons/src/websites/pleroma/pleroma.file.options.ts +++ b/commons/src/websites/pleroma/pleroma.file.options.ts @@ -16,7 +16,12 @@ export class PleromaFileOptionsEntity extends DefaultFileOptionsEntity @IsOptional() @IsString() spoilerText?: string; - + + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/commons/src/websites/pleroma/pleroma.notification.options.ts b/commons/src/websites/pleroma/pleroma.notification.options.ts index b39ca0ab..2350c943 100644 --- a/commons/src/websites/pleroma/pleroma.notification.options.ts +++ b/commons/src/websites/pleroma/pleroma.notification.options.ts @@ -17,6 +17,11 @@ export class PleromaNotificationOptionsEntity extends DefaultOptionsEntity @IsString() spoilerText?: string; + @Expose() + @IsBoolean() + @IsOptional() + spoilerTextOverwrite?: boolean; + @Expose() @IsString() @DefaultValue('public') diff --git a/electron-app/src/server/submission/parser/parser.service.ts b/electron-app/src/server/submission/parser/parser.service.ts index e9eabd3c..c7ebc692 100644 --- a/electron-app/src/server/submission/parser/parser.service.ts +++ b/electron-app/src/server/submission/parser/parser.service.ts @@ -68,6 +68,7 @@ export class ParserService { submission, tags, title: this.getTitle(submission, defaultPart, websitePart), + spoilerText: this.getSpoilerText(defaultPart, websitePart), }; if (this.isFileSubmission(submission)) { @@ -127,6 +128,22 @@ export class ParserService { return (websitePart.data.title || defaultPart.data.title || submission.title).substring(0, 160); } + private getSpoilerText( + defaultPart: SubmissionPartEntity, + websitePart: SubmissionPartEntity, + ): string { + const overwrite = websitePart.data.spoilerTextOverwrite; + const defaultSpoilerText = defaultPart.data.spoilerText || ''; + const websiteSpoilerText = `${websitePart.data.spoilerText || ''}`; + if (overwrite === undefined) { + return websiteSpoilerText.trim() === '' ? defaultSpoilerText : websiteSpoilerText; + } else if (overwrite) { + return websiteSpoilerText; + } else { + return defaultSpoilerText; + } + } + private isFileSubmission(submission: Submission): submission is FileSubmission { return submission instanceof FileSubmissionEntity; } diff --git a/electron-app/src/server/submission/parser/section-parsers/description.parser.ts b/electron-app/src/server/submission/parser/section-parsers/description.parser.ts index 9d37de07..b43562f3 100644 --- a/electron-app/src/server/submission/parser/section-parsers/description.parser.ts +++ b/electron-app/src/server/submission/parser/section-parsers/description.parser.ts @@ -53,7 +53,7 @@ export class DescriptionParser { ).trim(); if (description.length) { - // Insert {default}, {title}, {tags} shortcuts + // Insert {default}, {title}, {tags}, {cw} shortcuts let tags = await this.parserService.parseTags(website, defaultPart, websitePart); description = this.insertDefaultShortcuts(description, [ { @@ -68,6 +68,10 @@ export class DescriptionParser { name: 'tags', content: website.generateTagsString(tags, description, websitePart), }, + { + name: 'cw', + content: FormContent.getSpoilerText(defaultPart.data, websitePart.data), + }, ]); // Parse all potential shortcut data diff --git a/electron-app/src/server/submission/post/interfaces/post-data.interface.ts b/electron-app/src/server/submission/post/interfaces/post-data.interface.ts index d829cd19..f52b4b53 100644 --- a/electron-app/src/server/submission/post/interfaces/post-data.interface.ts +++ b/electron-app/src/server/submission/post/interfaces/post-data.interface.ts @@ -11,4 +11,5 @@ export interface PostData { submission: T; tags: string[]; title: string; + spoilerText: string; } diff --git a/electron-app/src/server/utils/form-content.util.ts b/electron-app/src/server/utils/form-content.util.ts index 7ea043eb..b6f2141f 100644 --- a/electron-app/src/server/utils/form-content.util.ts +++ b/electron-app/src/server/utils/form-content.util.ts @@ -20,4 +20,20 @@ export default class FormContent { ? _.get(websiteDescription, 'value', '') : _.get(defaultDescription, 'value', ''); } + + static getSpoilerText( + defaultData: { spoilerText?: string }, + partData: { spoilerText?: string; spoilerTextOverwrite?: boolean }, + ): string { + const partSpoilerText = partData.spoilerText || ''; + const overwrite = + partData.spoilerTextOverwrite === undefined + ? partSpoilerText.trim() !== '' + : partData.spoilerTextOverwrite; + if (overwrite) { + return partSpoilerText; + } else { + return defaultData.spoilerText || ''; + } + } } diff --git a/electron-app/src/server/websites/itaku/itaku.service.ts b/electron-app/src/server/websites/itaku/itaku.service.ts index bf1eca55..b5bcbc55 100644 --- a/electron-app/src/server/websites/itaku/itaku.service.ts +++ b/electron-app/src/server/websites/itaku/itaku.service.ts @@ -174,8 +174,8 @@ export class Itaku extends Website { postData.add_to_feed = 'true'; } - if (data.options.spoilerText) { - postData.content_warning = data.options.spoilerText; + if (data.spoilerText) { + postData.content_warning = data.spoilerText; } if (fileRecord.type === FileSubmissionType.IMAGE) { @@ -256,7 +256,7 @@ export class Itaku extends Website { validateFileSubmission( submission: FileSubmission, - submissionPart: SubmissionPart, + submissionPart: SubmissionPart, defaultPart: SubmissionPart, ): ValidationParts { const problems: string[] = []; @@ -292,6 +292,11 @@ export class Itaku extends Website { problems.push(`Posting multiple images requires share on feed to be enabled`); } + const spoilerText = FormContent.getSpoilerText(defaultPart.data, submissionPart.data); + if (spoilerText.length > 30) { + problems.push(`Max content warning length allowed is 30 characters`); + } + return { problems, warnings }; } diff --git a/electron-app/src/server/websites/megalodon/megalodon.service.ts b/electron-app/src/server/websites/megalodon/megalodon.service.ts index aa0d81a7..d7bfcca0 100644 --- a/electron-app/src/server/websites/megalodon/megalodon.service.ts +++ b/electron-app/src/server/websites/megalodon/megalodon.service.ts @@ -142,8 +142,8 @@ export abstract class Megalodon extends Website { statusOptions.in_reply_to_id = replyToId; } - if (data.options.spoilerText) { - statusOptions.spoiler_text = data.options.spoilerText; + if (data.spoilerText) { + statusOptions.spoiler_text = data.spoilerText; } // Mastodon may return a 422 error if the media is still processing, @@ -200,8 +200,8 @@ export abstract class Megalodon extends Website { let status = `${data.options.useTitle && data.title ? `${data.title}\n` : ''}${ data.description }`; - if (data.options.spoilerText) { - statusOptions.spoiler_text = data.options.spoilerText; + if (data.spoilerText) { + statusOptions.spoiler_text = data.spoilerText; } const replyToId = this.getPostIdFromUrl(data.options.replyToUrl); diff --git a/electron-app/src/server/websites/misskey/misskey.service.ts b/electron-app/src/server/websites/misskey/misskey.service.ts index 1e398eec..fd2c7847 100644 --- a/electron-app/src/server/websites/misskey/misskey.service.ts +++ b/electron-app/src/server/websites/misskey/misskey.service.ts @@ -155,8 +155,8 @@ export class MissKey extends Website { if (i !== 0) { statusOptions.in_reply_to_id = lastId; } - if (data.options.spoilerText) { - statusOptions.spoiler_text = data.options.spoilerText; + if (data.spoilerText) { + statusOptions.spoiler_text = data.spoilerText; } this.checkCancelled(cancellationToken); @@ -196,8 +196,8 @@ export class MissKey extends Website { let status = `${data.options.useTitle && data.title ? `${data.title}\n` : ''}${ data.description }`.substring(0, maxChars); - if (data.options.spoilerText) { - statusOptions.spoiler_text = data.options.spoilerText; + if (data.spoilerText) { + statusOptions.spoiler_text = data.spoilerText; } this.checkCancelled(cancellationToken); diff --git a/ui/src/views/submissions/submission-forms/form-components/DescriptionInput.tsx b/ui/src/views/submissions/submission-forms/form-components/DescriptionInput.tsx index a2c5ea00..34ca230e 100644 --- a/ui/src/views/submissions/submission-forms/form-components/DescriptionInput.tsx +++ b/ui/src/views/submissions/submission-forms/form-components/DescriptionInput.tsx @@ -181,6 +181,13 @@ export default class DescriptionInput extends React.Component { Inserts the website tags or the default tags separated by ' #' +
  • + {'{cw}'} + - + + Inserts the content warning + +
  • } diff --git a/ui/src/views/submissions/submission-forms/form-components/SpoilerTextInput.tsx b/ui/src/views/submissions/submission-forms/form-components/SpoilerTextInput.tsx new file mode 100644 index 00000000..bffa3269 --- /dev/null +++ b/ui/src/views/submissions/submission-forms/form-components/SpoilerTextInput.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { Form, Input, Switch } from 'antd'; +import { observer } from 'mobx-react'; + +interface Props { + label?: string; + maxLength?: number; + overwriteDefault?: boolean; + spoilerText?: string; + onChangeOverwriteDefault: (overwriteDefault: boolean) => void; + onChangeSpoilerText: (spoilerText: string) => void; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface State {} + +@observer +export default class SpoilerTextInput extends React.Component { + state: State = {}; + + private overwriteDefault: boolean; + private spoilerText: string; + + constructor(props: Props) { + super(props); + if (props.overwriteDefault === undefined) { + this.spoilerText = props.spoilerText || ''; + this.overwriteDefault = this.spoilerText.trim() !== ''; + if (this.overwriteDefault) { + this.props.onChangeOverwriteDefault(true); + } + } else { + this.overwriteDefault = !!props.overwriteDefault; + this.spoilerText = props.spoilerText || ''; + } + } + + handleOverwriteDefaultChange = (checked: boolean) => { + this.overwriteDefault = !checked; + this.props.onChangeOverwriteDefault(this.overwriteDefault); + if (!checked && this.props.overwriteDefault) { + this.handleSpoilerTextChange(this.props.spoilerText || ''); + } + }; + + handleSpoilerTextChange = (spoilerText: string) => { + this.spoilerText = spoilerText; + this.props.onChangeSpoilerText(this.spoilerText); + }; + + render() { + return ( + +
    + + + + Use default +
    + {this.props.overwriteDefault && ( + this.handleSpoilerTextChange(e.target.value)} + maxLength={this.props.maxLength} + /> + )} +
    + ); + } +} diff --git a/ui/src/views/submissions/submission-forms/form-sections/DefaultFormSection.tsx b/ui/src/views/submissions/submission-forms/form-sections/DefaultFormSection.tsx index ffa2fbad..168f96a1 100644 --- a/ui/src/views/submissions/submission-forms/form-sections/DefaultFormSection.tsx +++ b/ui/src/views/submissions/submission-forms/form-sections/DefaultFormSection.tsx @@ -62,6 +62,9 @@ export default class DefaultFormSection extends React.Component< Extreme + + + , - - - + , ); return elements; } diff --git a/ui/src/websites/mastodon/Mastodon.tsx b/ui/src/websites/mastodon/Mastodon.tsx index 2b3e2494..fc7ecebf 100644 --- a/ui/src/websites/mastodon/Mastodon.tsx +++ b/ui/src/websites/mastodon/Mastodon.tsx @@ -14,6 +14,7 @@ import GenericSubmissionSection from '../generic/GenericSubmissionSection'; import { LoginDialogProps } from '../interfaces/website.interface'; import { WebsiteImpl } from '../website.base'; import MastodonLogin from './MastodonLogin'; +import SpoilerTextInput from '../../views/submissions/submission-forms/form-components/SpoilerTextInput'; export class Mastodon extends WebsiteImpl { internalName: string = 'Mastodon'; @@ -72,12 +73,12 @@ class MastodonNotificationSubmissionForm extends GenericSubmissionSection< Use title , - - - , + , - , + , , - - - , + , - , + , , - - - , + , , - - - , + , - , + ,