@@ -17,6 +17,7 @@ public class Component : Category
1717 public string URL { get ; set ; }
1818 public string Hash { get ; set ; }
1919 public long Size { get ; set ; }
20+ public string LastUpdated { get ; set ; }
2021 public string Path { get ; set ; }
2122 public string [ ] Depends { get ; set ; } = new string [ ] { } ;
2223
@@ -79,6 +80,27 @@ public Component(XmlNode node) : base(node)
7980 Environment . Exit ( 1 ) ;
8081 }
8182
83+ // LastUpdated
84+
85+ long lastUpdated ;
86+
87+ if ( long . TryParse ( GetAttribute ( node , "date-modified" , true ) , out lastUpdated ) )
88+ {
89+ var dateTime = new DateTime ( 1970 , 1 , 1 , 0 , 0 , 0 , 0 ) . AddSeconds ( lastUpdated ) . ToLocalTime ( ) ;
90+
91+ LastUpdated = dateTime . ToShortDateString ( ) ;
92+ }
93+ else
94+ {
95+ MessageBox . Show (
96+ "An error occurred while parsing the component list XML. Please alert Flashpoint staff ASAP!\n \n " +
97+ $ "Description: Modified date of component \" { Title } \" is invalid",
98+ "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error
99+ ) ;
100+
101+ Environment . Exit ( 1 ) ;
102+ }
103+
82104 // Path
83105
84106 Path = GetAttribute ( node , "path" , false ) ;
@@ -150,36 +172,99 @@ public static class FPM
150172 {
151173 // Pointer to main form
152174 public static Main Main { get => ( Main ) Application . OpenForms [ "Main" ] ; }
175+ // Pointer to update check form
176+ public static UpdateCheck UpdateCheck { get => ( UpdateCheck ) Application . OpenForms [ "UpdateCheck" ] ; }
153177 // Internet location of component list XML
154- public static string ListURL { get => "https://nexus-dev.unstable.life/repository/development/components.xml" ; }
178+ public static string ListURL { get ; set ; } = "https://nexus-dev.unstable.life/repository/development/components.xml" ;
155179 // The parsed component list XML
156180 public static XmlDocument XmlTree { get ; set ; }
157181
182+ // Name of configuration file
183+ public static string ConfigFile { get => "fpm.cfg" ; }
184+
158185 // Check if Visual C++ 2015 x86 redistributable is installed
159186 public static bool RedistInstalled
160187 {
161188 get => Registry . LocalMachine . OpenSubKey ( "SOFTWARE\\ WOW6432Node\\ Microsoft\\ VisualStudio\\ 14.0\\ VC\\ Runtimes\\ X86" ) != null ;
162189 }
163190
164191 // Pointer to destination path textbox
192+ private static string destinationPath = "" ;
165193 public static string DestinationPath
166194 {
167- get { return Main . DestinationPath . Text ; }
168- set { Main . DestinationPath . Text = value ; }
195+ get { return destinationPath ; }
196+ set
197+ {
198+ if ( VerifyDestinationPath ( value ) )
199+ {
200+ destinationPath = value ;
201+
202+ if ( StartupMode != 2 )
203+ {
204+ Main . DestinationPath . Text = destinationPath ;
205+ }
206+ }
207+ }
169208 }
170209 // Pointer to source path textbox in Manage tab
210+ private static string sourcePath = "" ;
171211 public static string SourcePath
172212 {
173- get { return Main . SourcePath . Text ; }
174- set { Main . SourcePath . Text = value ; }
213+ get { return sourcePath ; }
214+ set
215+ {
216+ if ( VerifySourcePath ( value ) )
217+ {
218+ sourcePath = value ;
219+
220+ if ( StartupMode != 2 )
221+ {
222+ Main . SourcePath . Text = sourcePath ;
223+
224+ if ( ! Main . ComponentList2 . Enabled )
225+ {
226+ Main . ComponentList2 . Enabled = true ;
227+
228+ Main . UpdateButton . Enabled = true ;
229+ Main . ChangeButton . Enabled = true ;
230+
231+ Main . ManagerMessage2 . Text = "Click on a component to learn more about it." ;
232+
233+ Main . ComponentList2 . BeforeCheck += Main . ComponentList_BeforeCheck ;
234+ Main . ComponentList2 . AfterCheck += Main . ComponentList2_AfterCheck ;
235+ }
236+
237+ SyncManager ( true ) ;
238+ }
239+ }
240+ }
175241 }
176242 // Pointer to source path textbox in Remove tab
243+ private static string sourcePath2 = "" ;
177244 public static string SourcePath2
178245 {
179- get { return Main . SourcePath2 . Text ; }
180- set { Main . SourcePath2 . Text = value ; }
246+ get { return sourcePath2 ; }
247+ set
248+ {
249+ if ( VerifySourcePath ( value ) )
250+ {
251+ sourcePath2 = value ;
252+
253+ if ( StartupMode != 2 )
254+ {
255+ Main . SourcePath2 . Text = sourcePath2 ;
256+ Main . RemoveButton . Enabled = true ;
257+ }
258+ }
259+ }
181260 }
182261
262+ // Flag to control how the manager will start
263+ // 0 starts the manager normally
264+ // 1 starts the manager in the Manage Flashpoint tab
265+ // 2 starts the manager in the update window and exits once closed
266+ public static int StartupMode { get ; set ; } = 0 ;
267+
183268 // Flag to control how operation window will function
184269 // 0 is for downloading Flashpoint
185270 // 1 is for adding/removing components
@@ -224,14 +309,25 @@ public static class ComponentTracker
224309 public static List < Component > ToUpdate { get ; set ; } = new List < Component > ( ) ;
225310 }
226311
227- // Performs an operation on every node in the specified TreeView
228- public static void Iterate ( TreeNodeCollection parent , Action < TreeNode > action )
312+ // Performs an operation on every node in the specified TreeNodeCollection
313+ public static void IterateList ( TreeNodeCollection parent , Action < TreeNode > action )
229314 {
230315 foreach ( TreeNode childNode in parent )
231316 {
232317 action ( childNode ) ;
233318
234- Iterate ( childNode . Nodes , action ) ;
319+ IterateList ( childNode . Nodes , action ) ;
320+ }
321+ }
322+
323+ // Performs an operation on every node in the specified XmlNodeList
324+ public static void IterateXML ( XmlNodeList parent , Action < XmlNode > action )
325+ {
326+ foreach ( XmlNode childNode in parent )
327+ {
328+ action ( childNode ) ;
329+
330+ IterateXML ( childNode . ChildNodes , action ) ;
235331 }
236332 }
237333
@@ -296,21 +392,27 @@ public static void SyncManager(bool setCheckState = false)
296392 {
297393 ComponentTracker . Downloaded . Clear ( ) ;
298394
299- Iterate ( Main . ComponentList2 . Nodes , node =>
395+ IterateXML ( XmlTree . GetElementsByTagName ( "list" ) [ 0 ] . ChildNodes , node =>
300396 {
301- if ( node . Tag . GetType ( ) . ToString ( ) . EndsWith ( "Component" ) )
302- {
303- Component component = node . Tag as Component ;
304- string infoPath = Path . Combine ( SourcePath , "Components" , $ "{ component . ID } .txt") ;
397+ if ( node . Name != "component" ) return ;
305398
306- if ( File . Exists ( infoPath ) ) ComponentTracker . Downloaded . Add ( component ) ;
399+ Component component = new Component ( node ) ;
400+ string infoPath = Path . Combine ( SourcePath , "Components" , $ "{ component . ID } .txt") ;
307401
308- if ( setCheckState ) node . Checked = File . Exists ( infoPath ) ;
402+ if ( File . Exists ( infoPath ) ) ComponentTracker . Downloaded . Add ( component ) ;
403+
404+ if ( setCheckState && StartupMode != 2 )
405+ {
406+ TreeNode [ ] nodes = Main . ComponentList2 . Nodes . Find ( component . ID , true ) ;
407+ if ( nodes . Length > 0 ) nodes [ 0 ] . Checked = File . Exists ( infoPath ) ;
309408 }
310409 } ) ;
311410
312- SizeTracker . Downloaded = GetTotalSize ( Main . ComponentList2 ) ;
313- SizeTracker . ToChange = GetTotalSize ( Main . ComponentList2 ) ;
411+ if ( StartupMode != 2 )
412+ {
413+ SizeTracker . Downloaded = GetTotalSize ( Main . ComponentList2 ) ;
414+ SizeTracker . ToChange = GetTotalSize ( Main . ComponentList2 ) ;
415+ }
314416 }
315417
316418 // Deletes a file as well as any directories made empty by its deletion
@@ -336,8 +438,8 @@ public static void DeleteFileAndDirectories(string file)
336438 catch { }
337439 }
338440
339- // Checks if specified Flashpoint destination path is valid, and optionally updates its respective textbox
340- public static bool VerifyDestinationPath ( string path , bool updateText )
441+ // Checks if specified Flashpoint destination path is valid
442+ public static bool VerifyDestinationPath ( string path )
341443 {
342444 if ( ! Path . IsPathRooted ( path ) )
343445 {
@@ -366,8 +468,6 @@ public static bool VerifyDestinationPath(string path, bool updateText)
366468 }
367469 else
368470 {
369- if ( updateText ) DestinationPath = Path . Combine ( path , "Flashpoint" ) ;
370-
371471 return true ;
372472 }
373473
@@ -379,32 +479,27 @@ public static bool VerifyDestinationPath(string path, bool updateText)
379479 return false ;
380480 }
381481
382- // Checks if specified Flashpoint source path is valid, and optionally updates one of the textboxes
383- public static bool VerifySourcePath ( string path , int textBox = 0 )
482+ // Checks if specified Flashpoint source path is valid
483+ public static bool VerifySourcePath ( string path )
384484 {
385485 bool isFlashpoint = false ;
386486
387- Iterate ( Main . ComponentList . Nodes , node =>
487+ IterateXML ( XmlTree . GetElementsByTagName ( "list" ) [ 0 ] . ChildNodes , node =>
388488 {
389- if ( node . Tag . GetType ( ) . ToString ( ) . EndsWith ( "Component" ) )
390- {
391- Component component = node . Tag as Component ;
392- string infoPath = Path . Combine ( path , "Components" , $ "{ component . ID } .txt") ;
489+ if ( node . Name != "component" ) return ;
393490
394- if ( File . Exists ( infoPath ) )
395- {
396- isFlashpoint = true ;
491+ Component component = new Component ( node ) ;
492+ string infoPath = Path . Combine ( path , "Components" , $ "{ component . ID } .txt") ;
397493
398- return ;
399- }
494+ if ( File . Exists ( infoPath ) )
495+ {
496+ isFlashpoint = true ;
497+ return ;
400498 }
401499 } ) ;
402500
403501 if ( isFlashpoint )
404502 {
405- if ( textBox == 1 ) SourcePath = path ;
406- if ( textBox == 2 ) SourcePath2 = path ;
407-
408503 return true ;
409504 }
410505
@@ -421,7 +516,7 @@ public static bool CheckDependencies(TreeView sourceTree)
421516 List < string > missingDepends = new List < string > ( ) ;
422517
423518 // First, fill out a list of dependencies
424- Iterate ( sourceTree . Nodes , node =>
519+ IterateList ( sourceTree . Nodes , node =>
425520 {
426521 if ( node . Checked && node . Tag . GetType ( ) . ToString ( ) . EndsWith ( "Component" ) )
427522 {
@@ -440,7 +535,7 @@ public static bool CheckDependencies(TreeView sourceTree)
440535 } ) ;
441536
442537 // Then make sure they're all marked for installation
443- Iterate ( sourceTree . Nodes , node =>
538+ IterateList ( sourceTree . Nodes , node =>
444539 {
445540 if ( node . Tag . GetType ( ) . ToString ( ) . EndsWith ( "Component" ) )
446541 {
@@ -489,7 +584,7 @@ public static long GetTotalSize(TreeView sourceTree)
489584 {
490585 long size = 0 ;
491586
492- Iterate ( sourceTree . Nodes , node =>
587+ IterateList ( sourceTree . Nodes , node =>
493588 {
494589 if ( node . Checked && node . Tag . GetType ( ) . ToString ( ) . EndsWith ( "Component" ) )
495590 {
0 commit comments