diff --git a/protos/SignalService.proto b/protos/SignalService.proto index 127ed7eddb..64b2a5b396 100644 --- a/protos/SignalService.proto +++ b/protos/SignalService.proto @@ -417,9 +417,11 @@ message TextAttachment { } message Gradient { - optional uint32 startColor = 1; - optional uint32 endColor = 2; + optional uint32 startColor = 1; // deprecated: this field will be removed in a future release. + optional uint32 endColor = 2; // deprecated: this field will be removed in a future release. optional uint32 angle = 3; // degrees + repeated uint32 colors = 4; + repeated float positions = 5; // percent from 0 to 1 } optional string text = 1; diff --git a/ts/components/TextStoryCreator.tsx b/ts/components/TextStoryCreator.tsx index 948c97b27d..4f98e67c0a 100644 --- a/ts/components/TextStoryCreator.tsx +++ b/ts/components/TextStoryCreator.tsx @@ -4,7 +4,7 @@ import FocusTrap from 'focus-trap-react'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import classNames from 'classnames'; -import { get, has, noop } from 'lodash'; +import { noop } from 'lodash'; import { usePopper } from 'react-popper'; import type { EmojiPickDataType } from './emoji/EmojiPicker'; @@ -78,18 +78,18 @@ const BackgroundStyle = { BG5: { color: 4283667331 }, BG6: { angle: 180, - startColor: 4279871994, - endColor: 4294951785, + colors: [0xff19a9fa, 0xff7097d7, 0xffd1998d, 0xffffc369], + positions: [0, 0.33, 0.66, 1], }, BG7: { angle: 180, - startColor: 4282660824, - endColor: 4294938254, + colors: [0xff4437d8, 0xff6b70de, 0xffb774e0, 0xffff8e8e], + positions: [0, 0.33, 0.66, 1], }, BG8: { angle: 180, - startColor: 4278206532, - endColor: 4287871076, + colors: [0xff004044, 0xff2c5f45, 0xff648e52, 0xff93b864], + positions: [0, 0.33, 0.66, 1], }, }; @@ -98,16 +98,20 @@ type BackgroundStyleType = typeof BackgroundStyle[keyof typeof BackgroundStyle]; function getBackground( bgStyle: BackgroundStyleType ): Pick { - if (has(bgStyle, 'color')) { - return { color: get(bgStyle, 'color') }; + if ('color' in bgStyle) { + return { color: bgStyle.color }; } - const angle = get(bgStyle, 'angle'); - const startColor = get(bgStyle, 'startColor'); - const endColor = get(bgStyle, 'endColor'); + const { angle, colors, positions } = bgStyle; return { - gradient: { angle, startColor, endColor }, + gradient: { + angle, + startColor: colors.at(0), + endColor: colors.at(-1), + colors, + positions, + }, }; } diff --git a/ts/textsecure/SendMessage.ts b/ts/textsecure/SendMessage.ts index eb864a9706..600aa858ab 100644 --- a/ts/textsecure/SendMessage.ts +++ b/ts/textsecure/SendMessage.ts @@ -679,7 +679,13 @@ export default class MessageSender { } if (attachmentAttrs.gradient) { - textAttachment.gradient = attachmentAttrs.gradient; + const { colors, positions, ...rest } = attachmentAttrs.gradient; + + textAttachment.gradient = { + ...rest, + colors: colors?.slice(), + positions: positions?.slice(), + }; textAttachment.background = 'gradient'; } else { textAttachment.color = attachmentAttrs.color; diff --git a/ts/types/Attachment.ts b/ts/types/Attachment.ts index 6e3891d9b6..656ea53739 100644 --- a/ts/types/Attachment.ts +++ b/ts/types/Attachment.ts @@ -120,6 +120,8 @@ export type TextAttachmentType = { startColor?: number | null; endColor?: number | null; angle?: number | null; + colors?: ReadonlyArray | null; + positions?: ReadonlyArray | null; } | null; color?: number | null; }; diff --git a/ts/util/getStoryBackground.ts b/ts/util/getStoryBackground.ts index 93cd02b2eb..051e633354 100644 --- a/ts/util/getStoryBackground.ts +++ b/ts/util/getStoryBackground.ts @@ -15,6 +15,24 @@ export function getBackgroundColor({ color, gradient, }: Pick): string { + if ( + gradient?.colors?.length && + gradient?.colors.length === gradient?.positions?.length + ) { + const values = [`${gradient.angle}deg`]; + for (const [i, step] of gradient.colors.entries()) { + const position = gradient.positions[i] ?? 1; + const stepHex = getHexFromNumber(step || COLOR_WHITE_INT); + if (position == null) { + values.push(stepHex); + } else { + values.push(`${stepHex} ${position * 100}%`); + } + } + + return `linear-gradient(${values.join(', ')}) border-box`; + } + if (gradient) { return `linear-gradient(${gradient.angle}deg, ${getHexFromNumber( gradient.startColor || COLOR_WHITE_INT