From 4373365ff1a6a85f022ac7811f188ab1c6ebd6e6 Mon Sep 17 00:00:00 2001 From: Hatton Date: Fri, 5 Jan 2024 07:34:48 -0700 Subject: [PATCH] In Debugger mode watch files and refresh when they change --- src/BloomExe/Edit/EditingModel.cs | 113 +++++++++++++++++- .../web/controllers/BrandingSettings.cs | 9 ++ src/content/package.json | 2 +- 3 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/BloomExe/Edit/EditingModel.cs b/src/BloomExe/Edit/EditingModel.cs index 468d56a911a3..3dc1a5317e99 100644 --- a/src/BloomExe/Edit/EditingModel.cs +++ b/src/BloomExe/Edit/EditingModel.cs @@ -70,6 +70,16 @@ public class EditingModel internal const string PageScalingDivId = "page-scaling-container"; + /// + /// Currently this is only valid in EditingView, since it depends on the Javascript code being + /// configured to send appropriate messages to the editView/setIsSelectionRange API. + /// + public static bool IsTextSelected; + + private FileSystemWatcher _developerFileWatcher; + private DateTime _lastTimeWeReloadedBecauseOfDeveloperChange; + private bool _skipNextSaveBecauseDeveloperIsTweakingSupportingFiles; + //public event EventHandler UpdatePageList; public delegate EditingModel Factory(); //autofac uses this @@ -167,6 +177,22 @@ ITemplateFinder sourceCollectionsList } }); _contentLanguages = new List(); + + if (Debugger.IsAttached) + { + StartWatchingDeveloperChanges(); + } + } + + ~EditingModel() + { + // Note, as far as I can tell, EditingModels are never disposed of, so this is never caleld. + // New ones are created each time you open a new collection. + if (_developerFileWatcher != null) + { + _developerFileWatcher.Dispose(); + _developerFileWatcher = null; + } } private Form _oldActiveForm; @@ -695,7 +721,12 @@ public void ViewVisibleNowDoSlowStuff() private void OnPageSelectionChanging(object sender, EventArgs eventArgs) { CheckForBL2634("start of page selection changing--should have old IDs"); - if (_view != null && !_inProcessOfDeleting && !_inProcessOfLoading) + if ( + _view != null + && !_inProcessOfDeleting + && !_inProcessOfLoading + && !_skipNextSaveBecauseDeveloperIsTweakingSupportingFiles + ) { _view.ChangingPages = true; _view.RunJavascriptWithStringResult_Sync_Dangerous( @@ -706,6 +737,7 @@ private void OnPageSelectionChanging(object sender, EventArgs eventArgs) "if (typeof(editTabBundle) !=='undefined' && typeof(editTabBundle.getEditablePageBundleExports()) !=='undefined') {editTabBundle.getEditablePageBundleExports().disconnectForGarbageCollection();}" ); } + _skipNextSaveBecauseDeveloperIsTweakingSupportingFiles = false; } void OnPageSelectionChanged(object sender, EventArgs e) @@ -1732,10 +1764,79 @@ public void HandleEditPagePaintedEvent(object sender, EventArgs args) EditPagePainted?.Invoke(sender, args); } - /// - /// Currently this is only valid in EditingView, since it depends on the Javascript code being - /// configured to send appropriate messages to the editView/setIsSelectionRange API. - /// - public static bool IsTextSelected; + // This speeds up developing brandings. It may speed up other things, but I haven't tested those. + // Currently, branding.json changes won't be visible until you change pages (or click on the current page thumbnail) + private void StartWatchingDeveloperChanges() + { + // This speeds up the process of tweaking branding files + if (Debugger.IsAttached) + { + _developerFileWatcher = new FileSystemWatcher { IncludeSubdirectories = true, }; + _developerFileWatcher.Path = + FileLocationUtilities.GetDirectoryDistributedWithApplication( + BloomFileLocator.BrowserRoot + ); + _developerFileWatcher.Changed += async (sender, args) => + { + if (CurrentBook == null) + return; + // if we've been called already in the past 5 seconds, don't do it again + if ( + DateTime.Now + .Subtract(_lastTimeWeReloadedBecauseOfDeveloperChange) + .TotalSeconds < 2 + ) + return; + _lastTimeWeReloadedBecauseOfDeveloperChange = DateTime.Now; + + // About this doing one thing for json and another for css; at the moment, I can't only + // figure out how to do EITHER a BringBookUpToDate (make use of new json presets from branding) + // OR actually refresh the page (make use of new css). + // + // Enhance: I suspect all the problems here are related to us changing the page id's each time we load, which I don't understand. + // It may just be a mistake. + if (args.Name.EndsWith(".json")) + { + CurrentBook.BringBookUpToDate(new NullProgress()); + _view.Invoke( + (MethodInvoker)( + async () => + { + var pageIndex = _pageSelection.CurrentSelection.GetIndex(); + // Because BringBookUpToDate will have changed page id's, we need to rebuild the page + // list else the next time you click on one, that page won't be found. + _view.UpdatePageList(true); + // And also, when you click on another page, if we try to save the current page, it won't be found. + _skipNextSaveBecauseDeveloperIsTweakingSupportingFiles = true; + + // ** I tried a lot of things to get this to work but was stymied. So you have + // to manually reload the page to see these kinds of changes. + + // get the page object for the current page, which will have the new id + //var page = _currentlyDisplayedBook.GetPageByIndex(pageIndex); + //_pageSelection.SelectPage(page,true/* don't do anything else */); + + //await Task.Delay(500); + //RefreshDisplayOfCurrentPage(false); + // dies _pageSelection.SelectPage(page); + } + ) + ); + } + else // css, png, svg, js, etc. + { + CurrentBook.Storage.UpdateSupportFiles(); + _view.Invoke( + (MethodInvoker) + delegate + { + RefreshDisplayOfCurrentPage(false); + } + ); + } + }; + _developerFileWatcher.EnableRaisingEvents = true; + } + } } } diff --git a/src/BloomExe/web/controllers/BrandingSettings.cs b/src/BloomExe/web/controllers/BrandingSettings.cs index 8fd1b60749ea..56e1362e6dbb 100644 --- a/src/BloomExe/web/controllers/BrandingSettings.cs +++ b/src/BloomExe/web/controllers/BrandingSettings.cs @@ -174,6 +174,15 @@ out var flavor if (!string.IsNullOrEmpty(settingsPath)) { var content = RobustFile.ReadAllText(settingsPath); + if (string.IsNullOrEmpty(content)) + { + NonFatalProblem.Report( + ModalIf.Beta, + PassiveIf.All, + $"The branding settings at '{settingsPath}' are empty. Sometimes the watch:branding:files command starts emitting empty files." + ); + return null; + } var settings = JsonConvert.DeserializeObject(content); if (settings == null) { diff --git a/src/content/package.json b/src/content/package.json index f1bac8119b9d..9837c6f48171 100644 --- a/src/content/package.json +++ b/src/content/package.json @@ -25,7 +25,7 @@ "build:layout:less": "less-watch-compiler --source-map --run-once bookLayout ../../output/browser/bookLayout", "build:appearance": "cpx \"appearanceThemes/**/*.css\" ../../output/browser/appearanceThemes -v", "watch:appearance": "cpx \"appearanceThemes/**/*.css\" ../../output/browser/appearanceThemes --watch -v", - "watch:branding:files": "cpx \"branding/**/!(source)/*.{png,jpg,svg,css,json,htm,html,txt,js}\" ../../output/browser/branding --watch", + "watch:branding:files": "cpx \"branding/**/!(source)/*.{png,jpg,svg,css,json,htm,html,txt,js}\" ../../output/browser/branding --watch -v", "watch:branding:less": "less-watch-compiler --source-map branding ../../output/browser/branding", "watch:templates:less": "less-watch-compiler --source-map templates ../../output/browser/templates", "watch:layout:less": "less-watch-compiler --source-map bookLayout ../../output/browser/bookLayout",