Skip to content

Commit

Permalink
DYN-5816 locale splash screen (#14118)
Browse files Browse the repository at this point in the history
* Display the proper language in the Splash Screen

* spacing RootDirectories

* Keeping spacing

* Remove Splash Screen default title

* Dissect the Preferences creation from the DynamoModel ctor

* removing null validation

* Refactoring based on the PathManager and Preferences

* Adding a PathManager and Preference singleton

* cleaning text

* PathManager and PreferenceSetttings as singleton

* Cleaning spacing and others

* Using the singleton PathManager class instead of the Interface

* Changing the scope and documenting the function CreateIPathResolver

* Changing access to be flexible for integrators

* Removing unused function

* Setting the Preferences to the RecorderTests

* Add the PreferenceSettings.Instance to the DynamoCoreTests setup

* Adding the preference settings to the DynamoTestUIBase Start configuration

* Set the Preferences to the SystemTesttBase

* Set the PreferenceSettings.Instance to the DynamoViewModelUnitTest Start

* Dealing with the PathResolver

* Passing the Preferences to the DynamoModel Start function and update a comment

* Passing the Prererences to the VisualizationTest Start

* Update the MakeCLIModel function

* Passing the Preferences to the DefaultStartConfiguration

* Update AssemblySharedInfo.cs

* Passing the settings to the configuration from the parameter

* untouch the hostApplicationDirectory

* Untouching the preLoadedLibraries field and renaming

* Restoring fields and adding doc

* Adding the preferences to the start of some tests

* Validating the settings in the DynamoModelTestBase setup

* Adding Preferences to the config Settings Test

* Refactoring the PathManager and Preference creation on the DynamoModel ctor and DynamoModelTestBase

* Cleaning Tests setup and ignore Pref Instance property for xml

* Removing Pref Singleton to the CoreTest Setup

* Rollback fron the 6213 commit

* keep the StartInTestMode to false since this is an special case and set an explicit preferences instance

* Handling Preferences

* clieaning references

* Saving them with the proper Unicode

* Removing Singletion Preferences

* Explicit Settings since the StartInTestMode is false

* Add the specific Preferences

* Rollback the cc58

* Rollback the cc58

* Fix Solution

* Fixing the Assembly character and test file

* Forcing to update the cc58 commit

* Removing the test file

* Fixing Tests Unicode

* No new line

---------

Co-authored-by: Jesus Alfredo Alviño <[email protected]>
Co-authored-by: reddyashish <[email protected]>
  • Loading branch information
3 people authored Aug 9, 2023
1 parent 68b9ba4 commit 542dcfb
Show file tree
Hide file tree
Showing 13 changed files with 199 additions and 61 deletions.
35 changes: 33 additions & 2 deletions src/DynamoApplications/StartupUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using System.Text;
using System.Threading;
using CommandLine;
using Dynamo.Configuration;
using Dynamo.Core;
using Dynamo.Interfaces;
using Dynamo.Models;
using Dynamo.Scheduler;
Expand Down Expand Up @@ -241,6 +243,13 @@ private static IUpdateManager InitializeUpdateManager()
/// <returns></returns>
public static DynamoModel MakeCLIModel(string asmPath, string userDataFolder, string commonDataFolder, HostAnalyticsInfo info = new HostAnalyticsInfo(), bool isServiceMode = false)
{
IPathResolver pathResolver = CreatePathResolver(false, string.Empty, string.Empty, string.Empty);
PathManager.Instance.AssignIPathResolver(pathResolver);

Thread.CurrentThread.CurrentUICulture = new CultureInfo(PreferenceSettings.Instance.Locale);
Thread.CurrentThread.CurrentCulture = new CultureInfo(PreferenceSettings.Instance.Locale);
DynamoModel.OnDetectLanguage();

// Preload ASM and display corresponding message on splash screen
DynamoModel.OnRequestUpdateLoadBarStatus(new SplashScreenLoadEventArgs(Resources.SplashScreenPreLoadingAsm, 10));
var isASMloaded = PreloadASM(asmPath, out string geometryFactoryPath, out string preloaderLocation);
Expand Down Expand Up @@ -273,6 +282,13 @@ public static DynamoModel MakeModel(bool CLImode, string asmPath = "", string ho
/// <returns></returns>
public static DynamoModel MakeModel(bool CLImode, string asmPath = "", HostAnalyticsInfo info = new HostAnalyticsInfo())
{
IPathResolver pathResolver = CreatePathResolver(false, string.Empty, string.Empty, string.Empty);
PathManager.Instance.AssignIPathResolver(pathResolver);

Thread.CurrentThread.CurrentUICulture = new CultureInfo(PreferenceSettings.Instance.Locale);
Thread.CurrentThread.CurrentCulture = new CultureInfo(PreferenceSettings.Instance.Locale);
DynamoModel.OnDetectLanguage();

// Preload ASM and display corresponding message on splash screen
DynamoModel.OnRequestUpdateLoadBarStatus(new SplashScreenLoadEventArgs(Resources.SplashScreenPreLoadingAsm, 10));
var isASMloaded = PreloadASM(asmPath, out string geometryFactoryPath, out string preloaderLocation);
Expand All @@ -281,6 +297,20 @@ public static DynamoModel MakeModel(bool CLImode, string asmPath = "", string ho
return model;
}

/// <summary>
/// It returns an IPathResolver based on the mode and some locations
/// </summary>
/// <param name="CLImode">CLI mode starts the model in test mode and uses a seperate path resolver.</param>
/// <param name="preloaderLocation">Path to be used by PathResolver for preLoaderLocation</param>
/// <param name="userDataFolder">Path to be used by PathResolver for UserDataFolder</param>
/// <param name="commonDataFolder">Path to be used by PathResolver for CommonDataFolder</param>
/// <returns></returns>
private static IPathResolver CreatePathResolver(bool CLImode, string preloaderLocation, string userDataFolder, string commonDataFolder)
{
IPathResolver pathResolver = CLImode ? new CLIPathResolver(preloaderLocation, userDataFolder, commonDataFolder) as IPathResolver : new SandboxPathResolver(preloaderLocation) as IPathResolver;
return pathResolver;
}

/// <summary>
/// TODO (DYN-2118) remove this method in 3.0 and unify this method with the overload above.
/// Use this overload to construct a DynamoModel when the location of ASM to use is known.
Expand Down Expand Up @@ -377,8 +407,9 @@ private static DynamoModel StartDynamoWithDefaultConfig(bool CLImode,
AuthProvider = CLImode ? null : new Core.IDSDKManager(),
UpdateManager = CLImode ? null : OSHelper.IsWindows() ? InitializeUpdateManager() : null,
StartInTestMode = CLImode,
PathResolver = CLImode ? new CLIPathResolver(preloaderLocation, userDataFolder, commonDataFolder) as IPathResolver : new SandboxPathResolver(preloaderLocation) as IPathResolver,
IsServiceMode = isServiceMode
PathResolver = CreatePathResolver(CLImode, preloaderLocation, userDataFolder, commonDataFolder),
IsServiceMode = isServiceMode,
Preferences = PreferenceSettings.Instance
};

var model = DynamoModel.Start(config);
Expand Down
29 changes: 27 additions & 2 deletions src/DynamoCore/Configuration/PathManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,15 @@ struct PathManagerParams
internal IPathResolver PathResolver { get; set; }
}

class PathManager : IPathManager
public class PathManager : IPathManager
{
internal static Lazy<PathManager>
lazy =
new Lazy<PathManager>
(() => new PathManager(new PathManagerParams()));

public static PathManager Instance { get { return lazy.Value; } }

#region Class Private Data Members

public const string PackagesDirectoryName = "packages";
Expand Down Expand Up @@ -89,7 +96,7 @@ class PathManager : IPathManager
private readonly HashSet<string> preloadedLibraries;
private readonly HashSet<string> extensionsDirectories;
private readonly HashSet<string> viewExtensionsDirectories;
private readonly IPathResolver pathResolver;
private IPathResolver pathResolver;

#endregion

Expand Down Expand Up @@ -274,6 +281,14 @@ public int MinorFileVersion
get { return minorFileVersion; }
}

/// <summary>
/// This function indicates if there is an already assigned Path Resolver , otherwise it will take from the ctor config
/// </summary>
public bool HasPathResolver
{
get { return pathResolver != null; }
}

public void AddResolutionPath(string path)
{
if (string.IsNullOrEmpty(path))
Expand Down Expand Up @@ -346,6 +361,16 @@ public bool ResolveDocumentPath(ref string document)

#region Public Class Operational Methods

/// <summary>
/// Assigns an IPathResolver on demand with the same behavior as the Ctor.
/// </summary>
/// <param name="resolver"></param>
internal void AssignIPathResolver(IPathResolver resolver)
{
pathResolver = resolver;
LoadPathsFromResolver();
}

/// <summary>
/// Constructs an instance of PathManager object.
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions src/DynamoCore/Configuration/PreferenceSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ internal static void CopyProperties(this PreferenceSettings source, PreferenceSe
/// </summary>
public class PreferenceSettings : NotificationObject, IPreferences, IRenderPrecisionPreference, IDisablePackageLoadingPreferences, ILogSource, IHideAutocompleteMethodOptions
{
internal readonly static Lazy<PreferenceSettings>
lazy = new Lazy<PreferenceSettings>
(() => PreferenceSettings.Load(PathManager.Instance.PreferenceFilePath));

[XmlIgnore]
public static PreferenceSettings Instance { get { return lazy.Value; } }

private string numberFormat;
private string lastUpdateDownloadPath;
private int maxNumRecentFiles;
Expand Down
137 changes: 91 additions & 46 deletions src/DynamoCore/Models/DynamoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ public struct DefaultStartConfiguration : IStartConfiguration
/// <returns>The instance of <see cref="DynamoModel"/></returns>
public static DynamoModel Start()
{
return Start(new DefaultStartConfiguration() { ProcessMode = TaskProcessMode.Asynchronous });
return Start(new DefaultStartConfiguration() { ProcessMode = TaskProcessMode.Asynchronous, Preferences = PreferenceSettings.Instance });
}

/// <summary>
Expand All @@ -614,7 +614,7 @@ public static DynamoModel Start(IStartConfiguration configuration)
internal static readonly string BuiltInPackagesToken = @"%BuiltInPackages%";
[Obsolete("Only used for migration to the new for this directory - BuiltInPackages - do not use for other purposes")]
// Token representing the standard library directory
internal static readonly string StandardLibraryToken = @"%StandardLibrary%";
internal static readonly string StandardLibraryToken = @"%StandardLibrary%";

/// <summary>
/// Default constructor for DynamoModel
Expand All @@ -638,12 +638,7 @@ protected DynamoModel(IStartConfiguration config)

ClipBoard = new ObservableCollection<ModelBase>();

pathManager = new PathManager(new PathManagerParams
{
CorePath = config.DynamoCorePath,
HostPath = config.DynamoHostPath,
PathResolver = config.PathResolver
});
pathManager = CreatePathManager(config);

// Ensure we have all directories in place.
var exceptions = new List<Exception>();
Expand Down Expand Up @@ -677,13 +672,9 @@ protected DynamoModel(IStartConfiguration config)

OnRequestUpdateLoadBarStatus(new SplashScreenLoadEventArgs(Resources.SplashScreenInitPreferencesSettings, 30));

IPreferences preferences = CreateOrLoadPreferences(config.Preferences);
if (preferences is PreferenceSettings settings)
PreferenceSettings = CreatePreferences(config);
if (PreferenceSettings != null)
{
PreferenceSettings = settings;
// Setting the new locale for Dynamo after Preferences loaded
Thread.CurrentThread.CurrentUICulture = new CultureInfo(PreferenceSettings.Locale);
Thread.CurrentThread.CurrentCulture = new CultureInfo(PreferenceSettings.Locale);
PreferenceSettings.PropertyChanged += PreferenceSettings_PropertyChanged;
PreferenceSettings.MessageLogged += LogMessage;
}
Expand Down Expand Up @@ -1016,6 +1007,92 @@ protected DynamoModel(IStartConfiguration config)
DynamoReady(new ReadyParams(this));
}

/// <summary>
/// It returns a PathManager instance based on the mode in order to reuse it's Singleton instance or create a new one
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
internal PathManager CreatePathManager(IStartConfiguration config)
{
if (!config.StartInTestMode)
{
if (!Core.PathManager.Instance.HasPathResolver)
{
Core.PathManager.Instance.AssignIPathResolver(config.PathResolver);
}
return Core.PathManager.Instance;
}
else
{
return new PathManager(new PathManagerParams
{
CorePath = config.DynamoCorePath,
HostPath = config.DynamoHostPath,
PathResolver = config.PathResolver
});
}
}

/// <summary>
/// It returns a PreferenceSettings instance based on the mode in order to reuse it's Singleton instance or create a new one
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
internal PreferenceSettings CreatePreferences(IStartConfiguration config)
{
PreferenceSettings preferences = null;
if (!config.StartInTestMode)
{
if (config.Preferences is PreferenceSettings settings)
{
preferences = settings;
}
}
else
{
preferences = (PreferenceSettings)CreateOrLoadPreferences(config.Preferences);
}

return preferences;
}

/// <summary>
/// Create or load a preference checking the usage mode and if it already exists
/// </summary>
/// <param name="preferences"></param>
/// <returns></returns>
private IPreferences CreateOrLoadPreferences(IPreferences preferences)
{
if (preferences != null) // If there is preference settings provided...
return preferences;

//Skip file handling and trust location in service mode.
if (IsServiceMode)
{
var setting = new PreferenceSettings();
setting.SetTrustWarningsDisabled(true);
return setting;
}

// Is order for test cases not to interfere with the regular preference
// settings xml file, a test case usually specify a temporary xml file
// path from where preference settings are to be loaded. If that value
// is not set, then fall back to the file path specified in PathManager.
//
var xmlFilePath = PreferenceSettings.DynamoTestPath;
if (string.IsNullOrEmpty(xmlFilePath))
xmlFilePath = pathManager.PreferenceFilePath;

if (File.Exists(xmlFilePath))
{
// If the specified xml file path exists, load it.
return PreferenceSettings.Load(xmlFilePath);
}

// Otherwise make a default preference settings object.
return new PreferenceSettings();
}

private void CheckFeatureFlagTest()
{
if (!DynamoModel.IsTestMode)
Expand Down Expand Up @@ -1702,38 +1779,6 @@ private void LoadNodeModels(List<TypeLoadData> nodes, bool isPackageMember)
}
}

private IPreferences CreateOrLoadPreferences(IPreferences preferences)
{
if (preferences != null) // If there is preference settings provided...
return preferences;

//Skip file handling and trust location in service mode.
if (IsServiceMode)
{
var setting = new PreferenceSettings();
setting.SetTrustWarningsDisabled(true);
return setting;
}

// Is order for test cases not to interfere with the regular preference
// settings xml file, a test case usually specify a temporary xml file
// path from where preference settings are to be loaded. If that value
// is not set, then fall back to the file path specified in PathManager.
//
var xmlFilePath = PreferenceSettings.DynamoTestPath;
if (string.IsNullOrEmpty(xmlFilePath))
xmlFilePath = pathManager.PreferenceFilePath;

if (File.Exists(xmlFilePath))
{
// If the specified xml file path exists, load it.
return PreferenceSettings.Load(xmlFilePath);
}

// Otherwise make a default preference settings object.
return new PreferenceSettings();
}

private void InitializePreferences()
{
if (PreferenceSettings != null)
Expand Down
4 changes: 4 additions & 0 deletions src/DynamoCore/Models/DynamoModelDelegates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ namespace Dynamo.Models
/// <param name="args"></param>
internal delegate void SplashScreenLoadingHandler(SplashScreenLoadEventArgs args);

/// <summary>
/// This delegate is used to notify the detected language to the Splash Screen.
/// </summary>
internal delegate void SplashScreenLanguageDetected();
}
9 changes: 9 additions & 0 deletions src/DynamoCore/Models/DynamoModelEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ internal static void OnRequestUpdateLoadBarStatus(SplashScreenLoadEventArgs args
RequestUpdateLoadBarStatus?.Invoke(args);
}

/// <summary>
/// Event to throw for Splash Screen to display the content in the proper language
/// </summary>
internal static event SplashScreenLanguageDetected LanguageDetected;
internal static void OnDetectLanguage()
{
LanguageDetected?.Invoke();
}

/// <summary>
/// Occurs when changes in data may affect UI and UI needs to be refreshed
/// </summary>
Expand Down
11 changes: 9 additions & 2 deletions src/DynamoCoreWpf/Views/SplashScreen/SplashScreen.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,21 @@ public SplashScreen()
// Bind event handlers
webView.NavigationCompleted += WebView_NavigationCompleted;
DynamoModel.RequestUpdateLoadBarStatus += DynamoModel_RequestUpdateLoadBarStatus;
DynamoModel.LanguageDetected += DynamoModel_LanguageDetected;
StaticSplashScreenReady += OnStaticScreenReady;
RequestLaunchDynamo = LaunchDynamo;
RequestImportSettings = ImportSettings;
RequestSignIn = SignIn;
RequestSignOut = SignOut;
}

private void WebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
private void DynamoModel_LanguageDetected()
{
SetLabels();
}

private void WebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (webView != null)
{
webView.NavigationCompleted -= WebView_NavigationCompleted;
Expand Down Expand Up @@ -276,7 +281,7 @@ protected override async void OnContentRendered(EventArgs e)
webView.CoreWebView2.Settings.IsZoomControlEnabled = false;

var assembly = Assembly.GetExecutingAssembly();

using (Stream stream = assembly.GetManifestResourceStream(htmlEmbeddedFile))
using (StreamReader reader = new StreamReader(stream))
{
Expand All @@ -296,6 +301,7 @@ protected override async void OnContentRendered(EventArgs e)
jsonString = jsonString.Replace("#base64BackgroundImage", $"data:image/{imageFileExtension};base64,{resourceBase64}");
}

jsonString = jsonString.Replace("Welcome to Dynamo!", "");
htmlString = htmlString.Replace("mainJs", jsonString);

webView.NavigateToString(htmlString);
Expand Down Expand Up @@ -474,6 +480,7 @@ protected override void OnClosed(EventArgs e)
base.OnClosed(e);

DynamoModel.RequestUpdateLoadBarStatus -= DynamoModel_RequestUpdateLoadBarStatus;
DynamoModel.LanguageDetected -= DynamoModel_LanguageDetected;
webView.Dispose();
webView = null;

Expand Down
Loading

0 comments on commit 542dcfb

Please sign in to comment.