Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,38 @@ class LocalizedLabelEditorUI : BaseTab
readonly VisualElement m_Root;
VisualElement m_ListLang;
HelpBox m_ErrorHelpBox;
PopupField<string> m_SectionPopupField;
PopupField<string> m_TokenPopupField;

readonly LocalizedLabel m_LocalizedLabel;
readonly SerializedObject m_SerializedObject;
readonly SerializedProperty m_SectionProperty;
readonly SerializedProperty m_TokenProperty;

const string k_SectionPropertyPath = "m_Token.m_Section";
const string k_TokenIdPropertyPath = "m_Token.m_TokenId";

public LocalizedLabelEditorUI(LocalizedLabel localizedLabel, SerializedObject serializedObject)
: base($"{GoogleDocConnectorPackage.UILocalizationPath}/LocalizedLabelEditorUI")
{
m_LocalizedLabel = localizedLabel;
m_SerializedObject = serializedObject;
m_SectionProperty = serializedObject.FindProperty("m_Token.m_Section");
m_SectionProperty = serializedObject.FindProperty(k_SectionPropertyPath);
m_TokenProperty = serializedObject.FindProperty(k_TokenIdPropertyPath);
m_Root = this.Q<VisualElement>("LocalizedLabelEditorRoot");

RegisterCallback<AttachToPanelEvent>(OnAttachToPanelEventHandler, TrickleDown.TrickleDown);
RegisterCallback<DetachFromPanelEvent>(OnDetachFromPanelEventHandler, TrickleDown.TrickleDown);
}

~LocalizedLabelEditorUI()
{
UnregisterCallback<AttachToPanelEvent>(OnAttachToPanelEventHandler, TrickleDown.TrickleDown);
UnregisterCallback<DetachFromPanelEvent>(OnDetachFromPanelEventHandler, TrickleDown.TrickleDown);
}

void OnAttachToPanelEventHandler(AttachToPanelEvent e)
{
GoogleDocConnectorLocalization.SpreadsheetIdChanged += Bind;
try
{
Expand All @@ -42,20 +61,19 @@ public LocalizedLabelEditorUI(LocalizedLabel localizedLabel, SerializedObject se
Bind();
}

void OnDetachFromPanelEventHandler(DetachFromPanelEvent e)
{
GoogleDocConnectorLocalization.SpreadsheetIdChanged -= Bind;
LocalizationClient.Default.OnLanguageChanged -= UpdateLocalization;
}

void Bind()
{
m_Root.Clear();
PropertyField("Token Id", "m_Token.m_TokenId");
try
{
var values = LocalizationClient.Default.Sections;
if (!values.Contains(m_SectionProperty.stringValue))
{
m_SectionProperty.stringValue = values.First();
m_SerializedObject.ApplyModifiedProperties();
}

PropertyPopup("Section", "m_Token.m_Section", LocalizationClient.Default.Sections);
CreateListSection();
CreateListToken();
}
catch (Exception exception)
{
Expand All @@ -80,6 +98,58 @@ void Bind()
m_Root.Bind(so);
}

void CreateListSection()
{
var values = LocalizationClient.Default.Sections;
string selectedSectionName = m_SectionProperty.stringValue;
if (!values.Contains(selectedSectionName))
{
selectedSectionName = values.First();
}

UpdateSectionProperty(selectedSectionName);
PropertyPopup(out m_SectionPopupField, "Section", k_SectionPropertyPath, LocalizationClient.Default.Sections, OnSectionPopupChanged);
m_Root.Add(m_SectionPopupField);
}


void CreateListToken()
{
try
{
if (m_TokenPopupField != null && m_Root.Contains(m_TokenPopupField))
{
m_TokenPopupField.Clear();
m_Root.Remove(m_TokenPopupField);
}

Spreadsheet localizationSpreadsheet = GoogleDocConnector.GetSpreadsheet(GoogleDocConnectorLocalization.SpreadsheetId);
Sheet newSheet = localizationSpreadsheet.GetSheet(m_SectionProperty.stringValue);

var columnValues = newSheet.GetColumnValues<string>(0);
columnValues.RemoveAt(0);
if (columnValues.All(x => x == string.Empty))
{
throw new InvalidOperationException("There are no filled tokens on the selected sheet");
}

string selectedTokenName = m_TokenProperty.stringValue;
if (!columnValues.Contains(selectedTokenName))
{
selectedTokenName = columnValues.First();
}

PropertyPopup(out m_TokenPopupField, "Token Id", k_TokenIdPropertyPath, columnValues, OnTokenPopupChanged);
m_Root.Insert(1, m_TokenPopupField);

OnTokenPopupChanged(selectedTokenName);
}
catch (Exception e)
{
UpdateLocalizationError(e.Message);
}
}

void PropertyField(string propertyName, string bindingPath)
{
var propertyField = new TextField(propertyName) { bindingPath = bindingPath };
Expand All @@ -100,6 +170,12 @@ void PropertyPopup(string propertyName, string bindingPath, List<string> values)
m_Root.Add(propertyField);
}

void PropertyPopup(out PopupField<string> createdPopupField, string propertyName, string bindingPath, List<string> values, Action<string> onValueChanged = null)
{
createdPopupField = new PopupField<string>(propertyName, values, 0) { bindingPath = bindingPath };
createdPopupField.RegisterCallback<ChangeEvent<string>>(ev => onValueChanged?.Invoke(ev.newValue));
}

void UpdateLocalization()
{
try
Expand All @@ -123,11 +199,13 @@ void UpdateLocalizationError(string error)
if (string.IsNullOrEmpty(error))
{
m_ErrorHelpBox.style.display = DisplayStyle.None;
DisplayTokenPopupField(DisplayStyle.Flex);
return;
}

m_ErrorHelpBox.Text = error;
m_ErrorHelpBox.style.display = DisplayStyle.Flex;
DisplayTokenPopupField(DisplayStyle.None);
}

void SelectedLang(string langNew)
Expand Down Expand Up @@ -161,5 +239,41 @@ void InitErrorHelpBox()
m_ErrorHelpBox.AddToClassList("error-message");
m_Root.Add(m_ErrorHelpBox);
}

void OnSectionPopupChanged(string newValue)
{
m_SectionPopupField.value = newValue;
UpdateSectionProperty(newValue);
CreateListToken();
}

void OnTokenPopupChanged(string newValue)
{
m_TokenPopupField.value = newValue;
UpdateTokenProperty(newValue);
UpdateLocalization();
}

void UpdateSectionProperty(string newValue)
{
m_SerializedObject.Update();
m_SectionProperty.stringValue = newValue;
m_SerializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(m_LocalizedLabel);
}

void UpdateTokenProperty(string newValue)
{
m_SerializedObject.Update();
m_TokenProperty.stringValue = newValue;
m_SerializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(m_LocalizedLabel);
}

void DisplayTokenPopupField(DisplayStyle displayStyle)
{
if (m_TokenPopupField == null) return;
m_TokenPopupField.style.display = displayStyle;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ void CreateSheetList(Spreadsheet spreadsheet)

var sheetNames = spreadsheet.m_Sheets.Select(v => v.Name).ToList();
Spreadsheet localization = GoogleDocConnectorSettings.Instance.Spreadsheets.FirstOrDefault(s => s == spreadsheet);
string selectedSheetName = GoogleDocConnectorLocalization.LocalizationSheetId == k_DefaultLocalizationSheetId ?
sheetNames[0] : spreadsheet.m_Sheets.FirstOrDefault(s => s.Id == GoogleDocConnectorLocalization.LocalizationSheetId)?.Name;
string selectedSheetName = GoogleDocConnectorLocalization.SheetId == k_DefaultLocalizationSheetId ?
sheetNames[0] : spreadsheet.m_Sheets.FirstOrDefault(s => s.Id == GoogleDocConnectorLocalization.SheetId)?.Name;


if (localization != null)
Expand Down Expand Up @@ -341,7 +341,7 @@ void SelectedLang(string langNew)

void CheckLocalizationCacheFile()
{
if (string.IsNullOrEmpty(GoogleDocConnectorLocalization.SpreadsheetId) || GoogleDocConnectorLocalization.LocalizationSheetId == k_DefaultLocalizationSheetId) return;
if (string.IsNullOrEmpty(GoogleDocConnectorLocalization.SpreadsheetId) || GoogleDocConnectorLocalization.SheetId == k_DefaultLocalizationSheetId) return;

var localizationSpreadsheet = GoogleDocConnector.GetSpreadsheet(GoogleDocConnectorLocalization.SpreadsheetId);
if (!localizationSpreadsheet.IsSpreadsheetFileExist())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace StansAssets.GoogleDoc
/// </summary>
static class GoogleDocConnectorLocalization
{
internal static Action SpreadsheetIdChanged = delegate { };
internal static event Action SpreadsheetIdChanged = delegate { };
/// <summary>
/// Spreadsheet ID used for the Localization client
/// </summary>
Expand All @@ -17,7 +17,7 @@ static class GoogleDocConnectorLocalization
/// <summary>
/// Sheet ID used for the Localization client
/// </summary>
internal static int LocalizationSheetId => GoogleDocConnectorSettings.Instance.LocalizationSheetId;
internal static int SheetId => GoogleDocConnectorSettings.Instance.LocalizationSheetId;

/// <summary>
/// Set a new spreadsheet ID and sheet ID to be used for the Localization client
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ internal void ForceUpdateSpreadsheet(string id)
if (m_SpreadsheetsMap.TryGetValue(id, out var spreadsheet))
{
spreadsheet.InitFromCache();
spreadsheet.FinalizeDataUpdate();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static LocalizationClient Default
if (s_DefaultLocalizationClient == null)
{
var spr = GetSettingsLocalizationSpreadsheet();
s_DefaultLocalizationClient = new LocalizationClient(spr, GoogleDocConnectorLocalization.LocalizationSheetId);
s_DefaultLocalizationClient = new LocalizationClient(spr, GoogleDocConnectorLocalization.SheetId);
}

return s_DefaultLocalizationClient;
Expand All @@ -70,6 +70,7 @@ internal static void ClearDefault()
/// <exception cref="Exception">Will return an error if the sheet hasn't been selected</exception>
internal LocalizationClient(Spreadsheet spreadsheet, int sheetId)
{
spreadsheet.OnDataStoredOnDisk += NotifyLanguageChanged;
Refresh(spreadsheet, sheetId);
}

Expand Down Expand Up @@ -308,6 +309,30 @@ public string GetLocalizedString(ILocalizationToken localizationToken, string la
var token = localizationToken.Token.Trim();
var section = localizationToken.Section.Trim();

Sheet localizationSheet = m_LocalizationSpreadsheet.Sheets.FirstOrDefault(s => s.Name == section);
if (localizationSheet == null)
{
throw new InvalidOperationException("There are no selected sheet");
}

if (!localizationSheet.Rows.Any())
{
throw new InvalidOperationException("There are no filled lines on the first sheet of the table");
}

var row = localizationSheet.Rows.First();
if (!row.Cells.Any())
{
throw new InvalidOperationException("The first row on the first sheet of the table has no filled cells");
}

var cellToken = row.Cells.FirstOrDefault();
if (cellToken != null && cellToken.Value.StringValue.ToLower() != "token" && cellToken.Value.StringValue.ToLower() != "tokens")
{
throw new InvalidOperationException("Token column name not found");
}


if (!m_Sections.TryGetValue(section, out var sheetIndex))
{
throw new Exception($"Can't find sheet with name = {section}");
Expand Down Expand Up @@ -348,6 +373,14 @@ public string GetLocalizedString(ILocalizationToken localizationToken, string la

return finalText;
}

/// <summary>
/// Notify that the language settings of the spreadsheet have been changed
/// </summary>
void NotifyLanguageChanged()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void NotifyLanguageChanged()
void OnDataStoredOnDiskHandler()

The callback method name is out of our convention. Please, consider renaming.

{
OnLanguageChanged?.Invoke();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant null-check here. If you initialize event Action with an empty delegate (just like on Line 12), there is no need to check it for a null before invocation.

}

/// <summary>
/// Returns string converted by the textType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#if TMP_AVAILABLE
using TMPro;
#endif
using System;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
Expand Down Expand Up @@ -59,7 +60,7 @@ void OnDestroy()

internal void UpdateLocalization()
{
var text = LocalizationClient.Default.GetLocalizedString(m_Token);
string text = LocalizationClient.Default.GetLocalizedString(m_Token);
UpdateText(text);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public enum SyncState
/// An event to track spreadsheet sync state.
/// </summary>
public event Action<Spreadsheet> OnSyncStateChange = delegate { };

/// <summary>
/// An event track the saving of spreadsheet data.
/// </summary>
public event Action OnDataStoredOnDisk = delegate { };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public event Action OnDataStoredOnDisk = delegate { };
public event Action<DataStoredOnDiskArgs> OnDataStoredOnDisk = delegate { };

We should consider providing an Arguments struct for this event Action (yes, it will be just an empty struct DataStoredOnDiskArgs{} for the moment). It will save us from breaking changes in future updates. Just in case we will need to pass additional data with this Action.


[SerializeField] SyncState m_State;

Expand Down Expand Up @@ -199,6 +204,11 @@ internal void CleanupSheets()
{
m_Sheets.Clear();
}

internal void FinalizeDataUpdate()
{
OnDataStoredOnDisk?.Invoke();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OnDataStoredOnDisk?.Invoke();
OnDataStoredOnDisk.Invoke();

Redundant null-check here. If you initialize event Action with an empty delegate (just like on Line 55), there is no need to check it for a null before invocation.

}

/// <summary>
/// Returns `true` if spreadsheet contains a sheet with specified id, otherwise `false`.
Expand Down