Testing out timeline merging

This commit is contained in:
tezlm 2023-12-28 06:10:46 -08:00
parent c292609a6d
commit 5966e2cd9d
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA
5 changed files with 72 additions and 162 deletions

108
dist/src/timeline.js vendored
View file

@ -171,9 +171,12 @@ export class ThreadTimeline extends Timeline {
for (const event of events) { for (const event of events) {
const existing = this.timelineSet.timelineMap.get(event.id); const existing = this.timelineSet.timelineMap.get(event.id);
if (existing) { if (existing) {
const otherIdx = existing.getEvents().indexOf(event); // TODO
if (otherIdx === -1) // const merged = merge(this.timelineSet, this);
continue; // if (merged !== this) {
// this.emit("timelineReplace", merged);
// return 0;
// }
} }
else { else {
this.timelineSet.timelineMap.set(event.id, this); this.timelineSet.timelineMap.set(event.id, this);
@ -196,7 +199,7 @@ class TimelineSet {
return null; return null;
} }
} }
function merge2(timelines, tl) { function merge(timelines, tl) {
// [_, _, 2, 3, 4, 5, _, _, _] (current) // [_, _, 2, 3, 4, 5, _, _, _] (current)
// [_, _, _, 3, 4, 5, 6, 7, 8] (other1) // [_, _, _, 3, 4, 5, 6, 7, 8] (other1)
// [0, 1, 2, 3, 4, _, _, _, _] (other2) // [0, 1, 2, 3, 4, _, _, _, _] (other2)
@ -206,83 +209,43 @@ function merge2(timelines, tl) {
// event = 2, thisIdx = 0, otherIdx2 = 2 // event = 2, thisIdx = 0, otherIdx2 = 2
// event = 2, thisIdx = 0, otherIdx3 = 2 // event = 2, thisIdx = 0, otherIdx3 = 2
// event = 2, thisIdx = 0, otherIdx4 = 0 // event = 2, thisIdx = 0, otherIdx4 = 0
// [1, 2] + [4, 5] (events = [2, 3, 4])
const events = tl._eventList; const events = tl._eventList;
// let otherTl; for (let idx = 0; idx < events.length; idx++) {
for (const event of events) { const event = events[idx];
const other = timelines.timelineMap.get(event.id); const other = timelines.timelineMap.get(event.id);
if (!other) if (!other)
continue; continue;
if (tl === other) if (tl === other)
continue; continue;
// console.log("merge ", tl, other);
const idx = other._eventList.indexOf(event);
other._eventList.unshift(...events.slice(0, idx)); other._eventList.unshift(...events.slice(0, idx));
other.isAtBeginning = tl.isAtBeginning; other.isAtBeginning = tl.isAtBeginning;
for (const event of events.slice(0, idx)) { for (const event of events.slice(0, idx)) {
timelines.timelineMap.set(event.id, other); timelines.timelineMap.set(event.id, other);
} }
timelines.timelines.delete(tl); timelines.timelines.delete(tl);
tl.emit("timelineReplace", other);
tl = other;
}
// do it again because a thread can overlap 2 threads (before and after)
// maybe this works?
for (let idx = 0; idx < events.length; idx++) {
const event = events[idx];
const other = timelines.timelineMap.get(event.id);
if (!other)
continue;
if (tl === other)
continue;
other._eventList.unshift(...events.slice(0, idx));
other.isAtBeginning = tl.isAtBeginning;
for (const event of events.slice(0, idx)) {
timelines.timelineMap.set(event.id, other);
}
timelines.timelines.delete(tl);
tl.emit("timelineReplace", other);
tl = other; tl = other;
} }
// for (const event of events) {
// const other = timelines.timelineMap.get(event.id);
// if (!other) continue;
// if (tl === other) continue;
// console.log("merge ", tl, other);
// // const idx = other._eventList.indexOf(event);
// // other._eventList.splice(idx, other._eventList.length - idx);
// // other._eventList.push(...events.slice(idx));
// other.isAtEnd = tl.isAtEnd;
// tl = other;
// }
// for (let i = events.length - 1; i >= 0; i--) {
// const event = events[i];
// const other = timelines.timelineMap.get(event.id);
// if (!other) continue;
// if (tl === other) continue;
// const idx = other._eventList.lastIndexOf(event);
// other._eventList.push(...events.slice(idx));
// for (const event of events.slice(0, idx)) {
// timelines.timelineMap.set(event.id, other);
// }
// timelines.timelines.delete(tl);
// tl = other;
// }
return tl; return tl;
} }
// function merge(timelines: ThreadTimelineSet, events: Array<Event>): ThreadTimeline | null {
// for (const event of events) {
// const other = timelines.timelineMap.get(event.id);
// if (!other) continue;
// if (tl === other) continue;
// console.log("merge earliest with ", other);
// const idx = other._eventList.indexOf(event);
// other._eventList.unshift(...events.slice(0, idx));
// other.isAtBeginning = true;
// return other;
// }
// return null;
// }
// const realTimeline = merge(this, tl._eventList) ?? tl;
// function merge(timelines: ThreadTimelineSet, events: Array<Event>): ThreadTimeline | null {
// // [_, _, _, _, (4), 5, 6, 7]
// // [0, 1, 2, 3, 4 , 5]
// // ^
// for (const event of events) {
// const other = timelines.timelineMap.get(event.id);
// if (!other) continue;
// if (tl === other) continue;
// console.log("merge live with ", other);
// const idx = other._eventList.indexOf(event);
// other._eventList.splice(idx, other._eventList.length - idx); // delete 4, 5
// other._eventList.push(...events.slice(idx)); // push 4, 5, 6, 7
// other.isAtEnd = true;
// return other;
// }
// return null;
// }
// const realTimeline = merge(this, tl._eventList);
export class ThreadTimelineSet extends TimelineSet { export class ThreadTimelineSet extends TimelineSet {
constructor(thread) { constructor(thread) {
super(); super();
@ -322,14 +285,14 @@ export class ThreadTimelineSet extends TimelineSet {
this.timelines.add(this.live); this.timelines.add(this.live);
} }
async fetch(at, limit = 50) { async fetch(at, limit = 50) {
console.log("FETCH");
if (at === "end") { if (at === "end") {
const fetchCount = limit - this.live.getEvents().length; const fetchCount = limit - this.live.getEvents().length;
if (fetchCount > 0) if (fetchCount > 0)
await this.live.paginate("b", fetchCount); await this.live.paginate("b", fetchCount);
return this.live;
const tl = this.live; const tl = this.live;
const realTimeline = merge2(this, tl); const realTimeline = merge(this, tl);
if (realTimeline) { if (realTimeline !== tl) {
this.timelines.delete(tl); this.timelines.delete(tl);
this.live = realTimeline; this.live = realTimeline;
} }
@ -345,15 +308,16 @@ export class ThreadTimelineSet extends TimelineSet {
} }
else { else {
const tl = new ThreadTimeline(this, this.thread); const tl = new ThreadTimeline(this, this.thread);
await tl.paginate("b", limit); await tl.paginate("f", limit);
this.timelines.add(tl); const realTimeline = merge(this, tl);
return tl; if (realTimeline !== tl)
const realTimeline = merge2(this, tl) ?? tl; this.timelines.add(realTimeline);
return realTimeline; return realTimeline;
} }
} }
else { else {
// TODO: respect limit? // TODO: respect limit?
// TODO: merge threads
const existing = this.timelineMap.get(at); const existing = this.timelineMap.get(at);
if (existing) { if (existing) {
const fetchCount = limit - existing.getEvents().length; const fetchCount = limit - existing.getEvents().length;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -143,8 +143,12 @@ export class ThreadTimeline extends Timeline implements TypedEmitter<TimelineEve
for (const event of events) { for (const event of events) {
const existing = this.timelineSet.timelineMap.get(event.id); const existing = this.timelineSet.timelineMap.get(event.id);
if (existing) { if (existing) {
const otherIdx = existing.getEvents().indexOf(event); // TODO
if (otherIdx === -1) continue; // const merged = merge(this.timelineSet, this);
// if (merged !== this) {
// this.emit("timelineReplace", merged);
// return 0;
// }
} else { } else {
this.timelineSet.timelineMap.set(event.id, this); this.timelineSet.timelineMap.set(event.id, this);
room.events.set(event.id, event); room.events.set(event.id, event);
@ -170,7 +174,7 @@ abstract class TimelineSet {
} }
} }
function merge2(timelines: ThreadTimelineSet, tl: ThreadTimeline): ThreadTimeline { function merge(timelines: ThreadTimelineSet, tl: ThreadTimeline): ThreadTimeline {
// [_, _, 2, 3, 4, 5, _, _, _] (current) // [_, _, 2, 3, 4, 5, _, _, _] (current)
// [_, _, _, 3, 4, 5, 6, 7, 8] (other1) // [_, _, _, 3, 4, 5, 6, 7, 8] (other1)
// [0, 1, 2, 3, 4, _, _, _, _] (other2) // [0, 1, 2, 3, 4, _, _, _, _] (other2)
@ -181,18 +185,14 @@ function merge2(timelines: ThreadTimelineSet, tl: ThreadTimeline): ThreadTimelin
// event = 2, thisIdx = 0, otherIdx3 = 2 // event = 2, thisIdx = 0, otherIdx3 = 2
// event = 2, thisIdx = 0, otherIdx4 = 0 // event = 2, thisIdx = 0, otherIdx4 = 0
// [1, 2] + [4, 5] (events = [2, 3, 4])
const events = tl._eventList; const events = tl._eventList;
// let otherTl; for (let idx = 0; idx < events.length; idx++) {
for (const event of events) { const event = events[idx];
const other = timelines.timelineMap.get(event.id); const other = timelines.timelineMap.get(event.id);
if (!other) continue; if (!other) continue;
if (tl === other) continue; if (tl === other) continue;
// console.log("merge ", tl, other);
const idx = other._eventList.indexOf(event);
other._eventList.unshift(...events.slice(0, idx)); other._eventList.unshift(...events.slice(0, idx));
other.isAtBeginning = tl.isAtBeginning; other.isAtBeginning = tl.isAtBeginning;
@ -200,82 +200,32 @@ function merge2(timelines: ThreadTimelineSet, tl: ThreadTimeline): ThreadTimelin
timelines.timelineMap.set(event.id, other); timelines.timelineMap.set(event.id, other);
} }
timelines.timelines.delete(tl); timelines.timelines.delete(tl);
tl.emit("timelineReplace", other);
tl = other; tl = other;
} }
// for (const event of events) { // do it again because a thread can overlap 2 threads (before and after)
// const other = timelines.timelineMap.get(event.id); // maybe this works?
// if (!other) continue; for (let idx = 0; idx < events.length; idx++) {
// if (tl === other) continue; const event = events[idx];
const other = timelines.timelineMap.get(event.id);
if (!other) continue;
if (tl === other) continue;
// console.log("merge ", tl, other); other._eventList.unshift(...events.slice(0, idx));
// // const idx = other._eventList.indexOf(event); other.isAtBeginning = tl.isAtBeginning;
// // other._eventList.splice(idx, other._eventList.length - idx);
// // other._eventList.push(...events.slice(idx));
// other.isAtEnd = tl.isAtEnd;
// tl = other; for (const event of events.slice(0, idx)) {
// } timelines.timelineMap.set(event.id, other);
}
// for (let i = events.length - 1; i >= 0; i--) { timelines.timelines.delete(tl);
// const event = events[i]; tl.emit("timelineReplace", other);
// const other = timelines.timelineMap.get(event.id); tl = other;
// if (!other) continue; }
// if (tl === other) continue;
// const idx = other._eventList.lastIndexOf(event);
// other._eventList.push(...events.slice(idx));
// for (const event of events.slice(0, idx)) {
// timelines.timelineMap.set(event.id, other);
// }
// timelines.timelines.delete(tl);
// tl = other;
// }
return tl; return tl;
} }
// function merge(timelines: ThreadTimelineSet, events: Array<Event>): ThreadTimeline | null {
// for (const event of events) {
// const other = timelines.timelineMap.get(event.id);
// if (!other) continue;
// if (tl === other) continue;
// console.log("merge earliest with ", other);
// const idx = other._eventList.indexOf(event);
// other._eventList.unshift(...events.slice(0, idx));
// other.isAtBeginning = true;
// return other;
// }
// return null;
// }
// const realTimeline = merge(this, tl._eventList) ?? tl;
// function merge(timelines: ThreadTimelineSet, events: Array<Event>): ThreadTimeline | null {
// // [_, _, _, _, (4), 5, 6, 7]
// // [0, 1, 2, 3, 4 , 5]
// // ^
// for (const event of events) {
// const other = timelines.timelineMap.get(event.id);
// if (!other) continue;
// if (tl === other) continue;
// console.log("merge live with ", other);
// const idx = other._eventList.indexOf(event);
// other._eventList.splice(idx, other._eventList.length - idx); // delete 4, 5
// other._eventList.push(...events.slice(idx)); // push 4, 5, 6, 7
// other.isAtEnd = true;
// return other;
// }
// return null;
// }
// const realTimeline = merge(this, tl._eventList);
export class ThreadTimelineSet extends TimelineSet { export class ThreadTimelineSet extends TimelineSet {
// This is the one live timeline // This is the one live timeline
public client = this.thread.room.client; public client = this.thread.room.client;
@ -291,15 +241,13 @@ export class ThreadTimelineSet extends TimelineSet {
} }
public async fetch(at: EventId | "start" | "end", limit = 50): Promise<ThreadTimeline> { public async fetch(at: EventId | "start" | "end", limit = 50): Promise<ThreadTimeline> {
console.log("FETCH");
if (at === "end") { if (at === "end") {
const fetchCount = limit - this.live.getEvents().length; const fetchCount = limit - this.live.getEvents().length;
if (fetchCount > 0) await this.live.paginate("b", fetchCount); if (fetchCount > 0) await this.live.paginate("b", fetchCount);
return this.live;
const tl = this.live; const tl = this.live;
const realTimeline = merge(this, tl);
const realTimeline = merge2(this, tl); if (realTimeline !== tl) {
if (realTimeline) {
this.timelines.delete(tl); this.timelines.delete(tl);
this.live = realTimeline; this.live = realTimeline;
} }
@ -312,14 +260,14 @@ export class ThreadTimelineSet extends TimelineSet {
return existing; return existing;
} else { } else {
const tl = new ThreadTimeline(this, this.thread); const tl = new ThreadTimeline(this, this.thread);
await tl.paginate("b", limit); await tl.paginate("f", limit);
this.timelines.add(tl); const realTimeline = merge(this, tl);
return tl; if (realTimeline !== tl) this.timelines.add(realTimeline);
const realTimeline = merge2(this, tl) ?? tl;
return realTimeline; return realTimeline;
} }
} else { } else {
// TODO: respect limit? // TODO: respect limit?
// TODO: merge threads
const existing = this.timelineMap.get(at); const existing = this.timelineMap.get(at);
if (existing) { if (existing) {
const fetchCount = limit - existing.getEvents().length; const fetchCount = limit - existing.getEvents().length;

View file

@ -17,8 +17,6 @@
/* Linting */ /* Linting */
"strict": true, "strict": true,
"strictNullChecks": true, "strictNullChecks": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
}, },
"include": ["src"], "include": ["src"],