Compare commits
No commits in common. "6da9f4151911e9cc95d5b353008328ee9fbd4f07" and "5ab182e6159db0b7cbd2d0f5ae7bc46f49e3bae3" have entirely different histories.
6da9f41519
...
5ab182e615
5 changed files with 49 additions and 84 deletions
|
@ -27,7 +27,7 @@ class Chat extends ElemJS {
|
||||||
// connect to the new room's timeline updater
|
// connect to the new room's timeline updater
|
||||||
if (store.activeRoom.exists()) {
|
if (store.activeRoom.exists()) {
|
||||||
const timeline = store.activeRoom.value().timeline
|
const timeline = store.activeRoom.value().timeline
|
||||||
const beforeChangeSubscription = () => {
|
const subscription = () => {
|
||||||
// scroll anchor does not work if the timeline is scrolled to the top.
|
// scroll anchor does not work if the timeline is scrolled to the top.
|
||||||
// at the start, when there are not enough messages for a full screen, this is the case.
|
// at the start, when there are not enough messages for a full screen, this is the case.
|
||||||
// once there are enough messages that scrolling is necessary, we initiate a scroll down to activate the scroll anchor.
|
// once there are enough messages that scrolling is necessary, we initiate a scroll down to activate the scroll anchor.
|
||||||
|
@ -40,29 +40,12 @@ class Chat extends ElemJS {
|
||||||
}
|
}
|
||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
this.addSubscription("beforeChange", timeline, beforeChangeSubscription)
|
const name = "beforeChange"
|
||||||
|
this.removableSubscriptions.push({name, target: timeline, subscription})
|
||||||
//Make sure after loading scrollback we don't move the scroll position
|
timeline.subscribe(name, subscription)
|
||||||
const beforeScrollbackLoadSubscription = () => {
|
|
||||||
const lastScrollHeight = chatMessages.scrollHeight;
|
|
||||||
|
|
||||||
const afterScrollbackLoadSub = () => {
|
|
||||||
const scrollDiff = chatMessages.scrollHeight - lastScrollHeight;
|
|
||||||
chatMessages.scrollTop += scrollDiff;
|
|
||||||
|
|
||||||
timeline.unsubscribe("afterScrollbackLoad", afterScrollbackLoadSub)
|
|
||||||
}
|
|
||||||
|
|
||||||
timeline.subscribe("afterScrollbackLoad", afterScrollbackLoadSub)
|
|
||||||
}
|
|
||||||
this.addSubscription("beforeScrollbackLoad", timeline, beforeScrollbackLoadSubscription)
|
|
||||||
}
|
}
|
||||||
this.render()
|
this.render()
|
||||||
}
|
}
|
||||||
addSubscription(name, target, subscription) {
|
|
||||||
this.removableSubscriptions.push({name, target, subscription})
|
|
||||||
target.subscribe(name, subscription)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.clearChildren()
|
this.clearChildren()
|
||||||
|
|
|
@ -33,9 +33,9 @@ function eventSearch(list, event, min = 0, max = NO_MAX) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// recurse (below)
|
// recurse (below)
|
||||||
if (list[mid].data.origin_server_ts > event.data.origin_server_ts) return eventSearch(list, event, min, mid - 1)
|
if (list[mid].data.origin_server_ts > event.data.origin_server_ts) return eventSearch(list, event, min, mid-1)
|
||||||
// recurse (above)
|
// recurse (above)
|
||||||
else return eventSearch(list, event, mid + 1, max)
|
else return eventSearch(list, event, mid+1, max)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Event extends ElemJS {
|
class Event extends ElemJS {
|
||||||
|
@ -176,43 +176,16 @@ class EventGroup extends ElemJS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Displays a spinner and creates an event to notify timeline to load more messages */
|
|
||||||
class LoadMore extends ElemJS {
|
|
||||||
constructor(id) {
|
|
||||||
super("div")
|
|
||||||
this.class("c-message-notice")
|
|
||||||
this.id = id
|
|
||||||
|
|
||||||
this.child(
|
|
||||||
ejs("div").class("c-message-notice__inner").child(
|
|
||||||
ejs("span").class("loading-icon"),
|
|
||||||
ejs("span").text("Loading more...")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
const intersection_observer = new IntersectionObserver(e => this.intersectionHandler(e))
|
|
||||||
intersection_observer.observe(this.element)
|
|
||||||
}
|
|
||||||
|
|
||||||
intersectionHandler(e) {
|
|
||||||
if (e.some(e => e.isIntersecting)) {
|
|
||||||
store.rooms.get(this.id).value().timeline.loadScrollback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReactiveTimeline extends ElemJS {
|
class ReactiveTimeline extends ElemJS {
|
||||||
constructor(id, list) {
|
constructor(id, list) {
|
||||||
super("div")
|
super("div")
|
||||||
this.class("c-event-groups")
|
this.class("c-event-groups")
|
||||||
this.id = id
|
this.id = id
|
||||||
this.list = list
|
this.list = list
|
||||||
this.loadMore = new LoadMore(this.id)
|
|
||||||
this.render()
|
this.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
addEvent(event) {
|
addEvent(event) {
|
||||||
this.loadMore.remove()
|
|
||||||
// if (debug) console.log("running search", this.list, event)
|
// if (debug) console.log("running search", this.list, event)
|
||||||
// if (debug) debugger;
|
// if (debug) debugger;
|
||||||
const search = eventSearch(this.list, event)
|
const search = eventSearch(this.list, event)
|
||||||
|
@ -220,7 +193,7 @@ class ReactiveTimeline extends ElemJS {
|
||||||
if (!search.success) {
|
if (!search.success) {
|
||||||
if (search.i >= 1) {
|
if (search.i >= 1) {
|
||||||
// add at end
|
// add at end
|
||||||
this.tryAddGroups(event, [search.i - 1, search.i])
|
this.tryAddGroups(event, [search.i-1, search.i])
|
||||||
} else {
|
} else {
|
||||||
// add at start
|
// add at start
|
||||||
this.tryAddGroups(event, [0, -1])
|
this.tryAddGroups(event, [0, -1])
|
||||||
|
@ -228,8 +201,6 @@ class ReactiveTimeline extends ElemJS {
|
||||||
} else {
|
} else {
|
||||||
this.tryAddGroups(event, [search.i])
|
this.tryAddGroups(event, [search.i])
|
||||||
}
|
}
|
||||||
this.loadMore = new LoadMore(this.id)
|
|
||||||
this.childAt(0, this.loadMore)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tryAddGroups(event, indices) {
|
tryAddGroups(event, indices) {
|
||||||
|
@ -262,7 +233,6 @@ class ReactiveTimeline extends ElemJS {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.clearChildren()
|
this.clearChildren()
|
||||||
this.child(this.loadMore)
|
|
||||||
this.list.forEach(group => this.child(group))
|
this.list.forEach(group => this.child(group))
|
||||||
this.anchor = new Anchor()
|
this.anchor = new Anchor()
|
||||||
this.child(this.anchor)
|
this.child(this.anchor)
|
||||||
|
@ -274,15 +244,11 @@ class Timeline extends Subscribable {
|
||||||
super()
|
super()
|
||||||
Object.assign(this.events, {
|
Object.assign(this.events, {
|
||||||
beforeChange: [],
|
beforeChange: [],
|
||||||
afterChange: [],
|
afterChange: []
|
||||||
beforeScrollbackLoad: [],
|
|
||||||
afterScrollbackLoad: [],
|
|
||||||
})
|
})
|
||||||
Object.assign(this.eventDeps, {
|
Object.assign(this.eventDeps, {
|
||||||
beforeChange: [],
|
beforeChange: [],
|
||||||
afterChange: [],
|
afterChange: []
|
||||||
beforeScrollbackLoad: [],
|
|
||||||
afterScrollbackLoad: [],
|
|
||||||
})
|
})
|
||||||
this.room = room
|
this.room = room
|
||||||
this.id = this.room.id
|
this.id = this.room.id
|
||||||
|
@ -383,21 +349,16 @@ class Timeline extends Subscribable {
|
||||||
url.searchParams.set("access_token", lsm.get("access_token"))
|
url.searchParams.set("access_token", lsm.get("access_token"))
|
||||||
url.searchParams.set("from", this.from)
|
url.searchParams.set("from", this.from)
|
||||||
url.searchParams.set("dir", "b")
|
url.searchParams.set("dir", "b")
|
||||||
url.searchParams.set("limit", "20")
|
url.searchParams.set("limit", 10)
|
||||||
const filter = {
|
const filter = {
|
||||||
lazy_load_members: true
|
lazy_load_members: true
|
||||||
}
|
}
|
||||||
url.searchParams.set("filter", JSON.stringify(filter))
|
url.searchParams.set("filter", JSON.stringify(filter))
|
||||||
|
|
||||||
const root = await fetch(url.toString()).then(res => res.json())
|
const root = await fetch(url.toString()).then(res => res.json())
|
||||||
|
|
||||||
this.broadcast("beforeScrollbackLoad")
|
|
||||||
|
|
||||||
this.from = root.end
|
this.from = root.end
|
||||||
// console.log(this.updateEvents, root.chunk)
|
console.log(this.updateEvents, root.chunk)
|
||||||
if (root.state) this.updateStateEvents(root.state)
|
if (root.state) this.updateStateEvents(root.state)
|
||||||
this.updateEvents(root.chunk)
|
this.updateEvents(root.chunk)
|
||||||
this.broadcast("afterScrollbackLoad")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
send(body) {
|
send(body) {
|
||||||
|
@ -424,8 +385,32 @@ class Timeline extends Subscribable {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
})
|
})/*.then(() => {
|
||||||
|
const subscription = () => {
|
||||||
|
this.removeEvent(id)
|
||||||
|
this.unsubscribe("afterChange", subscription)
|
||||||
|
}
|
||||||
|
this.subscribe("afterChange", subscription)
|
||||||
|
})*/
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
getGroupedEvents() {
|
||||||
|
let currentSender = Symbol("N/A")
|
||||||
|
let groups = []
|
||||||
|
let currentGroup = []
|
||||||
|
for (const event of this.list) {
|
||||||
|
if (event.sender === currentSender) {
|
||||||
|
currentGroup.push(event)
|
||||||
|
} else {
|
||||||
|
if (currentGroup.length) groups.push(currentGroup)
|
||||||
|
currentGroup = [event]
|
||||||
|
currentSender = event.sender
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentGroup.length) groups.push(currentGroup)
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {Timeline}
|
module.exports = {Timeline}
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
@keyframes spin
|
|
||||||
0%
|
|
||||||
transform: rotate(0deg)
|
|
||||||
100%
|
|
||||||
transform: rotate(180deg)
|
|
||||||
|
|
||||||
.loading-icon
|
|
||||||
display: inline-block
|
|
||||||
background-color: #ccc
|
|
||||||
width: 12px
|
|
||||||
height: 12px
|
|
||||||
margin-right: 6px
|
|
||||||
animation: spin 0.7s infinite
|
|
|
@ -1,8 +1,6 @@
|
||||||
@use "./base"
|
@use "./base"
|
||||||
@use "./loading.sass"
|
|
||||||
@use "./colors.sass" as c
|
@use "./colors.sass" as c
|
||||||
|
|
||||||
|
|
||||||
.main
|
.main
|
||||||
justify-content: center
|
justify-content: center
|
||||||
align-items: center
|
align-items: center
|
||||||
|
@ -43,6 +41,19 @@
|
||||||
.form-error
|
.form-error
|
||||||
color: red
|
color: red
|
||||||
|
|
||||||
|
@keyframes spin
|
||||||
|
0%
|
||||||
|
transform: rotate(0deg)
|
||||||
|
100%
|
||||||
|
transform: rotate(180deg)
|
||||||
|
|
||||||
|
.loading-icon
|
||||||
|
display: inline-block
|
||||||
|
background-color: #ccc
|
||||||
|
width: 12px
|
||||||
|
height: 12px
|
||||||
|
margin-right: 6px
|
||||||
|
animation: spin 0.7s infinite
|
||||||
|
|
||||||
input, button
|
input, button
|
||||||
font-family: inherit
|
font-family: inherit
|
||||||
|
|
|
@ -5,4 +5,3 @@
|
||||||
@use "./components/chat"
|
@use "./components/chat"
|
||||||
@use "./components/chat-input"
|
@use "./components/chat-input"
|
||||||
@use "./components/anchor"
|
@use "./components/anchor"
|
||||||
@use "./loading"
|
|
||||||
|
|
Loading…
Reference in a new issue