OUT-369: Added hiding linked images functionality and button to show them. OUT-369
authornikolaj
Fri, 16 Mar 2018 17:36:43 +0100
branchOUT-369
changeset 20651677a990a6eb
parent 2059 6b6a22de190a
child 2066 e7d76f8725b5
OUT-369: Added hiding linked images functionality and button to show them.
UI/FormControlPreviewMessage.xaml
UI/FormControlPreviewMessage.xaml.cs
     1.1 --- a/UI/FormControlPreviewMessage.xaml	Thu Mar 15 09:58:34 2018 +0100
     1.2 +++ b/UI/FormControlPreviewMessage.xaml	Fri Mar 16 17:36:43 2018 +0100
     1.3 @@ -52,6 +52,7 @@
     1.4              <RowDefinition Height="Auto" />
     1.5              <RowDefinition Height="Auto" />
     1.6              <RowDefinition Height="*" />
     1.7 +            <RowDefinition Height="Auto" />
     1.8          </Grid.RowDefinitions>
     1.9  
    1.10          <!-- Buttons & preview text -->
    1.11 @@ -414,6 +415,8 @@
    1.12                      VerticalAlignment="Stretch"
    1.13                      Margin="0,10,0,0"
    1.14                      Visibility="{Binding Path='IsNoteModeEnabled', Mode=OneWay, Converter={StaticResource InvertBoolToVisibility}}" />
    1.15 -
    1.16 +        <Grid Grid.Row="7" x:Name="LoadImagesGrid" Visibility="Hidden">
    1.17 +            <Button Name="LoadImagesButton" Content="Load Images" Click="LoadImagesButton_Click"></Button>
    1.18 +        </Grid>
    1.19      </Grid>
    1.20  </UserControl>
    1.21 \ No newline at end of file
     2.1 --- a/UI/FormControlPreviewMessage.xaml.cs	Thu Mar 15 09:58:34 2018 +0100
     2.2 +++ b/UI/FormControlPreviewMessage.xaml.cs	Fri Mar 16 17:36:43 2018 +0100
     2.3 @@ -1,5 +1,7 @@
     2.4  ´╗┐using System;
     2.5 +using System.Collections.Generic;
     2.6  using System.ComponentModel;
     2.7 +using System.IO;
     2.8  using System.Text.RegularExpressions;
     2.9  using System.Windows;
    2.10  using System.Windows.Controls;
    2.11 @@ -82,6 +84,16 @@
    2.12              }
    2.13          }
    2.14  
    2.15 +
    2.16 +        /// <summary>
    2.17 +        /// Html string with <img> tags. To show in WebBrowser if user clicks "Load Images" button
    2.18 +        /// </summary>
    2.19 +        private string HtmlWithLinkedImages { get; set; }
    2.20 +
    2.21 +        /// <summary>
    2.22 +        /// List of temporary HTML files paths to delete them in DisposeOfAllComponents  
    2.23 +        /// </summary>
    2.24 +        private List<string> TempFiles { get; set; } = new List<string>();
    2.25          /**************************************************************
    2.26           * 
    2.27           * Methods
    2.28 @@ -103,6 +115,21 @@
    2.29                  this.displayState = null;
    2.30                  this.displayState = null;
    2.31                  this.GridLayoutRoot = null;
    2.32 +                this.LoadImagesButton = null;
    2.33 +                this.LoadImagesGrid = null;
    2.34 +                
    2.35 +                // delete temporary HTML files
    2.36 +                foreach(string tempFile in this.TempFiles)
    2.37 +                {
    2.38 +                    try
    2.39 +                    {
    2.40 +                        File.Delete(tempFile);
    2.41 +                    }
    2.42 +                    catch
    2.43 +                    {
    2.44 +
    2.45 +                    }
    2.46 +                }
    2.47              }
    2.48          }
    2.49  
    2.50 @@ -127,7 +154,7 @@
    2.51              {
    2.52                  // Get Html content
    2.53                  string htmlString = this.displayState.Message.LongMsgFormattedHtml;
    2.54 -
    2.55 +                               
    2.56                  // Ensure UTF-8 encoding
    2.57                  try
    2.58                  {
    2.59 @@ -154,17 +181,8 @@
    2.60                  if (this.displayState?.Message?.Attachments?.Count > 0)
    2.61                  {
    2.62                      // Look up embedded images in the Html string (<img> tag)
    2.63 -                    MatchCollection embeddedImages = null;
    2.64 -                    try
    2.65 -                    {
    2.66 -                        embeddedImages = Regex.Matches(htmlString, "<img[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
    2.67 -                    }
    2.68 -                    catch (Exception ex)
    2.69 -                    {
    2.70 -                        embeddedImages = null;
    2.71 -                        Log.Error("SetWebBrowserContent: Error getting embedded images. " + ex.ToString());
    2.72 -                    }
    2.73 -
    2.74 +                    MatchCollection embeddedImages = GetImagesMatches(htmlString);
    2.75 +                    
    2.76                      // If one or more embedded images were found, process each of them 
    2.77                      if (embeddedImages != null)
    2.78                      {
    2.79 @@ -211,16 +229,129 @@
    2.80                      }
    2.81                  }
    2.82  
    2.83 -                displayString = htmlString;
    2.84 +                MatchCollection imagesTags = GetImagesMatches(htmlString);
    2.85 +
    2.86 +                // If there are linked images:
    2.87 +                    // Show "Load Images" button
    2.88 +                    // Save HTML with linked images in case user wants to show them -> LoadImagesButton_Click handler
    2.89 +                    // Remove linked images from HTML
    2.90 +                if (imagesTags != null && IsLinkedImages(imagesTags))
    2.91 +                {                    
    2.92 +                    this.LoadImagesGrid.Visibility = Visibility.Visible;                    
    2.93 +                    this.HtmlWithLinkedImages = htmlString;                     
    2.94 +                    displayString = RemoveLinkedImages(htmlString, imagesTags);
    2.95 +                }
    2.96 +                else
    2.97 +                {
    2.98 +                    displayString = htmlString;
    2.99 +                }
   2.100              }
   2.101  
   2.102              // If we have something to display, pass it to the web browser
   2.103 -            if (string.IsNullOrEmpty(displayString) == false)
   2.104 -            {
   2.105 -                this.WebBrowser.NavigateToString(displayString);
   2.106 -            }
   2.107 +            ShowHtmlInBrowser(displayString);
   2.108          }
   2.109  
   2.110 +        /// <summary>
   2.111 +        /// Returns HTML string without linked images 
   2.112 +        /// </summary>
   2.113 +        /// <param name="htmlString">HTML string</param>
   2.114 +        /// <param name="imagesTags">MatchCollection of image tags</param>
   2.115 +        /// <returns></returns>
   2.116 +        private string RemoveLinkedImages(string htmlString, MatchCollection imagesTags)
   2.117 +        {
   2.118 +            if (imagesTags == null)
   2.119 +            {
   2.120 +                return htmlString;
   2.121 +            }
   2.122 +
   2.123 +            foreach (Match match in imagesTags)
   2.124 +            {
   2.125 +                if (string.IsNullOrEmpty(match?.Value) == false && match.Value.Contains("data:image/gif;base64") == false )
   2.126 +                {
   2.127 +                    htmlString = htmlString.Replace(match.Value, string.Empty);                               
   2.128 +                }
   2.129 +            }
   2.130 +
   2.131 +            return htmlString;
   2.132 +        }
   2.133 +
   2.134 +        /// <summary>
   2.135 +        /// Returns MatchCollection with <img> tags from HTML string
   2.136 +        /// </summary>
   2.137 +        /// <param name="htmlString">HTML string</param>
   2.138 +        /// <returns></returns>
   2.139 +        private MatchCollection GetImagesMatches(string htmlString)
   2.140 +        {
   2.141 +            if (string.IsNullOrEmpty(htmlString))
   2.142 +                {
   2.143 +                    return null;
   2.144 +                }
   2.145 +
   2.146 +            // Look up linked images in the Html string (<img> tag)
   2.147 +            MatchCollection imagesTags = null;
   2.148 +            try
   2.149 +            {
   2.150 +                imagesTags = Regex.Matches(htmlString, "<img[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
   2.151 +            }
   2.152 +            catch (Exception ex)
   2.153 +            {
   2.154 +                imagesTags = null;
   2.155 +                Log.Error("GetImagesMatches: Error getting images. " + ex.ToString());
   2.156 +            }
   2.157 +
   2.158 +            return imagesTags;
   2.159 +        }
   2.160 +
   2.161 +        /// <summary>
   2.162 +        /// Shows HTML in WebBrowser
   2.163 +        /// </summary>
   2.164 +        /// <param name="htmlString"></param>
   2.165 +        private void ShowHtmlInBrowser(string htmlString)
   2.166 +        {
   2.167 +            if (string.IsNullOrEmpty(htmlString))
   2.168 +            {
   2.169 +                Log.Error("ShowHtmlInBrowser: htmlString is empty or null");
   2.170 +                return;                
   2.171 +            }
   2.172 +
   2.173 +            string htmlTempFilePath = Path.GetTempFileName() + ".html";
   2.174 +
   2.175 +            try
   2.176 +            {
   2.177 +                File.WriteAllText(htmlTempFilePath, htmlString);
   2.178 +                this.WebBrowser.Navigate(htmlTempFilePath);
   2.179 +            }
   2.180 +            catch (Exception ex)
   2.181 +            {
   2.182 +                Log.Error("ShowHtmlInBrowser: " + ex.ToString()); 
   2.183 +            }
   2.184 +
   2.185 +            // Can not "File.Delete(htmlTempFilePath)" right here - WebBrowser does not show content
   2.186 +            // Files are deleted in DisposeOfAllComponents using this.TempFiles
   2.187 +
   2.188 +            this.TempFiles.Add(htmlTempFilePath);
   2.189 +        }
   2.190 +
   2.191 +        /// <summary>
   2.192 +        /// Returns True if if there is at least 1 linked image in HTML string
   2.193 +        /// </summary>
   2.194 +        /// <param name="imagesTags"></param>
   2.195 +        /// <returns></returns>
   2.196 +        private bool IsLinkedImages(MatchCollection imagesTags)
   2.197 +        {                        
   2.198 +            if (imagesTags != null)
   2.199 +            {
   2.200 +                foreach (Match match in imagesTags)
   2.201 +                {
   2.202 +                    if (string.IsNullOrEmpty(match?.Value) == false && match.Value.Contains("http") && match.Value.Contains("data:image/gif;base64") == false)
   2.203 +                    {
   2.204 +                        return true;
   2.205 +                    }
   2.206 +                }
   2.207 +            }
   2.208 +
   2.209 +            return false;
   2.210 +        }
   2.211          /**************************************************************
   2.212           * 
   2.213           * Event Handling
   2.214 @@ -620,5 +751,22 @@
   2.215                  return;
   2.216              }
   2.217          }
   2.218 +
   2.219 +        /// <summary>
   2.220 +        /// Load images button click event handler
   2.221 +        /// </summary>
   2.222 +        /// <param name="sender"></param>
   2.223 +        /// <param name="e"></param>                    
   2.224 +        private void LoadImagesButton_Click(object sender, RoutedEventArgs e)
   2.225 +        {
   2.226 +            this.LoadImagesButton.Visibility = Visibility.Hidden;
   2.227 +            
   2.228 +            if (string.IsNullOrEmpty(this.HtmlWithLinkedImages))
   2.229 +            {
   2.230 +                return;
   2.231 +            }
   2.232 +
   2.233 +            ShowHtmlInBrowser(this.HtmlWithLinkedImages);                  
   2.234 +        }
   2.235      }
   2.236  }