update license validation & urls
Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com>
This commit is contained in:
+11
-9
@@ -1,5 +1,6 @@
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { fetch } from '@tauri-apps/plugin-http'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { usePersistedStore } from './store'
|
||||
|
||||
export async function validateLicense(licenseKey: string) {
|
||||
@@ -20,11 +21,12 @@ export async function validateLicense(licenseKey: string) {
|
||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||
}
|
||||
|
||||
const validationResponse = await fetch('https://rcloneui.com/api/v1/validate', {
|
||||
const validationResponse = await fetch('https://rcloneui.com/api/v2/validate', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
licenseKey,
|
||||
id,
|
||||
platform: platform(),
|
||||
}),
|
||||
})
|
||||
.then((r) => r.json())
|
||||
@@ -49,21 +51,21 @@ export async function validateLicense(licenseKey: string) {
|
||||
console.log('[validateLicense] license validated')
|
||||
}
|
||||
|
||||
export async function revokeLicense(licenseKey: string) {
|
||||
console.log('[revokeLicense]')
|
||||
export async function revokeMachineLicense(licenseKey: string) {
|
||||
console.log('[revokeMachineLicense]')
|
||||
|
||||
let id
|
||||
|
||||
try {
|
||||
id = await invoke('get_uid')
|
||||
} catch (e) {
|
||||
console.error('[revokeLicense] failed to build unique identifier')
|
||||
console.error('[revokeMachineLicense] failed to build unique identifier')
|
||||
console.error(JSON.stringify(e))
|
||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
console.error('[revokeLicense] missing unique identifier')
|
||||
console.error('[revokeMachineLicense] missing unique identifier')
|
||||
throw new Error('Failed to build unique identifier. Please try again later.')
|
||||
}
|
||||
|
||||
@@ -76,22 +78,22 @@ export async function revokeLicense(licenseKey: string) {
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.catch((e) => {
|
||||
console.error('[revokeLicense] failed to revoke license, fetch failed')
|
||||
console.error('[revokeMachineLicense] failed to revoke license, fetch failed')
|
||||
console.error(JSON.stringify(e))
|
||||
throw new Error('Failed to revoke license. Are you connected to the internet?')
|
||||
})
|
||||
|
||||
if (revocationResponse.error) {
|
||||
console.error('[revokeLicense] failed to revoke license, has error response')
|
||||
console.error('[revokeMachineLicense] failed to revoke license, has error response')
|
||||
throw new Error(revocationResponse.error)
|
||||
}
|
||||
|
||||
if (!revocationResponse.revoked) {
|
||||
console.error('[revokeLicense] failed to revoke license, missing revoked response')
|
||||
console.error('[revokeMachineLicense] failed to revoke license, missing revoked response')
|
||||
throw new Error('Failed to revoke license. Please check your license key and try again.')
|
||||
}
|
||||
|
||||
usePersistedStore.setState({ licenseKey: undefined, licenseValid: false })
|
||||
|
||||
console.log('[revokeLicense] license revoked')
|
||||
console.log('[revokeMachineLicense] license revoked')
|
||||
}
|
||||
|
||||
@@ -73,24 +73,22 @@ async function validateInstance() {
|
||||
try {
|
||||
await validateLicense(licenseKey)
|
||||
} catch (e) {
|
||||
usePersistedStore.setState({ licenseValid: false })
|
||||
|
||||
if (e instanceof Error) {
|
||||
await ask(e.message, {
|
||||
title: 'Error',
|
||||
await message(e.message, {
|
||||
title: 'Error Validating License',
|
||||
kind: 'error',
|
||||
okLabel: 'Exit',
|
||||
cancelLabel: '',
|
||||
okLabel: 'OK',
|
||||
})
|
||||
await exit(0)
|
||||
return
|
||||
}
|
||||
|
||||
await ask('An error occurred while validating your license. Please try again.', {
|
||||
await message('An error occurred while validating your license. Please try again.', {
|
||||
title: 'Error',
|
||||
kind: 'error',
|
||||
okLabel: 'Exit',
|
||||
cancelLabel: '',
|
||||
okLabel: 'OK',
|
||||
})
|
||||
await exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -285,8 +285,32 @@
|
||||
{
|
||||
"url": "https://github.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://raw.githubusercontent.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://rcloneui.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://stripe.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://buy.stripe.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://checkout.stripe.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://js.stripe.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://donate.stripe.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://payments.stripe.com/**"
|
||||
},
|
||||
{
|
||||
"url": "https://checkout.link.com/**"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+60
-63
@@ -13,6 +13,7 @@ import {
|
||||
Tab,
|
||||
Tabs,
|
||||
Textarea,
|
||||
cn,
|
||||
} from '@heroui/react'
|
||||
import { getTauriVersion, getVersion as getUiVersion } from '@tauri-apps/api/app'
|
||||
import {
|
||||
@@ -45,8 +46,14 @@ import {
|
||||
ServerIcon,
|
||||
Trash2Icon,
|
||||
} from 'lucide-react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { revokeLicense, validateLicense } from '../../lib/license'
|
||||
import {
|
||||
type DetailedHTMLProps,
|
||||
type HTMLAttributes,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { revokeMachineLicense, validateLicense } from '../../lib/license'
|
||||
import { deleteRemote, getVersion as getCliVersion, getVersion } from '../../lib/rclone/api'
|
||||
import { getConfigPath, getDefaultPaths } from '../../lib/rclone/common'
|
||||
import { usePersistedStore, useStore } from '../../lib/store'
|
||||
@@ -58,6 +65,15 @@ import RemoteCreateDrawer from '../components/RemoteCreateDrawer'
|
||||
import RemoteDefaultsDrawer from '../components/RemoteDefaultsDrawer'
|
||||
import RemoteEditDrawer from '../components/RemoteEditDrawer'
|
||||
|
||||
declare global {
|
||||
// biome-ignore lint/style/noNamespace: <explanation>
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
'stripe-pricing-table': DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Settings() {
|
||||
const settingsPass = usePersistedStore((state) => state.settingsPass)
|
||||
|
||||
@@ -550,13 +566,30 @@ function LicenseSection() {
|
||||
const [isActivating, setIsActivating] = useState(false)
|
||||
const [licenseKeyInput, setLicenseKeyInput] = useState('')
|
||||
|
||||
const [showPricingTable, setShowPricingTable] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
setLicenseKeyInput(licenseKey || '')
|
||||
setIsLicenseEditable(!licenseKey)
|
||||
}, [licenseKey])
|
||||
|
||||
useEffect(() => {
|
||||
const script = document.createElement('script')
|
||||
script.src = 'https://js.stripe.com/v3/pricing-table.js'
|
||||
script.async = true
|
||||
document.body.appendChild(script)
|
||||
const cancelTimeout = setTimeout(() => {
|
||||
setShowPricingTable(true)
|
||||
}, 1000)
|
||||
return () => {
|
||||
clearTimeout(cancelTimeout)
|
||||
setShowPricingTable(false)
|
||||
document.body.removeChild(script)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-10">
|
||||
<div className="flex flex-col gap-8">
|
||||
<BaseHeader title="License" />
|
||||
|
||||
<div className="flex flex-row justify-center w-full gap-8 px-8">
|
||||
@@ -654,7 +687,7 @@ function LicenseSection() {
|
||||
|
||||
setIsRevoking(true)
|
||||
try {
|
||||
await revokeLicense(licenseKeyInput)
|
||||
await revokeMachineLicense(licenseKeyInput)
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
await ask(e.message, {
|
||||
@@ -689,65 +722,17 @@ function LicenseSection() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-row justify-center w-full gap-8 px-8">
|
||||
<div className="flex flex-col items-end w-2/6 gap-2 bg-transparent-500">
|
||||
<h3 className="font-medium">Buy</h3>
|
||||
|
||||
<p className="text-xs text-neutral-500 text-end">
|
||||
Includes access to future features and updates.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col w-4/6 gap-3 bg-transparent-500">
|
||||
<Button
|
||||
size="lg"
|
||||
fullWidth={true}
|
||||
color="primary"
|
||||
variant="shadow"
|
||||
onPress={async () => {
|
||||
await openUrl('https://buy.stripe.com/3csbKIb1t433a8obII')
|
||||
}}
|
||||
>
|
||||
Lifetime License — $7
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'w-full overflow-hidden border-0 border-red-500 left-28 h-[470px] opacity-0 transition-opacity duration-300 ease-in-out',
|
||||
showPricingTable && 'opacity-100'
|
||||
)}
|
||||
>
|
||||
<stripe-pricing-table
|
||||
pricing-table-id="prctbl_1RvnumE0hPdsH0naQ6l8Rd86"
|
||||
publishable-key="pk_live_51QmUqyE0hPdsH0naBICHzb0j5O5eTKyYnY72nOaS6aT99y3EBeCOyeihI2xX05D6cczifqPsX6vHhor8ozSblXPl00LqNwMxBE"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* <div className="flex flex-row justify-center w-full gap-8 px-8">
|
||||
<div className="flex flex-col items-end w-2/6 gap-2 bg-transparent-500">
|
||||
<h3 className="font-medium">Features</h3>
|
||||
<p className="text-xs text-neutral-500 text-end">What you get with a license</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col w-4/6 gap-2 bg-transparent-500">
|
||||
<Card className="border-none bg-background/60 dark:bg-default-100/60">
|
||||
<CardBody>
|
||||
<ul className="flex flex-col gap-3">
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckIcon className="w-5 h-5 text-green-500" />
|
||||
<span>Work with more than 3 remotes</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckIcon className="w-5 h-5 text-green-500" />
|
||||
<span>Runs on up to 5 devices</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckIcon className="w-5 h-5 text-green-500" />
|
||||
<span>File Commander</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckIcon className="w-5 h-5 text-green-500" />
|
||||
<span>Mobile Client</span>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<CheckIcon className="w-5 h-5 text-green-500" />
|
||||
<span>Supporting Open Source</span>
|
||||
</li>
|
||||
</ul>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -917,6 +902,8 @@ function RemotesSection() {
|
||||
}
|
||||
|
||||
function ConfigSection() {
|
||||
const licenseValid = usePersistedStore((state) => state.licenseValid)
|
||||
|
||||
const configFiles = usePersistedStore((state) => state.configFiles)
|
||||
const activeConfigFile = usePersistedStore((state) => state.activeConfigFile)
|
||||
|
||||
@@ -938,10 +925,20 @@ function ConfigSection() {
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu
|
||||
onAction={(key) => {
|
||||
setTimeout(() => {
|
||||
setTimeout(async () => {
|
||||
if (key === 'import') {
|
||||
setIsCreateDrawerOpen(true)
|
||||
} else {
|
||||
if (!licenseValid) {
|
||||
await message(
|
||||
'Community version does not support syncing configs.',
|
||||
{
|
||||
title: 'Missing license',
|
||||
kind: 'error',
|
||||
}
|
||||
)
|
||||
return
|
||||
}
|
||||
setIsSyncDrawerOpen(true)
|
||||
}
|
||||
}, 100)
|
||||
|
||||
Reference in New Issue
Block a user