mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-06-20 13:39:43 +02:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e2a9958b1a |
Generated
+9
-9
@@ -215,7 +215,7 @@ dependencies = [
|
||||
"objc2-foundation 0.3.1",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
"wl-clipboard-rs",
|
||||
"x11rb",
|
||||
]
|
||||
@@ -1151,7 +1151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static 1.5.0",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1970,7 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6534,7 +6534,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6547,7 +6547,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7508,9 +7508,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.45"
|
||||
version = "0.4.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
|
||||
checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
@@ -7988,7 +7988,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix 1.0.7",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9317,7 +9317,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Banner, VStack } from "@yaakapp-internal/ui";
|
||||
import { useState } from "react";
|
||||
import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir";
|
||||
import { appInfo } from "../lib/appInfo";
|
||||
import { CommercialUseBanner } from "./CommercialUseBanner";
|
||||
import { showErrorToast } from "../lib/toast";
|
||||
import { Button } from "./core/Button";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
@@ -90,10 +89,6 @@ export function CloneGitRepositoryDialog({ hide }: Props) {
|
||||
</Banner>
|
||||
)}
|
||||
|
||||
<CommercialUseBanner source="git-clone" title="Using Git for work?">
|
||||
A Yaak license is required for commercial use and helps support features like this.
|
||||
</CommercialUseBanner>
|
||||
|
||||
<PlainInput
|
||||
required
|
||||
label="Repository URL"
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { openUrl } from "@tauri-apps/plugin-opener";
|
||||
import type { LicenseCheckStatus } from "@yaakapp-internal/license";
|
||||
import { useEffect, useState } from "react";
|
||||
import { appInfo } from "../lib/appInfo";
|
||||
import { DismissibleBanner } from "./core/DismissibleBanner";
|
||||
|
||||
export function CommercialUseBanner({
|
||||
children,
|
||||
source,
|
||||
title,
|
||||
}: {
|
||||
children: string;
|
||||
source: string;
|
||||
title: string;
|
||||
}) {
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let canceled = false;
|
||||
|
||||
shouldShowCommercialUsePrompt()
|
||||
.then((shouldShow) => {
|
||||
if (!canceled) setVisible(shouldShow);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
return () => {
|
||||
canceled = true;
|
||||
};
|
||||
}, [source]);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<DismissibleBanner
|
||||
id="commercial-use"
|
||||
color="primary"
|
||||
className="w-full"
|
||||
dismissForDays={7}
|
||||
actions={[
|
||||
{
|
||||
label: "View plans",
|
||||
color: "primary",
|
||||
variant: "solid",
|
||||
onClick: () => {
|
||||
openCommercialUsePricing(source).catch(console.error);
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<div className="text-sm">
|
||||
<p className="font-semibold text-text">{title}</p>
|
||||
<p className="mt-0.5 text-text-subtle">{children}</p>
|
||||
</div>
|
||||
</DismissibleBanner>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
async function shouldShowCommercialUsePrompt(): Promise<boolean> {
|
||||
// Open-source builds omit the Rust license plugin, so never show commercial-use prompts there.
|
||||
if (appInfo.featureLicense !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const license = await invoke<LicenseCheckStatus>("plugin:yaak-license|check");
|
||||
return license.status !== "active" && license.status !== "trialing";
|
||||
} catch (err) {
|
||||
console.log("Failed to check license before commercial-use prompt", err);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function openCommercialUsePricing(source: string): Promise<void> {
|
||||
await openUrl(`https://yaak.app/pricing?s=${source}&ref=app.yaak.desktop`).catch(console.error);
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import slugify from "slugify";
|
||||
import { activeWorkspaceAtom } from "../hooks/useActiveWorkspace";
|
||||
import { pluralizeCount } from "../lib/pluralize";
|
||||
import { invokeCmd } from "../lib/tauri";
|
||||
import { CommercialUseBanner } from "./CommercialUseBanner";
|
||||
import { Button } from "./core/Button";
|
||||
import { Checkbox } from "./core/Checkbox";
|
||||
import { DetailsBanner } from "./core/DetailsBanner";
|
||||
@@ -86,12 +85,8 @@ function ExportDataDialogContent({
|
||||
const numSelected = Object.values(selectedWorkspaces).filter(Boolean).length;
|
||||
const noneSelected = numSelected === 0;
|
||||
return (
|
||||
<div className="h-full w-full grid grid-rows-[minmax(0,1fr)_auto] overflow-hidden rounded-b-lg">
|
||||
<div className="w-full grid grid-rows-[minmax(0,1fr)_auto]">
|
||||
<VStack space={3} className="overflow-auto px-5 pb-6">
|
||||
<CommercialUseBanner source="data-export" title="Exporting work data?">
|
||||
A Yaak license is required for commercial use and helps support features like this.
|
||||
</CommercialUseBanner>
|
||||
|
||||
<table className="w-full mb-auto min-w-full max-w-full divide-y divide-surface-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -142,9 +137,9 @@ function ExportDataDialogContent({
|
||||
/>
|
||||
</DetailsBanner>
|
||||
</VStack>
|
||||
<footer className="px-5 grid grid-cols-[1fr_auto] items-center bg-surface py-3 border-t border-border-subtle">
|
||||
<footer className="px-5 grid grid-cols-[1fr_auto] items-center bg-surface-highlight py-2 border-t border-border-subtle">
|
||||
<div>
|
||||
<Link href="https://yaak.app/button/new" noUnderline className="text-text-subtlest">
|
||||
<Link href="https://yaak.app/button/new" noUnderline className="text-text-subtle">
|
||||
Create Run Button
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { VStack } from "@yaakapp-internal/ui";
|
||||
import { useState } from "react";
|
||||
import { useLocalStorage } from "react-use";
|
||||
import { CommercialUseBanner } from "./CommercialUseBanner";
|
||||
import { Button } from "./core/Button";
|
||||
import { SelectFile } from "./SelectFile";
|
||||
|
||||
@@ -15,10 +14,6 @@ export function ImportDataDialog({ importData }: Props) {
|
||||
|
||||
return (
|
||||
<VStack space={5} className="pb-4">
|
||||
<CommercialUseBanner source="data-import" title="Importing work data?">
|
||||
A Yaak license is required for commercial use and helps support features like this.
|
||||
</CommercialUseBanner>
|
||||
|
||||
<VStack space={1}>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>OpenAPI 3.0, 3.1</li>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Heading, HStack, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useRef } from "react";
|
||||
import { showConfirmDelete } from "../../lib/confirm";
|
||||
import { CommercialUseBanner } from "../CommercialUseBanner";
|
||||
import { Button } from "../core/Button";
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
import { DetailsBanner } from "../core/DetailsBanner";
|
||||
@@ -233,10 +232,6 @@ export function SettingsCertificates() {
|
||||
</HStack>
|
||||
</div>
|
||||
|
||||
<CommercialUseBanner source="client-certificates" title="Using certificates for work?">
|
||||
A Yaak license is required for commercial use and helps support features like this.
|
||||
</CommercialUseBanner>
|
||||
|
||||
{certificates.length > 0 && (
|
||||
<VStack space={3}>
|
||||
{certificates.map((cert, index) => (
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
} from "../../lib/requestSettings";
|
||||
import { revealInFinderText } from "../../lib/reveal";
|
||||
import { CargoFeature } from "../CargoFeature";
|
||||
import { CommercialUseBanner } from "../CommercialUseBanner";
|
||||
import { IconButton } from "../core/IconButton";
|
||||
import {
|
||||
ModelSettingRowBoolean,
|
||||
@@ -39,15 +38,10 @@ export function SettingsGeneral() {
|
||||
|
||||
return (
|
||||
<VStack space={1.5} className="mb-4">
|
||||
<div>
|
||||
<div className="mb-4">
|
||||
<Heading>General</Heading>
|
||||
<p className="text-text-subtle">Configure general settings for update behavior and more.</p>
|
||||
</div>
|
||||
<div className="mt-3 mb-5">
|
||||
<CommercialUseBanner source="settings-general" title="Using Yaak for work?">
|
||||
A Yaak license is required for commercial use and helps support future development.
|
||||
</CommercialUseBanner>
|
||||
</div>
|
||||
<SettingsList className="space-y-8">
|
||||
<CargoFeature feature="updater">
|
||||
<SettingsSection title="Updates">
|
||||
|
||||
@@ -2,7 +2,6 @@ import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
||||
import type { ProxySetting } from "@yaakapp-internal/models";
|
||||
import { Heading, InlineCode, VStack } from "@yaakapp-internal/ui";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { CommercialUseBanner } from "../CommercialUseBanner";
|
||||
import {
|
||||
SettingRowBoolean,
|
||||
SettingRowSelect,
|
||||
@@ -34,9 +33,6 @@ export function SettingsProxy() {
|
||||
traffic, or routing through specific infrastructure.
|
||||
</p>
|
||||
</div>
|
||||
<CommercialUseBanner source="proxy-settings" title="Using a proxy for work?">
|
||||
A Yaak license is required for commercial use and helps support features like this.
|
||||
</CommercialUseBanner>
|
||||
<SettingsList className="space-y-8">
|
||||
<SettingsSection title="Proxy">
|
||||
<SettingRowSelect
|
||||
|
||||
@@ -1,84 +1,57 @@
|
||||
import type { Color } from "@yaakapp-internal/plugins";
|
||||
import type { BannerProps } from "@yaakapp-internal/ui";
|
||||
import { Banner } from "@yaakapp-internal/ui";
|
||||
import { Banner, HStack } from "@yaakapp-internal/ui";
|
||||
import classNames from "classnames";
|
||||
import { useKeyValue } from "../../hooks/useKeyValue";
|
||||
import type { ButtonProps } from "./Button";
|
||||
import { Button } from "./Button";
|
||||
|
||||
export function DismissibleBanner({
|
||||
children,
|
||||
className,
|
||||
dismissForDays,
|
||||
id,
|
||||
actions,
|
||||
...props
|
||||
}: BannerProps & {
|
||||
id: string;
|
||||
dismissForDays?: number;
|
||||
actions?: {
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
color?: Color;
|
||||
variant?: ButtonProps["variant"];
|
||||
}[];
|
||||
actions?: { label: string; onClick: () => void; color?: Color }[];
|
||||
}) {
|
||||
const {
|
||||
isLoading,
|
||||
set: setDismissed,
|
||||
value: dismissed,
|
||||
} = useKeyValue<boolean | string>({
|
||||
const { set: setDismissed, value: dismissed } = useKeyValue<boolean>({
|
||||
namespace: "global",
|
||||
key: ["dismiss-banner", id],
|
||||
fallback: false,
|
||||
});
|
||||
|
||||
if (isLoading || isDismissed(dismissed, dismissForDays)) return null;
|
||||
if (dismissed) return null;
|
||||
|
||||
return (
|
||||
<Banner className={classNames(className, "relative")} {...props}>
|
||||
<div className="@container">
|
||||
<div className="grid gap-2 @[34rem]:grid-cols-[minmax(0,1fr)_auto] @[34rem]:items-center @[34rem]:gap-3">
|
||||
{children}
|
||||
<div className="flex flex-wrap gap-1.5 @[34rem]:justify-end">
|
||||
<Button
|
||||
variant="border"
|
||||
color={props.color}
|
||||
size="xs"
|
||||
onClick={() => setDismissed(dismissForDays == null ? true : new Date().toISOString())}
|
||||
title="Dismiss message"
|
||||
>
|
||||
Dismiss
|
||||
</Button>
|
||||
{actions?.map((a) => (
|
||||
<Button
|
||||
key={a.label}
|
||||
variant={a.variant ?? "border"}
|
||||
color={a.color ?? props.color}
|
||||
size="xs"
|
||||
onClick={a.onClick}
|
||||
title={a.label}
|
||||
>
|
||||
{a.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Banner
|
||||
className={classNames(className, "relative grid grid-cols-[1fr_auto] gap-3")}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<HStack space={1.5}>
|
||||
{actions?.map((a) => (
|
||||
<Button
|
||||
key={a.label}
|
||||
variant="border"
|
||||
color={a.color ?? props.color}
|
||||
size="xs"
|
||||
onClick={a.onClick}
|
||||
title={a.label}
|
||||
>
|
||||
{a.label}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="border"
|
||||
color={props.color}
|
||||
size="xs"
|
||||
onClick={() => setDismissed((d) => !d)}
|
||||
title="Dismiss message"
|
||||
>
|
||||
Dismiss
|
||||
</Button>
|
||||
</HStack>
|
||||
</Banner>
|
||||
);
|
||||
}
|
||||
|
||||
function isDismissed(
|
||||
dismissed: boolean | string | null,
|
||||
dismissForDays: number | undefined,
|
||||
): boolean {
|
||||
if (dismissed === false || dismissed == null) return false;
|
||||
if (dismissed === true) return true;
|
||||
if (dismissForDays == null) return dismissed.length > 0;
|
||||
|
||||
const dismissedAt = new Date(dismissed).getTime();
|
||||
if (Number.isNaN(dismissedAt)) return false;
|
||||
|
||||
return Date.now() - dismissedAt < dismissForDays * 24 * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
@@ -292,8 +292,8 @@ function BaseInput({
|
||||
inputWrapperClassName,
|
||||
"flex-1 min-w-0 px-2",
|
||||
fullHeight && "h-full",
|
||||
leftSlot ? "pl-0" : null,
|
||||
rightSlot ? "pr-0" : null,
|
||||
leftSlot ? "pl-0.5 -ml-2" : null,
|
||||
rightSlot ? "pr-0.5 -mr-2" : null,
|
||||
)}
|
||||
>
|
||||
<Editor
|
||||
|
||||
@@ -16,7 +16,6 @@ import { resolvedModelName } from "../../lib/resolvedModelName";
|
||||
import { showConfirm } from "../../lib/confirm";
|
||||
import { showErrorToast } from "../../lib/toast";
|
||||
import { sync } from "../../init/sync";
|
||||
import { CommercialUseBanner } from "../CommercialUseBanner";
|
||||
import { Button } from "../core/Button";
|
||||
import type { CheckboxProps } from "../core/Checkbox";
|
||||
import { Checkbox } from "../core/Checkbox";
|
||||
@@ -206,10 +205,7 @@ export function GitCommitDialog({ syncDir, onDone, workspace }: Props) {
|
||||
layout="horizontal"
|
||||
defaultRatio={0.6}
|
||||
firstSlot={({ style }) => (
|
||||
<div style={style} className="h-full px-4 grid grid-rows-[auto_minmax(0,1fr)] gap-3">
|
||||
<CommercialUseBanner source="git-commit" title="Using Git for work?">
|
||||
A Yaak license is required for commercial use and helps support features like this.
|
||||
</CommercialUseBanner>
|
||||
<div style={style} className="h-full px-4">
|
||||
<SplitLayout
|
||||
storageKey="commit-vertical"
|
||||
layout="vertical"
|
||||
|
||||
@@ -69,7 +69,6 @@ function HttpTextViewer({ response, text, language, pretty, className }: HttpTex
|
||||
text={text}
|
||||
language={language}
|
||||
stateKey={`response.body.${response.id}`}
|
||||
filterStateKey={`response.body.${response.requestId}`}
|
||||
pretty={pretty}
|
||||
className={className}
|
||||
onFilter={filterCallback}
|
||||
|
||||
@@ -16,7 +16,6 @@ interface Props {
|
||||
text: string;
|
||||
language: EditorProps["language"];
|
||||
stateKey: string | null;
|
||||
filterStateKey?: string | null;
|
||||
pretty?: boolean;
|
||||
className?: string;
|
||||
onFilter?: (filter: string) => {
|
||||
@@ -28,25 +27,16 @@ interface Props {
|
||||
|
||||
const useFilterText = createGlobalState<Record<string, string | null>>({});
|
||||
|
||||
export function TextViewer({
|
||||
language,
|
||||
text,
|
||||
stateKey,
|
||||
filterStateKey,
|
||||
pretty,
|
||||
className,
|
||||
onFilter,
|
||||
}: Props) {
|
||||
const filterKey = filterStateKey ?? stateKey;
|
||||
export function TextViewer({ language, text, stateKey, pretty, className, onFilter }: Props) {
|
||||
const [filterTextMap, setFilterTextMap] = useFilterText();
|
||||
const filterText = filterKey ? (filterTextMap[filterKey] ?? null) : null;
|
||||
const filterText = stateKey ? (filterTextMap[stateKey] ?? null) : null;
|
||||
const debouncedFilterText = useDebouncedValue(filterText);
|
||||
const setFilterText = useCallback(
|
||||
(v: string | null) => {
|
||||
if (!filterKey) return;
|
||||
setFilterTextMap((m) => ({ ...m, [filterKey]: v }));
|
||||
if (!stateKey) return;
|
||||
setFilterTextMap((m) => ({ ...m, [stateKey]: v }));
|
||||
},
|
||||
[filterKey, setFilterTextMap],
|
||||
[setFilterTextMap, stateKey],
|
||||
);
|
||||
|
||||
const isSearching = filterText != null;
|
||||
@@ -74,7 +64,7 @@ export function TextViewer({
|
||||
nodes.push(
|
||||
<div key="input" className="w-full !opacity-100">
|
||||
<Input
|
||||
key={filterKey ?? "filter"}
|
||||
key={stateKey ?? "filter"}
|
||||
validate={!filteredResponse.error}
|
||||
hideLabel
|
||||
autoFocus
|
||||
@@ -86,7 +76,7 @@ export function TextViewer({
|
||||
defaultValue={filterText}
|
||||
onKeyDown={(e) => e.key === "Escape" && toggleSearch()}
|
||||
onChange={setFilterText}
|
||||
stateKey={filterKey ? `filter.${filterKey}` : null}
|
||||
stateKey={stateKey ? `filter.${stateKey}` : null}
|
||||
/>
|
||||
</div>,
|
||||
);
|
||||
@@ -107,12 +97,12 @@ export function TextViewer({
|
||||
return nodes;
|
||||
}, [
|
||||
canFilter,
|
||||
filterKey,
|
||||
filterText,
|
||||
filteredResponse.error,
|
||||
filteredResponse.isPending,
|
||||
isSearching,
|
||||
language,
|
||||
stateKey,
|
||||
setFilterText,
|
||||
toggleSearch,
|
||||
]);
|
||||
|
||||
@@ -125,11 +125,10 @@ function bannerColorVariables(color: YaakColor | null): Partial<CSSVariables> {
|
||||
if (color == null) return {};
|
||||
|
||||
return {
|
||||
text: color.desaturate(0.5).lift(0.12).css(),
|
||||
textSubtle: color.desaturate(0.58).lift(0.04).translucify(0.04).css(),
|
||||
textSubtlest: color.desaturate(0.65).translucify(0.18).css(),
|
||||
text: color.lift(0.8).css(),
|
||||
textSubtle: color.translucify(0.3).css(),
|
||||
textSubtlest: color.translucify(0.6).css(),
|
||||
surface: color.translucify(0.95).css(),
|
||||
surfaceHighlight: color.translucify(0.85).css(),
|
||||
border: color.lift(0.3).translucify(0.8).css(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,9 +69,6 @@ const config = JSON.stringify({
|
||||
const normalizedAdditionalArgs = [];
|
||||
for (let i = 0; i < additionalArgs.length; i++) {
|
||||
const arg = additionalArgs[i];
|
||||
if (arg === "--") {
|
||||
continue;
|
||||
}
|
||||
if (arg === "--config" && i + 1 < additionalArgs.length) {
|
||||
const value = additionalArgs[i + 1];
|
||||
const isInlineJson = value.trimStart().startsWith("{");
|
||||
|
||||
Reference in New Issue
Block a user