preview
This commit is contained in:
@@ -32,3 +32,4 @@ scripts/release.md
|
||||
src-tauri/binaries/*
|
||||
!src-tauri/binaries/.gitkeep
|
||||
/public/out.js
|
||||
video
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { type ReactNode, createContext, useContext } from 'react'
|
||||
|
||||
const PreviewContext = createContext(false)
|
||||
|
||||
export function PreviewProvider({ children }: { children: ReactNode }) {
|
||||
return <PreviewContext.Provider value={true}>{children}</PreviewContext.Provider>
|
||||
}
|
||||
|
||||
export function useIsPreview(): boolean {
|
||||
return useContext(PreviewContext)
|
||||
}
|
||||
@@ -15,7 +15,10 @@ async function buildExternal() {
|
||||
// Compile TypeScript using local tsc
|
||||
console.log('[buildExternal] Compiling TypeScript...')
|
||||
execSync(
|
||||
'npx tsc main.ts --target es2020 --module esnext --moduleResolution bundler --listEmittedFiles',
|
||||
// skipLibCheck mirrors tsconfig.json: a bare-CLI tsc ignores tsconfig and
|
||||
// auto-includes every node_modules/@types package, and Remotion's transitive
|
||||
// @types/dom-webcodecs collides with the WebCodecs types TS now bundles in lib.dom.
|
||||
'npx tsc main.ts --target es2020 --module esnext --moduleResolution bundler --skipLibCheck --listEmittedFiles',
|
||||
{
|
||||
stdio: 'inherit',
|
||||
cwd: projectRoot,
|
||||
|
||||
@@ -17,6 +17,7 @@ import { platform } from '@tauri-apps/plugin-os'
|
||||
import { ExternalLinkIcon, RefreshCwIcon, SearchCheckIcon, SquareIcon } from 'lucide-react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { formatBytes } from '../../lib/format'
|
||||
import { useIsPreview } from '../../lib/preview'
|
||||
import { notify } from '../../lib/notifications'
|
||||
import { startBatch } from '../../lib/rclone/api'
|
||||
import rclone from '../../lib/rclone/client'
|
||||
@@ -35,6 +36,7 @@ export default function JobDetailsDrawer({
|
||||
onSelectJob?: (job: JobItem) => void
|
||||
}) {
|
||||
const queryClient = useQueryClient()
|
||||
const isPreview = useIsPreview()
|
||||
const [retryStatus, setRetryStatus] = useState<
|
||||
Map<string, { status: 'pending' | 'started' | 'error'; jobId?: number; error?: string }>
|
||||
>(new Map())
|
||||
@@ -302,6 +304,7 @@ export default function JobDetailsDrawer({
|
||||
>
|
||||
<Progress
|
||||
value={item.percentage}
|
||||
disableAnimation={isPreview}
|
||||
classNames={{
|
||||
base: 'overflow-hidden rounded-full max-w-lg',
|
||||
}}
|
||||
|
||||
@@ -37,6 +37,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { Group, Panel, Separator } from 'react-resizable-panels'
|
||||
import { onErrorDialog, reportError } from '../../lib/errors'
|
||||
import { getFsInfo } from '../../lib/format'
|
||||
import { useIsPreview } from '../../lib/preview'
|
||||
// import { Document, Page, pdfjs } from 'react-pdf'
|
||||
import { formatBytes } from '../../lib/format.ts'
|
||||
import { notify } from '../../lib/notifications'
|
||||
@@ -524,6 +525,7 @@ function TransferItem({
|
||||
}
|
||||
status: 'transferring' | 'checking' | 'done' | 'error'
|
||||
}) {
|
||||
const isPreview = useIsPreview()
|
||||
const fileName = item.name?.split('/').pop() || item.name || 'Unknown'
|
||||
|
||||
return (
|
||||
@@ -562,6 +564,7 @@ function TransferItem({
|
||||
<div className="flex items-center gap-2">
|
||||
<Progress
|
||||
value={item.percentage || 0}
|
||||
disableAnimation={isPreview}
|
||||
size="sm"
|
||||
color={status === 'checking' ? 'warning' : 'primary'}
|
||||
className="flex-1"
|
||||
|
||||
@@ -275,12 +275,12 @@ export default function Delete() {
|
||||
{supportsPurge && (
|
||||
<Alert
|
||||
color="primary"
|
||||
title="LET ME SHARE A TIP"
|
||||
title="LET ME SHARE A TIP!"
|
||||
variant="faded"
|
||||
className="min-h-none h-fit max-h-fit"
|
||||
>
|
||||
If you're deleting a entire folder, "{sourceRemoteName}" supports Purge
|
||||
which is more efficient!
|
||||
which is more efficient.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
@@ -303,7 +303,6 @@ export default function Delete() {
|
||||
buttonText={buttonText}
|
||||
buttonIcon={buttonIcon}
|
||||
newLabel="NEW DELETE"
|
||||
newButtonPrimary={false}
|
||||
showViewTransfers={false}
|
||||
resetPathsLabel="Reset Path"
|
||||
onResetPaths={handleResetPaths}
|
||||
|
||||
@@ -91,7 +91,7 @@ export default function NotificationsSection() {
|
||||
/>
|
||||
))}
|
||||
<DummyProviderCard
|
||||
label="Telegram (bot-less)"
|
||||
label="Telegram (botless)"
|
||||
description="Get messages without your own bot"
|
||||
icon={<TelegramIcon className="text-sky-500 size-8 shrink-0" />}
|
||||
onPress={() =>
|
||||
@@ -166,6 +166,7 @@ function ProviderCard({
|
||||
onPress={onPress}
|
||||
className="h-24 bg-content2"
|
||||
data-focus-visible="false"
|
||||
data-provider={provider}
|
||||
>
|
||||
<CardBody className="relative flex flex-row items-center gap-3 px-4">
|
||||
<ProviderIcon
|
||||
|
||||
@@ -181,7 +181,7 @@ export default function RemotesSection() {
|
||||
if (remotes.length === 0 && !creatingDrawerOpen) {
|
||||
return withRoot(
|
||||
<div className="flex flex-col items-center justify-center gap-8">
|
||||
<h1 className="text-2xl font-bold">No remotes found</h1>
|
||||
<h1 className="text-2xl font-bold">Add your first remote!</h1>
|
||||
<Button
|
||||
onPress={() => setCreatingDrawerOpen(true)}
|
||||
color="primary"
|
||||
@@ -449,6 +449,7 @@ function RemoteCard({
|
||||
return (
|
||||
<Card
|
||||
key={remote}
|
||||
data-remote={remote}
|
||||
shadow="sm"
|
||||
isBlurred={true}
|
||||
className="w-full h-20 border-[0.5px] dark:border-none border-divider bg-content3/50 dark:bg-content2/90"
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
import { LOCAL_HOST_ID } from '../../../lib/hosts'
|
||||
import { useIsPreview } from '../../../lib/preview'
|
||||
import rclone from '../../../lib/rclone/client'
|
||||
import { useStore } from '../../../store/memory'
|
||||
import { useCurrentHost, usePersistedStore } from '../../../store/persisted'
|
||||
@@ -36,6 +37,7 @@ import RemotesSection from './RemotesSection'
|
||||
|
||||
export default function Settings() {
|
||||
const [searchParams] = useSearchParams()
|
||||
const isPreview = useIsPreview()
|
||||
const settingsPass = usePersistedStore((state) => state.settingsPass)
|
||||
const currentHost = useCurrentHost()
|
||||
const isRestartingRclone = useStore((state) => state.isRestartingRclone)
|
||||
@@ -144,8 +146,10 @@ export default function Settings() {
|
||||
className="flex-shrink-0 h-screen px-2 py-4 overflow-y-auto border-r w-52 dark:bg-transparent bg-content2 border-divider dark:border-neutral-700"
|
||||
classNames={{
|
||||
// pb clears the fixed version bar (and the connected-host strip above it) so the
|
||||
// last tabs stay reachable once the list scrolls.
|
||||
tabList: 'w-full gap-3 pb-10' + (platform() === 'macos' ? ' pt-6' : ''),
|
||||
// last tabs stay reachable once the list scrolls. pt-6 clears macOS's
|
||||
tabList:
|
||||
'w-full gap-3 pb-10' +
|
||||
(platform() === 'macos' && !isPreview ? ' pt-6' : ''),
|
||||
tab: 'h-14 justify-start rounded-large',
|
||||
tabContent: 'pl-8',
|
||||
}}
|
||||
@@ -316,6 +320,7 @@ export default function Settings() {
|
||||
>
|
||||
<ProxySection />
|
||||
</Tab>
|
||||
{!isPreview && (
|
||||
<Tab
|
||||
key="license"
|
||||
title={
|
||||
@@ -329,6 +334,7 @@ export default function Settings() {
|
||||
>
|
||||
<LicenseSection />
|
||||
</Tab>
|
||||
)}
|
||||
<Tab
|
||||
key="about"
|
||||
title={
|
||||
@@ -352,10 +358,15 @@ export default function Settings() {
|
||||
)}
|
||||
<div className="absolute bottom-0 left-0 flex flex-col h-12 gap-4 p-4 border-t border-r w-52 bg-content3 dark:bg-content1 border-divider dark:border-neutral-700">
|
||||
<p
|
||||
className="text-[10px] text-center text-neutral-500 hover:text-neutral-400 cursor-pointer"
|
||||
className={cn(
|
||||
'text-[10px] text-center cursor-pointer',
|
||||
isPreview
|
||||
? 'text-white font-semibold'
|
||||
: 'text-neutral-500 hover:text-neutral-400 '
|
||||
)}
|
||||
onClick={() => openUrl('https://github.com/rclone-ui/rclone-ui')}
|
||||
>
|
||||
UI v{uiVersion}, CLI v{cliVersion}
|
||||
{isPreview ? 'rcloneui.com' : `UI v${uiVersion}, CLI v${cliVersion}`}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { message } from '@tauri-apps/plugin-dialog'
|
||||
import { ChevronRightIcon, RefreshCcwIcon, SearchCheckIcon } from 'lucide-react'
|
||||
import { startTransition, useCallback, useMemo, useState } from 'react'
|
||||
import { buildReadablePathMultiple, formatBytes } from '../../lib/format'
|
||||
import { useIsPreview } from '../../lib/preview'
|
||||
import { listTransfers } from '../../lib/rclone/api'
|
||||
import { usePersistedStore } from '../../store/persisted'
|
||||
import type { JobItem } from '../../types/jobs'
|
||||
@@ -121,6 +122,7 @@ export default function Transfers() {
|
||||
}
|
||||
|
||||
function JobCard({ job, onSelect }: { job: JobItem; onSelect: (job: JobItem) => void }) {
|
||||
const isPreview = useIsPreview()
|
||||
return (
|
||||
<Card
|
||||
key={job.id}
|
||||
@@ -191,7 +193,8 @@ function JobCard({ job, onSelect }: { job: JobItem; onSelect: (job: JobItem) =>
|
||||
>
|
||||
<Progress
|
||||
value={job.progress}
|
||||
isStriped={true}
|
||||
disableAnimation={isPreview}
|
||||
isStriped={!(job.isChecking && job.totalBytes === 0)}
|
||||
isIndeterminate={job.isChecking && job.totalBytes === 0}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
@@ -6,6 +6,7 @@ export default {
|
||||
'./index.html',
|
||||
'./src/**/*.{js,ts,jsx,tsx}',
|
||||
'./lib/**/*.{js,ts,jsx,tsx}',
|
||||
'./video/**/*.{js,ts,jsx,tsx}',
|
||||
'./node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}',
|
||||
],
|
||||
theme: {
|
||||
|
||||
Reference in New Issue
Block a user