mirror of
https://github.com/sbrl/Nibriboard.git
synced 2018-01-10 21:33:49 +00:00
Finish hooking up Http server. Next up: client settings.
This commit is contained in:
parent
33f3c44d6e
commit
11a2c846fc
21 changed files with 724 additions and 27 deletions
|
@ -1,5 +0,0 @@
|
||||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
|
|
||||||
},{}]},{},[1]);
|
|
|
@ -1,2 +0,0 @@
|
||||||
"use strict";
|
|
||||||
|
|
73
Nibriboard/ClientFiles/BoardWindow.js
Normal file
73
Nibriboard/ClientFiles/BoardWindow.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// npm modules
|
||||||
|
window.EventEmitter = require("event-emitter-es6");
|
||||||
|
window.FaviconNotification = require("favicon-notification");
|
||||||
|
|
||||||
|
// Our files
|
||||||
|
import RippleLink from './RippleLink';
|
||||||
|
import { get } from './Utilities';
|
||||||
|
|
||||||
|
class BoardWindow extends EventEmitter
|
||||||
|
{
|
||||||
|
constructor(canvas)
|
||||||
|
{
|
||||||
|
super(); // Run the parent constructor
|
||||||
|
|
||||||
|
this.canvas = canvas;
|
||||||
|
this.context = canvas.getContext("2d");
|
||||||
|
FaviconNotification.init({
|
||||||
|
color: '#ff6333'
|
||||||
|
});
|
||||||
|
FaviconNotification.add();
|
||||||
|
|
||||||
|
get("/Settings.json").then(JSON.parse).then((function(settings) {
|
||||||
|
this.settings = settings;
|
||||||
|
this.setup();
|
||||||
|
}).bind(this), function(errorMessage) {
|
||||||
|
console.error(`Error: Failed to fetch settings from server! Response: ${errorMessage}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.trackWindowSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFrame()
|
||||||
|
{
|
||||||
|
this.update();
|
||||||
|
this.render(this.canvas, this.context);
|
||||||
|
requestAnimationFrame(this.nextFrame.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render(canvas, context)
|
||||||
|
{
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
context.fillStyle = "red";
|
||||||
|
context.fillRect(10, 10, 100, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the canvas size to match the current viewport size.
|
||||||
|
*/
|
||||||
|
matchWindowSize() {
|
||||||
|
this.canvas.width = window.innerWidth;
|
||||||
|
this.canvas.height = window.innerHeight;
|
||||||
|
|
||||||
|
this.render(this.canvas, this.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the canvas size track the window size.
|
||||||
|
*/
|
||||||
|
trackWindowSize() {
|
||||||
|
this.matchWindowSize();
|
||||||
|
window.addEventListener("resize", this.matchWindowSize.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BoardWindow;
|
11
Nibriboard/ClientFiles/Nibri.css
Normal file
11
Nibriboard/ClientFiles/Nibri.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
html, body { font-size: 100%; }
|
||||||
|
body
|
||||||
|
{
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas-main
|
||||||
|
{
|
||||||
|
position: absolute;
|
||||||
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
|
}
|
471
Nibriboard/ClientFiles/NibriClient.js
Normal file
471
Nibriboard/ClientFiles/NibriClient.js
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function get(u){return new Promise(function(r,t,a){a=new XMLHttpRequest();a.onload=function(b,c){b=a.status;c=a.response;if(b>199&&b<300){r(c);}else{t(c);}};a.open("GET",u,true);a.send(null);})}
|
||||||
|
|
||||||
|
// npm modules
|
||||||
|
window.EventEmitter = require("event-emitter-es6");
|
||||||
|
window.FaviconNotification = require("favicon-notification");
|
||||||
|
|
||||||
|
// Our files
|
||||||
|
class BoardWindow extends EventEmitter
|
||||||
|
{
|
||||||
|
constructor(canvas)
|
||||||
|
{
|
||||||
|
super(); // Run the parent constructor
|
||||||
|
|
||||||
|
this.canvas = canvas;
|
||||||
|
this.context = canvas.getContext("2d");
|
||||||
|
FaviconNotification.init({
|
||||||
|
color: '#ff6333'
|
||||||
|
});
|
||||||
|
FaviconNotification.add();
|
||||||
|
|
||||||
|
get("/Settings.json").then(JSON.parse).then((function(settings) {
|
||||||
|
this.settings = settings;
|
||||||
|
this.setup();
|
||||||
|
}).bind(this), function(errorMessage) {
|
||||||
|
console.error(`Error: Failed to fetch settings from server! Response: ${errorMessage}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.trackWindowSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
nextFrame()
|
||||||
|
{
|
||||||
|
this.update();
|
||||||
|
this.render(this.canvas, this.context);
|
||||||
|
requestAnimationFrame(this.nextFrame.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
update()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render(canvas, context)
|
||||||
|
{
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
context.fillStyle = "red";
|
||||||
|
context.fillRect(10, 10, 100, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the canvas size to match the current viewport size.
|
||||||
|
*/
|
||||||
|
matchWindowSize() {
|
||||||
|
this.canvas.width = window.innerWidth;
|
||||||
|
this.canvas.height = window.innerHeight;
|
||||||
|
|
||||||
|
this.render(this.canvas, this.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the canvas size track the window size.
|
||||||
|
*/
|
||||||
|
trackWindowSize() {
|
||||||
|
this.matchWindowSize();
|
||||||
|
window.addEventListener("resize", this.matchWindowSize.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("load", function (event) {
|
||||||
|
var canvas = document.getElementById("canvas-main"),
|
||||||
|
boardWindow = new BoardWindow(canvas);
|
||||||
|
boardWindow.nextFrame();
|
||||||
|
window.boardWindow = boardWindow;
|
||||||
|
});
|
||||||
|
|
||||||
|
},{"event-emitter-es6":2,"favicon-notification":3}],2:[function(require,module,exports){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||||
|
|
||||||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||||
|
|
||||||
|
var DEFAULT_VALUES = {
|
||||||
|
emitDelay: 10,
|
||||||
|
strictMode: false
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} EventEmitterListenerFunc
|
||||||
|
* @property {boolean} once
|
||||||
|
* @property {function} fn
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class EventEmitter
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @property {Object.<string, EventEmitterListenerFunc[]>} _listeners
|
||||||
|
* @property {string[]} events
|
||||||
|
*/
|
||||||
|
|
||||||
|
var EventEmitter = function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @param {{}} [opts]
|
||||||
|
* @param {number} [opts.emitDelay = 10] - Number in ms. Specifies whether emit will be sync or async. By default - 10ms. If 0 - fires sync
|
||||||
|
* @param {boolean} [opts.strictMode = false] - is true, Emitter throws error on emit error with no listeners
|
||||||
|
*/
|
||||||
|
|
||||||
|
function EventEmitter() {
|
||||||
|
var opts = arguments.length <= 0 || arguments[0] === undefined ? DEFAULT_VALUES : arguments[0];
|
||||||
|
|
||||||
|
_classCallCheck(this, EventEmitter);
|
||||||
|
|
||||||
|
var emitDelay = void 0,
|
||||||
|
strictMode = void 0;
|
||||||
|
|
||||||
|
if (opts.hasOwnProperty('emitDelay')) {
|
||||||
|
emitDelay = opts.emitDelay;
|
||||||
|
} else {
|
||||||
|
emitDelay = DEFAULT_VALUES.emitDelay;
|
||||||
|
}
|
||||||
|
this._emitDelay = emitDelay;
|
||||||
|
|
||||||
|
if (opts.hasOwnProperty('strictMode')) {
|
||||||
|
strictMode = opts.strictMode;
|
||||||
|
} else {
|
||||||
|
strictMode = DEFAULT_VALUES.strictMode;
|
||||||
|
}
|
||||||
|
this._strictMode = strictMode;
|
||||||
|
|
||||||
|
this._listeners = {};
|
||||||
|
this.events = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @param {string} type
|
||||||
|
* @param {function} listener
|
||||||
|
* @param {boolean} [once = false]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
_createClass(EventEmitter, [{
|
||||||
|
key: '_addListenner',
|
||||||
|
value: function _addListenner(type, listener, once) {
|
||||||
|
if (typeof listener !== 'function') {
|
||||||
|
throw TypeError('listener must be a function');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.events.indexOf(type) === -1) {
|
||||||
|
this._listeners[type] = [{
|
||||||
|
once: once,
|
||||||
|
fn: listener
|
||||||
|
}];
|
||||||
|
this.events.push(type);
|
||||||
|
} else {
|
||||||
|
this._listeners[type].push({
|
||||||
|
once: once,
|
||||||
|
fn: listener
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes on event type specified function
|
||||||
|
* @param {string} type
|
||||||
|
* @param {function} listener
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: 'on',
|
||||||
|
value: function on(type, listener) {
|
||||||
|
this._addListenner(type, listener, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes on event type specified function to fire only once
|
||||||
|
* @param {string} type
|
||||||
|
* @param {function} listener
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: 'once',
|
||||||
|
value: function once(type, listener) {
|
||||||
|
this._addListenner(type, listener, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes event with specified type. If specified listenerFunc - deletes only one listener of specified type
|
||||||
|
* @param {string} eventType
|
||||||
|
* @param {function} [listenerFunc]
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: 'off',
|
||||||
|
value: function off(eventType, listenerFunc) {
|
||||||
|
var _this = this;
|
||||||
|
|
||||||
|
var typeIndex = this.events.indexOf(eventType);
|
||||||
|
var hasType = eventType && typeIndex !== -1;
|
||||||
|
|
||||||
|
if (hasType) {
|
||||||
|
if (!listenerFunc) {
|
||||||
|
delete this._listeners[eventType];
|
||||||
|
this.events.splice(typeIndex, 1);
|
||||||
|
} else {
|
||||||
|
(function () {
|
||||||
|
var removedEvents = [];
|
||||||
|
var typeListeners = _this._listeners[eventType];
|
||||||
|
|
||||||
|
typeListeners.forEach(
|
||||||
|
/**
|
||||||
|
* @param {EventEmitterListenerFunc} fn
|
||||||
|
* @param {number} idx
|
||||||
|
*/
|
||||||
|
function (fn, idx) {
|
||||||
|
if (fn.fn === listenerFunc) {
|
||||||
|
removedEvents.unshift(idx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
removedEvents.forEach(function (idx) {
|
||||||
|
typeListeners.splice(idx, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!typeListeners.length) {
|
||||||
|
_this.events.splice(typeIndex, 1);
|
||||||
|
delete _this._listeners[eventType];
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies arguments to specified event type
|
||||||
|
* @param {string} eventType
|
||||||
|
* @param {*[]} eventArguments
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: '_applyEvents',
|
||||||
|
value: function _applyEvents(eventType, eventArguments) {
|
||||||
|
var typeListeners = this._listeners[eventType];
|
||||||
|
|
||||||
|
if (!typeListeners || !typeListeners.length) {
|
||||||
|
if (this._strictMode) {
|
||||||
|
throw 'No listeners specified for event: ' + eventType;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var removableListeners = [];
|
||||||
|
typeListeners.forEach(function (eeListener, idx) {
|
||||||
|
eeListener.fn.apply(null, eventArguments);
|
||||||
|
if (eeListener.once) {
|
||||||
|
removableListeners.unshift(idx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
removableListeners.forEach(function (idx) {
|
||||||
|
typeListeners.splice(idx, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits event with specified type and params.
|
||||||
|
* @param {string} type
|
||||||
|
* @param eventArgs
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: 'emit',
|
||||||
|
value: function emit(type) {
|
||||||
|
var _this2 = this;
|
||||||
|
|
||||||
|
for (var _len = arguments.length, eventArgs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
||||||
|
eventArgs[_key - 1] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._emitDelay) {
|
||||||
|
setTimeout(function () {
|
||||||
|
_this2._applyEvents.call(_this2, type, eventArgs);
|
||||||
|
}, this._emitDelay);
|
||||||
|
} else {
|
||||||
|
this._applyEvents(type, eventArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits event with specified type and params synchronously.
|
||||||
|
* @param {string} type
|
||||||
|
* @param eventArgs
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: 'emitSync',
|
||||||
|
value: function emitSync(type) {
|
||||||
|
for (var _len2 = arguments.length, eventArgs = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
|
||||||
|
eventArgs[_key2 - 1] = arguments[_key2];
|
||||||
|
}
|
||||||
|
|
||||||
|
this._applyEvents(type, eventArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys EventEmitter
|
||||||
|
*/
|
||||||
|
|
||||||
|
}, {
|
||||||
|
key: 'destroy',
|
||||||
|
value: function destroy() {
|
||||||
|
this._listeners = {};
|
||||||
|
this.events = [];
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
return EventEmitter;
|
||||||
|
}();
|
||||||
|
|
||||||
|
module.exports = EventEmitter;
|
||||||
|
|
||||||
|
},{}],3:[function(require,module,exports){
|
||||||
|
(function (root, factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
// AMD. Register as an anonymous module.
|
||||||
|
define([], factory);
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
// Node. Does not work with strict CommonJS, but
|
||||||
|
// only CommonJS-like environments that support module.exports,
|
||||||
|
// like Node.
|
||||||
|
module.exports = factory();
|
||||||
|
} else {
|
||||||
|
// Browser globals (root is window)
|
||||||
|
root.FaviconNotification = factory();
|
||||||
|
}
|
||||||
|
}(this, function() {
|
||||||
|
|
||||||
|
// Just return a value to define the module export.
|
||||||
|
// This example returns an object, but the module
|
||||||
|
// can return a function as the exported value.
|
||||||
|
|
||||||
|
// Only run in browser
|
||||||
|
if (typeof document === 'undefined') {
|
||||||
|
console.log('This script only run in browsers.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private properties
|
||||||
|
var _options = {};
|
||||||
|
|
||||||
|
var _defaults = {
|
||||||
|
url: '/favicon.ico',
|
||||||
|
color: '#eb361e',
|
||||||
|
lineColor: '#ffffff'
|
||||||
|
};
|
||||||
|
|
||||||
|
var _generatedFavicon;
|
||||||
|
var _iconElement;
|
||||||
|
|
||||||
|
// Provate methods
|
||||||
|
var _addFavicon = function(src) {
|
||||||
|
var head = document.getElementsByTagName('head')[0];
|
||||||
|
_iconElement = document.createElement('link');
|
||||||
|
_iconElement.type = 'image/x-icon';
|
||||||
|
_iconElement.rel = 'icon';
|
||||||
|
_iconElement.href = src;
|
||||||
|
|
||||||
|
// remove existing favicons
|
||||||
|
var links = document.getElementsByTagName('link');
|
||||||
|
for(var i=0, len=links.length; i < len; i++) {
|
||||||
|
var exists = (typeof(links[i]) !== 'undefined');
|
||||||
|
if (exists && (links[i].getAttribute('rel') || '').match(/\bicon\b/)) {
|
||||||
|
head.removeChild(links[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
head.appendChild(_iconElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
var _generateIcon = function(cb) {
|
||||||
|
var img = document.createElement('img');
|
||||||
|
img.src = _options.url;
|
||||||
|
|
||||||
|
img.onload = function() {
|
||||||
|
var lineWidth = 2;
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.width = img.width;
|
||||||
|
canvas.height = img.height;
|
||||||
|
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
context.clearRect(0, 0, img.width, img.height);
|
||||||
|
context.drawImage(img, 0, 0);
|
||||||
|
|
||||||
|
var centerX = img.width - (img.width / 4.5) - lineWidth;
|
||||||
|
var centerY = img.height - (img.height / 4.5) - lineWidth;
|
||||||
|
var radius = img.width / 4.5;
|
||||||
|
|
||||||
|
context.fillStyle = _options.color;
|
||||||
|
context.strokeStyle = _options.lineColor;
|
||||||
|
context.lineWidth = lineWidth;
|
||||||
|
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
|
||||||
|
context.closePath();
|
||||||
|
context.fill();
|
||||||
|
context.stroke();
|
||||||
|
|
||||||
|
cb(null, context.canvas.toDataURL());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var _setOptions = function(options) {
|
||||||
|
if (!options) {
|
||||||
|
_options = _defaults;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_options = {};
|
||||||
|
|
||||||
|
for(var key in _defaults){
|
||||||
|
_options[key] = options.hasOwnProperty(key) ? options[key] : _defaults[key];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var FaviconNotification = {
|
||||||
|
init: function(options) {
|
||||||
|
|
||||||
|
_setOptions(options);
|
||||||
|
|
||||||
|
_generateIcon(function(err, url){
|
||||||
|
_generatedFavicon = url;
|
||||||
|
});
|
||||||
|
|
||||||
|
_addFavicon(_options.url);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
add: function() {
|
||||||
|
if (!_generatedFavicon && !_iconElement) {
|
||||||
|
_setOptions();
|
||||||
|
_generateIcon(function(err, url) {
|
||||||
|
_generatedFavicon = url;
|
||||||
|
_addFavicon(url);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
_iconElement.href = _generatedFavicon;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function() {
|
||||||
|
_iconElement.href = _options.url;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return FaviconNotification;
|
||||||
|
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
},{}]},{},[1]);
|
12
Nibriboard/ClientFiles/RippleLink.js
Normal file
12
Nibriboard/ClientFiles/RippleLink.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
|
||||||
|
class RippleLink
|
||||||
|
{
|
||||||
|
constructor(socketUrl)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RippleLink;
|
7
Nibriboard/ClientFiles/Utilities.js
Normal file
7
Nibriboard/ClientFiles/Utilities.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function get(u){return new Promise(function(r,t,a){a=new XMLHttpRequest();a.onload=function(b,c){b=a.status;c=a.response;if(b>199&&b<300){r(c)}else{t(c)}};a.open("GET",u,true);a.send(null)})}
|
||||||
|
|
||||||
|
export {
|
||||||
|
get
|
||||||
|
};
|
BIN
Nibriboard/ClientFiles/favicon.ico
Normal file
BIN
Nibriboard/ClientFiles/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
15
Nibriboard/ClientFiles/index.html
Normal file
15
Nibriboard/ClientFiles/index.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8' />
|
||||||
|
<title>Nibriboard</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="canvas-main"></canvas>
|
||||||
|
|
||||||
|
<!---------------->
|
||||||
|
<link rel="stylesheet" href="Nibri.css" />
|
||||||
|
|
||||||
|
<script src="NibriClient.js" charset="utf-8"></script>
|
||||||
|
</head>
|
||||||
|
</html>
|
10
Nibriboard/ClientFiles/index.js
Normal file
10
Nibriboard/ClientFiles/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
import BoardWindow from './BoardWindow';
|
||||||
|
|
||||||
|
window.addEventListener("load", function (event) {
|
||||||
|
var canvas = document.getElementById("canvas-main"),
|
||||||
|
boardWindow = new BoardWindow(canvas);
|
||||||
|
boardWindow.nextFrame();
|
||||||
|
window.boardWindow = boardWindow;
|
||||||
|
});
|
|
@ -8,7 +8,7 @@ namespace Nibriboard
|
||||||
public static double SecondsSinceStart {
|
public static double SecondsSinceStart {
|
||||||
get {
|
get {
|
||||||
TimeSpan timeSinceStart = DateTime.Now - ServerStartTime;
|
TimeSpan timeSinceStart = DateTime.Now - ServerStartTime;
|
||||||
return timeSinceStart.TotalSeconds;
|
return Math.Round(timeSinceStart.TotalSeconds, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
75
Nibriboard/HttpEmbeddedFileHandler.cs
Normal file
75
Nibriboard/HttpEmbeddedFileHandler.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using IotWeb.Common.Http;
|
||||||
|
using MimeSharp;
|
||||||
|
|
||||||
|
using SBRLUtilities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Nibriboard
|
||||||
|
{
|
||||||
|
public class HttpEmbeddedFileHandler : IHttpRequestHandler
|
||||||
|
{
|
||||||
|
private string filePrefix;
|
||||||
|
|
||||||
|
private Mime mimeTypeFinder = new Mime();
|
||||||
|
private Dictionary<string, string> mimeTypeOverrides = new Dictionary<string, string>() {
|
||||||
|
["application/xhtml+xml"] = "text/html",
|
||||||
|
["application/tei+xml"] = "image/x-icon"
|
||||||
|
};
|
||||||
|
|
||||||
|
private List<string> embeddedFiles = new List<string>(EmbeddedFiles.ResourceList);
|
||||||
|
|
||||||
|
public HttpEmbeddedFileHandler(string inFilePrefix)
|
||||||
|
{
|
||||||
|
filePrefix = inFilePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HandleRequest(string uri, HttpRequest request, HttpResponse response, HttpContext context) {
|
||||||
|
StreamWriter responseData = new StreamWriter(response.Content) { AutoFlush = true };
|
||||||
|
if (request.Method != HttpMethod.Get) {
|
||||||
|
response.ResponseCode = HttpResponseCode.MethodNotAllowed;
|
||||||
|
response.ContentType = "text/plain";
|
||||||
|
responseData.WriteLine("Error: That method isn't supported yet.");
|
||||||
|
logRequest(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.ContentType = getMimeType(request.URI);
|
||||||
|
response.Headers.Add("content-type", response.ContentType);
|
||||||
|
|
||||||
|
string expandedFilePath = getEmbeddedFileReference(request.URI);
|
||||||
|
if (!embeddedFiles.Contains(expandedFilePath)) {
|
||||||
|
response.ResponseCode = HttpResponseCode.NotFound;
|
||||||
|
response.ContentType = "text/plain";
|
||||||
|
responseData.WriteLine("Can't find {0}.", expandedFilePath);
|
||||||
|
logRequest(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
byte[] embeddedFile = EmbeddedFiles.ReadAllBytes(expandedFilePath);
|
||||||
|
response.ContentLength = embeddedFile.Length;
|
||||||
|
response.Content.Write(embeddedFile, 0, embeddedFile.Length);
|
||||||
|
|
||||||
|
logRequest(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string getEmbeddedFileReference(string uri) {
|
||||||
|
return filePrefix + "." + uri.TrimStart("/".ToCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string getMimeType(string uri) {
|
||||||
|
string mimeType = mimeTypeFinder.Lookup(uri);
|
||||||
|
foreach (KeyValuePair<string, string> mimeMapping in mimeTypeOverrides) {
|
||||||
|
if (mimeType == mimeMapping.Key)
|
||||||
|
mimeType = mimeMapping.Value;
|
||||||
|
}
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logRequest(HttpRequest request, HttpResponse response) {
|
||||||
|
Log.WriteLine("[Http/FileHandler] {0} {1} {2} {3}", response.ResponseCode.ResponseCode(), response.ContentType, request.Method.ToString().ToUpper(), request.URI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
@ -6,7 +7,7 @@
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>Nibriboard</RootNamespace>
|
<RootNamespace>Nibriboard</RootNamespace>
|
||||||
<AssemblyName>Nibriboard</AssemblyName>
|
<AssemblyName>Nibriboard</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
@ -20,13 +21,10 @@
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
<CustomCommands>
|
<CustomCommands>
|
||||||
<CustomCommands>
|
<CustomCommands>
|
||||||
<Command>
|
<Command type="BeforeBuild" command="npm run build" workingdir="${ProjectDir}/ClientFiles" />
|
||||||
<type>BeforeBuild</type>
|
|
||||||
<command>npm run build</command>
|
|
||||||
<workingdir>${ProjectDir}/Client</workingdir>
|
|
||||||
</Command>
|
|
||||||
</CustomCommands>
|
</CustomCommands>
|
||||||
</CustomCommands>
|
</CustomCommands>
|
||||||
|
<Externalconsole>true</Externalconsole>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
|
@ -44,6 +42,12 @@
|
||||||
<Reference Include="IotWeb.Server">
|
<Reference Include="IotWeb.Server">
|
||||||
<HintPath>..\packages\IotWeb.0.8.6\lib\net45\IotWeb.Server.dll</HintPath>
|
<HintPath>..\packages\IotWeb.0.8.6\lib\net45\IotWeb.Server.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Newtonsoft.Json">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="MimeSharp">
|
||||||
|
<HintPath>..\packages\MimeSharp.1.0.0\lib\MimeSharp.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
|
@ -62,20 +66,22 @@
|
||||||
<Compile Include="Utilities\EmbeddedFiles.cs" />
|
<Compile Include="Utilities\EmbeddedFiles.cs" />
|
||||||
<Compile Include="Env.cs" />
|
<Compile Include="Env.cs" />
|
||||||
<Compile Include="RippleSpace\RippleSpaceManager.cs" />
|
<Compile Include="RippleSpace\RippleSpaceManager.cs" />
|
||||||
|
<Compile Include="HttpEmbeddedFileHandler.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Client\index.html" />
|
<EmbeddedResource Include="ClientFiles\index.html" />
|
||||||
<EmbeddedResource Include="Client\NibriClient.js" />
|
<EmbeddedResource Include="ClientFiles\NibriClient.js" />
|
||||||
<EmbeddedResource Include="Client\Nibri.css" />
|
<EmbeddedResource Include="ClientFiles\Nibri.css" />
|
||||||
|
<EmbeddedResource Include="ClientFiles\favicon.ico" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="RippleSpace\" />
|
<Folder Include="RippleSpace\" />
|
||||||
<Folder Include="Client\" />
|
|
||||||
<Folder Include="Utilities\" />
|
<Folder Include="Utilities\" />
|
||||||
|
<Folder Include="ClientFiles\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
<None Include="Client\index.js" />
|
<None Include="ClientFiles\index.js" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -24,11 +24,12 @@ namespace Nibriboard
|
||||||
httpServer = new HttpServer(Port);
|
httpServer = new HttpServer(Port);
|
||||||
httpServer.AddHttpRequestHandler(
|
httpServer.AddHttpRequestHandler(
|
||||||
"/",
|
"/",
|
||||||
new HttpResourceHandler(
|
new HttpEmbeddedFileHandler("Nibriboard.ClientFiles")
|
||||||
|
/*new HttpResourceHandler(
|
||||||
Assembly.GetExecutingAssembly(),
|
Assembly.GetExecutingAssembly(),
|
||||||
"Nibriboard",
|
"ClientFiles",
|
||||||
"index.html"
|
"index.html"
|
||||||
)
|
)*/
|
||||||
);
|
);
|
||||||
httpServer.AddWebSocketRequestHandler(
|
httpServer.AddWebSocketRequestHandler(
|
||||||
"/RipplespaceConnection",
|
"/RipplespaceConnection",
|
||||||
|
|
|
@ -36,6 +36,10 @@ namespace Nibriboard.RippleSpace
|
||||||
return $"{Plane.Name}-{X},{Y}.chunk";
|
return $"{Plane.Name}-{X},{Y}.chunk";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return $"({Plane.Name})+{X}+{Y}".GetHashCode();
|
||||||
|
}
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
ChunkReference otherChunkReference = obj as ChunkReference;
|
ChunkReference otherChunkReference = obj as ChunkReference;
|
||||||
|
|
|
@ -36,6 +36,10 @@ namespace Nibriboard.RippleSpace
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
public override int GetHashCode ()
|
||||||
|
{
|
||||||
|
return $"({Plane.Name})+{X}+{Y}".GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace SBRLUtilities
|
||||||
/// A collection of static methods for manipulating embedded resources.
|
/// A collection of static methods for manipulating embedded resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <description>
|
/// <description>
|
||||||
/// v0.2, by Starbeamrainbowlabs <feedback@starbeamrainbowlabs.com>
|
/// v0.3, by Starbeamrainbowlabs <feedback@starbeamrainbowlabs.com>
|
||||||
/// Last updated 8th August 2016.
|
/// Last updated 8th August 2016.
|
||||||
/// Licensed under MPL-2.0.
|
/// Licensed under MPL-2.0.
|
||||||
///
|
///
|
||||||
|
@ -20,6 +20,8 @@ namespace SBRLUtilities
|
||||||
/// - Initial release.
|
/// - Initial release.
|
||||||
/// v0.2 (8th August 2016):
|
/// v0.2 (8th August 2016):
|
||||||
/// - Changed namespace.
|
/// - Changed namespace.
|
||||||
|
/// v0.3 (21st January 2017):
|
||||||
|
/// - Added GetRawReader()
|
||||||
/// </description>
|
/// </description>
|
||||||
public static class EmbeddedFiles
|
public static class EmbeddedFiles
|
||||||
{
|
{
|
||||||
|
@ -52,11 +54,22 @@ namespace SBRLUtilities
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a StreamReader attached to the specified embedded resource.
|
/// Gets a StreamReader attached to the specified embedded resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The filename of the embedded resource to a StreamReader for.</param>
|
/// <param name="filename">The filename of the embedded resource to get a StreamReader of.</param>
|
||||||
/// <returns>A StreamReader attached to the specified embedded resource.</returns>
|
/// <returns>A StreamReader attached to the specified embedded resource.</returns>
|
||||||
public static StreamReader GetReader(string filename)
|
public static StreamReader GetReader(string filename)
|
||||||
{
|
{
|
||||||
return new StreamReader(Assembly.GetCallingAssembly().GetManifestResourceStream(filename));
|
return new StreamReader(GetRawReader(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a raw Stream that's attached to the specified embedded resource.
|
||||||
|
/// Useful when you want to copy an embedded resource to some other stream.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename">The path to the embedded resource.</param>
|
||||||
|
/// <returns>A raw Stream object attached to the specified file..</returns>
|
||||||
|
public static Stream GetRawReader(string filename)
|
||||||
|
{
|
||||||
|
return Assembly.GetCallingAssembly().GetManifestResourceStream(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -76,7 +89,7 @@ namespace SBRLUtilities
|
||||||
/// <returns>The specified embedded resource's content as a byte array.</returns>
|
/// <returns>The specified embedded resource's content as a byte array.</returns>
|
||||||
public static async Task<byte[]> ReadAllBytesAsync(string filename)
|
public static async Task<byte[]> ReadAllBytesAsync(string filename)
|
||||||
{
|
{
|
||||||
using (Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(filename))
|
using (Stream resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(filename))
|
||||||
using (MemoryStream temp = new MemoryStream())
|
using (MemoryStream temp = new MemoryStream())
|
||||||
{
|
{
|
||||||
await resourceStream.CopyToAsync(temp);
|
await resourceStream.CopyToAsync(temp);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="IotWeb" version="0.8.6" targetFramework="net452" />
|
<package id="IotWeb" version="0.8.6" targetFramework="net452" />
|
||||||
|
<package id="MimeSharp" version="1.0.0" targetFramework="net45" />
|
||||||
|
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
Loading…
Reference in a new issue