Selects custom color when created

This commit is contained in:
Josh Perez 2021-06-03 17:34:36 -04:00 committed by GitHub
parent 6d82acd23c
commit 53d6065c00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 158 additions and 79 deletions

View file

@ -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', () => <ChatColorPicker {...createProps()} />);

View file

@ -24,48 +24,60 @@ type CustomColorDataType = {
};
export type PropsDataType = {
conversationId?: string;
customColors?: Record<string, CustomColorType>;
getConversationsWithCustomColor: (colorId: string) => Array<ConversationType>;
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 = () => (
<CustomColorEditorWrapper
customColorToEdit={customColorToEdit}
@ -87,7 +123,7 @@ export const ChatColorPicker = ({
value: color,
});
} else {
addCustomColor(color);
addCustomColor(color, onColorAdded(color));
}
}}
/>
@ -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 = ({
</div>
</div>
<hr />
{onChatColorReset ? (
{conversationId ? (
<PanelRow
label={i18n('ChatColorPicker__reset')}
onClick={onChatColorReset}
onClick={() => {
colorSelected({ conversationId });
}}
/>
) : null}
<PanelRow

View file

@ -4,17 +4,11 @@
import React from 'react';
import { Modal } from './Modal';
import { LocalizerType } from '../types/Util';
import { ConversationColorType } from '../types/Colors';
type PropsType = {
i18n: LocalizerType;
isChatColorEditorVisible: boolean;
renderChatColorPicker: (actions: {
setGlobalDefaultConversationColor: (
color: ConversationColorType
) => 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()}
</Modal>
);
}

View file

@ -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;

View file

@ -141,7 +141,8 @@ function getDefaultCustomColorData() {
}
function addCustomColor(
payload: CustomColorType
customColor: CustomColorType,
nextAction: (uuid: string) => unknown
): ThunkAction<void, RootStateType, unknown, ItemPutAction> {
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);
};
}

View file

@ -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 = (

View file

@ -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 (
<SmartChatColorPicker
isGlobal
onSelectColor={setGlobalDefaultConversationColor}
/>
);
function renderChatColorPicker(): JSX.Element {
return <SmartChatColorPicker />;
}
const mapStateToProps = (state: StateType) => {

View file

@ -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);
},
}),
});