Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DYN-5816 locale splash screen (#14118) #14246

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
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
Loading