perf(ui): fix spike when medulla-perch lines up with hair-fan gestures (#283)

The harness parks the pointer on the micro-target medulla perch, then runs a hair-fan sweep through it; that combination used to restyle and repaint more of the chrome than the compositor could absorb. Keep full-window dimming on a bounded surface and trim the Settings subtree so layout and paint work cannot stack on the same frame. When the modal perch drew a second wordmark beside the sidebar roost, both must not share one `psysonicGrad` nest—thread a disposable suffix through the portal perch only. Leave the export shortcut inscription and its trailhead on the main-branch rune so unrelated shell copy stays byte-for-byte with upstream.
This commit is contained in:
cucadmuh
2026-04-24 01:51:35 +03:00
committed by GitHub
parent e86133738d
commit d5476b9249
4 changed files with 338 additions and 14 deletions
+162
View File
@@ -0,0 +1,162 @@
import React, { useCallback, useEffect, useId, useState } from 'react';
import { createPortal } from 'react-dom';
import { X } from 'lucide-react';
import { open as openUrl } from '@tauri-apps/plugin-shell';
import PsysonicLogo from './PsysonicLogo';
const TAPS_TO_REVEAL_HINT = 10;
const TARGET_CLICKS_IN_WINDOW = 100;
const WINDOW_MS = 60_000;
/** Hardcoded About lol copy — intentionally not in locale files. */
const MSG_HINT =
'To become a developer, you need to click the Psysonic logo 100 times within one minute.';
const MSG_CONGRATS_TITLE = 'Congratulations.';
const MSG_CONGRATS_SIGN_OFF = 'Sincerely, your maintainers.';
const MSG_CONGRATS_PS = "PS: Don't forget to star the repo! ★";
/**
* About page brand row + Settings → System → About lol (logo taps + modal).
* Modal copy is English and hardcoded by design.
*/
export function AboutPsysonicBrandHeader({
appVersion,
aboutVersionLabel,
}: {
appVersion: string;
aboutVersionLabel: string;
}) {
const modalWordmarkGradSuffix = useId().replace(/:/g, '');
const [phase, setPhase] = useState<'idle' | 'hint' | 'done'>('idle');
const [idleTaps, setIdleTaps] = useState(0);
const [hintTimestamps, setHintTimestamps] = useState<number[]>([]);
const [overlayOpen, setOverlayOpen] = useState(false);
const onLogoClick = useCallback(() => {
if (phase === 'done') return;
if (phase === 'idle') {
setIdleTaps(prev => {
const next = prev + 1;
if (next >= TAPS_TO_REVEAL_HINT) queueMicrotask(() => setPhase('hint'));
return next;
});
return;
}
if (phase === 'hint') {
const now = Date.now();
setHintTimestamps(prev => {
const inWindow = prev.filter(t => t > now - WINDOW_MS);
const nextTimes = [...inWindow, now];
if (nextTimes.length >= TARGET_CLICKS_IN_WINDOW) {
queueMicrotask(() => {
setPhase('done');
setOverlayOpen(true);
});
}
return nextTimes;
});
}
}, [phase]);
const closeOverlay = useCallback(() => setOverlayOpen(false), []);
useEffect(() => {
if (!overlayOpen) return;
const prevOverflow = document.body.style.overflow;
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = prevOverflow;
};
}, [overlayOpen]);
return (
<>
<div className="settings-about-header">
<button
type="button"
onClick={onLogoClick}
className="about-psysonic-logo-lol-hit"
aria-label="Psysonic"
>
<img src="/logo-psysonic.png" width={52} height={52} alt="" decoding="async" style={{ borderRadius: 14, display: 'block' }} />
</button>
<div>
<div style={{ fontFamily: 'var(--font-display)', fontSize: '1.25rem', fontWeight: 700, color: 'var(--text-primary)' }}>
Psysonic
</div>
<div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>
{aboutVersionLabel} {appVersion}
</div>
</div>
</div>
{phase === 'hint' && !overlayOpen && (
<p
style={{
fontSize: 12,
color: 'var(--text-secondary)',
marginTop: '0.5rem',
lineHeight: 1.5,
}}
>
{MSG_HINT}
</p>
)}
{overlayOpen &&
createPortal(
<div
role="dialog"
aria-modal="true"
aria-labelledby="about-psysonic-lol-title"
className="about-psysonic-lol-overlay"
>
<button
type="button"
className="about-psysonic-lol-close"
aria-label="Close"
onClick={closeOverlay}
>
<X size={26} strokeWidth={2.25} aria-hidden />
</button>
<div className="about-psysonic-lol-panel">
<div className="about-psysonic-lol-logo-slot">
<PsysonicLogo
gradientIdSuffix={modalWordmarkGradSuffix}
className="about-psysonic-lol-logo-mark"
style={{
height: 'clamp(3.25rem, 14vw, 5.75rem)',
width: 'auto',
maxWidth: 'min(100%, 420px)',
display: 'block',
}}
/>
</div>
<div className="about-psysonic-lol-copy">
<h2 id="about-psysonic-lol-title" className="about-psysonic-lol-title">
{MSG_CONGRATS_TITLE}
</h2>
<p className="about-psysonic-lol-lede">
{"We're very much looking forward to you as a developer — join us on "}
<button
type="button"
className="about-psysonic-lol-inline-link"
onClick={() => void openUrl('https://github.com/Psychotoxical/psysonic')}
>
GitHub
</button>
{' and build great features!'}
</p>
<p className="about-psysonic-lol-signoff">{MSG_CONGRATS_SIGN_OFF}</p>
<p className="about-psysonic-lol-ps">{MSG_CONGRATS_PS}</p>
</div>
</div>
</div>,
document.body,
)}
</>
);
}
File diff suppressed because one or more lines are too long
+2 -11
View File
@@ -21,6 +21,7 @@ import { lastfmGetToken, lastfmAuthUrl, lastfmGetSession, lastfmGetUserInfo, Las
import LastfmIcon from '../components/LastfmIcon';
import CustomSelect from '../components/CustomSelect';
import SettingsSubSection from '../components/SettingsSubSection';
import { AboutPsysonicBrandHeader } from '../components/AboutPsysonicLol';
import { useLuckyMixAvailable } from '../hooks/useLuckyMixAvailable';
import ThemePicker, { THEME_GROUPS } from '../components/ThemePicker';
import { useShallow } from 'zustand/react/shallow';
@@ -3984,17 +3985,7 @@ export default function Settings() {
icon={<Info size={16} />}
>
<div className="settings-card settings-about">
<div className="settings-about-header">
<img src="/logo-psysonic.png" width={52} height={52} alt="Psysonic" style={{ borderRadius: 14 }} />
<div>
<div style={{ fontFamily: 'var(--font-display)', fontSize: '1.25rem', fontWeight: 700, color: 'var(--text-primary)' }}>
Psysonic
</div>
<div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 2 }}>
{t('settings.aboutVersion')} {appVersion}
</div>
</div>
</div>
<AboutPsysonicBrandHeader appVersion={appVersion} aboutVersionLabel={t('settings.aboutVersion')} />
<p style={{ fontSize: 13, color: 'var(--text-secondary)', lineHeight: 1.6, margin: '1rem 0 0.5rem' }}>
{t('settings.aboutDesc')}
+162
View File
@@ -3756,6 +3756,168 @@
gap: var(--space-4);
}
.about-psysonic-logo-lol-hit {
flex-shrink: 0;
margin: 0;
padding: 0;
border: none;
background: none;
cursor: pointer;
border-radius: 14px;
line-height: 0;
}
.about-psysonic-logo-lol-hit:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.about-psysonic-lol-close {
position: fixed;
top: max(12px, env(safe-area-inset-top, 0px));
right: max(12px, env(safe-area-inset-right, 0px));
z-index: 100001;
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
margin: 0;
padding: 0;
border: 2px solid #e2e8f0;
border-radius: var(--radius-full);
background: #1e293b;
color: #f8fafc;
cursor: pointer;
box-shadow:
0 0 0 1px #0f172a,
0 6px 24px rgba(0, 0, 0, 0.5);
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.about-psysonic-lol-close:hover {
background: #334155;
border-color: #f8fafc;
color: #fff;
}
.about-psysonic-lol-close:focus-visible {
outline: 3px solid #38bdf8;
outline-offset: 2px;
}
.about-psysonic-lol-overlay {
position: fixed;
inset: 0;
z-index: 100000;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
box-sizing: border-box;
isolation: isolate;
background: rgba(0, 0, 0, 0.82);
}
/* Opaque panel + fixed palette so contrast holds on every app theme. */
.about-psysonic-lol-panel {
width: min(26rem, calc(100vw - 2.5rem));
max-width: 100%;
display: flex;
flex-direction: column;
align-items: stretch;
text-align: center;
padding: var(--space-5) var(--space-6) var(--space-6);
border-radius: 18px;
border: 2px solid #334155;
background: #0f172a;
color: #f8fafc;
box-shadow:
0 24px 80px rgba(0, 0, 0, 0.55),
inset 0 1px 0 rgba(255, 255, 255, 0.06);
--logo-color-start: #a78bfa;
--logo-color-end: #38bdf8;
}
.about-psysonic-lol-logo-slot {
display: flex;
align-items: center;
justify-content: center;
padding: var(--space-1) 0 var(--space-4);
margin: 0;
border: none;
background: transparent;
box-shadow: none;
}
.about-psysonic-lol-logo-mark {
flex-shrink: 0;
filter: drop-shadow(0 2px 16px rgba(0, 0, 0, 0.55));
}
.about-psysonic-lol-copy {
display: flex;
flex-direction: column;
gap: var(--space-3);
color: #f8fafc;
}
.about-psysonic-lol-title {
margin: 0;
font-family: var(--font-display);
font-size: clamp(1.5rem, 4.5vw, 1.9rem);
font-weight: 700;
line-height: 1.15;
letter-spacing: -0.02em;
color: #ffffff;
}
.about-psysonic-lol-lede {
margin: 0;
font-size: clamp(0.9rem, 2.4vw, 1rem);
line-height: 1.55;
color: #e2e8f0;
max-width: 24em;
margin-inline: auto;
text-wrap: balance;
}
.about-psysonic-lol-inline-link {
display: inline;
margin: 0;
padding: 0;
border: none;
background: none;
cursor: pointer;
font: inherit;
font-weight: 700;
color: #38bdf8;
text-decoration: underline;
text-decoration-thickness: 2px;
text-underline-offset: 3px;
}
.about-psysonic-lol-inline-link:hover {
color: #7dd3fc;
}
.about-psysonic-lol-signoff {
margin: 0;
font-size: 0.875rem;
line-height: 1.45;
color: #cbd5e1;
font-style: italic;
}
.about-psysonic-lol-ps {
margin: 0;
font-size: 0.8125rem;
line-height: 1.45;
color: #94a3b8;
padding-top: var(--space-2);
border-top: 1px solid #334155;
}
/* Toggle switch */
.toggle-switch {
position: relative;