-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Add guided tour functionality using driver.js #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
08ba8ca
1267da9
d5d84a7
d625f6e
8b185a5
7903308
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,6 @@ | ||||||||
| import { useEffect, useState } from "react"; | ||||||||
| import { useTranslation } from "react-i18next"; | ||||||||
| import "./driver.css"; | ||||||||
| import { | ||||||||
| Tabs, | ||||||||
| TabsContent, | ||||||||
|
|
@@ -13,6 +14,7 @@ import { | |||||||
| Send, | ||||||||
| History, | ||||||||
| Zap, | ||||||||
| HelpCircle, | ||||||||
| } from "lucide-react"; | ||||||||
| import { DeviceDetection } from "./components/DeviceDetection"; | ||||||||
| import { FileTransfer } from "./components/FileTransfer"; | ||||||||
|
|
@@ -29,6 +31,7 @@ import { AutoAcceptNotification } from './components/AutoAcceptNotification'; | |||||||
| import { TransferNotification } from './components/TransferNotification'; | ||||||||
| import { invoke } from "@tauri-apps/api/core"; | ||||||||
| import { listen } from "@tauri-apps/api/event"; | ||||||||
| import { useTour } from "./hooks/useTour"; | ||||||||
|
|
||||||||
| interface UploadFile { | ||||||||
| name: string; | ||||||||
|
|
@@ -52,9 +55,17 @@ type BackendTransferRecord = { | |||||||
|
|
||||||||
| function AppContent() { | ||||||||
| const { t } = useTranslation(); | ||||||||
|
|
||||||||
| const [selectedDevices, setSelectedDevices] = useState<any[]>([]); | ||||||||
| const [selectedFiles, setSelectedFiles] = useState<UploadFile[]>([]); | ||||||||
| const [activeTab, setActiveTab] = useState("transfer"); | ||||||||
|
|
||||||||
| const { startTour, checkAndStartTour } = useTour(setActiveTab); | ||||||||
|
|
||||||||
| useEffect(() => { | ||||||||
| checkAndStartTour(); | ||||||||
| }, []); | ||||||||
|
|
||||||||
| const [avgSpeedToday, setAvgSpeedToday] = useState<number>(0); | ||||||||
| const [route, setRoute] = useState<string>(window.location.hash || ""); | ||||||||
|
|
||||||||
|
|
@@ -146,7 +157,7 @@ function AppContent() { | |||||||
| </div> | ||||||||
|
|
||||||||
| {/* Header */} | ||||||||
| <header className="border-b backdrop-blur-md bg-background/85 dark:bg-background/70 sticky top-0 z-50 relative"> | ||||||||
| <header id="app-header" className="border-b backdrop-blur-md bg-background/85 dark:bg-background/70 sticky top-0 z-50 relative"> | ||||||||
| <div className="max-w-6xl mx-auto px-6 py-4"> | ||||||||
| <div className="flex items-center justify-between"> | ||||||||
| <div className="flex items-center gap-3"> | ||||||||
|
|
@@ -174,6 +185,14 @@ function AppContent() { | |||||||
| <div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" /> | ||||||||
| {t('common.online')} | ||||||||
| </Badge> | ||||||||
| <button | ||||||||
| id="start-tour-btn" | ||||||||
| onClick={startTour} | ||||||||
| className="p-2 rounded-full hover:bg-secondary/80 transition-colors" | ||||||||
| title={t('tour.start', 'Start Tour')} | ||||||||
|
||||||||
| title={t('tour.start', 'Start Tour')} | |
| title={t('tour.start', 'Start Tour')} | |
| aria-label={t('tour.start', 'Start Tour')} |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -105,7 +105,7 @@ export function DeviceDetection({ onDeviceSelect, selectedDevices }: DeviceDetec | |||||
| }; | ||||||
|
|
||||||
| return ( | ||||||
| <div className="space-y-6"> | ||||||
| <div id="device-list-container" className="space-y-6"> | ||||||
|
||||||
| <div id="device-list-container" className="space-y-6"> | |
| <div id="device-detection-container" className="space-y-6"> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
|
|
||
| /* Driver.js Custom Theme */ | ||
| .driverjs-theme { | ||
| background-color: var(--card) !important; | ||
| color: var(--card-foreground) !important; | ||
| border-radius: 1rem !important; | ||
| box-shadow: 0 10px 30px -10px rgba(0,0,0,0.2) !important; | ||
| border: 1px solid var(--border) !important; | ||
| font-family: inherit !important; | ||
| max-width: 350px !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-title { | ||
| font-size: 1.1rem !important; | ||
| font-weight: 600 !important; | ||
| margin-bottom: 0.5rem !important; | ||
| color: var(--primary) !important; | ||
| font-family: inherit !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-description { | ||
| font-size: 0.95rem !important; | ||
| line-height: 1.5 !important; | ||
| color: var(--muted-foreground) !important; | ||
| margin-bottom: 1rem !important; | ||
| font-family: inherit !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-footer { | ||
| display: flex !important; | ||
| gap: 0.5rem !important; | ||
| justify-content: flex-end !important; | ||
| margin-top: 0.5rem !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-btn { | ||
| border-radius: 0.5rem !important; | ||
| padding: 0.4rem 0.8rem !important; | ||
| font-size: 0.85rem !important; | ||
| font-weight: 500 !important; | ||
| transition: all 0.2s ease !important; | ||
| text-shadow: none !important; | ||
| border: none !important; | ||
| font-family: inherit !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-prev-btn { | ||
| background-color: var(--secondary) !important; | ||
| color: var(--secondary-foreground) !important; | ||
| border: 1px solid var(--border) !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-prev-btn:hover { | ||
| background-color: hsl(var(--secondary) / 0.8) !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-next-btn { | ||
| background-color: hsl(var(--primary)) !important; | ||
| color: hsl(var(--primary-foreground)) !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-next-btn:hover { | ||
| background-color: hsl(var(--primary) / 0.8) !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-close-btn { | ||
| color: hsl(var(--muted-foreground)) !important; | ||
| } | ||
|
|
||
| .driverjs-theme .driver-popover-progress-text { | ||
| color: hsl(var(--muted-foreground)) !important; | ||
| font-size: 0.75rem !important; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checkAndStartTour function is called in useEffect without being included in the dependency array. This violates React's exhaustive-deps rule and could lead to stale closures. Either add checkAndStartTour to the dependency array or wrap it with useCallback to ensure it has a stable reference.