Init Xamarin.Forms pages with the browser size
This commit is contained in:
parent
010d1f75d0
commit
1f1c90c250
|
@ -32,19 +32,30 @@ namespace Ooui.AspNetCore
|
|||
return id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static async Task HandleWebSocketRequestAsync (HttpContext context)
|
||||
{
|
||||
void BadRequest (string message)
|
||||
{
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
context.Response.ContentType = "text/plain; charset=utf-8";
|
||||
using (var sw = new System.IO.StreamWriter (context.Response.Body)) {
|
||||
sw.WriteLine (message);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure we get a good ID
|
||||
//
|
||||
if (!context.Request.Query.TryGetValue ("id", out var idValues)) {
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
BadRequest ("Missing `id`");
|
||||
return;
|
||||
}
|
||||
|
||||
var id = idValues.FirstOrDefault ();
|
||||
var id = idValues.LastOrDefault ();
|
||||
if (id == null || id.Length != 32) {
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
BadRequest ("Invalid `id`");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -52,7 +63,7 @@ namespace Ooui.AspNetCore
|
|||
// Find the pending session
|
||||
//
|
||||
if (!pendingSessions.TryRemove (id, out var pendingSession)) {
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
BadRequest ("Unknown `id`");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -60,16 +71,32 @@ namespace Ooui.AspNetCore
|
|||
// Reject the session if it's old
|
||||
//
|
||||
if ((DateTime.UtcNow - pendingSession.RequestTimeUtc) > SessionTimeout) {
|
||||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
BadRequest ("Old `id`");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the element's dimensions
|
||||
//
|
||||
if (!context.Request.Query.TryGetValue ("w", out var wValues) || wValues.Count < 1) {
|
||||
BadRequest ("Missing `w`");
|
||||
return;
|
||||
}
|
||||
if (!context.Request.Query.TryGetValue ("h", out var hValues) || hValues.Count < 1) {
|
||||
BadRequest ("Missing `h`");
|
||||
return;
|
||||
}
|
||||
if (!double.TryParse (wValues.Last (), out var w))
|
||||
w = 640;
|
||||
if (!double.TryParse (hValues.Last (), out var h))
|
||||
h = 480;
|
||||
|
||||
//
|
||||
// OK, Run
|
||||
//
|
||||
var token = CancellationToken.None;
|
||||
var webSocket = await context.WebSockets.AcceptWebSocketAsync ("ooui");
|
||||
var session = new Ooui.UI.Session (webSocket, pendingSession.Element, token);
|
||||
var session = new Ooui.UI.Session (webSocket, pendingSession.Element, w, h, token);
|
||||
await session.RunAsync ().ConfigureAwait (false);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,15 +8,35 @@ namespace Ooui.Forms.Extensions
|
|||
public static SizeRequest GetSizeRequest (this Ooui.Element self, double widthConstraint, double heightConstraint,
|
||||
double minimumWidth = -1, double minimumHeight = -1)
|
||||
{
|
||||
var s = self.Text.MeasureSize (self.Style);
|
||||
var rw = 0.0;
|
||||
var rh = 0.0;
|
||||
Size s = new Size (0, 0);
|
||||
var measured = false;
|
||||
|
||||
var request = new Size (
|
||||
double.IsPositiveInfinity (s.Width) ? double.PositiveInfinity : s.Width,
|
||||
double.IsPositiveInfinity (s.Height) ? double.PositiveInfinity : s.Height);
|
||||
var minimum = new Size (minimumWidth < 0 ? request.Width : minimumWidth,
|
||||
minimumHeight < 0 ? request.Height : minimumHeight);
|
||||
if (self.Style.Width.Equals ("inherit")) {
|
||||
s = self.Text.MeasureSize (self.Style);
|
||||
measured = true;
|
||||
rw = double.IsPositiveInfinity (s.Width) ? double.PositiveInfinity : s.Width;
|
||||
}
|
||||
else {
|
||||
rw = self.Style.GetNumberWithUnits ("width", "px", 640);
|
||||
}
|
||||
|
||||
return new SizeRequest (request, minimum);
|
||||
if (self.Style.Height.Equals ("inherit")) {
|
||||
if (!measured) {
|
||||
s = self.Text.MeasureSize (self.Style);
|
||||
measured = true;
|
||||
}
|
||||
rh = double.IsPositiveInfinity (s.Height) ? double.PositiveInfinity : s.Height;
|
||||
}
|
||||
else {
|
||||
rh = self.Style.GetNumberWithUnits ("height", "px", 480);
|
||||
}
|
||||
|
||||
var minimum = new Size (minimumWidth < 0 ? rw : minimumWidth,
|
||||
minimumHeight < 0 ? rh : minimumHeight);
|
||||
|
||||
return new SizeRequest (new Size (rw, rh), minimum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,9 @@ namespace Ooui.Forms
|
|||
{
|
||||
_renderer = new PlatformRenderer (this);
|
||||
|
||||
MessagingCenter.Subscribe(this, Page.AlertSignalName, (Page sender, AlertArguments arguments) =>
|
||||
{
|
||||
_renderer.Style.PropertyChanged += HandleRendererStyle_PropertyChanged;
|
||||
|
||||
MessagingCenter.Subscribe (this, Page.AlertSignalName, (Page sender, AlertArguments arguments) => {
|
||||
var alert = new DisplayAlert (arguments);
|
||||
alert.Clicked += CloseAlert;
|
||||
|
||||
|
@ -128,6 +129,12 @@ namespace Ooui.Forms
|
|||
Console.Error.WriteLine ("Potential view double add");
|
||||
}
|
||||
|
||||
void HandleRendererStyle_PropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
var pageRenderer = GetRenderer (Page);
|
||||
pageRenderer?.SetElementSize (Ooui.Forms.Extensions.ElementExtensions.GetSizeRequest (_renderer, double.PositiveInfinity, double.PositiveInfinity).Request);
|
||||
}
|
||||
|
||||
void INavigation.InsertPageBefore (Page page, Page before)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace Ooui.Forms
|
|||
|
||||
public Platform Platform => platform;
|
||||
|
||||
public override bool WantsFullScreen => true;
|
||||
|
||||
public PlatformRenderer (Platform platform)
|
||||
{
|
||||
this.platform = platform;
|
||||
|
|
|
@ -142,10 +142,10 @@ namespace Ooui.Forms
|
|||
bool shouldUpdate = width > 0 && height > 0 && parent != null && (boundsChanged || parentBoundsChanged);
|
||||
if (shouldUpdate) {
|
||||
uiview.Style.Position = "absolute";
|
||||
uiview.Style.Left = x + "px";
|
||||
uiview.Style.Top = y + "px";
|
||||
uiview.Style.Width = width + "px";
|
||||
uiview.Style.Height = height + "px";
|
||||
uiview.Style.Left = x;
|
||||
uiview.Style.Top = y;
|
||||
uiview.Style.Width = width;
|
||||
uiview.Style.Height = height;
|
||||
Renderer.SetControlSize (new Size (width, height));
|
||||
}
|
||||
else if (width <= 0 || height <= 0) {
|
||||
|
|
|
@ -18,6 +18,7 @@ const mouseEvents = {
|
|||
wheel: true,
|
||||
};
|
||||
|
||||
// Try to close the socket gracefully
|
||||
window.onbeforeunload = function() {
|
||||
if (socket != null) {
|
||||
socket.close (1001, "Unloading page");
|
||||
|
@ -27,10 +28,22 @@ window.onbeforeunload = function() {
|
|||
return null;
|
||||
}
|
||||
|
||||
function getSize () {
|
||||
return {
|
||||
height: window.innerHeight,
|
||||
width: window.innerWidth
|
||||
};
|
||||
}
|
||||
|
||||
// Main entrypoint
|
||||
function ooui (rootElementPath) {
|
||||
var opened = false;
|
||||
|
||||
socket = new WebSocket ("ws://" + document.location.host + rootElementPath, "ooui");
|
||||
var initialSize = getSize ();
|
||||
var wsArgs = (rootElementPath.indexOf("?") >= 0 ? "&" : "?") +
|
||||
"w=" + initialSize.width + "&h=" + initialSize.height;
|
||||
|
||||
socket = new WebSocket ("ws://" + document.location.host + rootElementPath + wsArgs, "ooui");
|
||||
|
||||
socket.addEventListener ("open", function (event) {
|
||||
console.log ("Web socket opened");
|
||||
|
@ -61,6 +74,34 @@ function ooui (rootElementPath) {
|
|||
});
|
||||
|
||||
console.log("Web socket created");
|
||||
|
||||
// Throttled window resize event
|
||||
(function() {
|
||||
window.addEventListener("resize", resizeThrottler, false);
|
||||
|
||||
var resizeTimeout;
|
||||
function resizeThrottler() {
|
||||
if (!resizeTimeout) {
|
||||
resizeTimeout = setTimeout(function() {
|
||||
resizeTimeout = null;
|
||||
actualResizeHandler();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
function resizeHandler() {
|
||||
const em = {
|
||||
m: "event",
|
||||
id: 42,
|
||||
k: "window.resize",
|
||||
v: getSize (),
|
||||
};
|
||||
const ems = JSON.stringify (em);
|
||||
if (socket != null)
|
||||
socket.send (ems);
|
||||
if (debug) console.log ("Event", em);
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
function getNode (id) {
|
||||
|
|
|
@ -90,6 +90,12 @@ namespace Ooui
|
|||
remove => RemoveEventListener ("wheel", value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A signal to Ooui that this element should take up the
|
||||
/// entire browser window.
|
||||
/// </summary>
|
||||
public virtual bool WantsFullScreen => false;
|
||||
|
||||
protected Element (string tagName)
|
||||
: base (tagName)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace Ooui
|
|||
|
||||
readonly Dictionary<string, Value> properties =
|
||||
new Dictionary<string, Value> ();
|
||||
static readonly private char[] numberChars = new char[] {
|
||||
'0','1','2','3','4','5','6','7','8','9',
|
||||
'.','-','+',
|
||||
};
|
||||
|
||||
public Value AlignSelf {
|
||||
get => this["align-self"];
|
||||
|
@ -126,7 +130,7 @@ namespace Ooui
|
|||
|
||||
public Value Bottom {
|
||||
get => this["bottom"];
|
||||
set => this["bottom"] = value;
|
||||
set => this["bottom"] = AddNumberUnits (value, "px");
|
||||
}
|
||||
|
||||
public Value Clear {
|
||||
|
@ -196,12 +200,12 @@ namespace Ooui
|
|||
|
||||
public Value Height {
|
||||
get => this["height"];
|
||||
set => this["height"] = value;
|
||||
set => this["height"] = AddNumberUnits (value, "px");
|
||||
}
|
||||
|
||||
public Value Left {
|
||||
get => this["left"];
|
||||
set => this["left"] = value;
|
||||
set => this["left"] = AddNumberUnits (value, "px");
|
||||
}
|
||||
|
||||
public Value LineHeight {
|
||||
|
@ -301,7 +305,7 @@ namespace Ooui
|
|||
|
||||
public Value Top {
|
||||
get => this["top"];
|
||||
set => this["top"] = value;
|
||||
set => this["top"] = AddNumberUnits (value, "px");
|
||||
}
|
||||
|
||||
public Value Transform {
|
||||
|
@ -326,7 +330,7 @@ namespace Ooui
|
|||
|
||||
public Value Width {
|
||||
get => this["width"];
|
||||
set => this["width"] = value;
|
||||
set => this["width"] = AddNumberUnits (value, "px");
|
||||
}
|
||||
|
||||
public Value ZIndex {
|
||||
|
@ -396,5 +400,34 @@ namespace Ooui
|
|||
}
|
||||
return o.ToString ();
|
||||
}
|
||||
|
||||
static string AddNumberUnits (object val, string units)
|
||||
{
|
||||
if (val is string s)
|
||||
return s;
|
||||
if (val is IConvertible c)
|
||||
return c.ToString (System.Globalization.CultureInfo.InvariantCulture) + units;
|
||||
return val.ToString ();
|
||||
}
|
||||
|
||||
public double GetNumberWithUnits (string key, string units, double baseValue)
|
||||
{
|
||||
var v = this[key];
|
||||
if (v == null)
|
||||
return 0;
|
||||
|
||||
if (v is string s) {
|
||||
var lastIndex = s.LastIndexOfAny (numberChars);
|
||||
if (lastIndex < 0)
|
||||
return 0;
|
||||
var num = double.Parse (s.Substring (0, lastIndex + 1), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
|
||||
return num;
|
||||
}
|
||||
|
||||
if (v is IConvertible c)
|
||||
return c.ToDouble (System.Globalization.CultureInfo.InvariantCulture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
Ooui/UI.cs
12
Ooui/UI.cs
|
@ -436,7 +436,7 @@ namespace Ooui
|
|||
// Create a new session and let it handle everything from here
|
||||
//
|
||||
try {
|
||||
var session = new Session (webSocket, element, serverToken);
|
||||
var session = new Session (webSocket, element, 1024, 768, serverToken);
|
||||
await session.RunAsync ().ConfigureAwait (false);
|
||||
}
|
||||
catch (WebSocketException ex) when (ex.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) {
|
||||
|
@ -473,11 +473,15 @@ namespace Ooui
|
|||
readonly System.Timers.Timer sendThrottle;
|
||||
DateTime lastTransmitTime = DateTime.MinValue;
|
||||
readonly TimeSpan throttleInterval = TimeSpan.FromSeconds (1.0 / 30); // 30 FPS max
|
||||
readonly double initialWidth;
|
||||
readonly double initialHeight;
|
||||
|
||||
public Session (WebSocket webSocket, Element element, CancellationToken serverToken)
|
||||
public Session (WebSocket webSocket, Element element, double initialWidth, double initialHeight, CancellationToken serverToken)
|
||||
{
|
||||
this.webSocket = webSocket;
|
||||
this.element = element;
|
||||
this.initialWidth = initialWidth;
|
||||
this.initialHeight = initialHeight;
|
||||
|
||||
//
|
||||
// Create a new session cancellation token that will trigger
|
||||
|
@ -525,6 +529,10 @@ namespace Ooui
|
|||
//
|
||||
// Add it to the document body
|
||||
//
|
||||
if (element.WantsFullScreen) {
|
||||
element.Style.Width = initialWidth;
|
||||
element.Style.Height = initialHeight;
|
||||
}
|
||||
QueueMessage (Message.Call ("document.body", "appendChild", element));
|
||||
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue