mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-23 09:51:28 +01:00
Rework licensing flows to be more friendly
This commit is contained in:
@@ -74,22 +74,22 @@ export default function Settings({ hide }: Props) {
|
||||
onChangeValue={setTab}
|
||||
tabs={tabs.map((value) => ({ value, label: capitalize(value) }))}
|
||||
>
|
||||
<TabContent value={TAB_GENERAL} className="overflow-y-auto h-full px-4">
|
||||
<TabContent value={TAB_GENERAL} className="overflow-y-auto h-full p-8">
|
||||
<SettingsGeneral />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_INTERFACE} className="overflow-y-auto h-full px-4">
|
||||
<TabContent value={TAB_INTERFACE} className="overflow-y-auto h-full p-8">
|
||||
<SettingsInterface />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_THEME} className="overflow-y-auto h-full px-4">
|
||||
<TabContent value={TAB_THEME} className="overflow-y-auto h-full p-8">
|
||||
<SettingsTheme />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_PLUGINS} className="h-full px-4 grid grid-rows-1">
|
||||
<TabContent value={TAB_PLUGINS} className="h-full grid grid-rows-1 p-8">
|
||||
<SettingsPlugins />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_PROXY} className="overflow-y-auto h-full px-4">
|
||||
<TabContent value={TAB_PROXY} className="overflow-y-auto h-full p-8!">
|
||||
<SettingsProxy />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_LICENSE} className="overflow-y-auto h-full px-4">
|
||||
<TabContent value={TAB_LICENSE} className="overflow-y-auto h-full px-8 !py-4">
|
||||
<SettingsLicense />
|
||||
</TabContent>
|
||||
</Tabs>
|
||||
|
||||
@@ -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' && (
|
||||
<Checkbox
|
||||
checked={!settings.licenseBadge}
|
||||
title="Hide personal use badge"
|
||||
onChange={async (hide) => {
|
||||
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 <Link href="https://yaak.app/">Purchase a License</Link>.
|
||||
</>
|
||||
),
|
||||
requireTyping: 'Personal Use',
|
||||
color: 'notice',
|
||||
});
|
||||
if (!confirmed) return;
|
||||
}
|
||||
await patchModel(settings, { licenseBadge: !hide });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type() !== 'macos' && (
|
||||
<Checkbox
|
||||
|
||||
@@ -2,88 +2,80 @@ import { openUrl } from '@tauri-apps/plugin-opener';
|
||||
import { useLicense } from '@yaakapp-internal/license';
|
||||
import { differenceInDays } from 'date-fns';
|
||||
import React, { useState } from 'react';
|
||||
import { useLicenseConfirmation } from '../../hooks/useLicenseConfirmation';
|
||||
import { useToggle } from '../../hooks/useToggle';
|
||||
import { pluralizeCount } from '../../lib/pluralize';
|
||||
import { Banner } from '../core/Banner';
|
||||
import { Button } from '../core/Button';
|
||||
import { Checkbox } from '../core/Checkbox';
|
||||
import { Icon } from '../core/Icon';
|
||||
import { Link } from '../core/Link';
|
||||
import { PlainInput } from '../core/PlainInput';
|
||||
import { HStack, VStack } from '../core/Stacks';
|
||||
import { LocalImage } from '../LocalImage';
|
||||
|
||||
export function SettingsLicense() {
|
||||
const { check, activate, deactivate } = useLicense();
|
||||
const [key, setKey] = useState<string>('');
|
||||
const [activateFormVisible, toggleActivateFormVisible] = useToggle(false);
|
||||
const [licenseDetails, setLicenseDetails] = useLicenseConfirmation();
|
||||
const [checked, setChecked] = useState<boolean>(false);
|
||||
|
||||
if (check.isPending) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 max-w-lg">
|
||||
<div className="flex flex-col gap-6 max-w-xl">
|
||||
{check.data?.type === 'commercial_use' ? (
|
||||
<Banner color="success">
|
||||
<strong>License active!</strong> Enjoy using Yaak for commercial use.
|
||||
</Banner>
|
||||
<Banner color="success">Your license is active 🥳</Banner>
|
||||
) : check.data?.type == 'trialing' ? (
|
||||
<Banner color="success" className="flex flex-col gap-3 max-w-lg">
|
||||
<p className="select-text">
|
||||
You have{' '}
|
||||
<strong>
|
||||
{pluralizeCount('day', differenceInDays(check.data.end, new Date()))} remaining
|
||||
</strong>{' '}
|
||||
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
|
||||
</p>
|
||||
</Banner>
|
||||
) : check.data?.type == 'personal_use' && !licenseDetails?.confirmedPersonalUse ? (
|
||||
) : check.data?.type == 'personal_use' ? (
|
||||
<Banner color="success" className="flex flex-col gap-3 max-w-lg">
|
||||
<p className="select-text">
|
||||
Your 30-day trial has ended. Please activate a license or confirm how you're using
|
||||
Yaak.
|
||||
</p>
|
||||
<form
|
||||
className="flex flex-col gap-3 items-start"
|
||||
onSubmit={async (e) => {
|
||||
e.preventDefault();
|
||||
await setLicenseDetails((v) => ({
|
||||
...v,
|
||||
confirmedPersonalUse: true,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
onChange={setChecked}
|
||||
title="I am only using Yaak for personal use"
|
||||
/>
|
||||
<Button type="submit" disabled={!checked} size="xs" variant="border" color="success">
|
||||
Confirm
|
||||
</Button>
|
||||
</form>
|
||||
<p>Your free trial has ended</p>
|
||||
</Banner>
|
||||
) : null}
|
||||
|
||||
<p className="select-text">
|
||||
A commercial license is required if using Yaak within a for-profit organization.{' '}
|
||||
<Link href="https://yaak.app/pricing" className="text-notice">
|
||||
Learn More
|
||||
</Link>
|
||||
</p>
|
||||
{check.data?.type !== 'commercial_use' && (
|
||||
<div className="grid grid-cols-[auto_minmax(0,1fr)] gap-6 items-center my-3 ">
|
||||
<LocalImage src="static/greg.jpeg" className="rounded-full h-20 w-20" />
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-lg font-bold">Hey, I'm Greg 👋🏼</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
<Link
|
||||
noUnderline
|
||||
href="https://yaak.app/pricing"
|
||||
className="text-sm text-notice opacity-80 hover:opacity-100"
|
||||
>
|
||||
Learn More
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{check.error && <Banner color="danger">{check.error}</Banner>}
|
||||
{activate.error && <Banner color="danger">{activate.error}</Banner>}
|
||||
|
||||
{check.data?.type === 'commercial_use' ? (
|
||||
<HStack space={2}>
|
||||
<Button variant="border" color="secondary" size="sm" onClick={() => {
|
||||
deactivate.mutate();
|
||||
}}>
|
||||
<Button
|
||||
variant="border"
|
||||
color="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
deactivate.mutate();
|
||||
}}
|
||||
>
|
||||
Deactivate License
|
||||
</Button>
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user