fix(desktop): improve ad marquee and hide windows consoles

This commit is contained in:
leokun
2026-09-05 00:36:11 +08:00
parent 20fdea8fb3
commit 7484bb9e07
3 changed files with 65 additions and 15 deletions
+30 -13
View File
@@ -21,24 +21,41 @@ type OverflowTextProps = {
};
function OverflowText({ children, className }: OverflowTextProps) {
const container = useRef<HTMLDivElement>(null);
const text = useRef<HTMLSpanElement>(null);
const [overflowing, setOverflowing] = useState(false);
useLayoutEffect(() => {
const element = text.current;
if (!element) return;
const update = () => setOverflowing(element.scrollWidth > element.clientWidth + 1);
const viewport = container.current;
if (!viewport) return;
const update = () => {
const element = text.current;
if (!element) return;
setOverflowing(element.scrollWidth > viewport.clientWidth + 1);
};
update();
const observer = new ResizeObserver(update);
observer.observe(element);
if (element.parentElement) observer.observe(element.parentElement);
return () => observer.disconnect();
}, [children]);
observer.observe(viewport);
if (text.current) observer.observe(text.current);
let disposed = false;
void document.fonts?.ready.then(() => {
if (!disposed) update();
});
return () => {
disposed = true;
observer.disconnect();
};
}, [children, overflowing]);
if (!overflowing) return <span ref={text} className={className}>{children}</span>;
return <Marquee className={styles.menuMarquee} repeat loop={0} speed={4} gap={24}>
<span ref={text} className={className}>{children}</span>
</Marquee>;
return <div ref={container} className={styles.menuOverflow}>
{overflowing
? <Marquee className={styles.menuMarquee} repeat loop={0} speed={4} gap={24}>
<span ref={text} className={className}>{children}</span>
</Marquee>
: <span ref={text} className={className}>{children}</span>}
</div>;
}
export function AdMenu({ ads, activeAdId, dismissingAdId, readAdIds, triggerRefs, onOpen, onDismiss }: AdMenuProps) {
@@ -60,10 +77,10 @@ export function AdMenu({ ads, activeAdId, dismissingAdId, readAdIds, triggerRefs
>
{!readAdIds.has(ad.id) && <span className={styles.unreadDot} aria-hidden="true" />}
<img className={styles.menuImage} src={ad.target.imageUrl} alt="" />
<span className={styles.menuCopy}>
<div className={styles.menuCopy}>
<OverflowText className={styles.menuTitle}>{ad.target.title}</OverflowText>
<OverflowText className={styles.menuSubtitle}>{ad.target.description}</OverflowText>
</span>
</div>
</button>
<button
type="button"
@@ -84,7 +84,9 @@
}
.menuCopy {
flex: 1 1 0;
min-width: 0;
overflow: hidden;
display: flex;
flex-direction: column;
gap: 1px;
@@ -98,18 +100,37 @@
text-overflow: ellipsis;
}
.menuOverflow {
flex: 0 0 auto;
width: 100%;
min-width: 0;
overflow: hidden;
}
.menuMarquee {
display: block;
flex: 0 0 auto;
width: 100%;
min-width: 0;
overflow: hidden;
}
.menuMarquee .menuTitle,
.menuMarquee .menuSubtitle {
flex: 0 0 auto;
width: max-content;
min-width: max-content;
max-width: none;
overflow: visible;
text-overflow: clip;
}
@media (prefers-reduced-motion: reduce) {
.menuMarquee [data-rcm-t] {
animation-play-state: running !important;
}
}
.menuTitle {
font-size: type.$font-size-xs;
font-weight: 500;
+14 -2
View File
@@ -4,6 +4,14 @@ use tokio::process::Command;
use crate::{Error, Result};
#[cfg(windows)]
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
#[cfg(windows)]
fn hide_console(command: &mut Command) {
command.creation_flags(CREATE_NO_WINDOW);
}
pub async fn terminate_cursor() -> Result<()> {
terminate_platform_cursor().await
}
@@ -42,7 +50,9 @@ async fn terminate_unix_process(name: &str) -> Result<()> {
#[cfg(target_os = "windows")]
async fn terminate_platform_cursor() -> Result<()> {
let processes = Command::new("tasklist")
let mut list = Command::new("tasklist");
hide_console(&mut list);
let processes = list
.args(["/FI", "IMAGENAME eq Cursor.exe", "/NH", "/FO", "CSV"])
.output()
.await?;
@@ -57,7 +67,9 @@ async fn terminate_platform_cursor() -> Result<()> {
{
return Ok(());
}
let terminated = Command::new("taskkill")
let mut kill = Command::new("taskkill");
hide_console(&mut kill);
let terminated = kill
.args(["/F", "/T", "/IM", "Cursor.exe"])
.status()
.await?;