Skip to content
Snippets Groups Projects
Commit bc94d885 authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Started work on rewrite

parent bd034a29
Branches
No related tags found
No related merge requests found
function load(url, data=null) {
return new Promise((resolve, reject) => {
const encodeData = (data) => {
const result = [];
for (key in data) {
if (data.hasOwnProperty(key)) {
result.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
}
}
return result.join("");
};
const request = new XMLHttpRequest();
const method = data===null ? "GET" : "POST";
request.onreadystatechange = () => {
if (request.readyState == 4) {
if (request.status >= 200 && request.status < 300) {
try {
resolve(JSON.parse(request.responseText));
} catch (e) {
reject(e);
}
} else {
reject(request.status + ": " + request.responseText);
}
}
};
request.open(method, url, true);
if (data!==null) {
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
request.send(encodeData(data));
} else {
request.send();
}
});
}
\ No newline at end of file
class MircColorHandler {
render(text) {
const CODE_BOLD = "\x02";
const CODE_COLOR = "\x03";
const CODE_ITALIC = "\x1D";
const CODE_UNDERLINE = "\x1F";
const CODE_SWAP = "\x16";
const CODE_RESET = "\x0F";
const readNumber = function (str, start, end) {
if (start >= end || start >= str.length)
return -1;
else
return parseInt(str.substr(start, end), 10);
};
const findEndOfNumber = function (str, start) {
const validCharCodes = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
let i;
let tmp = str.substr(start, 2);
for (i = 0; i < 2 && i < tmp.length; i++) {
if (validCharCodes.indexOf(tmp.charAt(i)) === -1)
break
}
return i + start;
};
const unescape = function (str) {
return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
};
const fromState = function (state) {
const elem = document.createElement("span");
if (state.bold) elem.classList.add("irc_bold");
if (state.italic) elem.classList.add("irc_italic");
if (state.underline) elem.classList.add("irc_underline");
if (state.foreground!==null) elem.dataset["irc_foreground"] = state.foreground;
if (state.background!==null) elem.dataset["irc_background"] = state.background;
return elem;
};
let apply = function (lastTag, str, i, normalCount, nodes) {
const s = unescape(str.substr(i - normalCount, normalCount));
if (normalCount === 0)
return;
lastTag.appendChild(document.createTextNode(s));
nodes.push(lastTag);
};
const formatString = function (str) {
if (!str)
return document.createTextNode("");
let state = {
bold: false,
italic: false,
underline: false,
foreground: null,
background: null
};
let lastTag = fromState(state);
let nodes = [];
let normalCount = 0;
for (let i = 0; i < str.length; i++) {
const character = str.charAt(i);
switch (character) {
case CODE_BOLD: {
apply(lastTag, str, i, normalCount, nodes);
normalCount = 0;
state.bold = !state.bold;
lastTag = fromState(state);
}
break;
case CODE_ITALIC: {
apply(lastTag, str, i, normalCount, nodes);
normalCount = 0;
state.italic = !state.italic;
lastTag = fromState(state);
}
break;
case CODE_UNDERLINE: {
apply(lastTag, str, i, normalCount, nodes);
normalCount = 0;
state.underline = !state.underline;
lastTag = fromState(state);
}
break;
case CODE_COLOR: {
apply(lastTag, str, i, normalCount, nodes);
normalCount = 0;
let foregroundStart = i + 1;
let foregroundEnd = findEndOfNumber(str, foregroundStart);
if (foregroundEnd > foregroundStart) {
let foreground = readNumber(str, foregroundStart, foregroundEnd);
let background = -1;
let backgroundStart = foregroundEnd + 1;
let backgroundEnd = -1;
if (str.length > foregroundEnd && str.charAt(foregroundEnd) === ',') {
backgroundEnd = findEndOfNumber(str, backgroundStart);
background = readNumber(str, backgroundStart, backgroundEnd);
}
if (state.foreground !== null) {
if (background === -1)
background = state.background;
}
state.foreground = foreground === -1 ? null : foreground;
state.background = background === -1 ? null : background;
lastTag = fromState(state);
i = ((backgroundEnd === -1) ? foregroundEnd : backgroundEnd ) - 1;
} else if (state.foreground !== null) {
state.foreground = null;
state.background = null;
lastTag = fromState(state);
}
}
break;
case CODE_SWAP: {
apply(lastTag, str, i, normalCount, nodes);
normalCount = 0;
if (state.foreground != null) {
state.foreground = state.background;
state.background = state.foreground;
lastTag = fromState(state);
}
}
break;
case CODE_RESET: {
apply(lastTag, str, i, normalCount, nodes);
normalCount = 0;
state.bold = false;
state.italic = false;
state.underline = false;
state.foreground = null;
state.background = null;
lastTag = fromState(state);
}
break;
default: {
normalCount++;
}
break;
}
}
apply(lastTag, str, str.length, normalCount, nodes);
return nodes;
};
return formatString(text);
}
highlight(text) {
let nodes = [];
let highlight = false;
let patternStart = "<b>";
let patternEnd = "</b>";
let pattern = patternStart;
let groupStart = 0;
let addFragment = function () {
const groupEnd = index === -1 ? text.length : index;
if (groupStart == groupEnd)
return;
if (highlight) {
const highlightNode = document.createElement("span");
highlightNode.classList.add("irc_highlight");
highlightNode.appendChild(document.createTextNode(text.substr(groupStart, groupEnd - groupStart)));
nodes.push(highlightNode);
} else {
nodes.push(document.createTextNode(text.substr(groupStart, groupEnd - groupStart)));
}
};
let index = -1;
while ((index = text.indexOf(pattern, groupStart)) < text.length && index > 0) {
addFragment();
groupStart = index + pattern.length;
pattern = highlight ? patternStart : patternEnd;
highlight = !highlight;
}
addFragment();
return nodes;
}
}
\ No newline at end of file
const sendercolor = function (nick) {
var sendercolors = [
class SenderColorHandler {
constructor(sendercolors = [
"#e90d7f",
"#8e55e9",
"#b30e0e",
......@@ -16,28 +16,30 @@ const sendercolor = function (nick) {
"#9d54b3",
"#b39775",
"#3176b3"
];
]) {
this.sendercolors = sendercolors;
}
var reflect = function (crc, n) {
var j = 1, crcout = 0;
for (var i = (1 << (n - 1)); i > 0; i >>= 1) {
static reflect(crc, n) {
let j = 1, crcout = 0;
for (let i = (1 << (n - 1)); i > 0; i >>= 1) {
if ((crc & i) > 0) {
crcout |= j;
}
j <<= 1;
}
return crcout;
};
}
var qChecksum = function (str) {
var crc = 0xffff;
var crcHighBitMask = 0x8000;
static qChecksum(str) {
let crc = 0xffff;
const crcHighBitMask = 0x8000;
for (var i = 0; i < str.length; i++) {
var b = str.codePointAt(i);
var c = reflect(b, 8);
for (var j = 0x80; j > 0; j >>= 1) {
var highBit = crc & crcHighBitMask;
for (let i = 0; i < str.length; i++) {
const b = str.codePointAt(i);
const c = SenderColorHandler.reflect(b, 8);
for (let j = 0x80; j > 0; j >>= 1) {
let highBit = crc & crcHighBitMask;
crc <<= 1;
if ((c & j) > 0) {
highBit ^= crcHighBitMask;
......@@ -48,17 +50,19 @@ const sendercolor = function (nick) {
}
}
crc = reflect(crc, 16);
crc = SenderColorHandler.reflect(crc, 16);
crc ^= 0xffff;
crc &= 0xffff;
return crc;
};
}
var senderIndex = function (str) {
var nickToHash = str.replace(/_*$/, "").toLowerCase();
return qChecksum(nickToHash) & 0xF;
};
static senderIndex(str) {
const nickToHash = str.replace(/_*$/, "").toLowerCase();
return SenderColorHandler.qChecksum(nickToHash) & 0xF;
}
return sendercolors[senderIndex(nick)];
};
\ No newline at end of file
nickToColor(nick) {
return this.sendercolors[SenderColorHandler.senderIndex(nick)];
}
}
\ No newline at end of file
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: local('Material Icons'),
local('MaterialIcons-Regular'),
url(MaterialIcons-Regular.woff2) format('woff2'),
url(MaterialIcons-Regular.woff) format('woff'),
url(MaterialIcons-Regular.ttf) format('truetype');
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}
/*
var state = {
query: "",
selected_history_entry: -1,
......@@ -5,6 +6,31 @@ var state = {
open: []
};
var bind_click = function (elem, handler) {
elem.unbind("mousedown");
elem.unbind("mouseup");
elem.mousedown(function (e) {
getSelection().removeAllRanges();
});
elem.mouseup(function (e) {
if (e.which === 1 && getSelection().isCollapsed)
handler(e);
});
};
var make_select_buffer = function (buffer, id) {
state.buffers[buffer].selected = true;
apply_selection();
};
var make_select_context = function (buffer, id) {
state.buffers[buffer].selected = true;
state.buffers[buffer].contexts[id].selected = true;
apply_selection();
};
var search_history = {
max_size: 8,
get: function () {
......@@ -60,33 +86,20 @@ var render = {
render.no_more();
},
buffer: {
auto: function (buffer) {
return (buffer.selected) ? render.buffer.full(buffer) : render.buffer.overview(buffer);
},
overview: function (buffer) {
return (
"<buffer id='buffer" + buffer.id + "' data-bufferid='" + buffer.id + "'>" + (
"<h2>" + buffer.network + "" + buffer.name + "</h2>" +
"<article>" + (
buffer.contexts.slice(0, 4).map(render.context.auto).join("") +
"<inline-button class='load_more'>" + (buffer.contexts.length > 4 ? translation.results.show_more : translation.results.load_more) + "</inline-button>"
) + "</article>"
) + "</buffer>"
)
},
full: function (buffer) {
return (
"<buffer id='buffer" + buffer.id + "' data-bufferid='" + buffer.id + "' class='selected'>" + (
"<buffer id='buffer" + buffer.id + "' data-bufferid='" + buffer.id + "'>" + (
"<h2>" + buffer.network + " – " + buffer.name + "</h2>" +
"<article>" + (
buffer.contexts.map(render.context.auto).join("") +
buffer.contexts.map(render.context.full).join("") +
"<inline-button class='load_more'>" + translation.results.load_more + "</inline-button>"
) + "</article>"
) + "</buffer>"
)
},
update: function (id) {
var renderedBuffer = render.buffer.auto(state.buffers[id]);
$("#buffer" + id).unbind();
var renderedBuffer = render.buffer.full(state.buffers[id]);
if ($("#buffer" + id).length)
$("#buffer" + id).replaceWith(renderedBuffer);
else
......@@ -97,8 +110,8 @@ var render = {
attach: function (elem) {
elem.unbind();
var id = elem.data("bufferid");
elem.click(make_toggle_buffer(id));
elem.find(".load_more").click(function (e) {
bind_click(elem, make_toggle_buffer(id));
bind_click(elem.find(".load_more"), function (e) {
e.stopPropagation();
if (state.buffers[id].selected || state.buffers[id].contexts.length <= 4)
......@@ -107,34 +120,29 @@ var render = {
deselect_buffers(id);
state.open.push(make_toggle_buffer(id));
state.buffers[id].selected = true;
render.buffer.update(id);
});
state.buffers[id].contexts.forEach(function (context) {
var ctx = elem.find("#context" + context.id);
if (ctx.length)
if (ctx.length) {
ctx.unbind();
render.context.attach(ctx);
}
})
}
},
context: {
auto: function (context) {
return context.selected ? render.context.full(context) : render.context.overview(context);
},
overview: function (context) {
return (
"<context id='context" + context.id + "' data-contextid='" + context.id + "' data-bufferid='" + context.buffer + "'>" + (
render.message(context.original, true, true)
) + "</context>"
)
},
full: function (context) {
return (
"<context id='context" + context.id + "' data-contextid='" + context.id + "' data-bufferid='" + context.buffer + "' class='selected'>" + (
"<inline-button class='load_before'>" + translation.context.load_earlier + "</inline-button>" + (
context.before.map(render.message).join("") +
"<context id='context" + context.id + "' data-contextid='" + context.id + "' data-bufferid='" + context.buffer + "'>" + (
"<div class='before'>" +(
"<inline-button class='load_before'>" + translation.context.load_earlier + "</inline-button>" +
context.before.map(render.message).join("")
) + "</div>" +
render.message(context.original, true) +
"<div class='after'>" +(
context.after.map(render.message).join("")
) + "<inline-button class='load_after'>" + translation.context.load_later + "</inline-button>"
+ "<inline-button class='load_after'>" + translation.context.load_later + "</inline-button>"
) + "</div>"
) + "</context>"
)
},
......@@ -146,17 +154,17 @@ var render = {
console.log("Undefined buffer: " + bufferid);
}
elem.click(function (e) {
bind_click(elem, function (e) {
e.stopPropagation();
});
$("#message" + state.buffers[bufferid].contexts[id].original.messageid).unbind();
$("#message" + state.buffers[bufferid].contexts[id].original.messageid).click(make_toggle_context(bufferid, id));
elem.find(".load_before").click(function (e) {
bind_click($("#message" + state.buffers[bufferid].contexts[id].original.messageid), make_toggle_context(bufferid, id));
bind_click(elem.find(".load_before"), function (e) {
e.stopPropagation();
load.context.earlier(bufferid, id, 5);
});
elem.find(".load_after").click(function (e) {
bind_click(elem.find(".load_after"), function (e) {
e.stopPropagation();
load.context.later(bufferid, id, 5);
......@@ -166,7 +174,7 @@ var render = {
message: function (message, highlight, preview) {
var content = preview === true ? message.preview : message.message;
return (
"<message id='message" + message.messageid + "' data-messageid='" + message.messageid + "' " + (highlight === true ? "" : "class='faded'") + ">" + (
"<message id='message" + message.messageid + "' data-messageid='" + message.messageid + "' " + (highlight === true ? "class='original'" : "") + ">" + (
"<time>" + new Date(message.time.replace(" ", "T") + "Z").toLocaleString() + "</time>" +
"<div class='container'>" + (
"<sender style='color: " + sendercolor(message.sender.split("!")[0]) + "'>" + message.sender.split("!")[0] + "</sender>" +
......@@ -187,6 +195,10 @@ var render = {
if (history.length == 0) {
container.append("<p>" + translation.history.error_unavailable + "</p>");
}
"<li id='history" + id + "' data-query='" + btoa(query) + "'>" + (
"<span class='icon'>history</span>" +
query
) + "</li>"
},
item: function (id, query) {
return (
......@@ -199,7 +211,7 @@ var render = {
attach: function (elem) {
elem.unbind();
var query = atob(elem.data("query"));
elem.click(function (e) {
bind_click(elem, function (e) {
e.stopPropagation();
$("#q").val(query);
......@@ -244,7 +256,6 @@ var load = {
"id": ctx++
};
}));
render.buffer.update(id);
});
}
},
......@@ -264,7 +275,7 @@ var load = {
load.context.raw(earliest, bufferid, amount, 0, function (messages) {
var newmsgs = messages.slice(0, messages.length - 1);
context.before = newmsgs.concat(context.before);
render.buffer.update(bufferid);
$("#buffer"+bufferid+" #context"+contextid+" .before .load_before").after(newmsgs.map(render.message).join(""))
})
},
later: function (bufferid, contextid, amount) {
......@@ -274,7 +285,7 @@ var load = {
load.context.raw(latest, bufferid, 0, amount, function (messages) {
var newmsgs = messages.slice(1);
context.after = context.after.concat(newmsgs);
render.buffer.update(bufferid);
$("#buffer"+bufferid+" #context"+contextid+" .after .load_after").before(newmsgs.map(render.message).join(""))
})
}
}
......@@ -284,7 +295,7 @@ var search = function () {
var results = $("#results");
results.children().remove();
$("#q").blur();
results.click(deselect_buffers);
bind_click(results, deselect_buffers);
state = {
"query": $("#q").val(),
"selected_history_entry": -1,
......@@ -305,21 +316,21 @@ var deselect_buffers = function (except) {
if (key !== except && buffer.selected) {
buffer.selected = false;
unselect_contexts(key);
render.buffer.update(key);
}
});
state.open = [];
};
var unselect_contexts = function (bufferid) {
state.buffers[bufferid].contexts = state.buffers[bufferid].contexts.map(function (context) {
state.buffers[bufferid].contexts.forEach(function (context) {
context.selected = false;
return context
})
};
var make_toggle_buffer = function (id) {
return function (e) {
console.log("toggle buffer " + id);
e.stopPropagation();
if (state.buffers[id].selected) {
......@@ -331,12 +342,14 @@ var make_toggle_buffer = function (id) {
state.open.push(make_toggle_buffer(id));
state.buffers[id].selected = true;
}
render.buffer.update(id);
apply_selection();
}
};
var make_toggle_context = function (buffer, id) {
return function (e) {
console.log("toggle_context " + buffer + " " + id);
e.stopPropagation();
var context = state.buffers[buffer].contexts[id];
......@@ -356,10 +369,19 @@ var make_toggle_context = function (buffer, id) {
if (context.before.length === 0) load.context.earlier(buffer, id, 5);
if (context.after.length === 0) load.context.later(buffer, id, 5);
}
render.buffer.update(buffer);
apply_selection();
}
};
var apply_selection = function () {
$.each(state.buffers, function (key, buffer) {
$("#buffer"+key).toggleClass("selected", state.buffers[key].selected);
state.buffers[key].contexts.map(function (ctx) {
$("#buffer"+key+" #context"+ctx.id).toggleClass("selected", ctx.selected);
})
});
};
var hashChange = function () {
var input = $("#q");
var newquery = decodeURIComponent(location.hash.substr(1));
......@@ -381,28 +403,7 @@ var init = function () {
$(window).on("hashchange", hashChange);
$("#q").on("keypress", function (e) {
var key = e.which || e.keyCode;
if (key === 13) {
search();
}
if (key === 40) {
$("#history" + state.selected_history_entry).removeClass("selected");
state.selected_history_entry = (state.selected_history_entry + 1) % get_history().length;
$("#q").val(get_history().reverse()[state.selected_history_entry]);
$("#history" + state.selected_history_entry).addClass("selected");
} else if (key === 38) {
$("#history" + state.selected_history_entry).removeClass("selected");
if (state.selected_history_entry === 0) {
state.selected_history_entry = -1;
$("#q").val("");
} else {
state.selected_history_entry = (state.selected_history_entry - 1) % get_history().length;
$("#q").val(get_history().reverse()[state.selected_history_entry]);
$("#history" + state.selected_history_entry).addClass("selected");
}
}
});
$("#q").on("focus", function () {
$("#autocomplete").addClass("active");
......@@ -419,3 +420,22 @@ var init = function () {
render.history.all(search_history.get());
};
init();
$("#q").on("keypress", function (e) {
const key = e.which || e.keyCode;
if (key === 13) {
search();
}
const index_before = historyHandler.index;
if (key === 40) {
historyHandler.navigateBefore();
} else if (key === 38) {
historyHandler.navigateLater();
}
if (index_before != historyHandler.index) {
$("[data-history="+index_before+"]").removeClass("selected");
$("[data-history="+historyHandler.index+"]").addClass("selected");
}
});
*/
\ No newline at end of file
......@@ -12,8 +12,8 @@
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="res/login.css">
<link rel="stylesheet" href="res/material-icons.css">
<link rel="stylesheet" href="res/css/login.css">
<link rel="stylesheet" href="res/css/icons.css">
</head>
<body>
......
......@@ -12,38 +12,27 @@
<link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="res/search.css">
<link rel="stylesheet" href="res/material-icons.css">
<link rel="stylesheet" href="res/css/search.css">
</head>
<body>
<nav>
<div class="wrapper">
<div id="searchbar">
<div id="searchicon" class="icon">search</div>
<input name="q" id="q" placeholder="<?php $t('search'); ?>" type="text" autocomplete="off">
</div>
</div>
<div id="actions">
<a title="<?php $t('logout'); ?>" href="login.php?action=logout">
<span class="icon">account_circle</span>
</a>
</div>
<div id="autocomplete">
<ul></ul>
</div>
</nav>
<section id="results">
</section>
<div id="modal-background"></div>
<div id="bg"></div>
<script src="res/jquery.js"></script>
<script>
var translation = <?php echo json_encode($translation); ?>;
const translation = <?php echo json_encode($translation); ?>;
</script>
<script src="res/sendercolor.js"></script>
<script src="res/search.js"></script>
<script src="res/js/util/loader.js"></script>
<script src="res/js/util/component.js"></script>
<script src="res/js/util/mirccolorhandler.js"></script>
<script src="res/js/util/sendercolorhandler.js"></script>
<script src="res/js/component/nohistoryelement.js"></script>
<script src="res/js/component/historyelement.js"></script>
<script src="res/js/component/history.js"></script>
<script src="res/js/component/nav.js"></script>
<script src="res/js/component/messagePreview.js"></script>
<script src="res/js/component/message.js"></script>
<script src="res/js/component/loadmore.js"></script>
<script src="res/js/component/context.js"></script>
<script src="res/js/component/buffer.js"></script>
<script src="res/js/component/urlbar.js"></script>
<script src="res/js/app.js"></script>
</body>
</html>
......@@ -10,12 +10,12 @@ require_once '../../backend/helper/SessionHelper.php';
$session = SessionHelper::getInstance();
$config = Config::createFromGlobals();
$renderer = new RendererHelper($config);
$backend = Backend::createFromConfig($config);
$backend = Database::createFromConfig($config);
if (!$backend->authenticate($session->username ?: '', $session->password ?: '')) {
$session->destroy();
$renderer->renderJsonError(false);
} else {
syslog(LOG_INFO, json_encode($_GET));
$renderer->renderJson($backend->context($_GET['anchor'] ?: 0, $_GET['buffer'] ?: 0, $_GET['before'], $_GET['after']));
$renderer->renderJson($backend->context($_REQUEST['anchor'] ?: 0, $_REQUEST['buffer'] ?: 0, $_REQUEST['before'], $_REQUEST['after']));
}
\ No newline at end of file
......@@ -10,11 +10,11 @@ require_once '../../backend/helper/SessionHelper.php';
$session = SessionHelper::getInstance();
$config = Config::createFromGlobals();
$renderer = new RendererHelper($config);
$backend = Backend::createFromConfig($config);
$backend = Database::createFromConfig($config);
if (!$backend->authenticate($session->username ?: '', $session->password ?: '')) {
$session->destroy();
$renderer->renderJsonError(false);
} else {
$renderer->renderJson($backend->find($_GET['query'] ?: "", $_GET['since'] ?: null, $_GET['before'] ?: null, $_GET['buffer'] ?: null, $_GET['network'] ?: null, 4));
$renderer->renderJson($backend->find($_REQUEST['query'] ?: "", $_REQUEST['since'] ?: null, $_REQUEST['before'] ?: null, $_REQUEST['buffer'] ?: null, $_REQUEST['network'] ?: null, 4));
}
\ No newline at end of file
......@@ -10,11 +10,11 @@ require_once '../../backend/helper/SessionHelper.php';
$session = SessionHelper::getInstance();
$config = Config::createFromGlobals();
$renderer = new RendererHelper($config);
$backend = Backend::createFromConfig($config);
$backend = Database::createFromConfig($config);
if (!$backend->authenticate($session->username ?: '', $session->password ?: '')) {
$session->destroy();
$renderer->renderJsonError(false);
} else {
$renderer->renderJson($backend->findInBuffer($_GET['query'] ?: "", $_GET['since'] ?: null, $_GET['before'] ?: null, $_GET['buffer'] ?: 0, $_GET['offset'] ?: 0, $_GET['limit'] ?: 20));
$renderer->renderJson($backend->findInBuffer($_REQUEST['query'] ?: "", $_REQUEST['since'] ?: null, $_REQUEST['before'] ?: null, $_REQUEST['buffer'] ?: 0, $_REQUEST['offset'] ?: 0, $_REQUEST['limit'] ?: 20));
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment