mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 17:48:30 +02:00
Better trial activation flows
This commit is contained in:
@@ -26,6 +26,7 @@ export function useLicense() {
|
|||||||
|
|
||||||
const CHECK_QUERY_KEY = ['license.check'];
|
const CHECK_QUERY_KEY = ['license.check'];
|
||||||
const check = useQuery<void, string, LicenseCheckStatus>({
|
const check = useQuery<void, string, LicenseCheckStatus>({
|
||||||
|
refetchInterval: 1000 * 60 * 60 * 12, // Refetch every 12 hours
|
||||||
queryKey: CHECK_QUERY_KEY,
|
queryKey: CHECK_QUERY_KEY,
|
||||||
queryFn: () => invoke('plugin:yaak-license|check'),
|
queryFn: () => invoke('plugin:yaak-license|check'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export function LicenseBadge() {
|
|||||||
if (check.data.type === 'trialing') {
|
if (check.data.type === 'trialing') {
|
||||||
await setLicenseDetails((v) => ({
|
await setLicenseDetails((v) => ({
|
||||||
...v,
|
...v,
|
||||||
dismissedTrial: true,
|
hasDismissedTrial: true,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
openSettings.mutate(SettingsTab.License);
|
openSettings.mutate(SettingsTab.License);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { openUrl } from '@tauri-apps/plugin-opener';
|
import { openUrl } from '@tauri-apps/plugin-opener';
|
||||||
import { useLicense } from '@yaakapp-internal/license';
|
import { useLicense } from '@yaakapp-internal/license';
|
||||||
import { formatDistanceToNowStrict } from 'date-fns';
|
import { differenceInDays } from 'date-fns';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useLicenseConfirmation } from '../../hooks/useLicenseConfirmation';
|
import { useLicenseConfirmation } from '../../hooks/useLicenseConfirmation';
|
||||||
import { useToggle } from '../../hooks/useToggle';
|
import { useToggle } from '../../hooks/useToggle';
|
||||||
|
import { pluralizeCount } from '../../lib/pluralize';
|
||||||
import { Banner } from '../core/Banner';
|
import { Banner } from '../core/Banner';
|
||||||
import { Button } from '../core/Button';
|
import { Button } from '../core/Button';
|
||||||
import { Checkbox } from '../core/Checkbox';
|
import { Checkbox } from '../core/Checkbox';
|
||||||
@@ -32,8 +33,12 @@ export function SettingsLicense() {
|
|||||||
) : check.data?.type == 'trialing' ? (
|
) : check.data?.type == 'trialing' ? (
|
||||||
<Banner color="success" className="flex flex-col gap-3 max-w-lg">
|
<Banner color="success" className="flex flex-col gap-3 max-w-lg">
|
||||||
<p className="select-text">
|
<p className="select-text">
|
||||||
<strong>{formatDistanceToNowStrict(check.data.end)} days remaining</strong> on your
|
You have{' '}
|
||||||
commercial use trial
|
<strong>
|
||||||
|
{pluralizeCount('day', differenceInDays(check.data.end, new Date()))} remaining
|
||||||
|
</strong>{' '}
|
||||||
|
on your commercial use trial. Once the trial ends, Yaak will be limited to personal use
|
||||||
|
until a license is activated.
|
||||||
</p>
|
</p>
|
||||||
</Banner>
|
</Banner>
|
||||||
) : check.data?.type == 'personal_use' && !licenseDetails?.confirmedPersonalUse ? (
|
) : check.data?.type == 'personal_use' && !licenseDetails?.confirmedPersonalUse ? (
|
||||||
@@ -76,12 +81,7 @@ export function SettingsLicense() {
|
|||||||
|
|
||||||
{check.data?.type === 'commercial_use' ? (
|
{check.data?.type === 'commercial_use' ? (
|
||||||
<HStack space={2}>
|
<HStack space={2}>
|
||||||
<Button
|
<Button variant="border" color="secondary" size="sm" onClick={toggleActivateFormVisible}>
|
||||||
variant="border"
|
|
||||||
color="secondary"
|
|
||||||
size="sm"
|
|
||||||
onClick={toggleActivateFormVisible}
|
|
||||||
>
|
|
||||||
Activate Another License
|
Activate Another License
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -95,11 +95,7 @@ export function SettingsLicense() {
|
|||||||
</HStack>
|
</HStack>
|
||||||
) : (
|
) : (
|
||||||
<HStack space={2}>
|
<HStack space={2}>
|
||||||
<Button
|
<Button color="primary" size="sm" onClick={toggleActivateFormVisible}>
|
||||||
color="primary"
|
|
||||||
size="sm"
|
|
||||||
onClick={toggleActivateFormVisible}
|
|
||||||
>
|
|
||||||
Activate
|
Activate
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -131,12 +127,7 @@ export function SettingsLicense() {
|
|||||||
onChange={setKey}
|
onChange={setKey}
|
||||||
placeholder="YK1-XXXXX-XXXXX-XXXXX-XXXXX"
|
placeholder="YK1-XXXXX-XXXXX-XXXXX-XXXXX"
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button type="submit" color="primary" size="sm" isLoading={activate.isPending}>
|
||||||
type="submit"
|
|
||||||
color="primary"
|
|
||||||
size="sm"
|
|
||||||
isLoading={activate.isPending}
|
|
||||||
>
|
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
</VStack>
|
</VStack>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { openUrl } from '@tauri-apps/plugin-opener';
|
import { openUrl } from '@tauri-apps/plugin-opener';
|
||||||
|
import { useLicense } from '@yaakapp-internal/license';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import { openSettings } from '../commands/openSettings';
|
import { openSettings } from '../commands/openSettings';
|
||||||
import { useAppInfo } from '../hooks/useAppInfo';
|
import { useAppInfo } from '../hooks/useAppInfo';
|
||||||
@@ -12,6 +13,7 @@ import { Dropdown } from './core/Dropdown';
|
|||||||
import { Icon } from './core/Icon';
|
import { Icon } from './core/Icon';
|
||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
|
import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
|
||||||
|
import { SettingsTab } from './Settings/SettingsTab';
|
||||||
|
|
||||||
export function SettingsDropdown() {
|
export function SettingsDropdown() {
|
||||||
const importData = useImportData();
|
const importData = useImportData();
|
||||||
@@ -19,6 +21,7 @@ export function SettingsDropdown() {
|
|||||||
const appInfo = useAppInfo();
|
const appInfo = useAppInfo();
|
||||||
const dropdownRef = useRef<DropdownRef>(null);
|
const dropdownRef = useRef<DropdownRef>(null);
|
||||||
const checkForUpdates = useCheckForUpdates();
|
const checkForUpdates = useCheckForUpdates();
|
||||||
|
const { check } = useLicense();
|
||||||
|
|
||||||
useListenToTauriEvent('settings', () => openSettings.mutate(null));
|
useListenToTauriEvent('settings', () => openSettings.mutate(null));
|
||||||
|
|
||||||
@@ -56,6 +59,13 @@ export function SettingsDropdown() {
|
|||||||
onSelect: () => exportData.mutate(),
|
onSelect: () => exportData.mutate(),
|
||||||
},
|
},
|
||||||
{ type: 'separator', label: `Yaak v${appInfo.version}` },
|
{ type: 'separator', label: `Yaak v${appInfo.version}` },
|
||||||
|
{
|
||||||
|
label: 'Purchase License',
|
||||||
|
color: 'success',
|
||||||
|
hidden: check.data == null || check.data.type === 'commercial_use',
|
||||||
|
leftSlot: <Icon icon="circle_dollar_sign" />,
|
||||||
|
onSelect: () => openSettings.mutate(SettingsTab.License),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Check for Updates',
|
label: 'Check for Updates',
|
||||||
leftSlot: <Icon icon="update" />,
|
leftSlot: <Icon icon="update" />,
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export type DropdownItemDefault = {
|
|||||||
label: ReactNode;
|
label: ReactNode;
|
||||||
hotKeyAction?: HotkeyAction;
|
hotKeyAction?: HotkeyAction;
|
||||||
hotKeyLabelOnly?: boolean;
|
hotKeyLabelOnly?: boolean;
|
||||||
color?: 'default' | 'danger' | 'info' | 'warning' | 'notice' | 'success';
|
color?: 'default' | 'primary' | 'danger' | 'info' | 'warning' | 'notice' | 'success';
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
leftSlot?: ReactNode;
|
leftSlot?: ReactNode;
|
||||||
@@ -645,6 +645,7 @@ function MenuItem({ className, focused, onFocus, item, onSelect, ...props }: Men
|
|||||||
'min-w-[8rem] outline-none px-2 mx-1.5 flex whitespace-nowrap',
|
'min-w-[8rem] outline-none px-2 mx-1.5 flex whitespace-nowrap',
|
||||||
'focus:bg-surface-highlight focus:text rounded',
|
'focus:bg-surface-highlight focus:text rounded',
|
||||||
item.color === 'danger' && '!text-danger',
|
item.color === 'danger' && '!text-danger',
|
||||||
|
item.color === 'primary' && '!text-primary',
|
||||||
item.color === 'success' && '!text-success',
|
item.color === 'success' && '!text-success',
|
||||||
item.color === 'warning' && '!text-warning',
|
item.color === 'warning' && '!text-warning',
|
||||||
item.color === 'notice' && '!text-notice',
|
item.color === 'notice' && '!text-notice',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const icons = {
|
|||||||
alert_triangle: lucide.AlertTriangleIcon,
|
alert_triangle: lucide.AlertTriangleIcon,
|
||||||
archive: lucide.ArchiveIcon,
|
archive: lucide.ArchiveIcon,
|
||||||
arrow_big_down_dash: lucide.ArrowBigDownDashIcon,
|
arrow_big_down_dash: lucide.ArrowBigDownDashIcon,
|
||||||
|
circle_dollar_sign: lucide.CircleDollarSignIcon,
|
||||||
arrow_right_circle: lucide.ArrowRightCircleIcon,
|
arrow_right_circle: lucide.ArrowRightCircleIcon,
|
||||||
arrow_big_left_dash: lucide.ArrowBigLeftDashIcon,
|
arrow_big_left_dash: lucide.ArrowBigLeftDashIcon,
|
||||||
arrow_big_right: lucide.ArrowBigRightIcon,
|
arrow_big_right: lucide.ArrowBigRightIcon,
|
||||||
|
|||||||
Reference in New Issue
Block a user