mirror of
https://github.com/matrix-org/sliding-sync.git
synced 2025-03-10 13:37:11 +00:00
client: use prettier; add README
This commit is contained in:
parent
3867cece40
commit
808d7f8d21
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
/syncv3
|
/syncv3
|
||||||
|
node_modules
|
||||||
|
13
client/README.md
Normal file
13
client/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
## Sliding Sync Client
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This is a basic JS client for Sliding Sync. It is designed to be easily readable and is aimed at
|
||||||
|
developers who want to implement Sliding Sync into their clients. The client is broken up into:
|
||||||
|
|
||||||
|
- `devtools.js` : Code for showing developer statistics.
|
||||||
|
- `index.js` : Entry point for the client and hooks into the DOM.
|
||||||
|
- `render.js` : Code to convert data structures into DOM nodes.
|
||||||
|
- `sync.js` : Sliding Sync code.
|
||||||
|
|
||||||
|
To understand sliding sync, you need to read `index.js` and `sync.js`. The rest of it can be ignored.
|
BIN
client/client.png
Normal file
BIN
client/client.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 438 KiB |
@ -1,14 +1,17 @@
|
|||||||
// This file contains code to render the developer tools overlay (bandwidth, list visualisations, etc)
|
// This file contains code to render the developer tools overlay (bandwidth, list visualisations, etc)
|
||||||
// You don't need to read this file to understand sliding sync.
|
// You don't need to read this file to understand sliding sync.
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the bandwidth values on the devtools display.
|
* Set the bandwidth values on the devtools display.
|
||||||
* @param {Element} domNode The node to insert the bandwidth stats to.
|
* @param {Element} domNode The node to insert the bandwidth stats to.
|
||||||
* @param {SlidingSyncConnection} conn The sliding sync connection
|
* @param {SlidingSyncConnection} conn The sliding sync connection
|
||||||
*/
|
*/
|
||||||
export function bandwidth(domNode, conn) {
|
export function bandwidth(domNode, conn) {
|
||||||
domNode.textContent = (conn.txBytes/1024.0).toFixed(2) + " KB Tx / " + (conn.rxBytes/1024.0).toFixed(2) + " KB Rx";
|
domNode.textContent =
|
||||||
|
(conn.txBytes / 1024.0).toFixed(2) +
|
||||||
|
" KB Tx / " +
|
||||||
|
(conn.rxBytes / 1024.0).toFixed(2) +
|
||||||
|
" KB Rx";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,8 +41,9 @@ export function svgify(domNode, activeLists, resp) {
|
|||||||
if (al.joinedCount > height) {
|
if (al.joinedCount > height) {
|
||||||
height = al.joinedCount;
|
height = al.joinedCount;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
if (height < (window.innerHeight/2)) { // we can double the vertical pixel height to make it easier to see
|
if (height < window.innerHeight / 2) {
|
||||||
|
// we can double the vertical pixel height to make it easier to see
|
||||||
verticalPixelHeight = 2;
|
verticalPixelHeight = 2;
|
||||||
}
|
}
|
||||||
svg.setAttribute("height", height * verticalPixelHeight);
|
svg.setAttribute("height", height * verticalPixelHeight);
|
||||||
@ -52,34 +56,52 @@ export function svgify(domNode, activeLists, resp) {
|
|||||||
const colorInvalidate = "#500000";
|
const colorInvalidate = "#500000";
|
||||||
const colorRoom = "#ffffff";
|
const colorRoom = "#ffffff";
|
||||||
activeLists.forEach((al, index) => {
|
activeLists.forEach((al, index) => {
|
||||||
const placeholders = document.createElementNS("http://www.w3.org/2000/svg",'rect');
|
const placeholders = document.createElementNS(
|
||||||
placeholders.setAttribute("x", index*2*horizontalPixelWidth);
|
"http://www.w3.org/2000/svg",
|
||||||
|
"rect"
|
||||||
|
);
|
||||||
|
placeholders.setAttribute("x", index * 2 * horizontalPixelWidth);
|
||||||
placeholders.setAttribute("y", 0);
|
placeholders.setAttribute("y", 0);
|
||||||
placeholders.setAttribute("width", horizontalPixelWidth);
|
placeholders.setAttribute("width", horizontalPixelWidth);
|
||||||
placeholders.setAttribute("height", al.joinedCount * verticalPixelHeight);
|
placeholders.setAttribute(
|
||||||
placeholders.setAttribute('fill', colorPlaceholder);
|
"height",
|
||||||
|
al.joinedCount * verticalPixelHeight
|
||||||
|
);
|
||||||
|
placeholders.setAttribute("fill", colorPlaceholder);
|
||||||
|
|
||||||
svg.appendChild(placeholders);
|
svg.appendChild(placeholders);
|
||||||
// [[0, 20], [50,60]];
|
// [[0, 20], [50,60]];
|
||||||
al.activeRanges.forEach((range) => {
|
al.activeRanges.forEach((range) => {
|
||||||
const rect = document.createElementNS("http://www.w3.org/2000/svg",'rect');
|
const rect = document.createElementNS(
|
||||||
rect.setAttribute('x',index*2*horizontalPixelWidth);
|
"http://www.w3.org/2000/svg",
|
||||||
rect.setAttribute('y',range[0]*verticalPixelHeight);
|
"rect"
|
||||||
rect.setAttribute('width',horizontalPixelWidth);
|
);
|
||||||
rect.setAttribute('height',(range[1]-range[0]) * verticalPixelHeight);
|
rect.setAttribute("x", index * 2 * horizontalPixelWidth);
|
||||||
rect.setAttribute('fill',colorInWindow);
|
rect.setAttribute("y", range[0] * verticalPixelHeight);
|
||||||
|
rect.setAttribute("width", horizontalPixelWidth);
|
||||||
|
rect.setAttribute(
|
||||||
|
"height",
|
||||||
|
(range[1] - range[0]) * verticalPixelHeight
|
||||||
|
);
|
||||||
|
rect.setAttribute("fill", colorInWindow);
|
||||||
svg.appendChild(rect);
|
svg.appendChild(rect);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const addLine = (index, y, colour, yLen) => {
|
const addLine = (index, y, colour, yLen) => {
|
||||||
const bar = document.createElementNS("http://www.w3.org/2000/svg",'rect');
|
const bar = document.createElementNS(
|
||||||
bar.setAttribute("x", index*2*horizontalPixelWidth);
|
"http://www.w3.org/2000/svg",
|
||||||
bar.setAttribute("y", y*verticalPixelHeight);
|
"rect"
|
||||||
bar.setAttribute('width',horizontalPixelWidth);
|
);
|
||||||
bar.setAttribute('height',verticalPixelHeight*(yLen?yLen:1));
|
bar.setAttribute("x", index * 2 * horizontalPixelWidth);
|
||||||
bar.setAttribute('fill', colour);
|
bar.setAttribute("y", y * verticalPixelHeight);
|
||||||
const animation = document.createElementNS("http://www.w3.org/2000/svg","animate");
|
bar.setAttribute("width", horizontalPixelWidth);
|
||||||
|
bar.setAttribute("height", verticalPixelHeight * (yLen ? yLen : 1));
|
||||||
|
bar.setAttribute("fill", colour);
|
||||||
|
const animation = document.createElementNS(
|
||||||
|
"http://www.w3.org/2000/svg",
|
||||||
|
"animate"
|
||||||
|
);
|
||||||
animation.setAttribute("attributeName", "visibility");
|
animation.setAttribute("attributeName", "visibility");
|
||||||
animation.setAttribute("from", "visible");
|
animation.setAttribute("from", "visible");
|
||||||
animation.setAttribute("to", "hidden");
|
animation.setAttribute("to", "hidden");
|
||||||
@ -87,7 +109,7 @@ export function svgify(domNode, activeLists, resp) {
|
|||||||
animation.setAttribute("repeatCount", "3");
|
animation.setAttribute("repeatCount", "3");
|
||||||
bar.appendChild(animation);
|
bar.appendChild(animation);
|
||||||
svg.appendChild(bar);
|
svg.appendChild(bar);
|
||||||
}
|
};
|
||||||
|
|
||||||
// add insertions, deletions and updates
|
// add insertions, deletions and updates
|
||||||
resp.ops.forEach((op) => {
|
resp.ops.forEach((op) => {
|
||||||
@ -98,24 +120,40 @@ export function svgify(domNode, activeLists, resp) {
|
|||||||
} else if (op.op === "UPDATE") {
|
} else if (op.op === "UPDATE") {
|
||||||
addLine(op.list, op.index, colorUpdate);
|
addLine(op.list, op.index, colorUpdate);
|
||||||
} else if (op.op === "SYNC") {
|
} else if (op.op === "SYNC") {
|
||||||
addLine(op.list, op.range[0], colorSync, op.range[1]-op.range[0]+1);
|
addLine(
|
||||||
|
op.list,
|
||||||
|
op.range[0],
|
||||||
|
colorSync,
|
||||||
|
op.range[1] - op.range[0] + 1
|
||||||
|
);
|
||||||
} else if (op.op === "INVALIDATE") {
|
} else if (op.op === "INVALIDATE") {
|
||||||
addLine(op.list, op.range[0], colorInvalidate, op.range[1]-op.range[0]+1);
|
addLine(
|
||||||
|
op.list,
|
||||||
|
op.range[0],
|
||||||
|
colorInvalidate,
|
||||||
|
op.range[1] - op.range[0] + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// this is expensive so only do it on smaller accounts
|
// this is expensive so only do it on smaller accounts
|
||||||
if (height < 500 && false) {
|
if (height < 500 && false) {
|
||||||
const fifth = horizontalPixelWidth/5;
|
const fifth = horizontalPixelWidth / 5;
|
||||||
// draw white dot for each room which has some kind of data stored
|
// draw white dot for each room which has some kind of data stored
|
||||||
activeLists.forEach((al, index) => {
|
activeLists.forEach((al, index) => {
|
||||||
for (let roomIndex of Object.keys(al.roomIndexToRoomId)) {
|
for (let roomIndex of Object.keys(al.roomIndexToRoomId)) {
|
||||||
const roomPixel = document.createElementNS("http://www.w3.org/2000/svg",'rect');
|
const roomPixel = document.createElementNS(
|
||||||
roomPixel.setAttribute("x", index*2*horizontalPixelWidth + fifth);
|
"http://www.w3.org/2000/svg",
|
||||||
roomPixel.setAttribute("y", roomIndex*verticalPixelHeight);
|
"rect"
|
||||||
roomPixel.setAttribute('width',fifth);
|
);
|
||||||
roomPixel.setAttribute('height',verticalPixelHeight);
|
roomPixel.setAttribute(
|
||||||
roomPixel.setAttribute('fill', colorRoom);
|
"x",
|
||||||
|
index * 2 * horizontalPixelWidth + fifth
|
||||||
|
);
|
||||||
|
roomPixel.setAttribute("y", roomIndex * verticalPixelHeight);
|
||||||
|
roomPixel.setAttribute("width", fifth);
|
||||||
|
roomPixel.setAttribute("height", verticalPixelHeight);
|
||||||
|
roomPixel.setAttribute("fill", colorRoom);
|
||||||
svg.appendChild(roomPixel);
|
svg.appendChild(roomPixel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
138
client/index.js
138
client/index.js
@ -1,7 +1,7 @@
|
|||||||
// This file contains the entry point for the client, as well as DOM interactions.
|
// This file contains the entry point for the client, as well as DOM interactions.
|
||||||
import { SlidingList, SlidingSyncConnection } from './sync.js';
|
import { SlidingList, SlidingSyncConnection } from "./sync.js";
|
||||||
import * as render from './render.js';
|
import * as render from "./render.js";
|
||||||
import * as devtools from './devtools.js';
|
import * as devtools from "./devtools.js";
|
||||||
|
|
||||||
let activeSessionId;
|
let activeSessionId;
|
||||||
let activeRoomId = ""; // the room currently being viewed
|
let activeRoomId = ""; // the room currently being viewed
|
||||||
@ -125,14 +125,18 @@ const intersectionObserver = new IntersectionObserver(
|
|||||||
listIndexToStartEnd[listIndex].endIndex = i;
|
listIndexToStartEnd[listIndex].endIndex = i;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("Intersection indexes:", JSON.stringify(listIndexToStartEnd));
|
console.log(
|
||||||
|
"Intersection indexes:",
|
||||||
|
JSON.stringify(listIndexToStartEnd)
|
||||||
|
);
|
||||||
// buffer range
|
// buffer range
|
||||||
const bufferRange = 5;
|
const bufferRange = 5;
|
||||||
|
|
||||||
Object.keys(listIndexToStartEnd).forEach((listIndex) => {
|
Object.keys(listIndexToStartEnd).forEach((listIndex) => {
|
||||||
let startIndex = listIndexToStartEnd[listIndex].startIndex;
|
let startIndex = listIndexToStartEnd[listIndex].startIndex;
|
||||||
let endIndex = listIndexToStartEnd[listIndex].endIndex;
|
let endIndex = listIndexToStartEnd[listIndex].endIndex;
|
||||||
startIndex = startIndex - bufferRange < 0 ? 0 : startIndex - bufferRange;
|
startIndex =
|
||||||
|
startIndex - bufferRange < 0 ? 0 : startIndex - bufferRange;
|
||||||
endIndex =
|
endIndex =
|
||||||
endIndex + bufferRange >= activeLists[listIndex].joinedCount
|
endIndex + bufferRange >= activeLists[listIndex].joinedCount
|
||||||
? activeLists[listIndex].joinedCount - 1
|
? activeLists[listIndex].joinedCount - 1
|
||||||
@ -212,15 +216,20 @@ const renderRoomContent = (roomId, refresh) => {
|
|||||||
}
|
}
|
||||||
let room = rooms.roomIdToRoom[activeRoomId];
|
let room = rooms.roomIdToRoom[activeRoomId];
|
||||||
if (!room) {
|
if (!room) {
|
||||||
console.error("renderRoomContent: unknown active room ID ", activeRoomId);
|
console.error(
|
||||||
|
"renderRoomContent: unknown active room ID ",
|
||||||
|
activeRoomId
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
document.getElementById("selectedroomname").textContent = room.name || room.room_id;
|
document.getElementById("selectedroomname").textContent =
|
||||||
|
room.name || room.room_id;
|
||||||
if (room.avatar) {
|
if (room.avatar) {
|
||||||
document.getElementById("selectedroomavatar").src =
|
document.getElementById("selectedroomavatar").src =
|
||||||
mxcToUrl(room.avatar) || "/client/placeholder.svg";
|
mxcToUrl(room.avatar) || "/client/placeholder.svg";
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("selectedroomavatar").src = "/client/placeholder.svg";
|
document.getElementById("selectedroomavatar").src =
|
||||||
|
"/client/placeholder.svg";
|
||||||
}
|
}
|
||||||
if (room.topic) {
|
if (room.topic) {
|
||||||
document.getElementById("selectedroomtopic").textContent = room.topic;
|
document.getElementById("selectedroomtopic").textContent = room.topic;
|
||||||
@ -270,7 +279,13 @@ const renderList = (container, listIndex) => {
|
|||||||
addCount += 1;
|
addCount += 1;
|
||||||
}
|
}
|
||||||
if (addCount > 0 || removeCount > 0) {
|
if (addCount > 0 || removeCount > 0) {
|
||||||
console.log("render: added ", addCount, "nodes, removed", removeCount, "nodes");
|
console.log(
|
||||||
|
"render: added ",
|
||||||
|
addCount,
|
||||||
|
"nodes, removed",
|
||||||
|
removeCount,
|
||||||
|
"nodes"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// loop all elements and modify the contents
|
// loop all elements and modify the contents
|
||||||
for (let i = 0; i < container.children.length; i++) {
|
for (let i = 0; i < container.children.length; i++) {
|
||||||
@ -278,10 +293,13 @@ const renderList = (container, listIndex) => {
|
|||||||
const roomId = listData.roomIndexToRoomId[i];
|
const roomId = listData.roomIndexToRoomId[i];
|
||||||
const r = rooms.roomIdToRoom[roomId];
|
const r = rooms.roomIdToRoom[roomId];
|
||||||
const roomNameSpan = roomCell.getElementsByClassName("roomname")[0];
|
const roomNameSpan = roomCell.getElementsByClassName("roomname")[0];
|
||||||
const roomContentSpan = roomCell.getElementsByClassName("roomcontent")[0];
|
const roomContentSpan =
|
||||||
|
roomCell.getElementsByClassName("roomcontent")[0];
|
||||||
const roomSenderSpan = roomCell.getElementsByClassName("roomsender")[0];
|
const roomSenderSpan = roomCell.getElementsByClassName("roomsender")[0];
|
||||||
const roomTimestampSpan = roomCell.getElementsByClassName("roomtimestamp")[0];
|
const roomTimestampSpan =
|
||||||
const unreadCountSpan = roomCell.getElementsByClassName("unreadcount")[0];
|
roomCell.getElementsByClassName("roomtimestamp")[0];
|
||||||
|
const unreadCountSpan =
|
||||||
|
roomCell.getElementsByClassName("unreadcount")[0];
|
||||||
unreadCountSpan.textContent = "";
|
unreadCountSpan.textContent = "";
|
||||||
unreadCountSpan.classList.remove("unreadcountnotify");
|
unreadCountSpan.classList.remove("unreadcountnotify");
|
||||||
unreadCountSpan.classList.remove("unreadcounthighlight");
|
unreadCountSpan.classList.remove("unreadcounthighlight");
|
||||||
@ -293,7 +311,8 @@ const renderList = (container, listIndex) => {
|
|||||||
roomContentSpan.style = "background: #e0e0e0; color: #e0e0e0;";
|
roomContentSpan.style = "background: #e0e0e0; color: #e0e0e0;";
|
||||||
roomSenderSpan.textContent = "";
|
roomSenderSpan.textContent = "";
|
||||||
roomTimestampSpan.textContent = "";
|
roomTimestampSpan.textContent = "";
|
||||||
roomCell.getElementsByClassName("roomavatar")[0].src = "/client/placeholder.svg";
|
roomCell.getElementsByClassName("roomavatar")[0].src =
|
||||||
|
"/client/placeholder.svg";
|
||||||
roomCell.style = "";
|
roomCell.style = "";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -305,7 +324,8 @@ const renderList = (container, listIndex) => {
|
|||||||
roomCell.getElementsByClassName("roomavatar")[0].src =
|
roomCell.getElementsByClassName("roomavatar")[0].src =
|
||||||
mxcToUrl(r.avatar) || "/client/placeholder.svg";
|
mxcToUrl(r.avatar) || "/client/placeholder.svg";
|
||||||
} else {
|
} else {
|
||||||
roomCell.getElementsByClassName("roomavatar")[0].src = "/client/placeholder.svg";
|
roomCell.getElementsByClassName("roomavatar")[0].src =
|
||||||
|
"/client/placeholder.svg";
|
||||||
}
|
}
|
||||||
if (roomId === activeRoomId) {
|
if (roomId === activeRoomId) {
|
||||||
roomCell.style = "background: #d7d7f7";
|
roomCell.style = "background: #d7d7f7";
|
||||||
@ -328,7 +348,9 @@ const renderList = (container, listIndex) => {
|
|||||||
const mostRecentEvent = r.timeline[r.timeline.length - 1];
|
const mostRecentEvent = r.timeline[r.timeline.length - 1];
|
||||||
roomSenderSpan.textContent = mostRecentEvent.sender;
|
roomSenderSpan.textContent = mostRecentEvent.sender;
|
||||||
// TODO: move to render.js
|
// TODO: move to render.js
|
||||||
roomTimestampSpan.textContent = render.formatTimestamp(mostRecentEvent.origin_server_ts);
|
roomTimestampSpan.textContent = render.formatTimestamp(
|
||||||
|
mostRecentEvent.origin_server_ts
|
||||||
|
);
|
||||||
|
|
||||||
const body = render.textForEvent(mostRecentEvent);
|
const body = render.textForEvent(mostRecentEvent);
|
||||||
if (mostRecentEvent.type === "m.room.member") {
|
if (mostRecentEvent.type === "m.room.member") {
|
||||||
@ -362,7 +384,12 @@ const indexInRange = (listIndex, i) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const doSyncLoop = async (accessToken, sessionId) => {
|
const doSyncLoop = async (accessToken, sessionId) => {
|
||||||
console.log("Starting sync loop. Active: ", activeSessionId, " this:", sessionId);
|
console.log(
|
||||||
|
"Starting sync loop. Active: ",
|
||||||
|
activeSessionId,
|
||||||
|
" this:",
|
||||||
|
sessionId
|
||||||
|
);
|
||||||
|
|
||||||
let currentPos;
|
let currentPos;
|
||||||
let currentSub = "";
|
let currentSub = "";
|
||||||
@ -380,7 +407,11 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
if (!currentPos) {
|
if (!currentPos) {
|
||||||
l.required_state = requiredStateEventsInList;
|
l.required_state = requiredStateEventsInList;
|
||||||
l.timeline_limit = 1;
|
l.timeline_limit = 1;
|
||||||
l.sort = ["by_highlight_count", "by_notification_count", "by_recency"];
|
l.sort = [
|
||||||
|
"by_highlight_count",
|
||||||
|
"by_notification_count",
|
||||||
|
"by_recency",
|
||||||
|
];
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}),
|
}),
|
||||||
@ -400,7 +431,11 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
// hold a ref to the active room ID as it may change by the time we return from doSyncRequest
|
// hold a ref to the active room ID as it may change by the time we return from doSyncRequest
|
||||||
subscribingToRoom = activeRoomId;
|
subscribingToRoom = activeRoomId;
|
||||||
}
|
}
|
||||||
resp = await syncConnection.doSyncRequest(accessToken, currentPos, reqBody);
|
resp = await syncConnection.doSyncRequest(
|
||||||
|
accessToken,
|
||||||
|
currentPos,
|
||||||
|
reqBody
|
||||||
|
);
|
||||||
currentPos = resp.pos;
|
currentPos = resp.pos;
|
||||||
// update what we think we're subscribed to.
|
// update what we think we're subscribed to.
|
||||||
if (subscribingToRoom) {
|
if (subscribingToRoom) {
|
||||||
@ -452,7 +487,8 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
// something is in this space, shift items out of the way
|
// something is in this space, shift items out of the way
|
||||||
if (gapIndex < 0) {
|
if (gapIndex < 0) {
|
||||||
console.log(
|
console.log(
|
||||||
"cannot work out where gap is, INSERT without previous DELETE! List: ", op.list,
|
"cannot work out where gap is, INSERT without previous DELETE! List: ",
|
||||||
|
op.list
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -474,7 +510,9 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
for (let i = gapIndex; i > op.index; i--) {
|
for (let i = gapIndex; i > op.index; i--) {
|
||||||
if (indexInRange(op.list, i)) {
|
if (indexInRange(op.list, i)) {
|
||||||
activeLists[op.list].roomIndexToRoomId[i] =
|
activeLists[op.list].roomIndexToRoomId[i] =
|
||||||
activeLists[op.list].roomIndexToRoomId[i - 1];
|
activeLists[op.list].roomIndexToRoomId[
|
||||||
|
i - 1
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (gapIndex < op.index) {
|
} else if (gapIndex < op.index) {
|
||||||
@ -483,13 +521,19 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
for (let i = gapIndex; i < op.index; i++) {
|
for (let i = gapIndex; i < op.index; i++) {
|
||||||
if (indexInRange(op.list, i)) {
|
if (indexInRange(op.list, i)) {
|
||||||
activeLists[op.list].roomIndexToRoomId[i] =
|
activeLists[op.list].roomIndexToRoomId[i] =
|
||||||
activeLists[op.list].roomIndexToRoomId[i + 1];
|
activeLists[op.list].roomIndexToRoomId[
|
||||||
|
i + 1
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
accumulateRoomData(op.room, rooms.roomIdToRoom[op.room.room_id] !== undefined);
|
accumulateRoomData(
|
||||||
activeLists[op.list].roomIndexToRoomId[op.index] = op.room.room_id;
|
op.room,
|
||||||
|
rooms.roomIdToRoom[op.room.room_id] !== undefined
|
||||||
|
);
|
||||||
|
activeLists[op.list].roomIndexToRoomId[op.index] =
|
||||||
|
op.room.room_id;
|
||||||
renderRoomContent(op.room.room_id);
|
renderRoomContent(op.room.room_id);
|
||||||
} else if (op.op === "UPDATE") {
|
} else if (op.op === "UPDATE") {
|
||||||
console.log("UPDATE", op.list, op.index, op.room.room_id, ";");
|
console.log("UPDATE", op.list, op.index, op.room.room_id, ";");
|
||||||
@ -507,15 +551,30 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
syncRooms.push(r.room_id);
|
syncRooms.push(r.room_id);
|
||||||
accumulateRoomData(r);
|
accumulateRoomData(r);
|
||||||
}
|
}
|
||||||
console.log("SYNC", op.list, op.range[0], op.range[1], syncRooms.join(" "), ";");
|
console.log(
|
||||||
|
"SYNC",
|
||||||
|
op.list,
|
||||||
|
op.range[0],
|
||||||
|
op.range[1],
|
||||||
|
syncRooms.join(" "),
|
||||||
|
";"
|
||||||
|
);
|
||||||
} else if (op.op === "INVALIDATE") {
|
} else if (op.op === "INVALIDATE") {
|
||||||
let invalidRooms = [];
|
let invalidRooms = [];
|
||||||
const startIndex = op.range[0];
|
const startIndex = op.range[0];
|
||||||
for (let i = startIndex; i <= op.range[1]; i++) {
|
for (let i = startIndex; i <= op.range[1]; i++) {
|
||||||
invalidRooms.push(activeLists[op.list].roomIndexToRoomId[i]);
|
invalidRooms.push(
|
||||||
|
activeLists[op.list].roomIndexToRoomId[i]
|
||||||
|
);
|
||||||
delete activeLists[op.list].roomIndexToRoomId[i];
|
delete activeLists[op.list].roomIndexToRoomId[i];
|
||||||
}
|
}
|
||||||
console.log("INVALIDATE", op.list, op.range[0], op.range[1], ";");
|
console.log(
|
||||||
|
"INVALIDATE",
|
||||||
|
op.list,
|
||||||
|
op.range[0],
|
||||||
|
op.range[1],
|
||||||
|
";"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const roomListElements = document.getElementsByClassName("roomlist");
|
const roomListElements = document.getElementsByClassName("roomlist");
|
||||||
@ -568,12 +627,21 @@ const doSyncLoop = async (accessToken, sessionId) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
devtools.svgify(document.getElementById("listgraph"), activeLists, resp);
|
devtools.svgify(
|
||||||
|
document.getElementById("listgraph"),
|
||||||
|
activeLists,
|
||||||
|
resp
|
||||||
|
);
|
||||||
}
|
}
|
||||||
console.log("active session: ", activeSessionId, " this session: ", sessionId, " terminating.");
|
console.log(
|
||||||
|
"active session: ",
|
||||||
|
activeSessionId,
|
||||||
|
" this session: ",
|
||||||
|
sessionId,
|
||||||
|
" terminating."
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const randomName = (i, long) => {
|
const randomName = (i, long) => {
|
||||||
if (i % 17 === 0) {
|
if (i % 17 === 0) {
|
||||||
return long
|
return long
|
||||||
@ -588,11 +656,17 @@ const randomName = (i, long) => {
|
|||||||
? "That’s how it is with people. Nobody cares how it works as long as it works."
|
? "That’s how it is with people. Nobody cares how it works as long as it works."
|
||||||
: "I know kung fu";
|
: "I know kung fu";
|
||||||
} else if (i % 7 === 0) {
|
} else if (i % 7 === 0) {
|
||||||
return long ? "The body cannot live without the mind." : "Free your mind";
|
return long
|
||||||
|
? "The body cannot live without the mind."
|
||||||
|
: "Free your mind";
|
||||||
} else if (i % 5 === 0) {
|
} else if (i % 5 === 0) {
|
||||||
return long ? "Perhaps we are asking the wrong questions…" : "Agent Smith";
|
return long
|
||||||
|
? "Perhaps we are asking the wrong questions…"
|
||||||
|
: "Agent Smith";
|
||||||
} else if (i % 3 === 0) {
|
} else if (i % 3 === 0) {
|
||||||
return long ? "You've been living in a dream world, Neo." : "Mr Anderson";
|
return long
|
||||||
|
? "You've been living in a dream world, Neo."
|
||||||
|
: "Mr Anderson";
|
||||||
} else {
|
} else {
|
||||||
return long ? "Mr. Wizard, get me the hell out of here! " : "Morpheus";
|
return long ? "Mr. Wizard, get me the hell out of here! " : "Morpheus";
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,9 @@ const membershipChangeText = (ev) => {
|
|||||||
if (nowMembership == prevMembership && nowMembership == "join") {
|
if (nowMembership == prevMembership && nowMembership == "join") {
|
||||||
// display name or avatar change
|
// display name or avatar change
|
||||||
if (prevContent.displayname !== ev.content.displayname) {
|
if (prevContent.displayname !== ev.content.displayname) {
|
||||||
return ev.state_key + " set their name to " + ev.content.displayname;
|
return (
|
||||||
|
ev.state_key + " set their name to " + ev.content.displayname
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (prevContent.avatar_url !== ev.content.avatar_url) {
|
if (prevContent.avatar_url !== ev.content.avatar_url) {
|
||||||
return ev.state_key + " changed their profile picture";
|
return ev.state_key + " changed their profile picture";
|
||||||
@ -79,11 +81,9 @@ export const renderEvent = (eventIdKey, ev) => {
|
|||||||
const msgCell = template.content.firstElementChild.cloneNode(true);
|
const msgCell = template.content.firstElementChild.cloneNode(true);
|
||||||
msgCell.setAttribute("id", eventIdKey);
|
msgCell.setAttribute("id", eventIdKey);
|
||||||
msgCell.getElementsByClassName("msgsender")[0].textContent = ev.sender;
|
msgCell.getElementsByClassName("msgsender")[0].textContent = ev.sender;
|
||||||
msgCell.getElementsByClassName("msgtimestamp")[0].textContent = formatTimestamp(
|
msgCell.getElementsByClassName("msgtimestamp")[0].textContent =
|
||||||
ev.origin_server_ts
|
formatTimestamp(ev.origin_server_ts);
|
||||||
);
|
|
||||||
let body = textForEvent(ev);
|
let body = textForEvent(ev);
|
||||||
msgCell.getElementsByClassName("msgcontent")[0].textContent = body;
|
msgCell.getElementsByClassName("msgcontent")[0].textContent = body;
|
||||||
return msgCell;
|
return msgCell;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
// This file contains the main sliding sync code.
|
// This file contains the main sliding sync code.
|
||||||
|
|
||||||
import * as devtools from './devtools.js';
|
import * as devtools from "./devtools.js";
|
||||||
|
|
||||||
// The default range to /always/ track on a list.
|
// The default range to /always/ track on a list.
|
||||||
// When you scroll the list, new windows are added to the first element. E.g [[0,20], [37,45]]
|
// When you scroll the list, new windows are added to the first element. E.g [[0,20], [37,45]]
|
||||||
// TODO: explain why
|
// TODO: explain why
|
||||||
const DEFAULT_RANGES = [[0, 20]];
|
const DEFAULT_RANGES = [[0, 20]];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SlidingSyncConnection is a thin wrapper around fetch() which performs a sliding sync request.
|
* SlidingSyncConnection is a thin wrapper around fetch() which performs a sliding sync request.
|
||||||
* The wrapper persists a small amount of extra data including the total number of tx/rx bytes,
|
* The wrapper persists a small amount of extra data including the total number of tx/rx bytes,
|
||||||
@ -41,7 +40,9 @@ export class SlidingSyncConnection {
|
|||||||
async doSyncRequest(accessToken, pos, reqBody) {
|
async doSyncRequest(accessToken, pos, reqBody) {
|
||||||
this.abortController = new AbortController();
|
this.abortController = new AbortController();
|
||||||
const jsonBody = JSON.stringify(reqBody);
|
const jsonBody = JSON.stringify(reqBody);
|
||||||
let resp = await fetch("/_matrix/client/v3/sync" + (pos ? "?pos=" + pos : ""), {
|
let resp = await fetch(
|
||||||
|
"/_matrix/client/v3/sync" + (pos ? "?pos=" + pos : ""),
|
||||||
|
{
|
||||||
signal: this.abortController.signal,
|
signal: this.abortController.signal,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@ -49,7 +50,8 @@ export class SlidingSyncConnection {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: jsonBody,
|
body: jsonBody,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let respBody = await resp.json();
|
let respBody = await resp.json();
|
||||||
if (respBody.ops) {
|
if (respBody.ops) {
|
||||||
@ -66,7 +68,9 @@ export class SlidingSyncConnection {
|
|||||||
if (respBody.error) {
|
if (respBody.error) {
|
||||||
this.lastError = respBody.error;
|
this.lastError = respBody.error;
|
||||||
}
|
}
|
||||||
throw new Error("/sync returned HTTP " + resp.status + " " + respBody.error);
|
throw new Error(
|
||||||
|
"/sync returned HTTP " + resp.status + " " + respBody.error
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.lastError = null;
|
this.lastError = null;
|
||||||
return respBody;
|
return respBody;
|
||||||
@ -119,12 +123,9 @@ export class SlidingList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SlidingSync {
|
class SlidingSync {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {[]SlidingList} activeLists
|
* @param {[]SlidingList} activeLists
|
||||||
*/
|
*/
|
||||||
constructor(activeLists) {
|
constructor(activeLists) {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
14
package.json
Normal file
14
package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "sliding-sync",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^2.1.2"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 4,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user