0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-10-30 18:39:02 +01:00
construct/modules/static/js/room/scroll.js
2018-02-05 21:24:34 -08:00

188 lines
4.1 KiB
JavaScript

/*
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
*/
'use strict';
/**************************************
* Scrolling & Viewport interface
*
*/
room.scroll = {};
/* Scrollback */
room.scroll.back = function(count = 128)
{
return this.scroll.io(count, "b");
}
room.scroll.front = function(count = 128)
{
return this.scroll.io(count, "f");
};
room.scroll.at = function(e = $(this.dom.items()))
{
return mc.scroll.at(e);
};
room.scroll.at.top = function(e = $(this.dom.items()))
{
return this.scroll.at(e) == 0;
};
room.scroll.at.bottom = function(e = $(this.dom.items()))
{
return mc.scroll.at.bottom(e);
};
room.scroll.to = function(pos, speed = "slow", e = $(this.dom.items()))
{
return mc.scroll.to(e, pos, speed);
};
room.scroll.to.top = function(speed = "slow", e = $(this.dom.items()))
{
return mc.scroll.to.top(e, speed);
};
room.scroll.to.bottom = function(speed = "slow", e = $(this.dom.items()))
{
return mc.scroll.to.bottom(e, speed);
};
room.scroll.to.event = function(event_id, speed = "slow", e = $(this.dom.items()))
{
let st = $(e).prop("scrollTop");
let item = $(this.dom.item(event_id));
let rect = mc.get_rect(item);
this.scroll.to(st + rect.top - 40, "fast", e);
};
/**
* top: the percentage of area invisible above the viewport.
* view: the percentage of the area in the viewport.
* bottom: the percentage of the area invisible below the viewport.
*/
room.scroll.pct = function(e = $(this.dom.items()))
{
return mc.scroll.pct(e);
};
/* Scroll event handler */
room.scroll.on = function(event)
{
let e = event.delegateTarget;
let pos = this.scroll.at(e);
if(this.control.scroll_pos_last == pos)
return;
let going_up = pos < this.control.scroll_pos_last;
let going_down = pos > this.control.scroll_pos_last;
let at_top = this.scroll.at.top(e);
let at_bottom = this.scroll.at.bottom(e);
let pcts = this.scroll.pct(e);
/*
debug.object(
{
pos: pos,
at_top: at_top,
at_bottom: at_bottom,
pcts: pcts,
going_up: going_up,
going_down: going_down
}, 3);
*/
if(going_up && !at_bottom && this.control.mode == "LIVE" && pcts.bottom > 0.05)
{
this.control.mode = "PAST";
mc.ng.apply();
}
else if(at_bottom && this.control.mode == "PAST" && pcts.bottom < 0.025)
{
this.control.mode = "LIVE";
mc.ng.apply();
}
if(at_top || (going_up && pcts.top < 0.15))
this.scroll.back(48);
if(!at_bottom && going_down && pcts.bottom < 0.15)
this.scroll.front(48);
this.control.scroll_pos_last = pos;
this.control.scroll_pct_last = pcts;
};
room.scroll.io = async function(limit = 64, dir = "b")
{
if(this.opts.local)
return;
if(this.control.scroll_requested)
return;
if(this.control.messages.stop == dir)
return;
else
this.control.messages.stop = null;
if(this.control.messages.dir == dir)
{
this.control.messages.start = this.control.messages.end;
delete this.control.messages.end;
} else {
this.control.messages.dir = dir;
delete this.control.messages.end;
}
this.control.messages.limit = limit;
this.control.scroll_requested = true;
room.sync.activity.call(this);
let opts =
{
query:
{
from: this.control.messages.start,
to: this.control.messages.end,
dir: this.control.messages.dir,
limit: this.control.messages.limit,
},
};
let request = mc.m.rooms.messages.get(this.id, opts); try
{
let data = await request.response;
let count = this.scroll.io.handle(data);
this.control.messages.stop = count? null : dir;
this.control.messages.start = data.start;
this.control.messages.end = data.end;
}
catch(e)
{
console.error(e);
}
finally
{
this.control.scroll_requested = false;
}
};
room.scroll.io.handle = function(data)
{
let events = data.chunk;
this.timeline.insert(events);
return events.length;
};