From 53d6065c008f646380c23d7f1bebac2a05dac0c3 Mon Sep 17 00:00:00 2001
From: Josh Perez <60019601+josh-signal@users.noreply.github.com>
Date: Thu, 3 Jun 2021 17:34:36 -0400
Subject: [PATCH] Selects custom color when created
---
ts/components/ChatColorPicker.stories.tsx | 6 +-
ts/components/ChatColorPicker.tsx | 76 ++++++++++++++-----
ts/components/GlobalModalContainer.tsx | 13 +---
ts/state/ducks/conversations.ts | 89 +++++++++++++++++++++++
ts/state/ducks/items.ts | 6 +-
ts/state/smart/ChatColorPicker.tsx | 10 ---
ts/state/smart/GlobalModalContainer.tsx | 14 +---
ts/views/conversation_view.ts | 23 ------
8 files changed, 158 insertions(+), 79 deletions(-)
diff --git a/ts/components/ChatColorPicker.stories.tsx b/ts/components/ChatColorPicker.stories.tsx
index c51fc7e79b..1da43063b8 100644
--- a/ts/components/ChatColorPicker.stories.tsx
+++ b/ts/components/ChatColorPicker.stories.tsx
@@ -24,17 +24,19 @@ const SAMPLE_CUSTOM_COLOR = {
const createProps = (): PropsType => ({
addCustomColor: action('addCustomColor'),
+ colorSelected: action('colorSelected'),
editCustomColor: action('editCustomColor'),
getConversationsWithCustomColor: (_: string) => [],
i18n,
- onChatColorReset: action('onChatColorReset'),
- onSelectColor: action('onSelectColor'),
removeCustomColor: action('removeCustomColor'),
removeCustomColorOnConversations: action('removeCustomColorOnConversations'),
resetAllChatColors: action('resetAllChatColors'),
resetDefaultChatColor: action('resetDefaultChatColor'),
selectedColor: select('selectedColor', ConversationColors, 'basil' as const),
selectedCustomColor: {},
+ setGlobalDefaultConversationColor: action(
+ 'setGlobalDefaultConversationColor'
+ ),
});
story.add('Default', () => );
diff --git a/ts/components/ChatColorPicker.tsx b/ts/components/ChatColorPicker.tsx
index ef22555782..631a76fedd 100644
--- a/ts/components/ChatColorPicker.tsx
+++ b/ts/components/ChatColorPicker.tsx
@@ -24,48 +24,60 @@ type CustomColorDataType = {
};
export type PropsDataType = {
+ conversationId?: string;
customColors?: Record;
getConversationsWithCustomColor: (colorId: string) => Array;
i18n: LocalizerType;
isGlobal?: boolean;
- onChatColorReset?: () => unknown;
- onSelectColor: (
+ selectedColor?: ConversationColorType;
+ selectedCustomColor: CustomColorDataType;
+};
+
+type PropsActionType = {
+ addCustomColor: (
+ color: CustomColorType,
+ nextAction: (uuid: string) => unknown
+ ) => unknown;
+ colorSelected: (payload: {
+ conversationId: string;
+ conversationColor?: ConversationColorType;
+ customColorData?: {
+ id: string;
+ value: CustomColorType;
+ };
+ }) => unknown;
+ editCustomColor: (colorId: string, color: CustomColorType) => unknown;
+ removeCustomColor: (colorId: string) => unknown;
+ removeCustomColorOnConversations: (colorId: string) => unknown;
+ resetAllChatColors: () => unknown;
+ resetDefaultChatColor: () => unknown;
+ setGlobalDefaultConversationColor: (
color: ConversationColorType,
customColorData?: {
id: string;
value: CustomColorType;
}
) => unknown;
- selectedColor?: ConversationColorType;
- selectedCustomColor: CustomColorDataType;
-};
-
-type PropsActionType = {
- addCustomColor: (color: CustomColorType) => unknown;
- editCustomColor: (colorId: string, color: CustomColorType) => unknown;
- removeCustomColor: (colorId: string) => unknown;
- removeCustomColorOnConversations: (colorId: string) => unknown;
- resetAllChatColors: () => unknown;
- resetDefaultChatColor: () => unknown;
};
export type PropsType = PropsDataType & PropsActionType;
export const ChatColorPicker = ({
addCustomColor,
+ colorSelected,
+ conversationId,
customColors = {},
editCustomColor,
getConversationsWithCustomColor,
i18n,
isGlobal = false,
- onChatColorReset,
- onSelectColor,
removeCustomColor,
removeCustomColorOnConversations,
resetAllChatColors,
resetDefaultChatColor,
selectedColor = ConversationColors[0],
selectedCustomColor,
+ setGlobalDefaultConversationColor,
}: PropsType): JSX.Element => {
const [confirmResetAll, setConfirmResetAll] = useState(false);
const [confirmResetWhat, setConfirmResetWhat] = useState(false);
@@ -73,6 +85,30 @@ export const ChatColorPicker = ({
CustomColorDataType | undefined
>(undefined);
+ const onSelectColor = (
+ conversationColor: ConversationColorType,
+ customColorData?: { id: string; value: CustomColorType }
+ ): void => {
+ if (conversationId) {
+ colorSelected({
+ conversationId,
+ conversationColor,
+ customColorData,
+ });
+ } else {
+ setGlobalDefaultConversationColor(conversationColor, customColorData);
+ }
+ };
+
+ const onColorAdded = (value: CustomColorType) => {
+ return (id: string) => {
+ onSelectColor('custom', {
+ id,
+ value,
+ });
+ };
+ };
+
const renderCustomColorEditorWrapper = () => (
@@ -192,7 +228,7 @@ export const ChatColorPicker = ({
removeCustomColorOnConversations(colorId);
}}
onDupe={() => {
- addCustomColor(colorValues);
+ addCustomColor(colorValues, onColorAdded(colorValues));
}}
onEdit={() => {
setCustomColorToEdit({ id: colorId, value: colorValues });
@@ -218,10 +254,12 @@ export const ChatColorPicker = ({
- {onChatColorReset ? (
+ {conversationId ? (
{
+ colorSelected({ conversationId });
+ }}
/>
) : null}
unknown;
- }) => JSX.Element;
- setGlobalDefaultConversationColor: (color: ConversationColorType) => unknown;
+ renderChatColorPicker: () => JSX.Element;
toggleChatColorEditor: () => unknown;
};
@@ -22,7 +16,6 @@ export const GlobalModalContainer = ({
i18n,
isChatColorEditorVisible,
renderChatColorPicker,
- setGlobalDefaultConversationColor,
toggleChatColorEditor,
}: PropsType): JSX.Element | null => {
if (isChatColorEditorVisible) {
@@ -35,9 +28,7 @@ export const GlobalModalContainer = ({
onClose={toggleChatColorEditor}
title={i18n('ChatColorPicker__global-chat-color')}
>
- {renderChatColorPicker({
- setGlobalDefaultConversationColor,
- })}
+ {renderChatColorPicker()}
);
}
diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts
index 5f88b3b2aa..a42c212402 100644
--- a/ts/state/ducks/conversations.ts
+++ b/ts/state/ducks/conversations.ts
@@ -342,6 +342,7 @@ export const getConversationCallMode = (
// Actions
+const COLOR_SELECTED = 'conversations/COLOR_SELECTED';
const COLORS_CHANGED = 'conversations/COLORS_CHANGED';
const CUSTOM_COLOR_REMOVED = 'conversations/CUSTOM_COLOR_REMOVED';
@@ -377,6 +378,18 @@ type ColorsChangedActionType = {
};
};
};
+type ColorSelectedPayloadType = {
+ conversationId: string;
+ conversationColor?: ConversationColorType;
+ customColorData?: {
+ id: string;
+ value: CustomColorType;
+ };
+};
+export type ColorSelectedActionType = {
+ type: typeof COLOR_SELECTED;
+ payload: ColorSelectedPayloadType;
+};
type CustomColorRemovedActionType = {
type: typeof CUSTOM_COLOR_REMOVED;
payload: {
@@ -637,6 +650,7 @@ export type ConversationActionType =
| ConversationRemovedActionType
| ConversationUnloadedActionType
| ColorsChangedActionType
+ | ColorSelectedActionType
| CustomColorRemovedActionType
| CreateGroupFulfilledActionType
| CreateGroupPendingActionType
@@ -689,6 +703,7 @@ export const actions = {
conversationChanged,
conversationRemoved,
conversationUnloaded,
+ colorSelected,
createGroup,
messageChanged,
messageDeleted,
@@ -798,6 +813,50 @@ function resetAllChatColors(): ThunkAction<
};
}
+function colorSelected({
+ conversationId,
+ conversationColor,
+ customColorData,
+}: ColorSelectedPayloadType): ThunkAction<
+ void,
+ RootStateType,
+ unknown,
+ ColorSelectedActionType
+> {
+ return async dispatch => {
+ // We don't want to trigger a model change because we're updating redux
+ // here manually ourselves. Au revoir Backbone!
+ const conversation = window.ConversationController.get(conversationId);
+ if (conversation) {
+ if (conversationColor) {
+ conversation.attributes.conversationColor = conversationColor;
+ if (customColorData) {
+ conversation.attributes.customColor = customColorData.value;
+ conversation.attributes.customColorId = customColorData.id;
+ } else {
+ delete conversation.attributes.customColor;
+ delete conversation.attributes.customColorId;
+ }
+ } else {
+ delete conversation.attributes.conversationColor;
+ delete conversation.attributes.customColor;
+ delete conversation.attributes.customColorId;
+ }
+
+ await window.Signal.Data.updateConversation(conversation.attributes);
+ }
+
+ dispatch({
+ type: COLOR_SELECTED,
+ payload: {
+ conversationId,
+ conversationColor,
+ customColorData,
+ },
+ });
+ };
+}
+
function cantAddContactToGroup(
conversationId: string
): CantAddContactToGroupActionType {
@@ -2531,6 +2590,36 @@ export function reducer(
return nextState;
}
+ if (action.type === COLOR_SELECTED) {
+ const { conversationLookup } = state;
+ const {
+ conversationId,
+ conversationColor,
+ customColorData,
+ } = action.payload;
+
+ const existing = conversationLookup[conversationId];
+ if (!existing) {
+ return state;
+ }
+
+ const changed = {
+ ...existing,
+ conversationColor,
+ customColor: customColorData?.value,
+ customColorId: customColorData?.id,
+ };
+
+ return {
+ ...state,
+ conversationLookup: {
+ ...conversationLookup,
+ [conversationId]: changed,
+ },
+ ...updateConversationLookups(changed, existing, state),
+ };
+ }
+
if (action.type === CUSTOM_COLOR_REMOVED) {
const { conversationLookup } = state;
const { colorId, defaultConversationColor } = action.payload;
diff --git a/ts/state/ducks/items.ts b/ts/state/ducks/items.ts
index d0cedc050d..44d235fd05 100644
--- a/ts/state/ducks/items.ts
+++ b/ts/state/ducks/items.ts
@@ -141,7 +141,8 @@ function getDefaultCustomColorData() {
}
function addCustomColor(
- payload: CustomColorType
+ customColor: CustomColorType,
+ nextAction: (uuid: string) => unknown
): ThunkAction {
return (dispatch, getState) => {
const { customColors = getDefaultCustomColorData() } = getState().items;
@@ -155,11 +156,12 @@ function addCustomColor(
...customColors,
colors: {
...customColors.colors,
- [uuid]: payload,
+ [uuid]: customColor,
},
};
dispatch(putItem('customColors', nextCustomColors));
+ nextAction(uuid);
};
}
diff --git a/ts/state/smart/ChatColorPicker.tsx b/ts/state/smart/ChatColorPicker.tsx
index 34ef2338b8..1dd3c7f3c2 100644
--- a/ts/state/smart/ChatColorPicker.tsx
+++ b/ts/state/smart/ChatColorPicker.tsx
@@ -8,7 +8,6 @@ import {
ChatColorPicker,
PropsDataType,
} from '../../components/ChatColorPicker';
-import { ConversationColorType, CustomColorType } from '../../types/Colors';
import { StateType } from '../reducer';
import {
getConversationSelector,
@@ -19,15 +18,6 @@ import { getIntl } from '../selectors/user';
export type SmartChatColorPickerProps = {
conversationId?: string;
- isGlobal?: boolean;
- onChatColorReset?: () => unknown;
- onSelectColor: (
- color: ConversationColorType,
- customColorData?: {
- id: string;
- value: CustomColorType;
- }
- ) => unknown;
};
const mapStateToProps = (
diff --git a/ts/state/smart/GlobalModalContainer.tsx b/ts/state/smart/GlobalModalContainer.tsx
index e1ac364a28..9fe87a8b29 100644
--- a/ts/state/smart/GlobalModalContainer.tsx
+++ b/ts/state/smart/GlobalModalContainer.tsx
@@ -8,19 +8,9 @@ import { GlobalModalContainer } from '../../components/GlobalModalContainer';
import { StateType } from '../reducer';
import { getIntl } from '../selectors/user';
import { SmartChatColorPicker } from './ChatColorPicker';
-import { ConversationColorType } from '../../types/Colors';
-function renderChatColorPicker({
- setGlobalDefaultConversationColor,
-}: {
- setGlobalDefaultConversationColor: (color: ConversationColorType) => unknown;
-}): JSX.Element {
- return (
-
- );
+function renderChatColorPicker(): JSX.Element {
+ return ;
}
const mapStateToProps = (state: StateType) => {
diff --git a/ts/views/conversation_view.ts b/ts/views/conversation_view.ts
index 2b8cacc8af..f756aa080d 100644
--- a/ts/views/conversation_view.ts
+++ b/ts/views/conversation_view.ts
@@ -4,7 +4,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { AttachmentType } from '../types/Attachment';
-import { ConversationColorType, CustomColorType } from '../types/Colors';
import { ConversationModel } from '../models/conversations';
import { GroupV2PendingMemberType } from '../model-types.d';
import { LinkPreviewType } from '../types/message/LinkPreviews';
@@ -3235,28 +3234,6 @@ Whisper.ConversationView = Whisper.View.extend({
className: 'panel',
JSX: window.Signal.State.Roots.createChatColorPicker(window.reduxStore, {
conversationId: conversation.get('id'),
- onSelectColor: (
- color: ConversationColorType,
- customColorData?: {
- id: string;
- value: CustomColorType;
- }
- ) => {
- conversation.set('conversationColor', color);
- if (customColorData) {
- conversation.set('customColor', customColorData.value);
- conversation.set('customColorId', customColorData.id);
- } else {
- conversation.unset('customColor');
- conversation.unset('customColorId');
- }
- window.Signal.Data.updateConversation(conversation.attributes);
- },
- onChatColorReset: () => {
- conversation.set('conversationColor', undefined);
- conversation.unset('customColor');
- window.Signal.Data.updateConversation(conversation.attributes);
- },
}),
});