Merge branch 'master' into mp/chat/firefox-take-2

This commit is contained in:
Liam Fitzgerald 2020-04-17 12:06:34 +10:00
commit 41be649764
20 changed files with 130 additions and 81 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9c47244803d87e8ab25bc257d34336ae72e9155a5400e5635a6a5f3ae608b239
size 9952079
oid sha256:418f7512f9ff24de9c222cb4f666ef892c35376c7ee50f9f9e389c7ffa4711fc
size 10010102

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c8dfc019cdf53e0d627e1afad91e4c9cd092f767c6ba0c8c9864dd422a14d814
size 1234152
oid sha256:9d131da321b891c126f62cc587c5e27c257695ff9ae15e502356159fba7f9bf3
size 1234415

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8ebc16b420b2ce8e8bf7e6b0c611a102355f9ec013475da3cf66cc078f35e4b3
size 12458781
oid sha256:816bb2cb6b59153c611ef8bc5342c2e02eb5ef3514f8f510c5aa2387df92e9a9
size 12470565

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,17 @@
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 =
@ -40,8 +52,10 @@ class Channel {
// disconnect function may be called exactly once.
//
this.outstandingSubscriptions = new Map();
}
this.deleteOnUnload();
setOnChannelError(onError = (err) => {}) {
this.onChannelError = onError;
}
deleteOnUnload() {
@ -196,8 +210,9 @@ class Channel {
}
this.eventSource.onerror = e => {
console.error("eventSource error:", e);
this.delete();
this.init();
this.onChannelError(e);
}
}

View File

@ -344,9 +344,11 @@
=* loop-whos $
?~ whos loop-socs(socs t.socs)
=^ caz state
?: ?=(%remove -.upd)
(leave-from-peer i.socs pax.upd i.whos)
(listen-to-peer i.socs pax.upd i.whos)
?. ?=(%remove -.upd)
(listen-to-peer i.socs pax.upd i.whos)
?: =(our.bowl i.whos)
(handle-listen-action %leave i.socs)
(leave-from-peer i.socs pax.upd i.whos)
loop-whos(whos t.whos, cards (weld cards caz))
::
:: link subscriptions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -35,7 +35,7 @@
=/ dbug
!<(poke vase)
=; =tang
((slog tang) [~ this])
((%*(. slog pri 1) tang) [~ this])
?- -.dbug
%bowl [(sell !>(bowl))]~
::
@ -47,6 +47,9 @@
(ream grab.dbug)
::
%incoming
=; =tang
?^ tang tang
[%leaf "no matching subscriptions"]~
%+ murn
%+ sort ~(tap by sup.bowl)
|= [[* a=[=ship =path]] [* b=[=ship =path]]]
@ -66,6 +69,9 @@
==
::
%outgoing
=; =tang
?^ tang tang
[%leaf "no matching subscriptions"]~
%+ murn
%+ sort ~(tap by wex.bowl)
|= [[[a=wire *] *] [[b=wire *] *]]

View File

@ -40,6 +40,10 @@
==
++ both-parser
;~ pose
%+ cook
|= [author=@ date-created=@da content=@t]
^- comment
[author date-created content %.n]
new-parser
%+ cook
|= [author=@ @ @ date-created=@da @ content=@t]

View File

@ -3165,10 +3165,12 @@
?~ q.parsed
=/ =path (rail-to-path source-rail)
%- return-error
:- :- %leaf
%+ weld "ford: %hood: syntax error at "
"[{<p.p.parsed>} {<q.p.parsed>}] in {<path>}"
~
=/ lyn p.p.parsed
=/ col q.p.parsed
:~ leaf+(runt [(dec col) '-'] "^")
leaf+(trip (snag (dec lyn) (to-wain:format q.q.as-cage)))
leaf+"ford: %hood: syntax error at [{<lyn>} {<col>}] in {<path>}"
==
::
(return-result %success %hood p.u.q.parsed)
::

View File

@ -77,7 +77,7 @@ export class ChatScreen extends Component {
);
} else if (props.chatInitialized &&
!(props.station in props.inbox) &&
!(props.station in props.chatSynced) ) {
(!!props.chatSynced && !(props.station in props.chatSynced))) {
props.history.push("/~chat");
} else if (
@ -241,7 +241,7 @@ export class ChatScreen extends Component {
}
let pendingMessages = props.pendingMessages.has(props.station)
? props.pendingMessages.get(props.station).reverse()
? props.pendingMessages.get(props.station)
: [];
pendingMessages.map(function (value) {
@ -302,12 +302,14 @@ export class ChatScreen extends Component {
<div
className="overflow-y-scroll bg-white bg-gray0-d pt3 pb2 flex flex-column-reverse"
style={{ height: "100%", resize: "vertical" }}
onScroll={this.onScroll}
>
<div
ref={el => {
this.scrollElement = el;
}}></div>
{(
props.chatSynced &&
!(props.station in props.chatSynced) &&
(messages.length > 0)
) ? (
@ -320,7 +322,7 @@ export class ChatScreen extends Component {
{messageElements}
</div>
)}
}
}
render() {
const { props, state } = this;

View File

@ -22,12 +22,11 @@ export class JoinScreen extends Component {
componentDidMount() {
const { props } = this;
if (props.autoJoin !== "/undefined/undefined" &&
props.autoJoin !== "/~/undefined/undefined") {
props.autoJoin !== "/~/undefined/undefined") {
let station = props.autoJoin.split('/');
let sig = props.autoJoin.includes("/~/");
let ship = !!sig ? station[2] : station[1];
station = station.join('/');
if (
station.length < 2 ||
(!!sig && station.length < 3) ||
@ -38,7 +37,7 @@ export class JoinScreen extends Component {
});
return;
}
station = props.autoJoin;
this.setState({
station,
@ -50,7 +49,7 @@ export class JoinScreen extends Component {
componentDidUpdate(prevProps, prevState) {
const { props, state } = this;
if (state.station in props.inbox ||
props.chatSynced !== prevProps.chatSynced) {
(props.chatSynced !== prevProps.chatSynced && state.station !== '/')) {
this.setState({ awaiting: false });
props.history.push(`/~chat/room${state.station}`);
}
@ -59,24 +58,13 @@ export class JoinScreen extends Component {
onClickJoin() {
const { props, state } = this;
let text = state.station;
if (text in props.inbox ||
text.length === 0) {
this.setState({
error: true,
});
return;
}
let station = text.split('/');
let sig = state.station.includes("~/");
let ship = !!sig ? station[1] : station[0];
station = station.join('/');
let station = state.station.split('/');
let sig = state.station.includes("/~/");
let ship = !!sig ? station[2] : station[1];
if (
(!sig && station.split('/').length < 2) ||
(!!sig && station.split('/').length < 3) ||
station.length < 2 ||
(!!sig && station.length < 3) ||
!urbitOb.isValidPatp(ship)
) {
this.setState({
@ -84,16 +72,19 @@ export class JoinScreen extends Component {
});
return;
}
station = state.station.trim();
this.setState({
station,
awaiting: true,
station: `/${station}`
}, () => props.api.chatView.join(ship, `/${station}`, true))
}, () => {
props.api.chatView.join(ship, station, true)
});
}
stationChange(event) {
this.setState({
station: event.target.value
station: `/${event.target.value}`
});
}

View File

@ -8,7 +8,11 @@ import { Sigil } from '/components/lib/icons/sigil';
import { uuid, uxToHex, hexToRgba } from '/lib/util';
const DEFAULT_INPUT_HEIGHT = 28;
// line height
const INPUT_LINE_HEIGHT = 28;
const INPUT_TOP_PADDING = 3;
function getAdvance(a, b) {
@ -103,7 +107,7 @@ export class ChatInput extends Component {
this.state = {
message: '',
textareaHeight: DEFAULT_INPUT_HEIGHT,
textareaHeight: INPUT_LINE_HEIGHT + INPUT_TOP_PADDING + 1,
patpSuggestions: [],
selectedSuggestion: null
};
@ -309,9 +313,8 @@ export class ChatInput extends Component {
}
textareaInput() {
const newHeight = this.textareaRef.current.scrollHeight < DEFAULT_INPUT_HEIGHT * 8
? `${this.textareaRef.current.scrollHeight}px`
: `${DEFAULT_INPUT_HEIGHT * 8}px`
const maxHeight = INPUT_LINE_HEIGHT * 8 + INPUT_TOP_PADDING;
const newHeight = `${Math.min(maxHeight, this.textareaRef.current.scrollHeight)}px`;
this.setState({
textareaHeight: newHeight
@ -418,7 +421,7 @@ export class ChatInput extends Component {
this.setState({
message: '',
textareaHeight: DEFAULT_INPUT_HEIGHT
textareaHeight: INPUT_LINE_HEIGHT + INPUT_TOP_PADDING + 1
});
}
@ -459,8 +462,8 @@ export class ChatInput extends Component {
</div>
<div className="fr h-100 flex bg-gray0-d" style={{ flexGrow: 1 }}>
<textarea
className={"pl3 bn bg-gray0-d white-d"}
style={{ flexGrow: 1, height: state.textareaHeight, paddingTop: 6, resize: "none" }}
className={"pl3 bn bg-gray0-d white-d lh-copy"}
style={{ flexGrow: 1, height: state.textareaHeight, paddingTop: INPUT_TOP_PADDING, resize: "none" }}
autoCapitalize="none"
autoFocus={(
/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(

View File

@ -39,7 +39,7 @@ export class Root extends Component {
if (envelopes.length === 0) {
messagePreviews[stat] = false;
} else {
messagePreviews[stat] = envelopes[envelopes.length - 1];
messagePreviews[stat] = envelopes[0];
}
unreads[stat] =

View File

@ -9,9 +9,22 @@ import { LocalReducer } from '/reducers/local.js';
class Store {
constructor() {
this.state = {
this.state = this.initialState();
this.initialReducer = new InitialReducer();
this.permissionUpdateReducer = new PermissionUpdateReducer();
this.contactUpdateReducer = new ContactUpdateReducer();
this.chatUpdateReducer = new ChatUpdateReducer();
this.inviteUpdateReducer = new InviteUpdateReducer();
this.metadataReducer = new MetadataReducer();
this.localReducer = new LocalReducer();
this.setState = () => {};
}
initialState() {
return {
inbox: {},
chatSynced: {},
chatSynced: null,
contacts: {},
permissions: {},
invites: {},
@ -24,15 +37,6 @@ class Store {
pendingMessages: new Map([]),
chatInitialized: false
};
this.initialReducer = new InitialReducer();
this.permissionUpdateReducer = new PermissionUpdateReducer();
this.contactUpdateReducer = new ContactUpdateReducer();
this.chatUpdateReducer = new ChatUpdateReducer();
this.inviteUpdateReducer = new InviteUpdateReducer();
this.metadataReducer = new MetadataReducer();
this.localReducer = new LocalReducer();
this.setState = () => {};
}
setStateHandler(setState) {
@ -42,6 +46,11 @@ class Store {
handleEvent(data) {
let json = data.data;
if ('clear' in json && json.clear) {
this.setState(this.initialState());
return;
}
console.log(json);
this.initialReducer.reduce(json, this.state);
this.permissionUpdateReducer.reduce(json, this.state);

View File

@ -13,11 +13,24 @@ export class Subscription {
start() {
if (api.authTokens) {
this.firstRoundSubscription();
window.urb.setOnChannelError(this.onChannelError.bind(this));
} else {
console.error("~~~ ERROR: Must set api.authTokens before operation ~~~");
}
}
onChannelError(err) {
console.error('event source error: ', err);
console.log('initiating new channel');
this.firstRoundSubscriptionComplete = false;
setTimeout(2000, () => {
store.handleEvent({
data: { clear : true}
});
this.start();
});
}
subscribe(path, app) {
api.bind(path, 'PUT', api.authTokens.ship, app,
this.handleEvent.bind(this),

View File

@ -80,7 +80,6 @@ export class Root extends Component {
associations={associations}
invites={invites}
groups={groups}
rightPanelHide={true}
sidebarShown={state.sidebarShown}
selectedGroups={selectedGroups}
links={links}
@ -118,7 +117,6 @@ export class Root extends Component {
invites={invites}
groups={groups}
selected={resourcePath}
rightPanelHide={true}
sidebarShown={state.sidebarShown}
selectedGroups={selectedGroups}
links={links}
@ -155,7 +153,6 @@ export class Root extends Component {
invites={invites}
groups={groups}
selected={resourcePath}
rightPanelHide={true}
sidebarShown={state.sidebarShown}
selectedGroups={selectedGroups}
popout={popout}

View File

@ -167,7 +167,7 @@ a {
.cm-s-tlon span.cm-variable-3, .cm-s-tlon span.cm-type { color: black; }
.cm-s-tlon span.cm-property { color: black; }
.cm-s-tlon span.cm-operator { color: black; }
.cm-s-tlon span.cm-comment { color: black; background-color: var(--light-gray); padding:2px; border-radius: 2px;}
.cm-s-tlon span.cm-comment { color: black; background-color: var(--light-gray); display: inline-block; border-radius: 2px;}
.cm-s-tlon span.cm-string { color: var(--dark-gray); }
.cm-s-tlon span.cm-string-2 { color: var(--gray); }
.cm-s-tlon span.cm-qualifier { color: #555; }
@ -362,10 +362,6 @@ md img {
background: #333;
color: #fff;
}
.CodeMirror-selected {
background: #4d4d4d !important;
color: white;
}
.cm-s-tlon span.cm-def {
color: white;
@ -392,12 +388,7 @@ md img {
color: white;
}
.cm-s-tlon span.cm-comment {
color: black;
background-color: var(--gray);
padding: 2px;
border-radius: 2px;
}
.cm-s-tlon span.cm-string {
color: var(--gray);
}
@ -417,4 +408,18 @@ md img {
.cm-s-tlon span.cm-link {
color: var(--gray);
}
}
/* set rules w/ both color & bg-color last to preserve legibility */
.CodeMirror-selected {
background: var(--medium-gray) !important;
color: white;
}
.cm-s-tlon span.cm-comment {
color: black;
display: inline-block;
padding: 0;
background-color: rgba(255,255,255, 0.3);
border-radius: 2px;
}
}