diff --git a/ts/services/backups/export.ts b/ts/services/backups/export.ts index ef441da2eebe..4aaeb60ea5dd 100644 --- a/ts/services/backups/export.ts +++ b/ts/services/backups/export.ts @@ -20,6 +20,7 @@ import { import type { PageMessagesCursorType } from '../../sql/Interface'; import * as log from '../../logging/log'; import { GiftBadgeStates } from '../../components/conversation/Message'; +import { type CustomColorType } from '../../types/Colors'; import { StorySendMode, MY_STORY_ID } from '../../types/Stories'; import { isPniString, @@ -37,6 +38,7 @@ import type { QuotedMessageType, } from '../../model-types.d'; import { drop } from '../../util/drop'; +import { isNotNil } from '../../util/isNotNil'; import { explodePromise } from '../../util/explodePromise'; import { isDirectConversation, @@ -2405,8 +2407,29 @@ export class BackupExportStream extends Readable { return []; } - const result = new Array(); + const { order = [] } = customColors; + const map = new Map( + order + .map((id: string): [string, CustomColorType] | undefined => { + const color = customColors.colors[id]; + if (color == null) { + return undefined; + } + return [id, color]; + }) + .filter(isNotNil) + ); + + // Add colors not present in the order list for (const [uuid, color] of Object.entries(customColors.colors)) { + if (map.has(uuid)) { + continue; + } + map.set(uuid, color); + } + + const result = new Array(); + for (const [uuid, color] of map.entries()) { const id = Long.fromNumber(result.length); this.customColorIdByUuid.set(uuid, id); diff --git a/ts/services/backups/import.ts b/ts/services/backups/import.ts index c4697fb6569d..c0cdfcb306eb 100644 --- a/ts/services/backups/import.ts +++ b/ts/services/backups/import.ts @@ -2853,15 +2853,19 @@ export class BackupImportStream extends Writable { return; } + const order = new Array(); const customColors: CustomColorsItemType = { version: 1, colors: {}, + order, }; for (const color of customChatColors) { const uuid = generateUuid(); let value: CustomColorType; + order.push(uuid); + if (color.solid) { value = { start: rgbIntToHSL(color.solid), diff --git a/ts/state/ducks/items.ts b/ts/state/ducks/items.ts index d0c01a5c67b1..09fe5cb8d8bf 100644 --- a/ts/state/ducks/items.ts +++ b/ts/state/ducks/items.ts @@ -142,6 +142,7 @@ function getDefaultCustomColorData() { return { colors: {} as Record, version: 1, + order: [], }; } @@ -157,12 +158,17 @@ function addCustomColor( uuid = getGuid(); } + const order = new Set(customColors.order ?? []); + order.delete(uuid); + order.add(uuid); + const nextCustomColors = { ...customColors, colors: { ...customColors.colors, [uuid]: customColor, }, + order: [...order], }; dispatch(putItem('customColors', nextCustomColors)); @@ -220,6 +226,7 @@ function removeCustomColor( const nextCustomColors = { ...customColors, colors: omit(customColors.colors, payload), + order: customColors.order?.filter(id => id !== payload), }; dispatch(putItem('customColors', nextCustomColors)); diff --git a/ts/types/Colors.ts b/ts/types/Colors.ts index 2e741a3dec82..8ec256fcf85a 100644 --- a/ts/types/Colors.ts +++ b/ts/types/Colors.ts @@ -187,6 +187,7 @@ export const DEFAULT_CONVERSATION_COLOR: DefaultConversationColorType = { export type CustomColorsItemType = { readonly colors: Record; readonly version: number; + readonly order?: ReadonlyArray; }; export function getAvatarColor(color?: AvatarColorType): AvatarColorType {