88} from "@/components/ui/dialog" ;
99import { PlayersContext } from "@/contexts/players-context" ;
1010import { parseSaveFile } from "@/lib/file" ;
11- import { useContext } from "react" ;
11+ import { useContext , useState } from "react" ;
1212import Dropzone from "react-dropzone" ;
1313import { toast } from "sonner" ;
1414import { Button } from "../ui/button" ;
@@ -18,8 +18,121 @@ interface Props {
1818 setOpen : ( open : boolean ) => void ;
1919}
2020
21+ interface InstructionsDialogProps {
22+ open : boolean ;
23+ setOpen : ( open : boolean ) => void ;
24+ platform : "Mac" | "Windows" | "Linux" | "Switch" ;
25+ }
26+
27+ const InstructionsDialog = ( {
28+ open,
29+ setOpen,
30+ platform,
31+ } : InstructionsDialogProps ) => {
32+ const getInstructions = ( ) => {
33+ switch ( platform ) {
34+ case "Mac" :
35+ return {
36+ title : "Finding your save file on Mac" ,
37+ path : "~/.config/StardewValley/Saves" ,
38+ steps : [
39+ "1. Open Finder" ,
40+ "2. Press Cmd + Shift + G" ,
41+ "3. Paste this path: ~/.config/StardewValley/Saves" ,
42+ "4. Your save files will be in this folder" ,
43+ "5. Look for a file named with your farmer's name and a number (e.g. 'Farmer_123456789')" ,
44+ ] ,
45+ } ;
46+ case "Windows" :
47+ return {
48+ title : "Finding your save file on Windows" ,
49+ path : "%appdata%\\StardewValley\\Saves" ,
50+ steps : [
51+ "1. Press Windows key + R" ,
52+ "2. Paste this path: %appdata%\\StardewValley\\Saves" ,
53+ "3. Your save files will be in this folder" ,
54+ "4. Look for a file named with your farmer's name and a number (e.g. 'Farmer_123456789')" ,
55+ ] ,
56+ } ;
57+ case "Linux" :
58+ return {
59+ title : "Finding your save file on Linux" ,
60+ path : "~/.config/StardewValley/Saves" ,
61+ steps : [
62+ "1. Open your file manager" ,
63+ "2. Press Alt + F2" ,
64+ "3. Paste this path: ~/.config/StardewValley/Saves" ,
65+ "4. Your save files will be in this folder" ,
66+ "5. Look for a file named with your farmer's name and a number (e.g. 'Farmer_123456789')" ,
67+ ] ,
68+ } ;
69+ case "Switch" :
70+ return {
71+ title : "Nintendo Switch Save Files" ,
72+ path : "" ,
73+ steps : [
74+ "Unfortunately, we don't support direct save file uploading from Nintendo Switch unless your console is modded." ,
75+ "" ,
76+ "If you want to track your progress, you'll need to manually enter your achievements and progress in the editor." ,
77+ "" ,
78+ "We apologize for any inconvenience this may cause." ,
79+ ] ,
80+ } ;
81+ }
82+ } ;
83+
84+ const instructions = getInstructions ( ) ;
85+
86+ // Copy path to clipboard when dialog opens
87+ if ( open && instructions && instructions . path ) {
88+ navigator . clipboard . writeText ( instructions . path ) ;
89+ }
90+
91+ return (
92+ < Dialog open = { open } onOpenChange = { setOpen } >
93+ < DialogContent >
94+ < DialogHeader >
95+ < DialogTitle > { instructions . title } </ DialogTitle >
96+ </ DialogHeader >
97+ < DialogDescription className = "space-y-2" >
98+ { instructions . path && (
99+ < p className = "text-muted-foreground text-sm" >
100+ (We've already copied the path to your clipboard!)
101+ </ p >
102+ ) }
103+ { instructions . steps . map ( ( step , index ) => (
104+ < p key = { index } > { step } </ p >
105+ ) ) }
106+ </ DialogDescription >
107+ < DialogFooter className = "sm:justify-left flex flex-col gap-2 sm:flex-row" >
108+ { platform === "Switch" ? (
109+ < Button onClick = { ( ) => setOpen ( false ) } > Close</ Button >
110+ ) : (
111+ < >
112+ < Button variant = "secondary" asChild >
113+ < a
114+ href = "https://discord.gg/stardewapp"
115+ target = "_blank"
116+ rel = "noopener noreferrer"
117+ >
118+ I need more help...
119+ </ a >
120+ </ Button >
121+ < Button onClick = { ( ) => setOpen ( false ) } > I found it!</ Button >
122+ </ >
123+ ) }
124+ </ DialogFooter >
125+ </ DialogContent >
126+ </ Dialog >
127+ ) ;
128+ } ;
129+
21130export const UploadDialog = ( { open, setOpen } : Props ) => {
22131 const { activePlayer, uploadPlayers } = useContext ( PlayersContext ) ;
132+ const [ instructionsOpen , setInstructionsOpen ] = useState ( false ) ;
133+ const [ selectedPlatform , setSelectedPlatform ] = useState <
134+ "Mac" | "Windows" | "Linux" | "Switch"
135+ > ( "Mac" ) ;
23136
24137 const handleChange = ( file : File ) => {
25138 setOpen ( false ) ;
@@ -65,84 +178,95 @@ export const UploadDialog = ({ open, setOpen }: Props) => {
65178 } ;
66179
67180 return (
68- < Dialog open = { open } onOpenChange = { setOpen } >
69- < DialogContent >
70- < DialogHeader >
71- < DialogTitle > Upload your save file</ DialogTitle >
72- </ DialogHeader >
73- < DialogDescription >
74- < Dropzone
75- onDrop = { ( acceptedFiles ) => {
76- handleChange ( acceptedFiles [ 0 ] ) ;
77- } }
78- useFsAccessApi = { false }
79- >
80- { ( { getRootProps, getInputProps } ) => (
81- < >
82- < input className = "h-full w-full" { ...getInputProps ( ) } />
83- < div className = "h-[250px]" >
84- < div
85- { ...getRootProps ( ) }
86- className = "flex h-full w-full cursor-pointer select-none items-center justify-center rounded-lg border-2 border-dashed border-gray-800 dark:border-gray-400"
87- >
88- < div className = "select-text text-center" >
89- < p >
90- Drag and drop your save file here, or click to browse!
91- </ p >
92- < br > </ br >
93- < span className = "font-bold" >
94- Need help finding your save? Click below for
95- instructions!
96- </ span >
181+ < >
182+ < Dialog open = { open } onOpenChange = { setOpen } >
183+ < DialogContent >
184+ < DialogHeader >
185+ < DialogTitle > Upload your save file</ DialogTitle >
186+ </ DialogHeader >
187+ < DialogDescription >
188+ < Dropzone
189+ onDrop = { ( acceptedFiles ) => {
190+ handleChange ( acceptedFiles [ 0 ] ) ;
191+ } }
192+ useFsAccessApi = { false }
193+ >
194+ { ( { getRootProps, getInputProps } ) => (
195+ < >
196+ < input className = "h-full w-full" { ...getInputProps ( ) } />
197+ < div className = "h-[250px]" >
198+ < div
199+ { ...getRootProps ( ) }
200+ className = "flex h-full w-full cursor-pointer select-none items-center justify-center rounded-lg border-2 border-dashed border-gray-800 dark:border-gray-400"
201+ >
202+ < div className = "select-text text-center" >
203+ < p >
204+ Drag and drop your save file here, or click to browse!
205+ </ p >
206+ </ div >
97207 </ div >
98208 </ div >
99- </ div >
100- </ >
101- ) }
102- </ Dropzone >
103- </ DialogDescription >
104- < DialogFooter className = "flex w-full" >
105- < Button
106- variant = { "secondary" }
107- onClick = { ( ) => {
108- navigator . clipboard . writeText ( "~/.config/StardewValley/Saves" ) ;
109- toast . info ( "Copied the folder location to your clipboard!" , {
110- description :
111- "To go to this folder, press Cmd+Shift+G in Finder and paste the path. Your save will be located there." ,
112- } ) ;
113- } }
114- className = "w-full"
115- >
116- Find save on Mac
117- </ Button >
118- < Button
119- variant = { "secondary" }
120- onClick = { ( ) => {
121- navigator . clipboard . writeText ( "%appdata%\\StardewValley\\Saves" ) ;
122- toast . info ( "Copied the folder location to your clipboard!" , {
123- description :
124- "To go to this folder, press Windows key + R and paste the path. Your save will be located there." ,
125- } ) ;
126- } }
127- className = "w-full"
128- >
129- ... Windows
130- </ Button >
131- < Button
132- variant = { "secondary" }
133- onClick = { ( ) => {
134- navigator . clipboard . writeText ( "~/.config/StardewValley/Saves" ) ;
135- toast . info ( "Copied the folder location to your clipboard!" , {
136- description :
137- "To go to this folder, press Alt + F2 and paste the path. Your save will be located there." ,
138- } ) ;
139- } }
140- className = "w-full"
141- >
142- ... or Linux
143- </ Button >
144- </ DialogFooter >
145- </ DialogContent >
146- </ Dialog >
209+ </ >
210+ ) }
211+ </ Dropzone >
212+ </ DialogDescription >
213+ < div className = "space-y-4" >
214+ < div className = "text-left" >
215+ < p className = "font-medium" > Need help finding your save?</ p >
216+ < p className = "text-muted-foreground text-sm" >
217+ What do you play on?
218+ </ p >
219+ </ div >
220+ < div className = "grid grid-cols-2 gap-2" >
221+ < Button
222+ variant = { "secondary" }
223+ onClick = { ( ) => {
224+ setSelectedPlatform ( "Mac" ) ;
225+ setInstructionsOpen ( true ) ;
226+ } }
227+ className = "w-full"
228+ >
229+ Mac
230+ </ Button >
231+ < Button
232+ variant = { "secondary" }
233+ onClick = { ( ) => {
234+ setSelectedPlatform ( "Windows" ) ;
235+ setInstructionsOpen ( true ) ;
236+ } }
237+ className = "w-full"
238+ >
239+ Windows
240+ </ Button >
241+ < Button
242+ variant = { "secondary" }
243+ onClick = { ( ) => {
244+ setSelectedPlatform ( "Linux" ) ;
245+ setInstructionsOpen ( true ) ;
246+ } }
247+ className = "w-full"
248+ >
249+ Linux
250+ </ Button >
251+ < Button
252+ variant = { "secondary" }
253+ onClick = { ( ) => {
254+ setSelectedPlatform ( "Switch" ) ;
255+ setInstructionsOpen ( true ) ;
256+ } }
257+ className = "w-full"
258+ >
259+ Nintendo Switch
260+ </ Button >
261+ </ div >
262+ </ div >
263+ </ DialogContent >
264+ </ Dialog >
265+ < InstructionsDialog
266+ open = { instructionsOpen }
267+ setOpen = { setInstructionsOpen }
268+ platform = { selectedPlatform }
269+ />
270+ </ >
147271 ) ;
148272} ;
0 commit comments