|
@@ -0,0 +1,125 @@
|
|
|
+// Copyright (c) 2025 TerraByte Inc.
|
|
|
+//
|
|
|
+// A modal editor window that displays pull conflicts and allows the user
|
|
|
+// to select files to reset before proceeding.
|
|
|
+
|
|
|
+using System;
|
|
|
+using System.Linq;
|
|
|
+using UnityEditor;
|
|
|
+using UnityEngine;
|
|
|
+using Terra.Arbitrator.Services;
|
|
|
+using System.Collections.Generic;
|
|
|
+
|
|
|
+namespace Terra.Arbitrator.GUI
|
|
|
+{
|
|
|
+ public class ConflictResolutionWindow : EditorWindow
|
|
|
+ {
|
|
|
+ private List<string> _conflictingFiles;
|
|
|
+ private List<bool> _filesToReset;
|
|
|
+ private Vector2 _scrollPosition;
|
|
|
+ private Action<List<string>> _onCloseCallback;
|
|
|
+ private bool _callbackInvoked;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Shows a modal window to display pull conflicts and get user action.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="conflictingFiles">The list of files that have conflicts.</param>
|
|
|
+ /// <param name="onCloseCallback">A callback that provides the list of files the user selected to reset. If the user cancels, the list will be null.</param>
|
|
|
+ public static void ShowWindow(List<string> conflictingFiles, Action<List<string>> onCloseCallback)
|
|
|
+ {
|
|
|
+ var window = GetWindow<ConflictResolutionWindow>(true, "Pull Conflicts Detected", true);
|
|
|
+ window.minSize = new Vector2(600, 400);
|
|
|
+ window._conflictingFiles = conflictingFiles;
|
|
|
+ window._filesToReset = new List<bool>(new bool[conflictingFiles.Count]); // Initialize all to false
|
|
|
+ window._onCloseCallback = onCloseCallback;
|
|
|
+ window._callbackInvoked = false;
|
|
|
+ window.ShowModalUtility();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnGUI()
|
|
|
+ {
|
|
|
+ EditorGUILayout.HelpBox("A pull would result in conflicts with your local changes. To proceed with a clean pull, you must reset your local changes for the conflicting files listed below.", MessageType.Warning);
|
|
|
+
|
|
|
+ EditorGUILayout.LabelField("Conflicting Files:", EditorStyles.boldLabel);
|
|
|
+
|
|
|
+ _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition, EditorStyles.helpBox);
|
|
|
+ for (var i = 0; i < _conflictingFiles.Count; i++)
|
|
|
+ {
|
|
|
+ EditorGUILayout.BeginHorizontal();
|
|
|
+ _filesToReset[i] = EditorGUILayout.Toggle(_filesToReset[i], GUILayout.Width(20));
|
|
|
+ EditorGUILayout.LabelField(_conflictingFiles[i]);
|
|
|
+ if (GUILayout.Button("Local Diff", GUILayout.Width(100)))
|
|
|
+ {
|
|
|
+ // Find the GitChange object to pass to the diff service.
|
|
|
+ var change = GitService.GetChangeForFile(_conflictingFiles[i]);
|
|
|
+ if (change != null)
|
|
|
+ {
|
|
|
+ GitService.LaunchExternalDiff(change);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Debug.LogWarning($"Could not get status for {_conflictingFiles[i]} to launch diff.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ EditorGUILayout.EndHorizontal();
|
|
|
+ }
|
|
|
+ EditorGUILayout.EndScrollView();
|
|
|
+
|
|
|
+ EditorGUILayout.Space();
|
|
|
+
|
|
|
+ // --- Action Buttons ---
|
|
|
+ DrawActionButtons();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DrawActionButtons()
|
|
|
+ {
|
|
|
+ var selectedCount = _filesToReset.Count(selected => selected);
|
|
|
+ var canReset = selectedCount > 0;
|
|
|
+
|
|
|
+ EditorGUILayout.BeginHorizontal();
|
|
|
+ GUILayout.FlexibleSpace();
|
|
|
+
|
|
|
+ // Reset Button
|
|
|
+ EditorGUI.BeginDisabledGroup(!canReset);
|
|
|
+ if (GUILayout.Button($"Reset {selectedCount} Selected File(s)", GUILayout.Height(30), GUILayout.Width(200)))
|
|
|
+ {
|
|
|
+ var filesToResetPaths = new List<string>();
|
|
|
+ for (var i = 0; i < _conflictingFiles.Count; i++)
|
|
|
+ {
|
|
|
+ if (_filesToReset[i])
|
|
|
+ {
|
|
|
+ filesToResetPaths.Add(_conflictingFiles[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _callbackInvoked = true;
|
|
|
+ _onCloseCallback?.Invoke(filesToResetPaths);
|
|
|
+ Close();
|
|
|
+ }
|
|
|
+ EditorGUI.EndDisabledGroup();
|
|
|
+
|
|
|
+ if (GUILayout.Button(new GUIContent("Pull Anyway", "This will perform the pull, leaving merge conflicts in your local files for you to resolve."), GUILayout.Height(30)))
|
|
|
+ {
|
|
|
+ // Signal "Pull Anyway" by invoking the callback with an empty, non-null list.
|
|
|
+ _callbackInvoked = true;
|
|
|
+ _onCloseCallback?.Invoke(new List<string>());
|
|
|
+ Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Cancel Button
|
|
|
+ if (GUILayout.Button("Cancel", GUILayout.Height(30)))
|
|
|
+ {
|
|
|
+ Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ EditorGUILayout.EndHorizontal();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnDestroy()
|
|
|
+ {
|
|
|
+ if (!_callbackInvoked)
|
|
|
+ {
|
|
|
+ _onCloseCallback?.Invoke(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|