mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-10-04 02:40:50 +08:00
fix(desktop): improve ad marquee and hide windows consoles
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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?;
|
||||
|
||||
Reference in New Issue
Block a user