fix(flags): align board flag rendering (#1142)

* fix(flags): align board flag rendering

* ci: run react doctor on changed pr files
This commit is contained in:
Tommaso Casaburi
2026-05-27 16:06:13 +07:00
committed by GitHub
parent 45a113c621
commit 029939089f
7 changed files with 112 additions and 24 deletions
+24
View File
@@ -19,6 +19,30 @@ describe('board-flags', () => {
x: 0,
y: 0,
});
expect(getBoardFlagDefinition('pol', 'MZ')).toMatchObject({
code: 'MZ',
label: 'Task Force Z',
x: 64,
y: 24,
});
expect(getBoardFlagDefinition('pol', 'NB')).toMatchObject({
code: 'NB',
label: 'National Bolshevik',
x: 0,
y: 36,
});
expect(getBoardFlagDefinition('pol', 'RE')).toMatchObject({
code: 'RE',
label: 'Republican',
x: 0,
y: 48,
});
expect(getBoardFlagDefinition('pol', 'TM')).toMatchObject({
code: 'TM',
label: 'Templar',
x: 16,
y: 48,
});
expect(getBoardFlagDefinition('pol', 'WP')).toMatchObject({ code: 'WP', x: 64, y: 48 });
});
@@ -4,6 +4,7 @@ import {
getCommentFlagPublishOptionsForDirectory,
getCommentFlagPublishOptionsFromSelection,
getCommentFlagRequestFromSelection,
hasCommentFlagsForDirectory,
} from '../comment-flag-selection';
describe('comment-flag-selection', () => {
@@ -11,6 +12,11 @@ describe('comment-flag-selection', () => {
expect(getCommentFlagOptionsForDirectory({ features: {}, title: '/mu/ - Music' })).toEqual([]);
});
it('detects flag-capable directories from directory metadata', () => {
expect(hasCommentFlagsForDirectory({ features: {}, title: '/mu/ - Music' })).toBe(false);
expect(hasCommentFlagsForDirectory({ features: { hasFlags: true }, title: '/pol/ - Politically Incorrect' })).toBe(true);
});
it('uses geographic location as the default for country flag boards', () => {
expect(
getCommentFlagOptionsForDirectory({
@@ -59,6 +65,14 @@ describe('comment-flag-selection', () => {
{ label: 'Confederate', value: 'pol:CF' },
{ label: 'Communist', value: 'pol:CM' },
]);
expect(options.slice(-6)).toEqual([
{ label: 'Republican', value: 'pol:RE' },
{ label: 'Task Force Z', value: 'pol:MZ' },
{ label: 'Templar', value: 'pol:TM' },
{ label: 'Tree Hugger', value: 'pol:TR' },
{ label: 'United Nations', value: 'pol:UN' },
{ label: 'White Supremacist', value: 'pol:WP' },
]);
});
it('matches the 4chan /mlp/ flag default', () => {
+55 -14
View File
@@ -21,6 +21,7 @@ const PONY_FLAG_HEIGHT = 16;
const PONY_FLAG_COLUMNS = 9;
const PONY_FLAG_SPRITE_PATH = 'assets/icons/flags-pony.png';
// Order follows 4chan's board flag selector. Coordinates follow flags/pol/flags.2.css.
const POLITICAL_FLAG_ENTRIES = [
['AC', 'Anarcho-Capitalist'],
['AN', 'Anarchist'],
@@ -42,13 +43,41 @@ const POLITICAL_FLAG_ENTRIES = [
['PC', 'Hippie'],
['PR', 'Pirate'],
['RE', 'Republican'],
['TM', 'Templar'],
['MZ', 'Task Force Z'],
['TM', 'Templar'],
['TR', 'Tree Hugger'],
['UN', 'United Nations'],
['WP', 'White Supremacist'],
] as const;
const POLITICAL_FLAG_COORDINATES = {
AC: [0, 0],
AN: [16, 0],
BL: [32, 0],
CF: [48, 0],
CM: [64, 0],
CT: [0, 12],
DM: [16, 12],
EU: [32, 12],
FC: [48, 12],
GN: [64, 12],
GY: [0, 24],
JH: [16, 24],
KN: [32, 24],
MF: [48, 24],
MZ: [64, 24],
NB: [0, 36],
NT: [16, 36],
NZ: [32, 36],
PC: [48, 36],
PR: [64, 36],
RE: [0, 48],
TM: [16, 48],
TR: [32, 48],
UN: [48, 48],
WP: [64, 48],
} as const satisfies Record<(typeof POLITICAL_FLAG_ENTRIES)[number][0], readonly [number, number]>;
const PONY_FLAG_ENTRIES = [
['4CC', '4cc /mlp/'],
['ADA', 'Adagio Dazzle'],
@@ -144,25 +173,37 @@ const buildFlagDefinitions = (
width: number,
height: number,
columns: number,
coordinatesByCode?: Readonly<Record<string, readonly [number, number]>>,
): ReadonlyMap<string, BoardFlagDefinition> =>
new Map(
entries.map(([code, label], index) => [
code,
{
kind,
entries.map(([code, label], index) => {
const [x, y] = coordinatesByCode?.[code] ?? [(index % columns) * width, Math.floor(index / columns) * height];
return [
code,
label,
spritePath,
width,
height,
x: (index % columns) * width,
y: Math.floor(index / columns) * height,
},
]),
{
kind,
code,
label,
spritePath,
width,
height,
x,
y,
},
] as const;
}),
);
const BOARD_FLAGS_BY_KIND: Record<BoardFlagKind, ReadonlyMap<string, BoardFlagDefinition>> = {
pol: buildFlagDefinitions(POLITICAL_FLAG_ENTRIES, 'pol', POLITICAL_FLAG_SPRITE_PATH, POLITICAL_FLAG_WIDTH, POLITICAL_FLAG_HEIGHT, POLITICAL_FLAG_COLUMNS),
pol: buildFlagDefinitions(
POLITICAL_FLAG_ENTRIES,
'pol',
POLITICAL_FLAG_SPRITE_PATH,
POLITICAL_FLAG_WIDTH,
POLITICAL_FLAG_HEIGHT,
POLITICAL_FLAG_COLUMNS,
POLITICAL_FLAG_COORDINATES,
),
pony: buildFlagDefinitions(PONY_FLAG_ENTRIES, 'pony', PONY_FLAG_SPRITE_PATH, PONY_FLAG_WIDTH, PONY_FLAG_HEIGHT, PONY_FLAG_COLUMNS),
};
+10 -7
View File
@@ -25,6 +25,8 @@ export interface CommentFlagPublishOptions {
flairs: CommentFlagRequest[] | undefined;
}
export type CommentFlagDirectory = Partial<Pick<DirectoryCommunity, 'directoryCode' | 'features' | 'title'>>;
const GEOGRAPHIC_LOCATION_OPTION: CommentFlagSelectOption = {
value: GEOGRAPHIC_LOCATION_FLAG_VALUE,
label: 'Geographic Location',
@@ -43,14 +45,18 @@ const getDirectoryCode = (directory: Pick<DirectoryCommunity, 'directoryCode' |
return directoryCode || directory?.title?.match(/^\/([^/]+)\//)?.[1]?.toLowerCase();
};
export const hasCommentFlagsForDirectory = (directory: CommentFlagDirectory | undefined): boolean => {
return directory?.features?.hasFlags === true;
};
const getBoardFlagOptions = (kind: BoardFlagKind): CommentFlagSelectOption[] =>
getBoardFlagDefinitions(kind).map((flag) => ({
value: `${flag.kind}:${flag.code}`,
label: flag.label,
}));
export const getCommentFlagOptionsForDirectory = (directory: Pick<DirectoryCommunity, 'directoryCode' | 'features' | 'title'> | undefined): CommentFlagSelectOption[] => {
if (directory?.features?.hasFlags !== true) {
export const getCommentFlagOptionsForDirectory = (directory: CommentFlagDirectory | undefined): CommentFlagSelectOption[] => {
if (!hasCommentFlagsForDirectory(directory)) {
return [];
}
@@ -70,11 +76,8 @@ export const getCommentFlagOptionsForDirectory = (directory: Pick<DirectoryCommu
return [GEOGRAPHIC_LOCATION_OPTION];
};
export const getCommentFlagPublishOptionsForDirectory = (
directory: Pick<DirectoryCommunity, 'directoryCode' | 'features' | 'title'> | undefined,
selectedValue?: string,
): CommentFlagPublishOptions => {
if (directory?.features?.hasFlags !== true) {
export const getCommentFlagPublishOptionsForDirectory = (directory: CommentFlagDirectory | undefined, selectedValue?: string): CommentFlagPublishOptions => {
if (!hasCommentFlagsForDirectory(directory)) {
return {
challengeRequest: undefined,
flairs: undefined,