mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(challenge-modal): center mobile modal in viewport
Use left: 50% with translateX(-50%) so the dialog stays centered on mobile instead of offset from a stale static position.
This commit is contained in:
@@ -18,6 +18,7 @@ const testState = vi.hoisted(() => ({
|
|||||||
} as Record<string, any>,
|
} as Record<string, any>,
|
||||||
challenges: [] as Array<{ challenge: any; id: number }>,
|
challenges: [] as Array<{ challenge: any; id: number }>,
|
||||||
commentsByCid: {} as Record<string, { author?: { shortAddress?: string } }>,
|
commentsByCid: {} as Record<string, { author?: { shortAddress?: string } }>,
|
||||||
|
isMobile: false,
|
||||||
publicationPreview: 'preview body',
|
publicationPreview: 'preview body',
|
||||||
publicationType: 'post',
|
publicationType: 'post',
|
||||||
removeChallengeMock: vi.fn(),
|
removeChallengeMock: vi.fn(),
|
||||||
@@ -55,7 +56,7 @@ vi.mock('../../../lib/utils/challenge-utils', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock('../../../hooks/use-is-mobile', () => ({
|
vi.mock('../../../hooks/use-is-mobile', () => ({
|
||||||
default: () => false,
|
default: () => testState.isMobile,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock('../../../hooks/use-theme', () => ({
|
vi.mock('../../../hooks/use-theme', () => ({
|
||||||
@@ -162,6 +163,7 @@ describe('ChallengeModal', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
testState.isMobile = false;
|
||||||
testState.publicationPreview = 'preview body';
|
testState.publicationPreview = 'preview body';
|
||||||
testState.publicationType = 'post';
|
testState.publicationType = 'post';
|
||||||
testState.removeChallengeMock.mockReset();
|
testState.removeChallengeMock.mockReset();
|
||||||
@@ -226,6 +228,27 @@ describe('ChallengeModal', () => {
|
|||||||
expect(testState.removeChallengeMock).toHaveBeenCalledOnce();
|
expect(testState.removeChallengeMock).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('centers the mobile modal from the viewport instead of its static position', async () => {
|
||||||
|
testState.isMobile = true;
|
||||||
|
Object.defineProperty(window, 'innerWidth', { configurable: true, value: 375 });
|
||||||
|
Object.defineProperty(window, 'innerHeight', { configurable: true, value: 667 });
|
||||||
|
testState.publicationType = 'reply';
|
||||||
|
testState.challenges = [
|
||||||
|
createStoredChallenge({
|
||||||
|
challenge: 'https://spamblocker.bitsocial.net/api/v1/iframe/session-123',
|
||||||
|
type: 'url/iframe',
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
await renderModal();
|
||||||
|
|
||||||
|
const dialog = container.querySelector<HTMLElement>('[role="dialog"]');
|
||||||
|
expect(container.textContent).toContain('wants to open spamblocker.bitsocial.net.');
|
||||||
|
expect(dialog?.style.left).toBe('50%');
|
||||||
|
expect(dialog?.style.top).toBe('0px');
|
||||||
|
expect(dialog?.style.transform).toBe('translate3d(-50%, 134px, 0)');
|
||||||
|
});
|
||||||
|
|
||||||
it('redacts generated fortune BBCode from challenge publication details', async () => {
|
it('redacts generated fortune BBCode from challenge publication details', async () => {
|
||||||
const publication = {
|
const publication = {
|
||||||
...createPublication(),
|
...createPublication(),
|
||||||
|
|||||||
@@ -481,8 +481,8 @@ const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => {
|
|||||||
if (publication?.parentCid) extraTitleParts.push(parentAddress ? `reply ${parentAddress}` : 'reply');
|
if (publication?.parentCid) extraTitleParts.push(parentAddress ? `reply ${parentAddress}` : 'reply');
|
||||||
if (publicationContent && publicationType !== 'vote') extraTitleParts.push(publicationContent);
|
if (publicationContent && publicationType !== 'vote') extraTitleParts.push(publicationContent);
|
||||||
|
|
||||||
const mobileX = isIframeVisible ? 5 : window.innerWidth / 2 - 150;
|
|
||||||
const mobileY = isIframeVisible ? Math.max(10, (window.innerHeight - 600) / 2) : window.innerHeight / 2 - 200;
|
const mobileY = isIframeVisible ? Math.max(10, (window.innerHeight - 600) / 2) : window.innerHeight / 2 - 200;
|
||||||
|
const mobileTransform = isIframeVisible ? `translate3d(5px, ${Math.round(mobileY)}px, 0)` : `translate3d(-50%, ${Math.round(mobileY)}px, 0)`;
|
||||||
const displayCommunityAddress = getDisplayCommunityAddress(shortCommunityAddress, communityAddress) || t('board');
|
const displayCommunityAddress = getDisplayCommunityAddress(shortCommunityAddress, communityAddress) || t('board');
|
||||||
const iframeConfirmMessage = stripLegacyIframeConfirmDetails(
|
const iframeConfirmMessage = stripLegacyIframeConfirmDetails(
|
||||||
t('iframe_challenge_confirm', {
|
t('iframe_challenge_confirm', {
|
||||||
@@ -524,9 +524,9 @@ const Challenge = ({ challenge, closeModal, abandonModal }: ChallengeProps) => {
|
|||||||
aria-modal='true'
|
aria-modal='true'
|
||||||
aria-labelledby='challenge-modal-title'
|
aria-labelledby='challenge-modal-title'
|
||||||
style={{
|
style={{
|
||||||
transform: isMobile
|
top: 0,
|
||||||
? `translate3d(${Math.round(mobileX)}px, ${Math.round(mobileY)}px, 0)`
|
left: isMobile && !isIframeVisible ? '50%' : 0,
|
||||||
: `translate3d(${Math.round(initialPosition.x)}px, ${Math.round(initialPosition.y)}px, 0)`,
|
transform: isMobile ? mobileTransform : `translate3d(${Math.round(initialPosition.x)}px, ${Math.round(initialPosition.y)}px, 0)`,
|
||||||
touchAction: 'none',
|
touchAction: 'none',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user