using System; using UnityEditor; using UnityEngine; using UnityEngine.Networking; namespace Flexalon.Editor { internal class FlexalonSurvey : EditorWindow { private struct SurveyData { public string version; public string unityVersion; public string buildTarget; public int xr; public int experience; public string benefits; public string improvements; public string layouts; } private enum SurveyState { Ask, DontAsk, Completed } private enum XRType { None, XRI, Oculus } private static readonly string[] _options = new string[] { "Very Disappointed", "Somewhat Disappointed", "Not Disappointed" }; private static readonly Vector2 _initialSize = new Vector2(580, 400); private static readonly Vector2 _expandedSize = new Vector2(580, 520); private static readonly string _stateKey = "FlexalonSurveyState"; private static readonly string _dateKey = "FlexalonSurveyDate"; private static readonly string _attemptKey = "FlexalonSurveyAttempt"; private static readonly TimeSpan _askFrequency = new TimeSpan(3, 0, 0, 0); private GUIStyle _bodyStyle; private GUIStyle _boldStyle; private GUIStyle _toggleStyle; private GUIStyle _buttonStyle; private GUIStyle _dontAskButtonStyle; private GUIStyle _textAreaStyle; private SurveyData _surveyData; private Texture _surveyImg; public static bool Completed => EditorPrefs.GetInt(_stateKey, 0) == (int)SurveyState.Completed; public static void ResetState() { EditorPrefs.SetInt(_stateKey, 0); } public static bool ShouldAsk() { if (SessionState.GetBool(_attemptKey, false)) { return false; } SessionState.SetBool(_attemptKey, true); if (EditorPrefs.GetInt(_stateKey, 0) != (int)SurveyState.Ask) { return false; } if (!EditorPrefs.HasKey(_dateKey)) { EditorPrefs.SetString(_dateKey, DateTime.Now.ToBinary().ToString()); return false; } var lastAsked = DateTime.FromBinary(Convert.ToInt64(EditorPrefs.GetString(_dateKey, "0"))); if (DateTime.Now - lastAsked < _askFrequency) { return false; } return true; } public static void ShowSurvey() { var window = GetWindow(true, "Flexalon Feedback", true); window.Show(); } private void Init() { if (_surveyData.version != null) return; _bodyStyle = new GUIStyle(EditorStyles.label); _bodyStyle.wordWrap = true; _bodyStyle.fontSize = 14; _bodyStyle.margin.left = 10; _bodyStyle.margin.bottom = 10; _bodyStyle.stretchWidth = false; _bodyStyle.alignment = TextAnchor.MiddleCenter; _boldStyle = new GUIStyle(_bodyStyle); _boldStyle.fontStyle = FontStyle.Bold; _toggleStyle = new GUIStyle(EditorStyles.miniButton); _toggleStyle.margin = new RectOffset(10, 10, 10, 10); _toggleStyle.fixedHeight = 45; _toggleStyle.fixedWidth = 180; _toggleStyle.fontSize = 14; _toggleStyle.alignment = TextAnchor.MiddleCenter; _buttonStyle = new GUIStyle(EditorStyles.miniButton); _buttonStyle.margin = new RectOffset(10, 10, 10, 10); _buttonStyle.fixedHeight = 35; _buttonStyle.fixedWidth = 170; _buttonStyle.fontSize = 14; _buttonStyle.alignment = TextAnchor.MiddleCenter; _dontAskButtonStyle = new GUIStyle(EditorStyles.miniButton); _dontAskButtonStyle.normal.background = null; _dontAskButtonStyle.margin = new RectOffset(10, 10, 10, 10); _dontAskButtonStyle.fixedWidth = 110; _textAreaStyle = new GUIStyle(EditorStyles.textArea); _textAreaStyle.margin.left = 10; _textAreaStyle.margin.right = 10; this.titleContent = new GUIContent("Flexalon Feedback"); this.minSize = this.maxSize = _expandedSize; WindowUtil.CenterOnEditor(this); _surveyData = new SurveyData { version = WindowUtil.GetVersion(), unityVersion = Application.unityVersion, buildTarget = EditorUserBuildSettings.activeBuildTarget.ToString(), #if FLEXALON_OCULUS xr = (int)XRType.Oculus, #elif UNITY_XRI xr = (int)XRType.XRI, #else xr = (int)XRType.None, #endif experience = -1, benefits = "", improvements = "", layouts = string.Join(",", WindowUtil.GetInstalledLayouts()) }; var surveyImgPath = AssetDatabase.GUIDToAssetPath("0ea942e8eabc7e34c8cfd062416108ac"); _surveyImg = AssetDatabase.LoadAssetAtPath(surveyImgPath); EditorPrefs.SetString(_dateKey, DateTime.Now.ToBinary().ToString()); } private int ToggleGroup(int selected, string[] options) { int newSelected = selected; EditorGUILayout.BeginHorizontal(); for (int i = 0; i < options.Length; i++) { var option = options[i]; if (GUILayout.Toggle(selected == i, option, _toggleStyle)) { newSelected = i; } if (i < options.Length - 1) { GUILayout.FlexibleSpace(); } } EditorGUILayout.EndHorizontal(); return newSelected; } private void BeginCenter() { EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); } private void EndCenter() { GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); } private void CenterLabel(string text, GUIStyle style) { BeginCenter(); GUILayout.Label(text, style); EndCenter(); } private void CenterImage(Texture image, params GUILayoutOption[] options) { BeginCenter(); GUILayout.Label(image, options); EndCenter(); } private void OnGUI() { Init(); EditorGUILayout.BeginVertical(); GUILayout.FlexibleSpace(); BeginCenter(); FlexalonGUI.Image("d0d1cda04ee3f144abf998efbfdfb8dc", 128, (int)(128 * 0.361f)); EndCenter(); GUILayout.FlexibleSpace(); CenterLabel("Please help improve Flexalon by answering 3 quick questions.", _boldStyle); if (_surveyData.experience == -1) { CenterImage(_surveyImg, GUILayout.Width(300), GUILayout.Height(200)); } CenterLabel("How would you feel if you could no longer use Flexalon 3D Layouts?", _bodyStyle); _surveyData.experience = ToggleGroup(_surveyData.experience, _options); if (_surveyData.experience == -1) { this.minSize = this.maxSize = _initialSize; GUILayout.FlexibleSpace(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Ask me later", _dontAskButtonStyle)) { Close(); } if (GUILayout.Button("Don't ask again", _dontAskButtonStyle)) { EditorPrefs.SetInt(_stateKey, (int)SurveyState.DontAsk); Close(); } EditorGUILayout.EndHorizontal(); } else if (_surveyData.experience == 0 || _surveyData.experience == 1) { this.minSize = this.maxSize = _expandedSize; GUILayout.FlexibleSpace(); GUILayout.Label("What is the main benefit you get from Flexalon?", _bodyStyle); _surveyData.benefits = GUILayout.TextArea(_surveyData.benefits, _textAreaStyle, GUILayout.Height(100)); GUILayout.FlexibleSpace(); GUILayout.Label("How can Flexalon be improved for you?", _bodyStyle); _surveyData.improvements = GUILayout.TextArea(_surveyData.improvements, _textAreaStyle, GUILayout.Height(100)); GUILayout.FlexibleSpace(); EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("Send Feedback", _buttonStyle)) { SendSurvey(); Close(); } GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); GUILayout.FlexibleSpace(); } else { SendSurvey(); Close(); } EditorGUILayout.EndVertical(); } private void SendSurvey() { #if UNITY_WEB_REQUEST var request = new UnityWebRequest("https://www.flexalon.com/api/survey", UnityWebRequest.kHttpVerbPOST); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Accept", "application/json"); var json = JsonUtility.ToJson(_surveyData); var jsonData = System.Text.Encoding.UTF8.GetBytes(json); request.uploadHandler = new UploadHandlerRaw(jsonData); request.downloadHandler = new DownloadHandlerBuffer(); request.SendWebRequest().completed += op => { if (request.responseCode == 200) { Debug.Log("Flexalon feedback sent successfully."); EditorPrefs.SetInt(_stateKey, (int)SurveyState.Completed); } else if (request.responseCode == 400) { Debug.LogError("Failed to send Flexalon feedback: " + request.downloadHandler.text); } else { Debug.LogError("Failed to send Flexalon feedback: " + request.error); } request.Dispose(); }; #else EditorPrefs.SetInt(_stateKey, (int)SurveyState.Completed); #endif } } }