diff --git a/src-tauri/capabilities/capabilities.json b/src-tauri/capabilities/capabilities.json index 3eca9861..b77c0d6f 100644 --- a/src-tauri/capabilities/capabilities.json +++ b/src-tauri/capabilities/capabilities.json @@ -11,6 +11,7 @@ "core:event:allow-emit", "core:event:allow-listen", "core:event:allow-unlisten", + "core:path:allow-resolve-directory", "os:allow-os-type", "clipboard-manager:allow-clear", "clipboard-manager:allow-write-text", diff --git a/src-tauri/static/greg.jpeg b/src-tauri/static/greg.jpeg new file mode 100644 index 00000000..eb7723cf Binary files /dev/null and b/src-tauri/static/greg.jpeg differ diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c7a98979..3ea40eec 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -15,7 +15,8 @@ "enable": true, "scope": { "allow": [ - "$APPDATA/responses/*" + "$APPDATA/responses/*", + "$RESOURCE/static/*" ] } } @@ -56,6 +57,7 @@ ], "longDescription": "A cross-platform desktop app for interacting with REST, GraphQL, and gRPC", "resources": [ + "static", "vendored/protoc/include", "vendored/plugins", "vendored/plugin-runtime" diff --git a/src-tauri/yaak-license/src/license.rs b/src-tauri/yaak-license/src/license.rs index dce35ebb..f71d6282 100644 --- a/src-tauri/yaak-license/src/license.rs +++ b/src-tauri/yaak-license/src/license.rs @@ -155,6 +155,7 @@ pub async fn check_license(window: &WebviewWindow) -> Result DbContext<'a> { update_channel: "stable".to_string(), autoupdate: true, colored_methods: false, + hide_license_badge: false, }; self.upsert(&settings, &UpdateSource::Background).expect("Failed to upsert settings") } diff --git a/src-web/components/LicenseBadge.tsx b/src-web/components/LicenseBadge.tsx index 8671e986..af275312 100644 --- a/src-web/components/LicenseBadge.tsx +++ b/src-web/components/LicenseBadge.tsx @@ -1,8 +1,9 @@ import type { LicenseCheckStatus } from '@yaakapp-internal/license'; import { useLicense } from '@yaakapp-internal/license'; +import { settingsAtom } from '@yaakapp-internal/models'; +import { useAtomValue } from 'jotai'; import type { ReactNode } from 'react'; import { openSettings } from '../commands/openSettings'; -import { useLicenseConfirmation } from '../hooks/useLicenseConfirmation'; import { appInfo } from '../lib/appInfo'; import { BadgeButton } from './core/BadgeButton'; import type { ButtonProps } from './core/Button'; @@ -19,7 +20,7 @@ const details: Record< export function LicenseBadge() { const { check } = useLicense(); - const [licenseDetails, setLicenseDetails] = useLicenseConfirmation(); + const settings = useAtomValue(settingsAtom); if (appInfo.isDev) { return null; @@ -32,17 +33,17 @@ export function LicenseBadge() { } // Hasn't loaded yet - if (licenseDetails == null || check.data == null) { + if (check.data == null) { return null; } - // User has confirmed they are using Yaak for personal use only, so hide badge - if (licenseDetails.confirmedPersonalUse) { + // Dismissed license badge + if (settings.hideLicenseBadge) { return null; } // User is trialing but has already seen the message, so hide badge - if (check.data.type === 'trialing' && licenseDetails.hasDismissedTrial) { + if (check.data.type === 'trialing') { return null; } @@ -55,12 +56,6 @@ export function LicenseBadge() { { - if (check.data.type === 'trialing') { - await setLicenseDetails((v) => ({ - ...v, - hasDismissedTrial: true, - })); - } openSettings.mutate('license'); }} > diff --git a/src-web/components/LocalImage.tsx b/src-web/components/LocalImage.tsx new file mode 100644 index 00000000..59cf8a93 --- /dev/null +++ b/src-web/components/LocalImage.tsx @@ -0,0 +1,33 @@ +import { useQuery } from '@tanstack/react-query'; +import { convertFileSrc } from '@tauri-apps/api/core'; +import { resolveResource } from '@tauri-apps/api/path'; +import classNames from 'classnames'; +import React from 'react'; + +interface Props { + src: string; + className?: string; +} + +export function LocalImage({ src: srcPath, className }: Props) { + const src = useQuery({ + queryKey: ['local-image', srcPath], + queryFn: async () => { + const p = await resolveResource(srcPath); + console.log("LOADING SRC", srcPath, p) + return convertFileSrc(p); + }, + }); + + return ( + Response preview + ); +} diff --git a/src-web/components/Settings/Settings.tsx b/src-web/components/Settings/Settings.tsx index 6fbad5f4..3af1ead7 100644 --- a/src-web/components/Settings/Settings.tsx +++ b/src-web/components/Settings/Settings.tsx @@ -74,22 +74,22 @@ export default function Settings({ hide }: Props) { onChangeValue={setTab} tabs={tabs.map((value) => ({ value, label: capitalize(value) }))} > - + - + - + - + - + - + diff --git a/src-web/components/Settings/SettingsInterface.tsx b/src-web/components/Settings/SettingsInterface.tsx index feacb660..3fd3684a 100644 --- a/src-web/components/Settings/SettingsInterface.tsx +++ b/src-web/components/Settings/SettingsInterface.tsx @@ -1,13 +1,16 @@ import { type } from '@tauri-apps/plugin-os'; import { useFonts } from '@yaakapp-internal/fonts'; +import { useLicense } from '@yaakapp-internal/license'; import type { EditorKeymap } from '@yaakapp-internal/models'; import { patchModel, settingsAtom } from '@yaakapp-internal/models'; import { useAtomValue } from 'jotai'; import React from 'react'; import { activeWorkspaceAtom } from '../../hooks/useActiveWorkspace'; import { clamp } from '../../lib/clamp'; +import { showConfirm } from '../../lib/confirm'; import { Checkbox } from '../core/Checkbox'; import { Icon } from '../core/Icon'; +import { Link } from '../core/Link'; import { Select } from '../core/Select'; import { HStack, VStack } from '../core/Stacks'; @@ -28,6 +31,7 @@ export function SettingsInterface() { const workspace = useAtomValue(activeWorkspaceAtom); const settings = useAtomValue(settingsAtom); const fonts = useFonts(); + const license = useLicense(); if (settings == null || workspace == null) { return null; @@ -123,6 +127,31 @@ export function SettingsInterface() { title="Colorize Request Methods" onChange={(coloredMethods) => patchModel(settings, { coloredMethods })} /> + {license.check.data?.type === 'personal_use' && ( + { + if (hide) { + const confirmed = await showConfirm({ + id: 'hide-license-badge', + title: 'Hide License Badge', + confirmText: 'Hide Badge', + description: ( + <> + Only proceed if you’re using Yaak for personal projects only. If you’re using it + at work, please Purchase a License. + + ), + requireTyping: 'Personal Use', + color: 'notice', + }); + if (!confirmed) return; + } + await patchModel(settings, { licenseBadge: !hide }); + }} + /> + )} {type() !== 'macos' && ( (''); const [activateFormVisible, toggleActivateFormVisible] = useToggle(false); - const [licenseDetails, setLicenseDetails] = useLicenseConfirmation(); - const [checked, setChecked] = useState(false); if (check.isPending) { return null; } return ( -
+
{check.data?.type === 'commercial_use' ? ( - - License active! Enjoy using Yaak for commercial use. - + Your license is active 🥳 ) : check.data?.type == 'trialing' ? (

- You have{' '} {pluralizeCount('day', differenceInDays(check.data.end, new Date()))} remaining {' '} - on your commercial use trial. Once the trial ends you agree to only use Yaak for - personal use until a license is activated. + on trial

- ) : check.data?.type == 'personal_use' && !licenseDetails?.confirmedPersonalUse ? ( + ) : check.data?.type == 'personal_use' ? ( -

- Your 30-day trial has ended. Please activate a license or confirm how you're using - Yaak. -

-
{ - e.preventDefault(); - await setLicenseDetails((v) => ({ - ...v, - confirmedPersonalUse: true, - })); - }} - > - - - +

Your free trial has ended

) : null} -

- A commercial license is required if using Yaak within a for-profit organization.{' '} - - Learn More - -

+ {check.data?.type !== 'commercial_use' && ( +
+ +
+

Hey, I'm Greg 👋🏼

+

+ Yaak is free for personal projects and learning.{' '} + {check.data?.type === 'trialing' ? 'After your trial, a ' : 'A '} + license is required for work or commercial use. +

+

+ + Learn More + +

+
+
+ )} {check.error && {check.error}} {activate.error && {activate.error}} {check.data?.type === 'commercial_use' ? ( -