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

feat: add EditMessageControl to winui #528

Merged
merged 2 commits into from
Feb 5, 2025
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
Original file line number Diff line number Diff line change
@@ -1,37 +1,47 @@
using System;
using Tuvi.App.Shared.Extensions;

#if WINDOWS_UWP
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#else
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
#endif

namespace Eppie.App.UI.Controls
{
public class RichTextEditor : RichEditBox
public partial class RichTextEditor : RichEditBox
{
private bool _skipUpdating;

public string Html
{
get { return (string)GetValue(HtmlProperty); }
set { SetValue(HtmlProperty, value); }
}
public static readonly DependencyProperty HtmlProperty =
DependencyProperty.Register(nameof(Html), typeof(string), typeof(RichTextEditor), new PropertyMetadata(""));
DependencyProperty.Register(nameof(Html), typeof(string), typeof(RichTextEditor), new PropertyMetadata(string.Empty));

public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(RichTextEditor), new PropertyMetadata("", OnTextChanged));
DependencyProperty.Register(nameof(Text), typeof(string), typeof(RichTextEditor), new PropertyMetadata(string.Empty, OnTextChanged));

private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is RichTextEditor editor)
{
editor.UpdateDocumentAsText((string)e.NewValue);
editor.UpdateDocumentAsText(editor.Text);
}
}

#if WINDOWS_UWP || WINDOWS10_0_19041_0_OR_GREATER

private bool _skipUpdating;

public RichTextEditor()
{
Expand All @@ -48,9 +58,14 @@ private void OnContentTextChanged(object sender, RoutedEventArgs e)
_skipUpdating = true;
try
{
Document.GetText(Windows.UI.Text.TextGetOptions.UseCrlf, out string text);
Document.GetText(TextGetOptions.UseCrlf, out string text);

if (!string.IsNullOrWhiteSpace(text))
if (string.IsNullOrWhiteSpace(text))
{
Text = string.Empty;
Html = string.Empty;
}
else
{
Text = text;
Html = Document.ToHtml();
Expand All @@ -66,8 +81,14 @@ private void UpdateDocumentAsText(string text)
{
if (!_skipUpdating && !string.IsNullOrEmpty(text))
{
Document?.SetText(Windows.UI.Text.TextSetOptions.None, text);
Document?.SetText(TextSetOptions.None, text);
}
}
#else
private void UpdateDocumentAsText(string text)
{
throw new System.NotImplementedException();
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\ProtonAccountSettingsControl.xaml.cs">
<DependentUpon>ProtonAccountSettingsControl.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Controls\RichTextEditor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Converters\BitmapSourceConverters.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Converters\BoolToValueConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Converters\ConverterChain.cs" />
Expand All @@ -72,6 +73,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Converters\VisibilityConverters.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\AttachedCommands.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\HyperlinkExtension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\TextDocumentExtension.Uno.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\TextDocumentExtension.UWP.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\TextDocumentExtension.Win.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\TextDocumentExtension.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\ElementHierarchyTools.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\IncrementalLoadingCollection.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#if WINDOWS_UWP

using System;
using System.Linq;
using System.Text;
using Windows.UI.Text;

namespace Tuvi.App.Shared.Extensions
{
public static partial class TextDocumentExtension
{
public static string ToHtml(this ITextDocument document)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

document.GetText(TextGetOptions.None, out string text);

// it seems that we have a bug in rich edit and we always get extra '\r, cut it off
int length = text.Last() == SpecialChar.NewLine ? text.Length - 1 : text.Length;
ITextRange txtRange = document.GetRange(0, length);

return GetHtml(txtRange, length);
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#if HAS_UNO

using System;
using System.Text;
using Microsoft.UI.Text;

namespace Tuvi.App.Shared.Extensions
{
public static partial class TextDocumentExtension
{
public static string ToHtml(this RichEditTextDocument document)
{
throw new NotImplementedException();
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#if WINDOWS10_0_19041_0_OR_GREATER

using System;
using System.Linq;
using System.Text;
using Microsoft.UI.Text;

namespace Tuvi.App.Shared.Extensions
{
public static partial class TextDocumentExtension
{
public static string ToHtml(this RichEditTextDocument document)
{
ArgumentNullException.ThrowIfNull(document);

document.GetText(TextGetOptions.None, out string text);

// it seems that we have a bug in rich edit and we always get extra '\r, cut it off
int length = text.Last() == SpecialChar.NewLine ? text.Length - 1 : text.Length;
ITextRange txtRange = document.GetRange(0, length);

return GetHtml(txtRange, length);
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
using System;
using System.Text;

#if WINDOWS_UWP
using Windows.UI.Text;
#else
using Microsoft.UI.Text;
#endif

namespace Tuvi.App.Shared.Extensions
{
public static class TextDocumentExtension
public static partial class TextDocumentExtension
{
private readonly struct SpecialChar
{
public static readonly char NewLine = '\r';
public static readonly char Space = ' ';
}

private struct ListProcessor
{
private StringBuilder _sb;
Expand Down Expand Up @@ -38,7 +49,7 @@ public bool Process(bool condition, char character)
_itemOpened = true;
}

if (character == Convert.ToChar(13))
if (character == SpecialChar.NewLine)
{
_sb.Append("</li>");
_itemOpened = false;
Expand Down Expand Up @@ -93,69 +104,68 @@ public void Process(bool condition)
}
}
}
public static string ToHtml(this ITextDocument document)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

document.GetText(TextGetOptions.None, out string text); // ToDo: warning Uno0001

// it seems that we have a bug in rich edit and we always get extra '\r, cut it off
int endPosition = text.Length == 0 ? text.Length : text.Length - 1;
ITextRange txtRange = document.GetRange(0, endPosition); // ToDo: warning Uno0001
#if WINDOWS_UWP || WINDOWS10_0_19041_0_OR_GREATER

private static string GetHtml(ITextRange range, int length)
{
var strHTML = new StringBuilder("<html><head></head><body>");

float shtSize = 11; // Default font size
float fontSize = 11; // Default font size

var boldProcessor = new FormatProcessor(strHTML, "b");
var italicProcessor = new FormatProcessor(strHTML, "i");
var underlineProcessor = new FormatProcessor(strHTML, "u");
var bulletList = new ListProcessor(strHTML, "<ul>", "</ul>");
var numberedList = new ListProcessor(strHTML, "<ol type=\"i\">", "</ol>");

for (int i = 0; i < endPosition; i++)
for (int i = 0; i < length; i++)
{
txtRange.SetRange(i, i + 1); // ToDo: warning Uno0001
range.SetRange(i, i + 1);

if (i == 0)
{
shtSize = OpenNewFontSpan();
fontSize = OpenNewFontSpan();
}

if (txtRange.CharacterFormat.Size != shtSize) // ToDo: warning Uno0001
if (range.CharacterFormat.Size != fontSize)
{
strHTML.Append("</span>");
shtSize = OpenNewFontSpan();
fontSize = OpenNewFontSpan();
}

// bullet
bool appendToOutput = bulletList.Process(txtRange.ParagraphFormat.ListType == MarkerType.Bullet, txtRange.Character); // ToDo: warning Uno0001
bool appendToOutput = bulletList.Process(range.ParagraphFormat.ListType == MarkerType.Bullet, range.Character);

// numbering
appendToOutput = numberedList.Process(txtRange.ParagraphFormat.ListType == MarkerType.LowercaseRoman, txtRange.Character); // ToDo: warning Uno0001
appendToOutput = numberedList.Process(range.ParagraphFormat.ListType == MarkerType.LowercaseRoman, range.Character);

// new line should be placed here, right after list processing, to assure that we correctly processed list items
if (appendToOutput && txtRange.Character == Convert.ToChar(13)) // ToDo: warning Uno0001
if (appendToOutput && range.Character == SpecialChar.NewLine)
{
strHTML.Append("<br/>");
appendToOutput = false;
}

// to insert multiple spaces into a document
if (appendToOutput && range.Character == SpecialChar.Space)
{
strHTML.Append("&nbsp;");
appendToOutput = false;
}

// bold
boldProcessor.Process(txtRange.CharacterFormat.Bold == FormatEffect.On); // ToDo: warning Uno0001
boldProcessor.Process(range.CharacterFormat.Bold == FormatEffect.On);

// italic
italicProcessor.Process(txtRange.CharacterFormat.Italic == FormatEffect.On); // ToDo: warning Uno0001
italicProcessor.Process(range.CharacterFormat.Italic == FormatEffect.On);

// underline
underlineProcessor.Process(txtRange.CharacterFormat.Underline == UnderlineType.Single); // ToDo: warning Uno0001
underlineProcessor.Process(range.CharacterFormat.Underline == UnderlineType.Single);

if (appendToOutput)
{
strHTML.Append(txtRange.Character); // ToDo: warning Uno0001
strHTML.Append(range.Character);
}
}

Expand All @@ -165,16 +175,18 @@ public static string ToHtml(this ITextDocument document)

float OpenNewFontSpan()
{
float fontSize = txtRange.CharacterFormat.Size; // ToDo: warning Uno0001
string strFntName = txtRange.CharacterFormat.Name; // ToDo: warning Uno0001
float size = range.CharacterFormat.Size;
string name = range.CharacterFormat.Name;
strHTML.Append("<span style=\"font-family:")
.Append(strFntName)
.Append(name)
.Append("; font-size: ")
.Append(fontSize)
.Append(size)
.Append("pt;")
.Append("\">");
return fontSize;
return size;
}
}
#endif

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
mc:Ignorable="d">

<Grid>
<local:RichTextEditor Html="{x:Bind Html, Mode=TwoWay}"
Text="{x:Bind Text, Mode=TwoWay}" />

<local:RichTextEditor Html="{x:Bind Html, Mode=TwoWay}" Text="{x:Bind Text, Mode=TwoWay}" />
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@
<Compile Include="Controls\MessageControl.xaml.cs">
<DependentUpon>MessageControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\RichTextEditor.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\Eppie.App.UI.UWP.rd.xml" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,18 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Eppie.App.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:not_win="http://uno.ui/not_win"
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
mc:Ignorable="d not_win">

<Grid>

<!-- ToDo: Control is not implemented -->
<!-- WebView2 should be used in WinUI and WebAssembly -->

<!--<xamarin:WebView HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
android:IsTapEnabled="True"
android:Tapped="OnEmailBodyTapped"
extensions:WebViewExtension.StringSource="{x:Bind ViewModel.HtmlBody, Mode=OneWay}"
ios:IsTapEnabled="True"
ios:Tapped="OnEmailBodyTapped"
IsEnabled="{x:Bind ViewModel.LoadingContent, Mode=OneWay, Converter={StaticResource InverseBoolConverter}}" />-->

<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Not Implemented"
TextAlignment="Center" />
<win:Grid>
<local:RichTextEditor Html="{x:Bind Html, Mode=TwoWay}" Text="{x:Bind Text, Mode=TwoWay}" />
</win:Grid>
<not_win:Grid>
<TextBox Text="{x:Bind Text, Mode=TwoWay}" />
</not_win:Grid>
</Grid>
</UserControl>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
await HtmlView.EnsureCoreWebView2Async();

HtmlView.CoreWebView2.Settings.IsScriptEnabled = false;
HtmlView.CoreWebView2.Settings.IsScriptEnabled = false; // ToDo: Uno0001

Check warning on line 13 in src/Eppie.App/Eppie.App.UI/Eppie.App.UI.Uno/Controls/MessageControl.xaml.cs

View workflow job for this annotation

GitHub Actions / windows-latest './src/Eppie.App/Eppie.App.sln'

Microsoft.Web.WebView2.Core.CoreWebView2Settings.IsScriptEnabled is not implemented in Uno (https://aka.platform.uno/notimplemented?m=Microsoft.Web.WebView2.Core.CoreWebView2Settings.IsScriptEnabled) (https://aka.platform.uno/notimplemented)
HtmlView.NavigateToString(HtmlBody);
}
}
Expand Down
Loading