Skip to content
Permalink
Browse files

owari

  • Loading branch information...
pgrho committed Sep 14, 2017
1 parent d5035b9 commit 269e0504af1aa54494d552c6dc3d2c7ecb9c2dad
@@ -106,6 +106,7 @@
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="MessageWebViewRenderer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@@ -0,0 +1,38 @@
using System;
using System.Threading.Tasks;
using KokoroIO.XamarinForms.UWP;
using KokoroIO.XamarinForms.Views;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ExportRenderer(typeof(MessageWebView), typeof(MessageWebViewRenderer))]

namespace KokoroIO.XamarinForms.UWP
{
public sealed class MessageWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
var mwv = e.OldElement as MessageWebView;

if (mwv != null)
{
mwv.InvokeScriptAsyncCore = null;
}

base.OnElementChanged(e);

mwv = e.NewElement as MessageWebView;

if (mwv != null)
{
mwv.InvokeScriptAsyncCore = InvokeScriptAsyncCore;
}
}

private async Task InvokeScriptAsyncCore(string script)
{
await Control.InvokeScriptAsync("eval", new[] { script });
}
}
}
@@ -1,6 +1,17 @@
function setMessages(messages) {
function asArray(messages) {
if (!messages) {
return null;
} else if (Array.isArray(messages)) {
return messages;
}
return JSON.parse(messages);
}

function setMessages(messages) {
document.body.innerHTML = "";

messages = asArray(messages);

if (!messages) {
return;
}
@@ -15,11 +26,62 @@
var content = m.Content;
var isMerged = m.IsMerged;

var talk = document.createElement("div");
talk.classList.add("talk");
talk.classList.add(isMerged ? "continued" : "not-continued");
talk.setAttribute("data-message-id", id);
var talk = createTaklElement(m);
document.body.appendChild(talk);
}
}
function addMessages(messages) {
var talks = document.querySelectorAll("div.talk");

messages = asArray(messages);

var j = 0;
for (var i = 0; i < messages.length; i++) {
var m = messages[i];

var id = m.Id;
var avatarUrl = m.Avatar;
var displayName = m.DisplayName;
var publishedAt = m.PublishedAt;
var content = m.Content;
var isMerged = m.IsMerged;

for (; ;) {
var prev = talks[j];
var aft = talks[j + 1];
var pid = prev ? parseInt(prev.getAttribute("data-message-id"), 10) : -1;
var aid = aft ? parseInt(aft.getAttribute("data-message-id"), 10) : Number.MAX_VALUE;

if (pid < id && id < aid) {
var talk = createTaklElement(m);
if (aft) {
document.body.insertBefore(talk, aft);
} else {
document.body.appendChild(talk);
}
j++;
break;
} else {
j++;
}
}
}
}

function createTaklElement(m) {
var id = m.Id;
var avatarUrl = m.Avatar;
var displayName = m.DisplayName;
var publishedAt = m.PublishedAt;
var content = m.Content;
var isMerged = m.IsMerged;

var talk = document.createElement("div");
talk.classList.add("talk");
talk.classList.add(isMerged ? "continued" : "not-continued");
talk.setAttribute("data-message-id", id);

try {
var avatar = document.createElement("div");
avatar.classList.add("avatar");
talk.appendChild(avatar);
@@ -53,7 +115,20 @@
filteredText.classList.add("filtered_text");
filteredText.innerHTML = content;
message.appendChild(filteredText);

document.body.appendChild(talk);
} catch (ex) {
talk.innerText = ex;
}
}

return talk;
}
function setMessage(id, avatar, displayName, publishedAt, content, isMerged) {
setMessages([{
Id: parseInt(Id, 10),
Avatar: avatar,
DisplayName: displayName,
PublishedAt: publishedAt,
Content: content,
IsMerged: !!isMerged
}]);
}
window.setMessage = setMessage;
@@ -1,5 +1,5 @@
using System.Collections.ObjectModel;
using System.Linq;
using KokoroIO.XamarinForms.Helpers;
using Xamarin.Forms;

namespace KokoroIO.XamarinForms.ViewModels
@@ -21,15 +21,15 @@ internal MessagesViewModel(RoomViewModel room)

public Command OpenUrlCommand => Application.OpenUrlCommand;

private ObservableCollection<MessageInfo> _Messages;
private ObservableRangeCollection<MessageInfo> _Messages;

public ObservableCollection<MessageInfo> Messages
public ObservableRangeCollection<MessageInfo> Messages
{
get
{
if (_Messages == null)
{
_Messages = new ObservableCollection<MessageInfo>();
_Messages = new ObservableRangeCollection<MessageInfo>();
BeginLoadMessages();
}
return _Messages;
@@ -92,25 +92,58 @@ private async void BeginLoadMessages(bool prepend = false)

HasPrevious &= aid != null || messages.Length >= PAGE_SIZE;

var i = 0;
if (!messages.Any())
{
return;
}

foreach (var m in messages.OrderBy(e => e.Id))
var minId = messages.Min(m => m.Id);
var maxId = messages.Max(m => m.Id);

if (!_Messages.Any() || _Messages.Last().Id < minId)
{
var vm = new MessageInfo(this, m);
for (; ; i++)
var mvms = messages.OrderBy(m => m.Id).Select(m => new MessageInfo(this, m)).ToList();
for (var i = 0; i < mvms.Count; i++)
{
var prev = i == 0 ? null : _Messages[i - 1];
var next = i >= _Messages.Count ? null : _Messages[i];
mvms[i].SetIsMerged(i == 0 ? _Messages.LastOrDefault() : mvms[i - 1]);
}

if (!(prev?.Id > vm.Id)
|| !(vm.Id >= next?.Id))
{
_Messages.Insert(i, vm);
i++;
_Messages.AddRange(mvms);
}
else if (maxId < _Messages.First().Id)
{
var mvms = messages.OrderBy(m => m.Id).Select(m => new MessageInfo(this, m)).ToList();
for (var i = 1; i < mvms.Count; i++)
{
mvms[i].SetIsMerged(mvms[i - 1]);
}

_Messages[0].SetIsMerged(mvms.LastOrDefault());

_Messages.AddRange(mvms);
}
else
{
var i = 0;

vm.SetIsMerged(prev);
next?.SetIsMerged(vm);
break;
foreach (var m in messages.OrderBy(e => e.Id))
{
var vm = new MessageInfo(this, m);
for (; ; i++)
{
var prev = i == 0 ? null : _Messages[i - 1];
var next = i >= _Messages.Count ? null : _Messages[i];

if (!(prev?.Id > vm.Id)
|| !(vm.Id >= next?.Id))
{
_Messages.Insert(i, vm);
i++;

vm.SetIsMerged(prev);
next?.SetIsMerged(vm);
break;
}
}
}
}
@@ -1,8 +1,10 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Xml;
using KokoroIO.XamarinForms.ViewModels;
@@ -52,6 +54,7 @@ private static void MessagesChanged(BindableObject bindable, object oldValue, ob
cc.CollectionChanged += mwv.Cc_CollectionChanged;
}
}

mwv.RefreshMessages();
}

@@ -74,7 +77,21 @@ private static Stream GetManifestResourceStream(string fileName)
#endif
}

private void RefreshMessages()
internal Func<string, Task> InvokeScriptAsyncCore;

private async Task InvokeScriptAsync(string script)
{
if (InvokeScriptAsyncCore != null)
{
await InvokeScriptAsyncCore(script);
}
else
{
Eval(script);
}
}

private async void RefreshMessages()
{
InitHtml();

@@ -84,25 +101,33 @@ private void RefreshMessages()
}
else
{
var js = new JsonSerializer();

using (var sw = new StringWriter())
try
{
sw.Write("setMessages(");
js.Serialize(sw, Messages.Select(m => new
var js = new JsonSerializer();

using (var sw = new StringWriter())
{
m.Id,
m.Profile.Avatar,
m.Profile.DisplayName,
m.PublishedAt,
m.Content,
m.IsMerged
}));
sw.Write(")");

var script = sw.ToString();

Eval(script);
sw.Write("setMessages(");

js.Serialize(sw, Messages.Select(m => new
{
m.Id,
m.Profile.Avatar,
m.Profile.DisplayName,
m.PublishedAt,
m.Content,
m.IsMerged
}));

sw.WriteLine(")");

var script = sw.ToString();

await InvokeScriptAsync(script);
}
}
catch
{
}
}
}
@@ -117,7 +142,8 @@ private void InitHtml()
using (var sw = new StringWriter())
using (var xw = XmlWriter.Create(sw, new XmlWriterSettings()
{
CheckCharacters = false
CheckCharacters = false,
OmitXmlDeclaration = true
}))
{
xw.WriteDocType("html", null, null, null);
@@ -129,23 +155,23 @@ private void InitHtml()
using (var rs = GetManifestResourceStream("Messages.css"))
using (var sr = new StreamReader(rs))
{
xw.WriteString(sr.ReadToEnd());
xw.WriteRaw(sr.ReadToEnd());
}
xw.WriteEndElement();

xw.WriteStartElement("style");
using (var rs = GetManifestResourceStream("MessageBox.css"))
using (var sr = new StreamReader(rs))
{
xw.WriteString(sr.ReadToEnd());
xw.WriteRaw(sr.ReadToEnd());
}
xw.WriteEndElement();

xw.WriteStartElement("style");
using (var rs = GetManifestResourceStream("Pygments.css"))
using (var sr = new StreamReader(rs))
{
xw.WriteString(sr.ReadToEnd());
xw.WriteRaw(sr.ReadToEnd());
}
xw.WriteEndElement();

0 comments on commit 269e050

Please sign in to comment.
You can’t perform that action at this time.