mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-13 12:13:42 +01:00
Yaak Proxy: square app icons beside long names, and the final uncovered why line
App icons keep their square however a long app name squeezes them, in the card's buttons, the strip's Choose menu and the sidebar, and a long entry hint truncates instead of the button's label. A connection nothing on the list covers reads "Encrypted Content: Enable decryption to see requests to <host>", with the host as code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e3ff29ee6d
commit
c0f75bcfc2
7 files changed
+48
-16
No files matched your search
@@ -42,8 +42,13 @@ export function AppIcon({ path, className = "size-4" }: { path: string; classNam
|
||||
}, [path]);
|
||||
|
||||
return url == null ? (
|
||||
<span aria-hidden className={classNames(className, "inline-block shrink-0")} />
|
||||
<span aria-hidden className={classNames(className, "inline-block shrink-0 aspect-square")} />
|
||||
) : (
|
||||
<img alt="" src={url} className={classNames(className, "shrink-0")} />
|
||||
// Square whatever squeezes it, beside text that truncates
|
||||
<img
|
||||
alt=""
|
||||
src={url}
|
||||
className={classNames(className, "shrink-0 aspect-square object-contain")}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -185,6 +185,11 @@ function LineText({ line }: { line: Line }) {
|
||||
typeof part === "string" ? (
|
||||
// oxlint-disable-next-line react/no-array-index-key -- the parts of one fixed line
|
||||
<span key={i}>{part}</span>
|
||||
) : "bold" in part ? (
|
||||
// oxlint-disable-next-line react/no-array-index-key -- the parts of one fixed line
|
||||
<span key={i} className="font-semibold">
|
||||
{part.bold}
|
||||
</span>
|
||||
) : (
|
||||
// oxlint-disable-next-line react/no-array-index-key -- the parts of one fixed line
|
||||
<InlineCode key={i}>{part.code}</InlineCode>
|
||||
@@ -222,7 +227,7 @@ function ActionButton({
|
||||
flow.clientPath == null ? (
|
||||
<Icon icon="box" size="sm" />
|
||||
) : (
|
||||
<AppIcon path={flow.clientPath} className="size-4" />
|
||||
<AppIcon path={flow.clientPath} className="size-4 min-w-4" />
|
||||
)
|
||||
) : (
|
||||
<Icon icon={ICONS[action.icon]} size="sm" />
|
||||
@@ -241,7 +246,7 @@ function ActionButton({
|
||||
action.hint == null ? undefined : (
|
||||
<span
|
||||
className={classNames(
|
||||
"ml-auto pl-3 font-mono text-xs text-text-subtlest truncate max-w-[50%]",
|
||||
"block ml-auto pl-3 font-mono text-xs text-text-subtlest truncate max-w-[11rem]",
|
||||
action.removes && "line-through",
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -77,9 +77,9 @@ export function HttpsStrip() {
|
||||
app.path == null ? (
|
||||
app.name
|
||||
) : (
|
||||
<span className="flex items-center gap-2">
|
||||
<AppIcon path={app.path} className="size-4" />
|
||||
{app.name}
|
||||
<span className="flex items-center gap-2 min-w-0">
|
||||
<AppIcon path={app.path} className="size-4 min-w-4" />
|
||||
<span className="truncate">{app.name}</span>
|
||||
</span>
|
||||
),
|
||||
keepOpenOnSelect: true,
|
||||
|
||||
@@ -85,7 +85,9 @@ function ItemInner({ item }: { item: SidebarItem }) {
|
||||
{item.kind === "encrypted" && <Icon icon="lock" size="sm" className="text-text-subtle" />}
|
||||
{item.kind === "saved" && <Icon icon="bookmark" size="sm" className="text-text-subtle" />}
|
||||
{item.kind === "folder" && <Icon icon="folder" size="sm" className="text-text-subtle" />}
|
||||
{item.appPath != null && <AppIcon path={item.appPath} className="size-[1.125rem]" />}
|
||||
{item.appPath != null && (
|
||||
<AppIcon path={item.appPath} className="size-[1.125rem] min-w-[1.125rem]" />
|
||||
)}
|
||||
{item.kind === "folder" && item.path != null ? (
|
||||
// Named by its last part; the whole path on hover
|
||||
<Tooltip wrap content={item.path} delay={CONTROL_TOOLTIP_DELAY}>
|
||||
|
||||
@@ -40,6 +40,12 @@ const apps = {
|
||||
clientBundleId: "com.1password.1password",
|
||||
clientPath: "/Applications/1Password.app",
|
||||
},
|
||||
headless: {
|
||||
clientName: "chrome-headless-shell",
|
||||
clientBundleId: null,
|
||||
clientPath:
|
||||
"/Users/you/.cache/ms-playwright/chromium_headless_shell-1208/chrome-headless-shell",
|
||||
},
|
||||
acme: {
|
||||
clientName: "Acme Sync",
|
||||
clientBundleId: "dev.acme.sync",
|
||||
@@ -124,6 +130,7 @@ function encryptedScene(): Flow[] {
|
||||
tunnel(10, "fonts.gstatic.com", apps.dia),
|
||||
tunnel(11, "clients2.google.com", apps.chrome),
|
||||
tunnel(12, "home.taila714c.ts.net:8317", apps.dia, { url: "home.taila714c.ts.net:8317" }),
|
||||
tunnel(13, "optimizationguide-pa.googleapis.com", apps.headless),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,9 @@ describe("the card of an encrypted connection", () => {
|
||||
|
||||
test("something else listed: not on the list, with the same choices", () => {
|
||||
const c = card({ list: [...user("host:api.stripe.com"), ...BUILT_INS] });
|
||||
expect(lineText(c.why)).toBe("Decryption not configured for `www.google.com`");
|
||||
expect(lineText(c.why)).toBe(
|
||||
"**Encrypted Content:** Enable decryption to see requests to `www.google.com`",
|
||||
);
|
||||
expect(c.actions.map((a) => a.label)).toEqual([
|
||||
"Decrypt www.google.com",
|
||||
"Decrypt Dia",
|
||||
@@ -108,10 +110,10 @@ describe("the card of an encrypted connection", () => {
|
||||
test("names the host nothing on the list covers, its port only when not 443", () => {
|
||||
const list = [...user("host:api.stripe.com"), ...BUILT_INS];
|
||||
expect(lineText(card({ list, flow: { ...tunnel, url: "t.yaak.app:443" } }).why)).toBe(
|
||||
"Decryption not configured for `t.yaak.app`",
|
||||
"**Encrypted Content:** Enable decryption to see requests to `t.yaak.app`",
|
||||
);
|
||||
expect(lineText(card({ list, flow: { ...tunnel, url: "home.ts.net:8317" } }).why)).toBe(
|
||||
"Decryption not configured for `home.ts.net:8317`",
|
||||
"**Encrypted Content:** Enable decryption to see requests to `home.ts.net:8317`",
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -78,12 +78,19 @@ export interface CardAction {
|
||||
icon: "host" | "app" | "everything" | "lock" | "lock_open" | "refresh" | "shield" | "terminal";
|
||||
}
|
||||
|
||||
/** A line of text, the hosts, apps and entries in it shown as code, as Yaak shows literal values */
|
||||
export type Line = (string | { code: string })[];
|
||||
/**
|
||||
* A line of text, the hosts, apps and entries in it shown as code, as Yaak shows literal values,
|
||||
* and a lead in bold
|
||||
*/
|
||||
export type Line = (string | { code: string } | { bold: string })[];
|
||||
|
||||
/** A line as plain text, its code in backticks */
|
||||
/** A line as plain text, its code in backticks and its bold in asterisks */
|
||||
export function lineText(line: Line): string {
|
||||
return line.map((part) => (typeof part === "string" ? part : `\`${part.code}\``)).join("");
|
||||
return line
|
||||
.map((part) =>
|
||||
typeof part === "string" ? part : "code" in part ? `\`${part.code}\`` : `**${part.bold}**`,
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
export interface EncryptedCardModel {
|
||||
@@ -265,7 +272,11 @@ function whyLine(
|
||||
? ["Nothing is decrypted yet"]
|
||||
: decryptsNow
|
||||
? ["Not on the decrypt list"]
|
||||
: ["Decryption not configured for ", { code: c.label }],
|
||||
: [
|
||||
{ bold: "Encrypted Content:" },
|
||||
" Enable decryption to see requests to ",
|
||||
{ code: c.label },
|
||||
],
|
||||
whySub: null,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user