mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-05-07 08:34:06 +02:00
Move debug resource hot swap into a separate class
This commit is contained in:
parent
92716ea3e0
commit
a6963a18d4
@ -14,7 +14,6 @@
|
||||
using TweetDuck.Core.Other.Analytics;
|
||||
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||
using TweetDuck.Core.Utils;
|
||||
using TweetDuck.Resources;
|
||||
using TweetDuck.Updates;
|
||||
using TweetLib.Core.Features.Plugins;
|
||||
using TweetLib.Core.Features.Plugins.Events;
|
||||
@ -371,14 +370,7 @@ public void ReinjectCustomCSS(string css){
|
||||
}
|
||||
|
||||
public void ReloadToTweetDeck(){
|
||||
#if DEBUG
|
||||
ScriptLoader.HotSwap();
|
||||
#else
|
||||
if (ModifierKeys.HasFlag(Keys.Shift)){
|
||||
ScriptLoader.ClearCache();
|
||||
}
|
||||
#endif
|
||||
|
||||
Program.Resources.OnReloadTriggered();
|
||||
ignoreUpdateCheckError = false;
|
||||
browser.ReloadToTweetDeck();
|
||||
AnalyticsFile.BrowserReloads.Trigger();
|
||||
|
@ -59,7 +59,12 @@ static Program(){
|
||||
Reporter.SetupUnhandledExceptionHandler("TweetDuck Has Failed :(");
|
||||
|
||||
Config = new ConfigManager();
|
||||
|
||||
#if DEBUG
|
||||
Resources = new ScriptLoaderDebug();
|
||||
#else
|
||||
Resources = new ScriptLoader();
|
||||
#endif
|
||||
|
||||
Lib.Initialize(new App.Builder{
|
||||
ErrorHandler = Reporter,
|
||||
|
@ -7,36 +7,33 @@
|
||||
using TweetDuck.Core.Other;
|
||||
using TweetLib.Core.Application;
|
||||
|
||||
#if DEBUG
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using TweetDuck.Core;
|
||||
using TweetLib.Core.Features.Plugins;
|
||||
#endif
|
||||
|
||||
namespace TweetDuck.Resources{
|
||||
sealed class ScriptLoader : IAppResourceHandler{
|
||||
private static readonly Dictionary<string, string> CachedData = new Dictionary<string, string>(16);
|
||||
|
||||
public static void ClearCache(){
|
||||
CachedData.Clear();
|
||||
}
|
||||
|
||||
class ScriptLoader : IAppResourceHandler{
|
||||
private readonly Dictionary<string, string> cache = new Dictionary<string, string>(16);
|
||||
private Control sync;
|
||||
|
||||
public void Initialize(Control sync){
|
||||
this.sync = sync;
|
||||
}
|
||||
|
||||
public string Load(string path){
|
||||
return LoadInternal(path, silent: false);
|
||||
protected void ClearCache(){
|
||||
cache.Clear();
|
||||
}
|
||||
|
||||
public string LoadSilent(string path){
|
||||
return LoadInternal(path, silent: true);
|
||||
public virtual void OnReloadTriggered(){
|
||||
if (Control.ModifierKeys.HasFlag(Keys.Shift)){
|
||||
ClearCache();
|
||||
}
|
||||
}
|
||||
|
||||
private string LoadInternal(string name, bool silent){
|
||||
public string Load(string path) => LoadInternal(path, silent: false);
|
||||
public string LoadSilent(string path) => LoadInternal(path, silent: true);
|
||||
|
||||
protected virtual string LocateFile(string path){
|
||||
return Path.Combine(Program.ScriptPath, path);
|
||||
}
|
||||
|
||||
private string LoadInternal(string path, bool silent){
|
||||
if (sync == null){
|
||||
throw new InvalidOperationException("Cannot use ScriptLoader before initialization.");
|
||||
}
|
||||
@ -44,23 +41,15 @@ private string LoadInternal(string name, bool silent){
|
||||
return null; // better than crashing I guess...?
|
||||
}
|
||||
|
||||
if (CachedData.TryGetValue(name, out string resourceData)){
|
||||
if (cache.TryGetValue(path, out string resourceData)){
|
||||
return resourceData;
|
||||
}
|
||||
|
||||
string path = Program.ScriptPath;
|
||||
|
||||
#if DEBUG
|
||||
if (Directory.Exists(HotSwapTargetDir)){
|
||||
path = Path.Combine(HotSwapTargetDir, "scripts");
|
||||
Debug.WriteLine($"Hot swap active, redirecting {name}");
|
||||
}
|
||||
#endif
|
||||
|
||||
string location = LocateFile(path);
|
||||
string resource;
|
||||
|
||||
try{
|
||||
string contents = File.ReadAllText(Path.Combine(path, name), Encoding.UTF8);
|
||||
string contents = File.ReadAllText(location, Encoding.UTF8);
|
||||
int separator;
|
||||
|
||||
// first line can be either:
|
||||
@ -68,7 +57,7 @@ private string LoadInternal(string name, bool silent){
|
||||
// #<version>\n
|
||||
|
||||
if (contents[0] != '#'){
|
||||
ShowLoadError(silent ? null : sync, $"File {name} appears to be corrupted, please try reinstalling the app.");
|
||||
ShowLoadError(silent ? null : sync, $"File {path} appears to be corrupted, please try reinstalling the app.");
|
||||
separator = 0;
|
||||
}
|
||||
else{
|
||||
@ -76,98 +65,21 @@ private string LoadInternal(string name, bool silent){
|
||||
string fileVersion = contents.Substring(1, separator-1).TrimEnd();
|
||||
|
||||
if (fileVersion != Program.VersionTag){
|
||||
ShowLoadError(silent ? null : sync, $"File {name} is made for a different version of TweetDuck ({fileVersion}) and may not function correctly in this version, please try reinstalling the app.");
|
||||
ShowLoadError(silent ? null : sync, $"File {path} is made for a different version of TweetDuck ({fileVersion}) and may not function correctly in this version, please try reinstalling the app.");
|
||||
}
|
||||
}
|
||||
|
||||
resource = contents.Substring(separator).TrimStart();
|
||||
}catch(Exception ex){
|
||||
ShowLoadError(silent ? null : sync, $"Could not load {name}. The program will continue running with limited functionality.\n\n{ex.Message}");
|
||||
ShowLoadError(silent ? null : sync, $"Could not load {path}. The program will continue running with limited functionality.\n\n{ex.Message}");
|
||||
resource = null;
|
||||
}
|
||||
|
||||
return CachedData[name] = resource;
|
||||
return cache[path] = resource;
|
||||
}
|
||||
|
||||
private static void ShowLoadError(Control sync, string message){
|
||||
sync?.InvokeSafe(() => FormMessage.Error("Resource Error", message, FormMessage.OK));
|
||||
}
|
||||
|
||||
// TODO move hot swap to another implementation
|
||||
|
||||
#if DEBUG
|
||||
private static readonly string HotSwapProjectRoot = FixPathSlash(Path.GetFullPath(Path.Combine(Program.ProgramPath, "../../../")));
|
||||
private static readonly string HotSwapTargetDir = FixPathSlash(Path.Combine(HotSwapProjectRoot, "bin", "tmp"));
|
||||
private static readonly string HotSwapRebuildScript = Path.Combine(HotSwapProjectRoot, "bld", "post_build.exe");
|
||||
|
||||
static ScriptLoader(){
|
||||
if (File.Exists(HotSwapRebuildScript)){
|
||||
Debug.WriteLine("Activating resource hot swap...");
|
||||
|
||||
ResetHotSwap();
|
||||
Application.ApplicationExit += (sender, args) => ResetHotSwap();
|
||||
}
|
||||
}
|
||||
|
||||
public static void HotSwap(){
|
||||
if (!File.Exists(HotSwapRebuildScript)){
|
||||
Debug.WriteLine($"Failed resource hot swap, missing rebuild script: {HotSwapRebuildScript}");
|
||||
return;
|
||||
}
|
||||
|
||||
ResetHotSwap();
|
||||
Directory.CreateDirectory(HotSwapTargetDir);
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
using(Process process = Process.Start(new ProcessStartInfo{
|
||||
FileName = HotSwapRebuildScript,
|
||||
Arguments = $"\"{HotSwapTargetDir}\\\" \"{HotSwapProjectRoot}\\\" \"Debug\" \"{Program.VersionTag}\"",
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
})){
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
if (!process.WaitForExit(8000)){
|
||||
Debug.WriteLine("Failed resource hot swap, script did not finish in time");
|
||||
return;
|
||||
}
|
||||
else if (process.ExitCode != 0){
|
||||
Debug.WriteLine($"Failed resource hot swap, script exited with code {process.ExitCode}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Debug.WriteLine($"Finished rebuild script in {sw.ElapsedMilliseconds} ms");
|
||||
|
||||
ClearCache();
|
||||
|
||||
// Force update plugin manager setup scripts
|
||||
|
||||
string newPluginRoot = Path.Combine(HotSwapTargetDir, "plugins");
|
||||
|
||||
const BindingFlags flagsInstance = BindingFlags.Instance | BindingFlags.NonPublic;
|
||||
|
||||
Type typePluginManager = typeof(PluginManager);
|
||||
Type typeFormBrowser = typeof(FormBrowser);
|
||||
|
||||
// ReSharper disable PossibleNullReferenceException
|
||||
object instPluginManager = typeFormBrowser.GetField("plugins", flagsInstance).GetValue(FormManager.TryFind<FormBrowser>());
|
||||
typePluginManager.GetField("pluginFolder", flagsInstance).SetValue(instPluginManager, newPluginRoot);
|
||||
|
||||
Debug.WriteLine("Reloading hot swapped plugins...");
|
||||
((PluginManager)instPluginManager).Reload();
|
||||
// ReSharper restore PossibleNullReferenceException
|
||||
}
|
||||
|
||||
private static void ResetHotSwap(){
|
||||
try{
|
||||
Directory.Delete(HotSwapTargetDir, true);
|
||||
}catch(DirectoryNotFoundException){}
|
||||
}
|
||||
|
||||
private static string FixPathSlash(string path){
|
||||
return path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + '\\';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
100
Resources/ScriptLoaderDebug.cs
Normal file
100
Resources/ScriptLoaderDebug.cs
Normal file
@ -0,0 +1,100 @@
|
||||
#if DEBUG
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Core;
|
||||
using TweetLib.Core.Features.Plugins;
|
||||
|
||||
namespace TweetDuck.Resources{
|
||||
sealed class ScriptLoaderDebug : ScriptLoader{
|
||||
private static readonly string HotSwapProjectRoot = FixPathSlash(Path.GetFullPath(Path.Combine(Program.ProgramPath, "../../../")));
|
||||
private static readonly string HotSwapTargetDir = FixPathSlash(Path.Combine(HotSwapProjectRoot, "bin", "tmp"));
|
||||
private static readonly string HotSwapRebuildScript = Path.Combine(HotSwapProjectRoot, "bld", "post_build.exe");
|
||||
|
||||
private static string FixPathSlash(string path){
|
||||
return path.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + '\\';
|
||||
}
|
||||
|
||||
public ScriptLoaderDebug(){
|
||||
if (File.Exists(HotSwapRebuildScript)){
|
||||
Debug.WriteLine("Activating resource hot swap...");
|
||||
|
||||
ResetHotSwap();
|
||||
Application.ApplicationExit += (sender, args) => ResetHotSwap();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnReloadTriggered(){
|
||||
HotSwap();
|
||||
}
|
||||
|
||||
protected override string LocateFile(string path){
|
||||
if (Directory.Exists(HotSwapTargetDir)){
|
||||
Debug.WriteLine($"Hot swap active, redirecting {path}");
|
||||
return Path.Combine(HotSwapTargetDir, "scripts", path);
|
||||
}
|
||||
|
||||
return base.LocateFile(path);
|
||||
}
|
||||
|
||||
private void HotSwap(){
|
||||
if (!File.Exists(HotSwapRebuildScript)){
|
||||
Debug.WriteLine($"Failed resource hot swap, missing rebuild script: {HotSwapRebuildScript}");
|
||||
return;
|
||||
}
|
||||
|
||||
ResetHotSwap();
|
||||
Directory.CreateDirectory(HotSwapTargetDir);
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
using(Process process = Process.Start(new ProcessStartInfo{
|
||||
FileName = HotSwapRebuildScript,
|
||||
Arguments = $"\"{HotSwapTargetDir}\\\" \"{HotSwapProjectRoot}\\\" \"Debug\" \"{Program.VersionTag}\"",
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
})){
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
if (!process.WaitForExit(8000)){
|
||||
Debug.WriteLine("Failed resource hot swap, script did not finish in time");
|
||||
return;
|
||||
}
|
||||
else if (process.ExitCode != 0){
|
||||
Debug.WriteLine($"Failed resource hot swap, script exited with code {process.ExitCode}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Debug.WriteLine($"Finished rebuild script in {sw.ElapsedMilliseconds} ms");
|
||||
|
||||
ClearCache();
|
||||
|
||||
// Force update plugin manager setup scripts
|
||||
|
||||
string newPluginRoot = Path.Combine(HotSwapTargetDir, "plugins");
|
||||
|
||||
const BindingFlags flagsInstance = BindingFlags.Instance | BindingFlags.NonPublic;
|
||||
|
||||
Type typePluginManager = typeof(PluginManager);
|
||||
Type typeFormBrowser = typeof(FormBrowser);
|
||||
|
||||
// ReSharper disable PossibleNullReferenceException
|
||||
object instPluginManager = typeFormBrowser.GetField("plugins", flagsInstance).GetValue(FormManager.TryFind<FormBrowser>());
|
||||
typePluginManager.GetField("pluginFolder", flagsInstance).SetValue(instPluginManager, newPluginRoot);
|
||||
|
||||
Debug.WriteLine("Reloading hot swapped plugins...");
|
||||
((PluginManager)instPluginManager).Reload();
|
||||
// ReSharper restore PossibleNullReferenceException
|
||||
}
|
||||
|
||||
private void ResetHotSwap(){
|
||||
try{
|
||||
Directory.Delete(HotSwapTargetDir, true);
|
||||
}catch(DirectoryNotFoundException){}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -256,6 +256,7 @@
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Reporter.cs" />
|
||||
<Compile Include="Resources\ScriptLoaderDebug.cs" />
|
||||
<Compile Include="Updates\FormUpdateDownload.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
Loading…
Reference in New Issue
Block a user