landscape: moved chat files to landscape directory and updated to use landscape SPA

This commit is contained in:
Logan Allen 2020-05-05 18:27:39 -04:00
parent 23cdb8f07e
commit 1bbeb8d2a4
29 changed files with 11522 additions and 90 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -26,11 +26,10 @@
[%pass /group-bind %arvo %e %connect [~ /'~groups'] %landscape]
[%pass /link-bind %arvo %e %connect [~ /'~link'] %landscape]
[%pass /dojo-bind %arvo %e %connect [~ /'~dojo'] %landscape]
[%pass /modulo-bind %arvo %e %connect [~ /'~modulo'] %landscape]
[%pass /channel-bind %arvo %e %connect [~ /'~channel'] %landscape]
[%pass /launch-bind %arvo %e %connect [~ /'~launch'] %landscape]
[%pass /landscape-bind %arvo %e %connect [~ /'~landscape'] %landscape]
[%pass /index-bind %arvo %e %connect [~ /] %landscape]
==
::
++ on-save !>(state)
++ on-load
|= old-vase=vase
@ -44,6 +43,7 @@
?+ mark (on-poke:def mark vase)
%handle-http-request
=+ !<([id=@ta req=inbound-request:eyre] vase)
~& req
:_ this
%+ give-simple-payload:app id
%+ require-authorization:app req
@ -53,6 +53,7 @@
++ handle-http-request
|= =inbound-request:eyre
^- simple-payload:http
~& inbound-request
?. =(src.bowl our.bowl) [[403 ~] ~]
=* req request.inbound-request
=/ req-line (parse-request-line url.req)
@ -63,6 +64,8 @@
++ handle-get
|= [headers=header-list:http req-line=request-line]
^- simple-payload:http
~& headers
~& req-line
?~ ext.req-line
$(req-line [[[~ %html] (snoc site.req-line 'index')] args.req-line])
?~ site.req-line not-found:gen
@ -73,21 +76,16 @@
not-found:gen
=/ file=(unit octs)
?+ site.req-line ~
[%'' %'index' ~] (get-file-at /app/launch [t.site u.ext]:req-line)
[%'~launch' *] (get-file-at /app/launch [t.site u.ext]:req-line)
[%'~link' *] (get-file-at /app/link [t.site u.ext]:req-line)
[%'~chat' *] (get-file-at /app/chat [t.site u.ext]:req-line)
[%'~dojo' *] (get-file-at /app/soto [t.site u.ext]:req-line)
[%'~groups' *] (get-file-at /app/groups [t.site u.ext]:req-line)
[%'~modulo' %session ~]
%- some
%- as-octt:mimes:html
%+ weld
"window.ship = '{+:(scow %p our.bowl)}';"
"window.urb = new Channel();"
[%'' %'index' ~] (get-file-at /app/landscape [t.site u.ext]:req-line)
[%'~link' *] (get-file-at /app/landscape [t.site u.ext]:req-line)
[%'~chat' *] (get-file-at /app/landscape [t.site u.ext]:req-line)
[%'~dojo' *] (get-file-at /app/landscape [t.site u.ext]:req-line)
[%'~groups' *] (get-file-at /app/landscape [t.site u.ext]:req-line)
[%'~landscape' %session ~]
(some (as-octt:mimes:html "window.ship = '{+:(scow %p our.bowl)}';"))
::
[%'~channel' %channel ~]
(get-file-at /app/launch/js /channel u.ext.req-line)
[%'~landscape' %channel ~]
(get-file-at /app/landscape/js /channel u.ext.req-line)
==
?~ file not-found:gen
?+ u.ext.req-line not-found:gen
@ -121,6 +119,7 @@
++ on-arvo
|= [=wire sign=sign-arvo]
^- (quip card _this)
~& [wire sign]
?+ +<.sign (on-arvo:def wire sign)
%bound [~ this]
==

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 611 B

After

Width:  |  Height:  |  Size: 611 B

View File

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 255 B

View File

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 865 B

View File

Before

Width:  |  Height:  |  Size: 1010 B

After

Width:  |  Height:  |  Size: 1010 B

View File

Before

Width:  |  Height:  |  Size: 679 B

After

Width:  |  Height:  |  Size: 679 B

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 951 B

After

Width:  |  Height:  |  Size: 951 B

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -8,8 +8,8 @@
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-touch-fullscreen" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<link rel="apple-touch-icon" href="/~chat/img/touch_icon.png">
<link rel="icon" type="image/png" href="/~launch/img/Favicon.png">
<link rel="apple-touch-icon" href="/~landscape/img/touch_icon.png">
<link rel="icon" type="image/png" href="/~landscape/img/Favicon.png">
<link rel="manifest"
href='data:application/manifest+json,{
"name": "Chat",
@ -18,13 +18,12 @@
"display": "standalone",
"background_color": "%23FFFFFF",
"theme_color": "%23000000"}' />
</head>
<body>
<div id="root"/>
<script src="/~channel/channel.js"></script>
<script src="/~modulo/session.js"></script>
<script src="/~chat/js/index.js"></script>
<script src="/~landscape/js/channel.js"></script>
<script src="/~landscape/js/session.js"></script>
<script src="/~landscape/js/index.js"></script>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.1.12.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,230 @@
class Channel {
constructor() {
this.init();
this.deleteOnUnload();
// a way to handle channel errors
//
//
this.onChannelError = (err) => {
console.error('event source error: ', err);
};
}
init() {
// unique identifier: current time and random number
//
this.uid =
new Date().getTime().toString() +
"-" +
Math.random().toString(16).slice(-6);
this.requestId = 1;
// the currently connected EventSource
//
this.eventSource = null;
// the id of the last EventSource event we received
//
this.lastEventId = 0;
// this last event id acknowledgment sent to the server
//
this.lastAcknowledgedEventId = 0;
// a registry of requestId to successFunc/failureFunc
//
// These functions are registered during a +poke and are executed
// in the onServerEvent()/onServerError() callbacks. Only one of
// the functions will be called, and the outstanding poke will be
// removed after calling the success or failure function.
//
this.outstandingPokes = new Map();
// a registry of requestId to subscription functions.
//
// These functions are registered during a +subscribe and are
// executed in the onServerEvent()/onServerError() callbacks. The
// event function will be called whenever a new piece of data on this
// subscription is available, which may be 0, 1, or many times. The
// disconnect function may be called exactly once.
//
this.outstandingSubscriptions = new Map();
}
setOnChannelError(onError = (err) => {}) {
this.onChannelError = onError;
}
deleteOnUnload() {
window.addEventListener("unload", (event) => {
this.delete();
});
}
// sends a poke to an app on an urbit ship
//
poke(ship, app, mark, json, successFunc, failureFunc) {
let id = this.nextId();
this.outstandingPokes.set(
id,
{
success: successFunc,
fail: failureFunc
}
);
this.sendJSONToChannel({
id,
action: "poke",
ship,
app,
mark,
json
});
}
// subscribes to a path on an specific app and ship.
//
// Returns a subscription id, which is the same as the same internal id
// passed to your Urbit.
subscribe(
ship,
app,
path,
connectionErrFunc = () => {},
eventFunc = () => {},
quitFunc = () => {}) {
let id = this.nextId();
this.outstandingSubscriptions.set(
id,
{
err: connectionErrFunc,
event: eventFunc,
quit: quitFunc
}
);
this.sendJSONToChannel({
id,
action: "subscribe",
ship,
app,
path
});
return id;
}
// quit the channel
//
delete() {
let id = this.nextId();
navigator.sendBeacon(this.channelURL(), JSON.stringify([{
id,
action: "delete"
}]));
}
// unsubscribe to a specific subscription
//
unsubscribe(subscription) {
let id = this.nextId();
this.sendJSONToChannel({
id,
action: "unsubscribe",
subscription
});
}
// sends a JSON command command to the server.
//
sendJSONToChannel(j) {
let req = new XMLHttpRequest();
req.open("PUT", this.channelURL());
req.setRequestHeader("Content-Type", "application/json");
if (this.lastEventId == this.lastAcknowledgedEventId) {
let x = JSON.stringify([j]);
req.send(x);
} else {
// we add an acknowledgment to clear the server side queue
//
// The server side puts messages it sends us in a queue until we
// acknowledge that we received it.
//
let x = JSON.stringify(
[{action: "ack", "event-id": parseInt(this.lastEventId)}, j]
);
req.send(x);
this.lastEventId = this.lastAcknowledgedEventId;
}
this.connectIfDisconnected();
}
// connects to the EventSource if we are not currently connected
//
connectIfDisconnected() {
if (this.eventSource) {
return;
}
this.eventSource = new EventSource(this.channelURL(), {withCredentials:true});
this.eventSource.onmessage = e => {
this.lastEventId = e.lastEventId;
let obj = JSON.parse(e.data);
let pokeFuncs = this.outstandingPokes.get(obj.id);
let subFuncs = this.outstandingSubscriptions.get(obj.id);
if (obj.response == "poke" && !!pokeFuncs) {
let funcs = pokeFuncs;
if (obj.hasOwnProperty("ok")) {
funcs["success"]();
} else if (obj.hasOwnProperty("err")) {
funcs["fail"](obj.err);
} else {
console.error("Invalid poke response: ", obj);
}
this.outstandingPokes.delete(obj.id);
} else if (obj.response == "subscribe" ||
(obj.response == "poke" && !!subFuncs)) {
let funcs = subFuncs;
// on a response to a subscribe, we only notify the caller on err
//
if (obj.hasOwnProperty("err")) {
funcs["err"](obj.err);
this.outstandingSubscriptions.delete(obj.id);
}
} else if (obj.response == "diff") {
let funcs = subFuncs;
funcs["event"](obj.json);
} else if (obj.response == "quit") {
let funcs = subFuncs;
funcs["quit"](obj);
this.outstandingSubscriptions.delete(obj.id);
} else {
console.log("Unrecognized response: ", e);
}
}
this.eventSource.onerror = e => {
this.delete();
this.init();
this.onChannelError(e);
}
}
channelURL() {
return "/~/channel/" + this.uid;
}
nextId() {
return this.requestId++;
}
};

View File

View File

@ -8,6 +8,7 @@
[%3 *]
[%4 state-zero]
==
::
+$ state-zero
$: tiles=(map term tile:launch)
tile-ordering=(list term)
@ -30,7 +31,7 @@
::
++ on-init
^- (quip card _this)
:_ this(state *[%3 state-two])
:_ this(state *[%4 state-zero])
[(launch-who q.byk.bol)]~
::
++ on-save !>(state)
@ -42,8 +43,8 @@
?: ?=(%4 -.old-state)
[~ this(state old-state)]
:_ this
%+ weld
[]~ :: TODO: kill all subscriptions
::%+ weld
:: []~ :: TODO: kill all subscriptions
:~ (launch-who q.byk.bol)
[%pass / %arvo %e %disconnect [~ /]]
==
@ -59,51 +60,27 @@
?. =(jon [%s 'disable welcome message'])
this
this(first-time %.n)
::
%launch-action
=/ act !<(action:launch vas)
?- -.act
%add
=/ beforedata (~(get by data) name.act)
=/ newdata
?~ beforedata
(~(put by data) name.act [*json url.act])
(~(put by data) name.act [jon.u.beforedata url.act])
=/ new-tile `tile:launch`[`@tas`name.act `path`subscribe.act]
:- [%pass subscribe.act %agent [our.bol name.act] %watch subscribe.act]~
%= this
tiles (~(put in tiles) new-tile)
data newdata
path-to-tile (~(put by path-to-tile) subscribe.act name.act)
==
::
%remove
:- [%pass subscribe.act %agent [our.bol name.act] %leave ~]~
%= this
tiles (~(del in tiles) [name.act subscribe.act])
data (~(del by data) name.act)
path-to-tile (~(del by path-to-tile) subscribe.act)
==
==
==
::
++ on-watch
|= =path
^- (quip card _this)
|^
?> (team:title our.bowl src.bowl)
=/ cards=(list card)
?+ path (on-watch:def path)
[%keys ~] (give %chat-update !>([%keys ~(key by inbox)]))
[%all ~] (give %chat-initial !>(inbox))
==
[cards this]
::
++ give
|= =cage
^- (list card)
[%give %fact ~ cage]~
--
(on-watch:def path)
::
:: |^
:: ?> (team:title our.bowl src.bowl)
:: =/ cards=(list card)
:: ?+ path (on-watch:def path)
:: [%keys ~] (give %chat-update !>([%keys ~(key by inbox)]))
:: [%all ~] (give %chat-initial !>(inbox))
:: ==
:: [cards this]
:: ::
:: ++ give
:: |= =cage
:: ^- (list card)
:: [%give %fact ~ cage]~
:: --
++ on-peek on-peek:def
::
++ on-arvo
@ -111,6 +88,7 @@
^- (quip card:agent:gall _this)
?: ?=(%bound +<.sin) [~ this]
(on-arvo:def wir sin)
::
++ on-agent on-agent:def
++ on-leave on-leave:def
++ on-fail on-fail:def

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,17 +0,0 @@
<!doctype html>
<html>
<head>
<title>Dojo</title>
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
<link rel="icon" type="image/png" href="/~launch/img/Favicon.png">
</head>
<body>
<div id="root">
</div>
<script src="/~channel/channel.js"></script>
<script src="/~modulo/session.js"></script>
<script src="/~launch/js/index.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -58,7 +58,7 @@ module.exports = {
output: {
filename: 'index.js',
chunkFilename: 'index.js',
path: path.resolve(urbitrc.URBIT_PIERS[0] + '/app/launch/', 'js'),
path: path.resolve(urbitrc.URBIT_PIERS[0] + '/app/landscape/', 'js'),
publicPath: '/'
},
optimization: {

View File

@ -57,7 +57,7 @@ module.exports = {
output: {
filename: 'index.js',
chunkFilename: 'index.js',
path: path.resolve(urbitrc.URBIT_PIERS[0] + '/app/launch/', 'js'),
path: path.resolve(urbitrc.URBIT_PIERS[0] + '/app/landscape/', 'js'),
publicPath: '/'
},
optimization: {

File diff suppressed because it is too large Load Diff