From 70b68cd242f0c246fe8c6d54d5a16bd3cc28c09e Mon Sep 17 00:00:00 2001
From: srosse <stephane.rosse@frentix.com>
Date: Tue, 10 Dec 2019 16:10:22 +0100
Subject: [PATCH] OO-4418: cache the image in the editor to prevent flickering

Allow the browser to cache the images in the page editor (new images
will get new mappers and therefore update is not an issue), don't create
new image component by settings changes but update them to allow again
the browser to use the cached images.
---
 .../gui/components/image/ImageComponent.java  |  13 ++-
 .../gui/components/image/ImageRenderer.java   |  16 +--
 .../ceditor/ui/ImageEditorController.java     |  10 +-
 .../ceditor/ui/ImageRunController.java        | 100 ++++++++++--------
 4 files changed, 81 insertions(+), 58 deletions(-)

diff --git a/src/main/java/org/olat/core/gui/components/image/ImageComponent.java b/src/main/java/org/olat/core/gui/components/image/ImageComponent.java
index fe7b46b8895..d0b669657fa 100644
--- a/src/main/java/org/olat/core/gui/components/image/ImageComponent.java
+++ b/src/main/java/org/olat/core/gui/components/image/ImageComponent.java
@@ -77,11 +77,14 @@ public class ImageComponent extends AbstractComponent implements Disposable {
 	private float scalingFactor;
 	private boolean divImageWrapper = true;
 	private boolean cropSelectionEnabled = false;
+	private boolean preventBrowserCaching = true;
 	
 	private final MapperService mapperService;
 
 	/**
-	 * @param name
+	 * 
+	 * @param usess The user session
+	 * @param name The name of the component
 	 */
 	public ImageComponent(UserSession usess, String name) {
 		super(name);
@@ -104,6 +107,14 @@ public class ImageComponent extends AbstractComponent implements Disposable {
 		this.alt = alt;
 	}
 
+	public boolean isPreventBrowserCaching() {
+		return preventBrowserCaching;
+	}
+
+	public void setPreventBrowserCaching(boolean preventBrowserCaching) {
+		this.preventBrowserCaching = preventBrowserCaching;
+	}
+
 	public boolean isDivImageWrapper() {
 		return divImageWrapper;
 	}
diff --git a/src/main/java/org/olat/core/gui/components/image/ImageRenderer.java b/src/main/java/org/olat/core/gui/components/image/ImageRenderer.java
index 3a31ee9dbdb..9d970d087e8 100644
--- a/src/main/java/org/olat/core/gui/components/image/ImageRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/image/ImageRenderer.java
@@ -96,14 +96,12 @@ public class ImageRenderer extends DefaultComponentRenderer {
 		}
 		sb.append("' class='o_video_wrapper'></div>")
 		  .append("<script>")
-		  .append("/* <![CDATA[ */")
 		  .append("BPlayer.insertPlayer('").append(Settings.createServerURI()).append(mapperUrl);
 		sb.append("','").append(imgId).append("',").append(width).append(",").append(height).append(",'video'");
 		if (poster != null) {
 			sb.append(",null,null,null,null,null,null,'").append(poster).append("'");
 		}
 		sb.append(");")
-		  .append("/* ]]> */")
 		  .append("</script>")
 		  .append("</div>"); // ENDcomponent
 	}
@@ -140,10 +138,16 @@ public class ImageRenderer extends DefaultComponentRenderer {
 
 		String mapperUrl = ic.getMapperUrl();
 		String name = ic.getMedia().getName();
-		if(name.lastIndexOf('.') > 0) {
-			mapperUrl += "/" + name + "?" + System.nanoTime();
+		if(ic.isPreventBrowserCaching()) {
+			if(name.lastIndexOf('.') > 0) {
+				mapperUrl += "/" + name + "?" + System.nanoTime();
+			} else {
+				mapperUrl += "/?" + System.nanoTime();
+			}
+		} else if(name.lastIndexOf('.') > 0) {
+			mapperUrl += "/" + name;
 		} else {
-			mapperUrl += "/?" + System.nanoTime();
+			mapperUrl += "/";
 		}
 		sb.append(" src='").append(mapperUrl).append("' alt=\"");
 		if(StringHelper.containsNonWhitespace(ic.getAlt())) {
@@ -160,7 +164,6 @@ public class ImageRenderer extends DefaultComponentRenderer {
 			  .append("<input id='").append(imgId).append("_h' name='").append(imgId).append("_h' type='hidden' value='' />");
 			
 			sb.append("<script>\n")
-			  .append("/* <![CDATA[ */ \n")
 			  .append("jQuery(function() {\n")
 			  .append("  jQuery('#").append(imgId).append("').cropper({\n")
 			  .append("    aspectRatio:1,\n")
@@ -172,7 +175,6 @@ public class ImageRenderer extends DefaultComponentRenderer {
 			  .append("    }")
 			  .append("  });")
 			  .append("});")
-		      .append("/* ]]> */\n")
 		      .append("</script>");
 		}
 		sb.append("</div>", divWrapper); // ENDcomponent
diff --git a/src/main/java/org/olat/modules/ceditor/ui/ImageEditorController.java b/src/main/java/org/olat/modules/ceditor/ui/ImageEditorController.java
index 6998f439094..ab4cdaa2efc 100644
--- a/src/main/java/org/olat/modules/ceditor/ui/ImageEditorController.java
+++ b/src/main/java/org/olat/modules/ceditor/ui/ImageEditorController.java
@@ -326,11 +326,13 @@ public class ImageEditorController extends FormBasicController implements PageEl
 		String settingsXml = ContentEditorXStream.toXml(settings);
 		imageElement.setLayoutOptions(settingsXml);
 		imageElement = store.savePageElement(imageElement);
+		settings = imageElement.getImageSettings();
 		
-		removeAsListenerAndDispose(imagePreview);
-		imagePreview = new ImageRunController(ureq, getWindowControl(), dataStorage, imageElement, new StandardMediaRenderingHints());
-		listenTo(imagePreview);
-		flc.getFormItemComponent().put("imagePreview", imagePreview.getInitialComponent());
+		DublinCoreMetadata meta = null;
+		if(imageElement.getStoredData() instanceof DublinCoreMetadata) {
+			meta = (DublinCoreMetadata)imageElement.getStoredData();
+		}
+		imagePreview.updateImageSettings(settings, meta);
 		
 		fireEvent(ureq, new ChangePartEvent(imageElement));
 	}
diff --git a/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java b/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java
index 0473c2cd7a6..dd8414ca466 100644
--- a/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java
+++ b/src/main/java/org/olat/modules/ceditor/ui/ImageRunController.java
@@ -64,53 +64,11 @@ public class ImageRunController extends BasicController implements PageRunElemen
 		
 		ImageSettings settings = media.getImageSettings();
 		if(settings != null) {
-			if(settings.getAlignment() != null) {
-				mainVC.contextPut("alignment", settings.getAlignment().name());
-			}
-			if(settings.getSize() != null) {
-				mainVC.contextPut("size", settings.getSize().name());
-			}
-			if(StringHelper.containsNonWhitespace(settings.getStyle())) {
-				imageCmp.setCssClasses(settings.getStyle());
-			}
-			
-			if(settings.getSize() != null) {
-				mainVC.contextPut("imageSizeStyle", settings.getSize().name());
-			}
-			
-			mainVC.contextPut("someId", CodeHelper.getRAMUniqueID());
-			
+			DublinCoreMetadata meta = null;
 			if(media.getStoredData() instanceof DublinCoreMetadata) {
-				DublinCoreMetadata dMeta = (DublinCoreMetadata)media.getStoredData();
-				boolean hasSource = settings.isShowSource() && StringHelper.containsNonWhitespace(dMeta.getSource());
-				if(hasSource) {
-					mainVC.contextPut("source", dMeta.getSource());
-					mainVC.contextPut("showSource", Boolean.valueOf(settings.isShowSource()));
-				}
-			}
-			
-			boolean hasDescriptionToShow = settings.isShowDescription() && StringHelper.containsNonWhitespace(settings.getDescription());
-			mainVC.contextPut("showDescription", Boolean.valueOf(hasDescriptionToShow));
-			if(hasDescriptionToShow) {
-				mainVC.contextPut("description", settings.getDescription());
-			}
-			
-			boolean hasCaptionToShow = StringHelper.containsNonWhitespace(settings.getCaption());
-			mainVC.contextPut("showCaption", Boolean.valueOf(hasCaptionToShow));
-			if(hasCaptionToShow) {
-				mainVC.contextPut("caption", settings.getCaption());
-			}
-			
-			boolean hasTitle = StringHelper.containsNonWhitespace(settings.getTitle());
-			mainVC.contextPut("showTitle", Boolean.valueOf(hasTitle));
-			if(hasTitle) {
-				mainVC.contextPut("title", settings.getTitle());
-				ImageTitlePosition position = settings.getTitlePosition() == null ? ImageTitlePosition.above : settings.getTitlePosition();
-				mainVC.contextPut("titlePosition", position.name());
-				if(StringHelper.containsNonWhitespace(settings.getTitleStyle())) {
-					mainVC.contextPut("titleStyle", settings.getTitleStyle());
-				}
+				meta = (DublinCoreMetadata)media.getStoredData();
 			}
+			updateImageSettings(settings, meta);
 		}
 	}
 
@@ -123,6 +81,7 @@ public class ImageRunController extends BasicController implements PageRunElemen
 		imageCmp = new ImageComponent(ureq.getUserSession(), "image");
 		imageCmp.setMedia(mediaFile);
 		imageCmp.setDivImageWrapper(false);
+		imageCmp.setPreventBrowserCaching(false);
 		
 		mainVC.put("image", imageCmp);
 		mainVC.contextPut("imageSizeStyle", "none");
@@ -149,11 +108,60 @@ public class ImageRunController extends BasicController implements PageRunElemen
 		mainPanel.setDomReplaceable(false);
 	}
 	
+	public void updateImageSettings(ImageSettings settings, DublinCoreMetadata meta) {
+		if(settings.getAlignment() != null) {
+			mainVC.contextPut("alignment", settings.getAlignment().name());
+		}
+		if(settings.getSize() != null) {
+			mainVC.contextPut("size", settings.getSize().name());
+		}
+		if(StringHelper.containsNonWhitespace(settings.getStyle())) {
+			imageCmp.setCssClasses(settings.getStyle());
+		}
+		
+		if(settings.getSize() != null) {
+			mainVC.contextPut("imageSizeStyle", settings.getSize().name());
+		}
+		
+		mainVC.contextPut("someId", CodeHelper.getRAMUniqueID());
+		
+		if(meta != null) {
+			boolean hasSource = settings.isShowSource() && StringHelper.containsNonWhitespace(meta.getSource());
+			if(hasSource) {
+				mainVC.contextPut("source", meta.getSource());
+				mainVC.contextPut("showSource", Boolean.valueOf(settings.isShowSource()));
+			}
+		}
+		
+		boolean hasDescriptionToShow = settings.isShowDescription() && StringHelper.containsNonWhitespace(settings.getDescription());
+		mainVC.contextPut("showDescription", Boolean.valueOf(hasDescriptionToShow));
+		if(hasDescriptionToShow) {
+			mainVC.contextPut("description", settings.getDescription());
+		}
+		
+		boolean hasCaptionToShow = StringHelper.containsNonWhitespace(settings.getCaption());
+		mainVC.contextPut("showCaption", Boolean.valueOf(hasCaptionToShow));
+		if(hasCaptionToShow) {
+			mainVC.contextPut("caption", settings.getCaption());
+		}
+		
+		boolean hasTitle = StringHelper.containsNonWhitespace(settings.getTitle());
+		mainVC.contextPut("showTitle", Boolean.valueOf(hasTitle));
+		if(hasTitle) {
+			mainVC.contextPut("title", settings.getTitle());
+			ImageTitlePosition position = settings.getTitlePosition() == null ? ImageTitlePosition.above : settings.getTitlePosition();
+			mainVC.contextPut("titlePosition", position.name());
+			if(StringHelper.containsNonWhitespace(settings.getTitleStyle())) {
+				mainVC.contextPut("titleStyle", settings.getTitleStyle());
+			}
+		}
+	}
+	
 	/**
 	 * @param ureq The user request
 	 * @param storedData To be extended 
 	 */
-	protected void initMetadata(UserRequest ureq, StoredData storedData) {
+	protected void  initMetadata(UserRequest ureq, StoredData storedData) {
 		//
 	}
 
-- 
GitLab