Fix custom color backup import/export

This commit is contained in:
ayumi-signal 2024-12-11 08:57:34 -08:00 committed by GitHub
parent 734929f74f
commit c7dc4279a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 96 additions and 31 deletions

View file

@ -110,7 +110,7 @@ import {
AdhocCallStatus,
} from '../../types/CallDisposition';
import { isAciString } from '../../util/isAciString';
import { hslToRGB } from '../../util/hslToRGB';
import { hslToRGBInt } from '../../util/hslToRGB';
import type { AboutMe, LocalChatStyle } from './types';
import { BackupType } from './types';
import { messageHasPaymentEvent } from '../../messages/helpers';
@ -2588,10 +2588,10 @@ export class BackupExportStream extends Readable {
const id = Long.fromNumber(result.length + 1);
this.customColorIdByUuid.set(uuid, id);
const start = hslToRGBInt(
const start = desktopHslToRgbInt(
color.start.hue,
color.start.saturation,
color.start.luminance
color.start.lightness
);
if (color.end == null) {
@ -2600,10 +2600,10 @@ export class BackupExportStream extends Readable {
solid: start,
});
} else {
const end = hslToRGBInt(
const end = desktopHslToRgbInt(
color.end.hue,
color.end.saturation,
color.end.luminance
color.end.lightness
);
result.push({
@ -2776,10 +2776,13 @@ function checkServiceIdEquivalence(
return leftConvo && rightConvo && leftConvo === rightConvo;
}
function hslToRGBInt(hue: number, saturation: number, luminance = 1): number {
const { r, g, b } = hslToRGB(hue, saturation, luminance);
// eslint-disable-next-line no-bitwise
return ((0xff << 24) | (r << 16) | (g << 8) | b) >>> 0;
function desktopHslToRgbInt(
hue: number,
saturation: number,
lightness = 1
): number {
// Desktop stores saturation not as 0.123 (0 to 1.0) but 12.3 (percentage)
return hslToRGBInt(hue, saturation / 100, lightness);
}
function toGroupCallStateProto(state: CallStatus): Backups.GroupCall.State {

View file

@ -89,7 +89,7 @@ import type { GroupV2ChangeDetailType } from '../../groups';
import { queueAttachmentDownloads } from '../../util/queueAttachmentDownloads';
import { isNotNil } from '../../util/isNotNil';
import { isGroup } from '../../util/whatTypeOfConversation';
import { rgbToHSL } from '../../util/rgbToHSL';
import { rgbIntToHSL } from '../../util/rgbToHSL';
import {
convertBackupMessageAttachmentToAttachment,
convertFilePointerToAttachment,
@ -3061,7 +3061,7 @@ export class BackupImportStream extends Writable {
if (color.solid) {
value = {
start: rgbIntToHSL(color.solid),
start: rgbIntToDesktopHSL(color.solid),
};
} else {
strictAssert(color.gradient != null, 'Either solid or gradient');
@ -3076,8 +3076,8 @@ export class BackupImportStream extends Writable {
strictAssert(deg != null, 'Missing angle');
value = {
start: rgbIntToHSL(start),
end: rgbIntToHSL(end),
start: rgbIntToDesktopHSL(start),
end: rgbIntToDesktopHSL(end),
deg,
};
}
@ -3226,20 +3226,15 @@ export class BackupImportStream extends Writable {
}
}
function rgbIntToHSL(intValue: number): {
function rgbIntToDesktopHSL(intValue: number): {
hue: number;
saturation: number;
luminance: number;
lightness: number;
} {
// eslint-disable-next-line no-bitwise
const r = (intValue >>> 16) & 0xff;
// eslint-disable-next-line no-bitwise
const g = (intValue >>> 8) & 0xff;
// eslint-disable-next-line no-bitwise
const b = intValue & 0xff;
const { h: hue, s: saturation, l: luminance } = rgbToHSL(r, g, b);
const { h: hue, s: saturation, l: lightness } = rgbIntToHSL(intValue);
return { hue, saturation, luminance };
// Desktop stores saturation not as 0.123 (0 to 1.0) but 12.3 (percentage)
return { hue, saturation: saturation * 100, lightness };
}
function fromGroupCallStateProto(

View file

@ -0,0 +1,35 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { hslToRGB, hslToRGBInt } from '../../util/hslToRGB';
describe('hslToRGB', () => {
it('converts pure rgb colors', () => {
assert.deepStrictEqual(hslToRGB(0, 1, 0.5), { r: 255, g: 0, b: 0 });
assert.deepStrictEqual(hslToRGB(120, 1, 0.5), { r: 0, g: 255, b: 0 });
assert.deepStrictEqual(hslToRGB(240, 1, 0.5), { r: 0, g: 0, b: 255 });
});
it('converts random sampled hsl colors', () => {
assert.deepStrictEqual(hslToRGB(50, 0.233333, 0.41), {
r: 129,
g: 121,
b: 80,
});
assert.deepStrictEqual(hslToRGB(170, 0.97, 0.1), {
r: 1,
g: 50,
b: 42,
});
});
});
describe('hslToRGBInt', () => {
it('converts pure rgb colors', () => {
assert.equal(hslToRGBInt(0, 1, 0.5), 4294901760);
assert.equal(hslToRGBInt(120, 1, 0.5), 4278255360);
assert.equal(hslToRGBInt(240, 1, 0.5), 4278190335);
});
});

View file

@ -3,7 +3,7 @@
import { assert } from 'chai';
import { rgbToHSL } from '../../util/rgbToHSL';
import { rgbIntToHSL, rgbToHSL } from '../../util/rgbToHSL';
describe('rgbToHSL', () => {
it('converts pure rgb colors', () => {
@ -40,3 +40,11 @@ describe('rgbToHSL', () => {
});
});
});
describe('rgbIntToHSL', () => {
it('converts pure rgb colors', () => {
assert.deepStrictEqual(rgbIntToHSL(4294901760), { h: 0, s: 1, l: 0.5 });
assert.deepStrictEqual(rgbIntToHSL(4278255360), { h: 120, s: 1, l: 0.5 });
assert.deepStrictEqual(rgbIntToHSL(4278190335), { h: 240, s: 1, l: 0.5 });
});
});

View file

@ -159,8 +159,8 @@ export const ContactNameColors = [
export type ContactNameColorType = (typeof ContactNameColors)[number];
export type CustomColorType = {
start: { hue: number; saturation: number; luminance?: number };
end?: { hue: number; saturation: number; luminance?: number };
start: { hue: number; saturation: number; lightness?: number };
end?: { hue: number; saturation: number; lightness?: number };
deg?: number;
};

View file

@ -46,17 +46,17 @@ export function getHSL(
{
hue,
saturation,
luminance,
lightness,
}: {
hue: number;
saturation: number;
luminance?: number;
lightness?: number;
},
adjustedLightness = 0
): string {
return `hsl(${hue}, ${saturation}%, ${
luminance == null
lightness == null
? adjustLightnessValue(calculateLightness(hue), adjustedLightness)
: luminance * 100
: lightness * 100
}%)`;
}

View file

@ -24,3 +24,13 @@ export function hslToRGB(
b: Math.round(255 * f(4)),
};
}
export function hslToRGBInt(
hue: number,
saturation: number,
lightness: number
): number {
const { r, g, b } = hslToRGB(hue, saturation, lightness);
// eslint-disable-next-line no-bitwise
return ((0xff << 24) | (r << 16) | (g << 8) | b) >>> 0;
}

View file

@ -26,7 +26,7 @@ export function rgbToHSL(
if (c === 0) {
h = 0;
} else if (v === rn) {
h = 60 * (((gn - bn) / c) % 6);
h = 60 * (((gn - bn) / c + 6) % 6);
} else if (v === gn) {
h = 60 * ((bn - rn) / c + 2);
} else {
@ -43,3 +43,17 @@ export function rgbToHSL(
return { h, s, l };
}
export function rgbIntToHSL(intValue: number): {
h: number;
s: number;
l: number;
} {
// eslint-disable-next-line no-bitwise
const r = (intValue >>> 16) & 0xff;
// eslint-disable-next-line no-bitwise
const g = (intValue >>> 8) & 0xff;
// eslint-disable-next-line no-bitwise
const b = intValue & 0xff;
return rgbToHSL(r, g, b);
}