private async void ScriptUpdateCommand_Executed(object sender, ExecutedRoutedEventArgs e) { // Force update of script interface controls (if changed) ScriptUpdateButton.Focus(); // Must be filtered by ScriptCommand_CanExecute before if (Model.WorkInProgress) { Global.Logger.SystemWrite(new LogInfo(LogState.CriticalError, $"Race condition with {nameof(Model.WorkInProgress)} happened in {nameof(ScriptUpdateCommand_Executed)}")); return; } // Get instances of Script and Project Script targetScript = Model.CurMainTree.Script; Project p = Model.CurMainTree.Script.Project; // Do not apply updateMultipleScript to MainScript, because users should use project update for this job. bool updateMultipleScript = targetScript.Type == ScriptType.Directory; if (!updateMultipleScript && !targetScript.IsUpdateable) { Global.Logger.SystemWrite(new LogInfo(LogState.CriticalError, $"Race condition with {nameof(Script.IsUpdateable)} happened in {nameof(ScriptUpdateCommand_Executed)}")); return; } // Define local variables Script[] targetScripts = null; // Update one script Script newScript = null; LogInfo updaterLog = null; // Update scripts Script[] newScripts = null; LogInfo[] updaterLogs = null; // Turn on progress ring Model.WorkInProgress = true; try { // Populate BuildTree ProjectTreeItemModel treeRoot = MainViewModel.PopulateOneTreeItem(targetScript, null, null); Model.BuildTreeItems.Clear(); if (updateMultipleScript) { // Update a list of scripts // We have to search in p.AllScripts rather than in ProjectTreeItemModel to find hidden scripts // (ProjectTreeItemModel only contains visible scripts) targetScripts = p.AllScripts .Where(x => x.TreePath.StartsWith(targetScript.TreePath, StringComparison.OrdinalIgnoreCase) && x.IsUpdateable) .ToArray(); MainViewModel.ScriptListToTreeViewModel(p, targetScripts, false, treeRoot); targetScripts = targetScripts.Where(x => x.Type != ScriptType.Directory).ToArray(); if (targetScripts.Length == 0) { // Ask user for confirmation MessageBox.Show(this, $"Directory [{targetScript.Title}] does not contain any scripts that are able to be updated.", "No updateable scripts", MessageBoxButton.OK, MessageBoxImage.Warning); return; } } Model.BuildTreeItems.Add(treeRoot); Model.CurBuildTree = null; Debug.Assert(updateMultipleScript && targetScript != null && targetScripts != null || !updateMultipleScript && targetScript != null && targetScripts == null, $"Check {updateMultipleScript}"); // Ask user for confirmation string targetScriptCountStr; if (updateMultipleScript) { targetScriptCountStr = targetScripts.Length == 1 ? "1 script" : $"{targetScripts.Length} scripts"; } else { targetScriptCountStr = $"script [{targetScript.Title}]"; } MessageBoxResult result = MessageBox.Show(this, $"Are you sure you want to update {targetScriptCountStr}?", "Continue?", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.No) { return; } // Switch to Build View Model.BuildScriptFullProgressVisibility = Visibility.Collapsed; Model.SwitchNormalBuildInterface = false; Stopwatch watch = Stopwatch.StartNew(); // Run Updater string customUserAgent = Global.Setting.General.UseCustomUserAgent ? Global.Setting.General.CustomUserAgent : null; FileUpdater updater = new FileUpdater(p, Model, customUserAgent); if (updateMultipleScript) // Update a list of scripts { (newScripts, updaterLogs) = await updater.UpdateScriptsAsync(targetScripts, true); Logger.SystemWrite(updaterLogs); } else { (newScript, updaterLog) = await updater.UpdateScriptAsync(targetScript, true); Logger.SystemWrite(updaterLog); } watch.Stop(); TimeSpan t = watch.Elapsed; Model.StatusBarText = $"Updated {targetScript.Title} ({t:h\\:mm\\:ss})"; } finally { // Turn off progress ring Model.BuildScriptFullProgressVisibility = Visibility.Visible; Model.WorkInProgress = false; // Build Ended, Switch to Normal View Model.SwitchNormalBuildInterface = true; Model.DisplayScript(Model.CurMainTree.Script); } // Report results if (updateMultipleScript) { // Updated multiple scripts PackIconMaterialKind msgBoxIcon = PackIconMaterialKind.Information; StringBuilder b = new StringBuilder(updaterLogs.Length + 6); if (0 < newScripts.Length) { b.AppendLine($"Successfully updated [{newScripts.Length}] scripts"); } foreach (Script newSc in newScripts) { ProjectTreeItemModel node = Model.CurMainTree.FindScriptByRealPath(newSc.RealPath); Debug.Assert(node != null, "Internal error with MainTree management"); Model.PostRefreshScript(node, newSc); b.AppendLine($"- {newSc.Title}"); } LogInfo[] errorLogs = updaterLogs.Where(x => x.State == LogState.Error).ToArray(); if (0 < errorLogs.Length) { // Failure if (0 < newScripts.Length) { b.AppendLine(); } b.AppendLine($"Failed to update [{targetScripts.Length - newScripts.Length}] scripts"); foreach (LogInfo log in errorLogs) { b.AppendLine($"- {log.Message}"); } msgBoxIcon = PackIconMaterialKind.Alert; } const string msgTitle = "Script Update Report"; TextViewDialog dialog = new TextViewDialog(this, msgTitle, msgTitle, b.ToString(), msgBoxIcon); dialog.ShowDialog(); } else { // Updated single script if (newScript != null) { // Success ProjectTreeItemModel node = Model.CurMainTree.FindScriptByRealPath(newScript.RealPath); Debug.Assert(node != null, "Internal error with MainTree management"); Model.PostRefreshScript(node, newScript); MessageBox.Show(this, $"Successfully updated script {newScript.Title}", "Script Update Success", MessageBoxButton.OK, MessageBoxImage.Information); } else { // Failure StringBuilder b = new StringBuilder(updaterLogs.Length + 6); LogInfo[] errorLogs = updaterLogs.Where(x => x.State == LogState.Error).ToArray(); foreach (LogInfo log in errorLogs) { b.AppendLine($"- {log.Message}"); } MessageBox.Show(this, b.ToString(), "Script Update Failure", MessageBoxButton.OK, MessageBoxImage.Error); } } }
private async void CreateScriptMetaFilesCommand_Executed(object sender, ExecutedRoutedEventArgs e) { // Force update of script interface controls (if changed) ScriptUpdateButton.Focus(); // Must be filtered by ScriptCommand_CanExecute before if (Model.WorkInProgress) { Global.Logger.SystemWrite(new LogInfo(LogState.CriticalError, $"Race condition with {nameof(Model.WorkInProgress)} happened in {nameof(ScriptUpdateCommand_Executed)}")); return; } // Get instances of Script and Project Script targetScript = Model.CurMainTree.Script; Project p = Model.CurMainTree.Script.Project; // Define local variables Script[] targetScripts; List <LogInfo> logs = new List <LogInfo>(); // Turn on progress ring Model.WorkInProgress = true; int successCount = 0; int errorCount = 0; try { // Populate BuildTree ProjectTreeItemModel treeRoot = MainViewModel.PopulateOneTreeItem(targetScript, null, null); Model.BuildTreeItems.Clear(); if (targetScript.Type == ScriptType.Directory || targetScript.IsMainScript) { // Update a list of scripts // We have to search in p.AllScripts rather than in ProjectTreeItemModel to find hidden scripts // (ProjectTreeItemModel only contains visible scripts) if (targetScript.IsMainScript) { targetScripts = p.AllScripts.ToArray(); } else { targetScripts = p.AllScripts .Where(x => x.TreePath.StartsWith(targetScript.TreePath, StringComparison.OrdinalIgnoreCase)) .ToArray(); } MainViewModel.ScriptListToTreeViewModel(p, targetScripts, false, treeRoot); targetScripts = targetScripts.Where(x => x.Type != ScriptType.Directory).ToArray(); if (targetScripts.Length == 0) { // Ask user for confirmation MessageBox.Show(this, $"Directory [{targetScript.Title}] does not contain any scripts.", "No child scripts", MessageBoxButton.OK, MessageBoxImage.Warning); return; } } else { targetScripts = new Script[] { targetScript }; } Model.BuildTreeItems.Add(treeRoot); Model.CurBuildTree = null; // Switch to Build View Model.BuildScriptProgressVisibility = Visibility.Collapsed; Model.BuildFullProgressMax = targetScripts.Length; Model.BuildFullProgressValue = 0; Model.SwitchNormalBuildInterface = false; // I do not know why, but this line must come after SwitchNormalBuildInterface. Model.BuildEchoMessage = "Creating meta files..."; Stopwatch watch = Stopwatch.StartNew(); // Run Updater int idx = 0; foreach (Script sc in targetScripts) { // Display script information idx += 1; Model.BuildFullProgressValue = idx; Model.DisplayScriptTexts(sc, null); Model.ScriptTitleText = Model.ScriptTitleText; Model.BuildEchoMessage = $"Creating meta files... ({idx * 100 / targetScripts.Length}%)"; Application.Current?.Dispatcher?.BeginInvoke((Action)(() => { Model.DisplayScriptLogo(sc); // BuildTree is empty -> return if (Model.BuildTreeItems.Count == 0) { return; } if (Model.CurBuildTree != null) { Model.CurBuildTree.Focus = false; } Model.CurBuildTree = ProjectTreeItemModel.FindScriptByRealPath(Model.BuildTreeItems[0], sc.RealPath); if (Model.CurBuildTree != null) { Model.CurBuildTree.Focus = true; } })); // Do the real job string destJsonFile = Path.ChangeExtension(sc.RealPath, ".meta.json"); try { await UpdateJson.CreateScriptUpdateJsonAsync(sc, destJsonFile); logs.Add(new LogInfo(LogState.Success, $"Created meta file for [{sc.Title}]")); successCount += 1; } catch (Exception ex) { logs.Add(new LogInfo(LogState.Error, $"Unable to create meta file for [{sc.Title}] - {Logger.LogExceptionMessage(ex)}")); errorCount += 1; } } // Log messages Logger.SystemWrite(logs); watch.Stop(); TimeSpan t = watch.Elapsed; Model.StatusBarText = $"Updated {targetScript.Title} ({t:h\\:mm\\:ss})"; } finally { // Turn off progress ring Model.WorkInProgress = false; // Build Ended, Switch to Normal View Model.BuildScriptProgressVisibility = Visibility.Visible; Model.BuildEchoMessage = string.Empty; Model.SwitchNormalBuildInterface = true; Model.DisplayScript(Model.CurMainTree.Script); } PackIconMaterialKind msgBoxIcon = PackIconMaterialKind.Information; StringBuilder b = new StringBuilder(targetScripts.Length + 4); b.AppendLine($"Created [{successCount}] script meta files."); foreach (LogInfo log in logs.Where(x => x.State == LogState.Success)) { b.AppendLine($"- {log.Message}"); } if (0 < errorCount) { // Failure b.AppendLine(); b.AppendLine($"Failed to create [{errorCount}] script meta files"); foreach (LogInfo log in logs.Where(x => x.State == LogState.Error)) { b.AppendLine($"- {log.Message}"); } msgBoxIcon = PackIconMaterialKind.Alert; } const string msgTitle = "Script Meta Files Report"; TextViewDialog dialog = new TextViewDialog(this, msgTitle, msgTitle, b.ToString(), msgBoxIcon); dialog.ShowDialog(); }
public void ShowTextPreview(string script, string title) { var dialog = new TextViewDialog(script, title); dialog.ShowDialog(); }