mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-28 20:21:52 +01:00
License and updater Cargo features (#258)
This commit is contained in:
20
src-web/components/CargoFeature.tsx
Normal file
20
src-web/components/CargoFeature.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { appInfo } from '../lib/appInfo';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
feature: 'updater' | 'license';
|
||||
}
|
||||
|
||||
const featureMap: Record<Props['feature'], boolean> = {
|
||||
updater: appInfo.featureUpdater,
|
||||
license: appInfo.featureLicense,
|
||||
};
|
||||
|
||||
export function CargoFeature({ children, feature }: Props) {
|
||||
if (featureMap[feature]) {
|
||||
return <>{children}</>;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { useAtomValue } from 'jotai';
|
||||
import type { ReactNode } from 'react';
|
||||
import { openSettings } from '../commands/openSettings';
|
||||
import { appInfo } from '../lib/appInfo';
|
||||
import { CargoFeature } from './CargoFeature';
|
||||
import { BadgeButton } from './core/BadgeButton';
|
||||
import type { ButtonProps } from './core/Button';
|
||||
|
||||
@@ -19,6 +20,14 @@ const details: Record<
|
||||
};
|
||||
|
||||
export function LicenseBadge() {
|
||||
return (
|
||||
<CargoFeature feature="license">
|
||||
<LicenseBadgeCmp />
|
||||
</CargoFeature>
|
||||
);
|
||||
}
|
||||
|
||||
function LicenseBadgeCmp() {
|
||||
const { check } = useLicense();
|
||||
const settings = useAtomValue(settingsAtom);
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ import { type } from '@tauri-apps/plugin-os';
|
||||
import classNames from 'classnames';
|
||||
import React, { useState } from 'react';
|
||||
import { useKeyPressEvent } from 'react-use';
|
||||
import { appInfo } from '../../lib/appInfo';
|
||||
import { capitalize } from '../../lib/capitalize';
|
||||
import { HStack } from '../core/Stacks';
|
||||
import type { TabItem } from '../core/Tabs/Tabs';
|
||||
import { TabContent, Tabs } from '../core/Tabs/Tabs';
|
||||
import { HeaderSize } from '../HeaderSize';
|
||||
import { SettingsInterface } from './SettingsInterface';
|
||||
@@ -72,21 +74,27 @@ export default function Settings({ hide }: Props) {
|
||||
tabListClassName="min-w-[10rem] bg-surface x-theme-sidebar border-r border-border pl-3"
|
||||
label="Settings"
|
||||
onChangeValue={setTab}
|
||||
tabs={tabs.map((value) => ({ value, label: capitalize(value) }))}
|
||||
tabs={tabs.map(
|
||||
(value): TabItem => ({
|
||||
value,
|
||||
label: capitalize(value),
|
||||
hidden: !appInfo.featureLicense && value === TAB_LICENSE,
|
||||
}),
|
||||
)}
|
||||
>
|
||||
<TabContent value={TAB_GENERAL} className="overflow-y-auto h-full p-8">
|
||||
<TabContent value={TAB_GENERAL} className="overflow-y-auto h-full px-8 !py-4">
|
||||
<SettingsGeneral />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_INTERFACE} className="overflow-y-auto h-full p-8">
|
||||
<TabContent value={TAB_INTERFACE} className="overflow-y-auto h-full px-8 !py-4">
|
||||
<SettingsInterface />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_THEME} className="overflow-y-auto h-full p-8">
|
||||
<TabContent value={TAB_THEME} className="overflow-y-auto h-full px-8 !py-4">
|
||||
<SettingsTheme />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_PLUGINS} className="h-full grid grid-rows-1 p-8">
|
||||
<TabContent value={TAB_PLUGINS} className="h-full grid grid-rows-1 px-8 !py-4">
|
||||
<SettingsPlugins />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_PROXY} className="overflow-y-auto h-full p-8!">
|
||||
<TabContent value={TAB_PROXY} className="overflow-y-auto h-full px-8 !py-4">
|
||||
<SettingsProxy />
|
||||
</TabContent>
|
||||
<TabContent value={TAB_LICENSE} className="overflow-y-auto h-full px-8 !py-4">
|
||||
|
||||
@@ -6,6 +6,7 @@ import { activeWorkspaceAtom } from '../../hooks/useActiveWorkspace';
|
||||
import { appInfo } from '../../lib/appInfo';
|
||||
import { useCheckForUpdates } from '../../hooks/useCheckForUpdates';
|
||||
import { revealInFinderText } from '../../lib/reveal';
|
||||
import { CargoFeature } from '../CargoFeature';
|
||||
import { Checkbox } from '../core/Checkbox';
|
||||
import { Heading } from '../core/Heading';
|
||||
import { IconButton } from '../core/IconButton';
|
||||
@@ -26,43 +27,45 @@ export function SettingsGeneral() {
|
||||
|
||||
return (
|
||||
<VStack space={1.5} className="mb-4">
|
||||
<div className="grid grid-cols-[minmax(0,1fr)_auto] gap-1">
|
||||
<CargoFeature feature="updater">
|
||||
<div className="grid grid-cols-[minmax(0,1fr)_auto] gap-1">
|
||||
<Select
|
||||
name="updateChannel"
|
||||
label="Update Channel"
|
||||
labelPosition="left"
|
||||
labelClassName="w-[14rem]"
|
||||
size="sm"
|
||||
value={settings.updateChannel}
|
||||
onChange={(updateChannel) => patchModel(settings, { updateChannel })}
|
||||
options={[
|
||||
{ label: 'Stable', value: 'stable' },
|
||||
{ label: 'Beta (more frequent)', value: 'beta' },
|
||||
]}
|
||||
/>
|
||||
<IconButton
|
||||
variant="border"
|
||||
size="sm"
|
||||
title="Check for updates"
|
||||
icon="refresh"
|
||||
spin={checkForUpdates.isPending}
|
||||
onClick={() => checkForUpdates.mutateAsync()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Select
|
||||
name="updateChannel"
|
||||
label="Update Channel"
|
||||
name="autoupdate"
|
||||
value={settings.autoupdate ? 'auto' : 'manual'}
|
||||
label="Update Behavior"
|
||||
labelPosition="left"
|
||||
labelClassName="w-[14rem]"
|
||||
size="sm"
|
||||
value={settings.updateChannel}
|
||||
onChange={(updateChannel) => patchModel(settings, { updateChannel })}
|
||||
labelClassName="w-[14rem]"
|
||||
onChange={(v) => patchModel(settings, { autoupdate: v === 'auto' })}
|
||||
options={[
|
||||
{ label: 'Stable', value: 'stable' },
|
||||
{ label: 'Beta (more frequent)', value: 'beta' },
|
||||
{ label: 'Automatic', value: 'auto' },
|
||||
{ label: 'Manual', value: 'manual' },
|
||||
]}
|
||||
/>
|
||||
<IconButton
|
||||
variant="border"
|
||||
size="sm"
|
||||
title="Check for updates"
|
||||
icon="refresh"
|
||||
spin={checkForUpdates.isPending}
|
||||
onClick={() => checkForUpdates.mutateAsync()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Select
|
||||
name="autoupdate"
|
||||
value={settings.autoupdate ? 'auto' : 'manual'}
|
||||
label="Update Behavior"
|
||||
labelPosition="left"
|
||||
size="sm"
|
||||
labelClassName="w-[14rem]"
|
||||
onChange={(v) => patchModel(settings, { autoupdate: v === 'auto' })}
|
||||
options={[
|
||||
{ label: 'Automatic', value: 'auto' },
|
||||
{ label: 'Manual', value: 'manual' },
|
||||
]}
|
||||
/>
|
||||
</CargoFeature>
|
||||
|
||||
<Select
|
||||
name="switchWorkspaceBehavior"
|
||||
|
||||
@@ -4,6 +4,7 @@ import { differenceInDays } from 'date-fns';
|
||||
import React, { useState } from 'react';
|
||||
import { useToggle } from '../../hooks/useToggle';
|
||||
import { pluralizeCount } from '../../lib/pluralize';
|
||||
import { CargoFeature } from '../CargoFeature';
|
||||
import { Banner } from '../core/Banner';
|
||||
import { Button } from '../core/Button';
|
||||
import { Icon } from '../core/Icon';
|
||||
@@ -13,6 +14,14 @@ import { HStack, VStack } from '../core/Stacks';
|
||||
import { LocalImage } from '../LocalImage';
|
||||
|
||||
export function SettingsLicense() {
|
||||
return (
|
||||
<CargoFeature feature="license">
|
||||
<SettingsLicenseCmp />
|
||||
</CargoFeature>
|
||||
);
|
||||
}
|
||||
|
||||
function SettingsLicenseCmp() {
|
||||
const { check, activate, deactivate } = useLicense();
|
||||
const [key, setKey] = useState<string>('');
|
||||
const [activateFormVisible, toggleActivateFormVisible] = useToggle(false);
|
||||
|
||||
@@ -74,6 +74,7 @@ export function SettingsDropdown() {
|
||||
{
|
||||
label: 'Check for Updates',
|
||||
leftSlot: <Icon icon="update" />,
|
||||
hidden: !appInfo.featureUpdater,
|
||||
onSelect: () => checkForUpdates.mutate(),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ export type TabItem =
|
||||
| {
|
||||
value: string;
|
||||
label: string;
|
||||
hidden?: boolean;
|
||||
rightSlot?: ReactNode;
|
||||
}
|
||||
| {
|
||||
@@ -97,6 +98,10 @@ export function Tabs({
|
||||
)}
|
||||
>
|
||||
{tabs.map((t) => {
|
||||
if ('hidden' in t && t.hidden) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isActive = t.value === value;
|
||||
const btnClassName = classNames(
|
||||
'h-sm flex items-center rounded whitespace-nowrap',
|
||||
|
||||
Reference in New Issue
Block a user