mirror of
https://github.com/Nioux/AideDeJeu.git
synced 2025-10-30 15:06:06 +00:00
ToSpeakableText
This commit is contained in:
parent
dc64a1f3da
commit
e4d6c9f542
1 changed files with 203 additions and 4 deletions
|
|
@ -1,5 +1,11 @@
|
||||||
using AideDeJeuLib;
|
using AideDeJeuLib;
|
||||||
|
using Markdig;
|
||||||
|
using Markdig.Syntax;
|
||||||
|
using Markdig.Syntax.Inlines;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
@ -43,12 +49,12 @@ namespace AideDeJeu.ViewModels
|
||||||
private CancellationTokenSource _CancellationTokenSource = null;
|
private CancellationTokenSource _CancellationTokenSource = null;
|
||||||
public async Task ExecuteSpeakItemCommandAsync(Item item)
|
public async Task ExecuteSpeakItemCommandAsync(Item item)
|
||||||
{
|
{
|
||||||
if(Speaking)
|
if (Speaking)
|
||||||
{
|
{
|
||||||
ExecuteCancelSpeakCommand();
|
ExecuteCancelSpeakCommand();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var md = item.Markdown;
|
var md = MarkdownToSpeakableString(item.Markdown);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_CancellationTokenSource = new CancellationTokenSource();
|
_CancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
@ -56,7 +62,7 @@ namespace AideDeJeu.ViewModels
|
||||||
OnPropertyChanged(nameof(NotSpeaking));
|
OnPropertyChanged(nameof(NotSpeaking));
|
||||||
await Xamarin.Essentials.TextToSpeech.SpeakAsync(md, _CancellationTokenSource.Token);
|
await Xamarin.Essentials.TextToSpeech.SpeakAsync(md, _CancellationTokenSource.Token);
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -73,5 +79,198 @@ namespace AideDeJeu.ViewModels
|
||||||
{
|
{
|
||||||
_CancellationTokenSource?.Cancel();
|
_CancellationTokenSource?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string MarkdownToSpeakableString(string md)
|
||||||
|
{
|
||||||
|
var pipeline = new Markdig.MarkdownPipelineBuilder().UseYamlFrontMatter().UsePipeTables().Build();
|
||||||
|
var parsed = Markdig.Markdown.Parse(md, pipeline);
|
||||||
|
var speakable = Render(parsed.AsEnumerable());
|
||||||
|
return speakable;
|
||||||
|
}
|
||||||
|
private string Render(IEnumerable<Block> blocks)
|
||||||
|
{
|
||||||
|
var phrases = "";
|
||||||
|
foreach (var block in blocks)
|
||||||
|
{
|
||||||
|
var phrase = this.Render(block);
|
||||||
|
if (phrase != null)
|
||||||
|
{
|
||||||
|
phrases += phrase;
|
||||||
|
}
|
||||||
|
if (block.IsBreakable)
|
||||||
|
{
|
||||||
|
phrases += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return phrases;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Render(Block block)
|
||||||
|
{
|
||||||
|
switch (block)
|
||||||
|
{
|
||||||
|
case HeadingBlock heading:
|
||||||
|
return Render(heading);
|
||||||
|
|
||||||
|
case ParagraphBlock paragraph:
|
||||||
|
return Render(paragraph);
|
||||||
|
|
||||||
|
//case QuoteBlock quote:
|
||||||
|
// Render(quote);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
//case CodeBlock code:
|
||||||
|
// Render(code);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case ListBlock list:
|
||||||
|
return Render(list);
|
||||||
|
//break;
|
||||||
|
|
||||||
|
//case ThematicBreakBlock thematicBreak:
|
||||||
|
// Render(thematicBreak);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
//case HtmlBlock html:
|
||||||
|
// Render(html);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
case Markdig.Extensions.Tables.Table table:
|
||||||
|
return Render(table);
|
||||||
|
//break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Debug.WriteLine($"Can't render {block.GetType()} blocks.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (queuedViews.Any())
|
||||||
|
//{
|
||||||
|
// foreach (var view in queuedViews)
|
||||||
|
// {
|
||||||
|
// this.stack.Children.Add(view);
|
||||||
|
// }
|
||||||
|
// queuedViews.Clear();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Render(HeadingBlock block)
|
||||||
|
{
|
||||||
|
return CreateFormatted(block.Inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Render(ParagraphBlock block)
|
||||||
|
{
|
||||||
|
return CreateFormatted(block.Inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Render(ListBlock block)
|
||||||
|
{
|
||||||
|
//listScope++;
|
||||||
|
|
||||||
|
var views = "";
|
||||||
|
for (int i = 0; i < block.Count(); i++)
|
||||||
|
{
|
||||||
|
var item = block.ElementAt(i);
|
||||||
|
|
||||||
|
if (item is ListItemBlock itemBlock)
|
||||||
|
{
|
||||||
|
var subviews = Render(itemBlock);
|
||||||
|
if (subviews != null)
|
||||||
|
{
|
||||||
|
views += subviews;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//listScope--;
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Render(ListItemBlock block)
|
||||||
|
{
|
||||||
|
var stack = "";
|
||||||
|
|
||||||
|
var subv = this.Render(block.AsEnumerable());
|
||||||
|
subv.ToList().ForEach(v => stack += v);
|
||||||
|
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Render(Markdig.Extensions.Tables.Table tableBlock)
|
||||||
|
{
|
||||||
|
int maxColumns = 0;
|
||||||
|
foreach (Markdig.Extensions.Tables.TableRow row in tableBlock)
|
||||||
|
{
|
||||||
|
maxColumns = Math.Max(maxColumns, row.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = "";
|
||||||
|
foreach (Markdig.Extensions.Tables.TableRow row in tableBlock)
|
||||||
|
{
|
||||||
|
foreach (Markdig.Extensions.Tables.TableCell cell in row)
|
||||||
|
{
|
||||||
|
var phrase = "";
|
||||||
|
foreach (var blockpar in cell)
|
||||||
|
{
|
||||||
|
var par = blockpar as Markdig.Syntax.ParagraphBlock;
|
||||||
|
var blockPhrase = CreateFormatted(par.Inline);
|
||||||
|
phrase += blockPhrase;
|
||||||
|
}
|
||||||
|
table += phrase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private string CreateFormatted(ContainerInline inlines)
|
||||||
|
{
|
||||||
|
var phrase = "";
|
||||||
|
foreach (var inline in inlines)
|
||||||
|
{
|
||||||
|
var spans = CreateChunks(inline);
|
||||||
|
if (spans != null)
|
||||||
|
{
|
||||||
|
foreach (var span in spans)
|
||||||
|
{
|
||||||
|
phrase += span;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return phrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> CreateChunks(Inline inline)
|
||||||
|
{
|
||||||
|
switch (inline)
|
||||||
|
{
|
||||||
|
case LiteralInline literal:
|
||||||
|
return new string[]
|
||||||
|
{
|
||||||
|
literal.Content.Text.Substring(literal.Content.Start, literal.Content.Length)
|
||||||
|
};
|
||||||
|
case EmphasisInline emphasis:
|
||||||
|
var espans = emphasis.SelectMany(x => CreateChunks(x));
|
||||||
|
return espans.ToArray();
|
||||||
|
|
||||||
|
case LineBreakInline breakline:
|
||||||
|
return new string[] { "\n" };
|
||||||
|
|
||||||
|
case LinkInline link:
|
||||||
|
return link.SelectMany(x => CreateChunks(x));
|
||||||
|
|
||||||
|
case CodeInline code:
|
||||||
|
|
||||||
|
case HtmlInline html:
|
||||||
|
|
||||||
|
default:
|
||||||
|
return new string[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue