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

Introduce context option

parent 0582dbe4
No related branches found
No related tags found
No related merge requests found
Showing
with 2996 additions and 223 deletions
...@@ -209,7 +209,7 @@ class PostgresSmartBackend implements Backend ...@@ -209,7 +209,7 @@ class PostgresSmartBackend implements Backend
JOIN network ON buffer.networkid = network.networkid JOIN network ON buffer.networkid = network.networkid
WHERE buffer.userid = :userid WHERE buffer.userid = :userid
AND backlog.bufferid = :bufferid AND backlog.bufferid = :bufferid
AND backlog.messageid >= :anchor AND backlog.messageid > :anchor
ORDER BY backlog.messageid ASC ORDER BY backlog.messageid ASC
LIMIT :limit; LIMIT :limit;
"); ");
......
This diff is collapsed.
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
"description": "This is a websearch frontend for a quassel database.", "description": "This is a websearch frontend for a quassel database.",
"scripts": { "scripts": {
"jsx": "node_modules/nativejsx/bin/nativejsx res/js/**/*.jsx", "jsx": "node_modules/nativejsx/bin/nativejsx res/js/**/*.jsx",
"dep": "cp node_modules/nativejsx/dist/nativejsx-prototypes.js res/js/util/" "dep": "cp node_modules/nativejsx/dist/nativejsx-prototypes.js res/js/util/",
"sass": "node_modules/node-sass/bin/node-sass res/css/login.sass -o res/css/ && node_modules/node-sass/bin/node-sass res/css/search.sass -o res/css/"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
...@@ -16,7 +17,8 @@ ...@@ -16,7 +17,8 @@
"url": "https://github.com/justjanne/quassel-rest-search/issues" "url": "https://github.com/justjanne/quassel-rest-search/issues"
}, },
"homepage": "https://github.com/justjanne/quassel-rest-search#readme", "homepage": "https://github.com/justjanne/quassel-rest-search#readme",
"dependencies": { "devDependencies": {
"nativejsx": "^4.1.0" "nativejsx": "https://github.com/j3l11234/nativejsx/archive/4.2.0.2.tar.gz",
"node-sass": "^4.7.2"
} }
} }
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
padding: 6px 16px padding: 6px 16px
font-size: 13px font-size: 13px
line-height: 1.846 line-height: 1.846
-moz-user-select: none @include vendor-prefix('user-select', 'none')
text-decoration: none text-decoration: none
box-sizing: border-box box-sizing: border-box
font-family: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif font-family: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif
...@@ -187,14 +187,13 @@ ...@@ -187,14 +187,13 @@
.context .context
position: relative position: relative
.container &.focus
.before
.after
&.active
padding: 0 padding: 0
margin: 1rem -1rem margin: 1rem -1rem
@media(max-width: 800px)
margin: 1rem 0
&:before &:before
bottom: 0 bottom: 0
box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, .12), 0 2px 4px rgba(0, 0, 0, .24) box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, .12), 0 2px 4px rgba(0, 0, 0, .24)
...@@ -206,6 +205,9 @@ ...@@ -206,6 +205,9 @@
right: 0 right: 0
top: 0 top: 0
> .container > .inline-button
box-shadow: none
&:not(.focus) &:not(.focus)
> .before, > .after > .before, > .after
display: none display: none
...@@ -220,9 +222,39 @@ ...@@ -220,9 +222,39 @@
border-bottom: 1px solid #e5e5e5 border-bottom: 1px solid #e5e5e5
color: #212121 color: #212121
background: #fff background: #fff
position: relative
> .more
height: 56px
width: 56px
position: relative
padding: 16px 13px
cursor: pointer
color: #555
transition: all .15s
text-decoration: none
text-align: center
margin-right: -24px
margin-top: -12px
@include vendor-prefix('user-select', 'none')
&:last-child &:before
border-bottom: none background-color: rgba(255, 255, 255, .12)
bottom: 9px
content: ' '
left: 9px
margin: auto
padding: 4px
position: absolute
right: 9px
top: 9px
z-index: -1
border-radius: 50%
opacity: 0
transition: opacity 100ms
&:hover:before
opacity: 1
time time
width: 136px width: 136px
...@@ -260,6 +292,10 @@ ...@@ -260,6 +292,10 @@
overflow: hidden overflow: hidden
text-overflow: ellipsis text-overflow: ellipsis
.invisible
font-size: 0
opacity: 0
@media(max-width: 800px) @media(max-width: 800px)
width: initial width: initial
padding: 0 padding: 0
...@@ -278,4 +314,5 @@ ...@@ -278,4 +314,5 @@
color: #212121 !important color: #212121 !important
@media(max-width: 800px) @media(max-width: 800px)
vertical-align: top
display: inline display: inline
\ No newline at end of file
@font-face { @font-face {
font-family: "Material Icons"; font-family: 'Material Icons';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local("Material Icons"), local("MaterialIcons-Regular"), url(../icons/MaterialIcons-Regular.woff2) format("woff2"), url(../icons/MaterialIcons-Regular.woff) format("woff"); } src: local("Material Icons"), local("MaterialIcons-Regular"), url(../icons/MaterialIcons-Regular.woff2) format("woff2"), url(../icons/MaterialIcons-Regular.woff) format("woff"); }
.icon { .icon {
font-family: "Material Icons", sans-serif; font-family: 'Material Icons', sans-serif;
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
font-size: 24px; font-size: 24px;
...@@ -24,18 +25,21 @@ ...@@ -24,18 +25,21 @@
/* Support for Firefox. */ /* Support for Firefox. */
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
/* Support for IE. */ /* Support for IE. */
font-feature-settings: "liga"; } font-feature-settings: 'liga';
}
@font-face { @font-face {
font-family: "Roboto"; font-family: 'Roboto';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local("Roboto"), local("Roboto-Regular"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-regular.woff2") format("woff2"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-regular.woff") format("woff"); } src: local("Roboto"), local("Roboto-Regular"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-regular.woff2") format("woff2"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-regular.woff") format("woff"); }
@font-face { @font-face {
font-family: "Roboto"; font-family: 'Roboto';
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local("Roboto Bold"), local("Roboto-Bold"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-700.woff2") format("woff2"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-700.woff") format("woff"); } src: local("Roboto Bold"), local("Roboto-Bold"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-700.woff2") format("woff2"), url("../fonts/roboto-v15-latin-ext_cyrillic_greek-ext_cyrillic-ext_latin_greek_vietnamese-700.woff") format("woff"); }
* { * {
padding: 0; padding: 0;
margin: 0; margin: 0;
...@@ -44,14 +48,15 @@ ...@@ -44,14 +48,15 @@
body { body {
background: #F2F2F2; background: #F2F2F2;
font-family: "Roboto", sans-serif; font-family: 'Roboto', sans-serif;
font-size: 81.25%; font-size: 81.25%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 100vh; min-height: 100vh;
position: relative; position: relative;
padding-right: 0.9375rem; padding-right: .9375rem;
padding-left: 0.9375rem; } padding-left: .9375rem;
}
body .header, body .footer { body .header, body .footer {
flex-grow: 1; } flex-grow: 1; }
...@@ -68,10 +73,14 @@ form { ...@@ -68,10 +73,14 @@ form {
margin: 0 auto; margin: 0 auto;
color: #212121; color: #212121;
box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); } box-shadow: 0 -1px 0 #e5e5e5, 0 0 2px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.24); }
@media (max-width: 320px) { @media (max-width: 320px) {
form { form {
padding: 8px 16px; padding: 8px 16px;
margin: initial; } } margin: initial;
}
}
.header { .header {
display: flex; display: flex;
flex-direction: column; } flex-direction: column; }
...@@ -96,12 +105,14 @@ h2 { ...@@ -96,12 +105,14 @@ h2 {
text-align: center; } text-align: center; }
input[type=text], input[type=password] { input[type=text], input[type=password] {
-moz-appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none;
-ms-appearance: none;
-o-appearance: none;
appearance: none;
appearance: none; appearance: none;
height: 36px; height: 36px;
padding: 0 8px; padding: 0 8px;
margin: 0;
background: #fff; background: #fff;
border: 1px solid #d9d9d9; border: 1px solid #d9d9d9;
border-top: 1px solid #c0c0c0; border-top: 1px solid #c0c0c0;
...@@ -111,7 +122,7 @@ input[type=text], input[type=password] { ...@@ -111,7 +122,7 @@ input[type=text], input[type=password] {
color: #404040; color: #404040;
width: 100%; width: 100%;
display: block; display: block;
margin-bottom: 10px; margin: 0 0 10px;
z-index: 1; z-index: 1;
position: relative; } position: relative; }
...@@ -131,17 +142,15 @@ input[type="submit"] { ...@@ -131,17 +142,15 @@ input[type="submit"] {
font-weight: 500; font-weight: 500;
line-height: 20px; line-height: 20px;
font-size: 14px; font-size: 14px;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
-blink-user-select: none; -moz-user-select: none;
background-repeat: no-repeat; -ms-user-select: none;
background-position: center center; -o-user-select: none;
user-select: none;
background-size: 0; background-size: 0;
min-width: 88px; min-width: 88px;
transition: background-size 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), background-color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), box-shadow 300ms; transition: background-size 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), background-color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), box-shadow 300ms;
background-color: #0a70c0; background: #0a70c0 radial-gradient(circle, #105a94 10%, transparent 10.001%, transparent) no-repeat center center;
background-image: radial-gradient(circle, #105a94 10%, transparent 10.001%, transparent);
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2); box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2);
color: #fff; color: #fff;
width: 100%; width: 100%;
...@@ -159,5 +168,3 @@ form .message { ...@@ -159,5 +168,3 @@ form .message {
form .message.error { form .message.error {
color: #b71c1c; } color: #b71c1c; }
/*# sourceMappingURL=login.css.map */
...@@ -65,12 +65,10 @@ h2 ...@@ -65,12 +65,10 @@ h2
text-align: center text-align: center
input[type=text], input[type=password] input[type=text], input[type=password]
-moz-appearance: none @include vendor-prefix('appearance', 'none')
-webkit-appearance: none
appearance: none appearance: none
height: 36px height: 36px
padding: 0 8px padding: 0 8px
margin: 0
background: #fff background: #fff
border: 1px solid #d9d9d9 border: 1px solid #d9d9d9
border-top: 1px solid #c0c0c0 border-top: 1px solid #c0c0c0
...@@ -80,7 +78,7 @@ input[type=text], input[type=password] ...@@ -80,7 +78,7 @@ input[type=text], input[type=password]
color: #404040 color: #404040
width: 100% width: 100%
display: block display: block
margin-bottom: 10px margin: 0 0 10px
z-index: 1 z-index: 1
position: relative position: relative
...@@ -100,17 +98,11 @@ input[type="submit"] ...@@ -100,17 +98,11 @@ input[type="submit"]
font-weight: 500 font-weight: 500
line-height: 20px line-height: 20px
font-size: 14px font-size: 14px
user-select: none @include vendor-prefix('user-select', 'none')
-moz-user-select: none
-webkit-user-select: none
-blink-user-select: none
background-repeat: no-repeat
background-position: center center
background-size: 0 background-size: 0
min-width: 88px min-width: 88px
transition: background-size 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), background-color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), box-shadow 300ms transition: background-size 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), background-color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), color 500ms cubic-bezier(0.98, 0.005, 0.79, 1.005), box-shadow 300ms
background-color: #0a70c0 background: #0a70c0 radial-gradient(circle, #105a94 10%, rgba(0, 0, 0, 0) 10.001%, rgba(0, 0, 0, 0)) no-repeat center center
background-image: radial-gradient(circle, #105a94 10%, rgba(0, 0, 0, 0) 10.001%, rgba(0, 0, 0, 0))
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2) box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), 0 1px 5px 0 rgba(0, 0, 0, 0.2)
color: #fff color: #fff
width: 100% width: 100%
......
This diff is collapsed.
...@@ -4,6 +4,9 @@ class App { ...@@ -4,6 +4,9 @@ class App {
this.navigation = new Navigation(); this.navigation = new Navigation();
this.buffers = []; this.buffers = [];
this.loadingQuery = 0; this.loadingQuery = 0;
if (Storage.exists('language')) {
moment.locale(Storage.get('language'));
}
this.render(); this.render();
this.navigation.addEventListener('search', query => { this.navigation.addEventListener('search', query => {
this.search(query); this.search(query);
...@@ -42,7 +45,7 @@ class App { ...@@ -42,7 +45,7 @@ class App {
return; return;
this.buffers = result.map(buffer => { this.buffers = result.map(buffer => {
return new Buffer(buffer.bufferid, buffer.buffername, buffer.networkname, buffer.hasmore, buffer.messages.map(msg => { return new Buffer(buffer.bufferid, buffer.buffername, buffer.networkname, buffer.hasmore, buffer.messages.map(msg => {
return new Context(new Message(msg.messageid, msg.time, msg.sender, msg.message)); return new Context(new Message(msg.messageid, msg.time, msg.sender, msg.message, true));
})); }));
}); });
this.buffers.forEach(buffer => this.insert(buffer)); this.buffers.forEach(buffer => this.insert(buffer));
...@@ -62,6 +65,12 @@ class App { ...@@ -62,6 +65,12 @@ class App {
insert(buffer) { insert(buffer) {
this.resultContainer.appendChild(buffer.elem); this.resultContainer.appendChild(buffer.elem);
buffer.addEventListener('loadMore', () => this.bufferLoadMore(buffer)); buffer.addEventListener('loadMore', () => this.bufferLoadMore(buffer));
buffer.addEventListener('loadBefore', (context, initialLoad) => {
this.contextLoadBefore(buffer, context, initialLoad);
});
buffer.addEventListener('loadAfter', (context, initialLoad) => {
this.contextLoadAfter(buffer, context, initialLoad);
});
} }
bufferLoadMore(buffer) { bufferLoadMore(buffer) {
if (buffer.loading) if (buffer.loading)
...@@ -77,7 +86,36 @@ class App { ...@@ -77,7 +86,36 @@ class App {
buffer.setLoading(false); buffer.setLoading(false);
}); });
} }
contextLoadBefore(buffer, context, initialLoad) {
if (context.loading && initialLoad !== true)
return;
context.setLoading(true);
const amount = initialLoad ? 4 : 10;
load('web/backlog/', statehandler.parse({
buffer: buffer.id,
anchor: context.anchorBefore,
after: 0,
before: amount
})).then(result => {
context.loadBefore(result.map(msg => new Message(msg.messageid, msg.time, msg.sender, msg.message)));
context.setLoading(false);
});
}
contextLoadAfter(buffer, context, initialLoad) {
if (context.loading && initialLoad !== true)
return;
context.setLoading(true);
const amount = initialLoad ? 4 : 10;
load('web/backlog/', statehandler.parse({
buffer: buffer.id,
anchor: context.anchorAfter,
after: amount,
before: 0
})).then(result => {
context.loadAfter(result.map(msg => new Message(msg.messageid, msg.time, msg.sender, msg.message)));
context.setLoading(false);
});
}
} }
moment.locale(navigator.languages || navigator.language);
const app = new App(); const app = new App();
document.body.insertBefore(app.elem, document.body.firstChild); document.body.insertBefore(app.elem, document.body.firstChild);
\ No newline at end of file
...@@ -7,6 +7,10 @@ class App { ...@@ -7,6 +7,10 @@ class App {
this.loadingQuery = 0; this.loadingQuery = 0;
if (Storage.exists('language')) {
moment.locale(Storage.get('language'));
}
this.render(); this.render();
this.navigation.addEventListener("search", (query) => { this.navigation.addEventListener("search", (query) => {
this.search(query) this.search(query)
...@@ -45,7 +49,7 @@ class App { ...@@ -45,7 +49,7 @@ class App {
this.buffers = result.map((buffer) => { this.buffers = result.map((buffer) => {
return new Buffer(buffer.bufferid, buffer.buffername, buffer.networkname, buffer.hasmore, buffer.messages.map((msg) => { return new Buffer(buffer.bufferid, buffer.buffername, buffer.networkname, buffer.hasmore, buffer.messages.map((msg) => {
return new Context(new Message(msg.messageid, msg.time, msg.sender, msg.message)); return new Context(new Message(msg.messageid, msg.time, msg.sender, msg.message, true));
})); }));
}); });
this.buffers.forEach((buffer) => this.insert(buffer)); this.buffers.forEach((buffer) => this.insert(buffer));
...@@ -67,7 +71,13 @@ class App { ...@@ -67,7 +71,13 @@ class App {
insert(buffer) { insert(buffer) {
this.resultContainer.appendChild(buffer.elem); this.resultContainer.appendChild(buffer.elem);
buffer.addEventListener("loadMore", () => this.bufferLoadMore(buffer)) buffer.addEventListener("loadMore", () => this.bufferLoadMore(buffer));
buffer.addEventListener("loadBefore", (context, initialLoad) => {
this.contextLoadBefore(buffer, context, initialLoad);
});
buffer.addEventListener("loadAfter", (context, initialLoad) => {
this.contextLoadAfter(buffer, context, initialLoad);
});
} }
bufferLoadMore(buffer) { bufferLoadMore(buffer) {
...@@ -82,8 +92,41 @@ class App { ...@@ -82,8 +92,41 @@ class App {
buffer.setLoading(false); buffer.setLoading(false);
}); });
} }
contextLoadBefore(buffer, context, initialLoad) {
if (context.loading && initialLoad !== true)
return;
context.setLoading(true);
const amount = initialLoad ? 4 : 10;
load("web/backlog/", statehandler.parse({
buffer: buffer.id,
anchor: context.anchorBefore,
after: 0,
before: amount
})).then((result) => {
context.loadBefore(result.map((msg) => new Message(msg.messageid, msg.time, msg.sender, msg.message)));
context.setLoading(false);
});
}
contextLoadAfter(buffer, context, initialLoad) {
if (context.loading && initialLoad !== true)
return;
context.setLoading(true);
const amount = initialLoad ? 4 : 10;
load("web/backlog/", statehandler.parse({
buffer: buffer.id,
anchor: context.anchorAfter,
after: amount,
before: 0
})).then((result) => {
context.loadAfter(result.map((msg) => new Message(msg.messageid, msg.time, msg.sender, msg.message)));
context.setLoading(false);
});
}
} }
moment.locale(navigator.languages || navigator.language);
const app = new App(); const app = new App();
document.body.insertBefore(app.elem, document.body.firstChild); document.body.insertBefore(app.elem, document.body.firstChild);
\ No newline at end of file
...@@ -56,8 +56,6 @@ class Buffer extends Component { ...@@ -56,8 +56,6 @@ class Buffer extends Component {
return this.contextList.length; return this.contextList.length;
} }
loadMore() { loadMore() {
console.log(this.neverLoaded);
console.log(this.hasMore);
if (this.elem.classList.contains('focus') || this.hasMore && this.neverLoaded) { if (this.elem.classList.contains('focus') || this.hasMore && this.neverLoaded) {
this.sendEvent('loadMore', []); this.sendEvent('loadMore', []);
} }
...@@ -86,6 +84,18 @@ class Buffer extends Component { ...@@ -86,6 +84,18 @@ class Buffer extends Component {
insert(context) { insert(context) {
let container = this.insertContainerFirst.childElementCount < 4 ? this.insertContainerFirst : this.insertContainer; let container = this.insertContainerFirst.childElementCount < 4 ? this.insertContainerFirst : this.insertContainer;
container.appendChild(context.elem); container.appendChild(context.elem);
context.addEventListener('loadBefore', (context, initialLoad) => {
this.sendEvent('loadBefore', [
context,
initialLoad
]);
});
context.addEventListener('loadAfter', (context, initialLoad) => {
this.sendEvent('loadAfter', [
context,
initialLoad
]);
});
this.neverLoaded = false; this.neverLoaded = false;
} }
setLoading(value) { setLoading(value) {
......
...@@ -49,8 +49,6 @@ class Buffer extends Component { ...@@ -49,8 +49,6 @@ class Buffer extends Component {
} }
loadMore() { loadMore() {
console.log(this.neverLoaded);
console.log(this.hasMore);
if (this.elem.classList.contains("focus") || (this.hasMore && this.neverLoaded)) { if (this.elem.classList.contains("focus") || (this.hasMore && this.neverLoaded)) {
this.sendEvent("loadMore", []); this.sendEvent("loadMore", []);
} }
...@@ -86,6 +84,12 @@ class Buffer extends Component { ...@@ -86,6 +84,12 @@ class Buffer extends Component {
insert(context) { insert(context) {
let container = (this.insertContainerFirst.childElementCount < 4 ? this.insertContainerFirst : this.insertContainer); let container = (this.insertContainerFirst.childElementCount < 4 ? this.insertContainerFirst : this.insertContainer);
container.appendChild(context.elem); container.appendChild(context.elem);
context.addEventListener("loadBefore", (context, initialLoad) => {
this.sendEvent("loadBefore", [context, initialLoad])
});
context.addEventListener("loadAfter", (context, initialLoad) => {
this.sendEvent("loadAfter", [context, initialLoad])
});
this.neverLoaded = false; this.neverLoaded = false;
} }
......
class Context { class Context extends Component {
constructor(message, beforeList = [], afterList = []) { constructor(message, beforeList = [], afterList = []) {
super();
this.message = message; this.message = message;
this.beforeList = beforeList; this.beforeList = beforeList;
this.afterList = afterList; this.afterList = afterList;
this.render(); this.render();
this.insertAfterTarget = this.loadAfterBtn; this.insertAfterTarget = this.loadAfterBtn.elem;
this.beforeList.forEach(this.insertBefore); this.beforeList.forEach(it => this.insertBefore(it));
this.afterList.forEach(this.insertAfter); this.afterList.forEach(it => this.insertAfter(it));
this.message.addEventListener('focus', () => this.focus());
this.anchorBefore = this.message.id;
this.anchorAfter = this.message.id;
this.loading = false;
} }
render() { render() {
return this.elem = function () { return this.elem = function () {
...@@ -15,28 +20,59 @@ class Context { ...@@ -15,28 +20,59 @@ class Context {
$$a.appendChildren(this.containerBefore = function () { $$a.appendChildren(this.containerBefore = function () {
var $$c = document.createElement('div'); var $$c = document.createElement('div');
$$c.setAttribute('class', 'container before'); $$c.setAttribute('class', 'container before');
$$c.appendChildren((this.loadBeforeBtn = new LoadMore(translation.context.load_earlier, this.loadBefore)).elem); $$c.appendChildren((this.loadBeforeBtn = new LoadMore(translation.context.load_earlier, () => this.triggerLoadBefore())).elem);
return $$c; return $$c;
}.call(this)); }.call(this));
$$a.appendChildren(this.message.elem); $$a.appendChildren(this.message.elem);
$$a.appendChildren(this.containerAfter = function () { $$a.appendChildren(this.containerAfter = function () {
var $$g = document.createElement('div'); var $$g = document.createElement('div');
$$g.setAttribute('class', 'container after'); $$g.setAttribute('class', 'container after');
$$g.appendChildren((this.loadAfterBtn = new LoadMore(translation.context.load_later, this.loadAfter)).elem); $$g.appendChildren((this.loadAfterBtn = new LoadMore(translation.context.load_later, () => this.triggerLoadAfter())).elem);
return $$g; return $$g;
}.call(this)); }.call(this));
return $$a; return $$a;
}.call(this); }.call(this);
} }
loadBefore() { focus(focus) {
if (focus === undefined)
focus = !this.elem.classList.contains('focus');
if (this.anchorBefore === this.message.id && this.anchorAfter === this.message.id) {
this.triggerLoadBefore(true);
this.triggerLoadAfter(true);
}
this.elem.classList.toggle('focus', focus);
this.sendEvent('focus', focus);
} }
insertBefore(message) { insertBefore(message) {
this.containerBefore.insertBefore(message.elem, this.insertBeforeTarget); this.containerBefore.insertBefore(message.elem, this.insertBeforeTarget);
this.insertBeforeTarget = message.elem; this.insertBeforeTarget = message.elem;
} this.anchorBefore = message.id;
loadAfter() {
} }
insertAfter(message) { insertAfter(message) {
this.containerAfter.insertBefore(message.elem, this.insertAfterTarget); this.containerAfter.insertBefore(message.elem, this.insertAfterTarget);
this.anchorAfter = message.id;
}
triggerLoadBefore(initialLoad) {
this.sendEvent('loadBefore', [
this,
initialLoad === true
]);
}
triggerLoadAfter(initialLoad) {
this.sendEvent('loadAfter', [
this,
initialLoad === true
]);
}
loadBefore(elements) {
this.beforeList = elements.concat(this.beforeList);
elements.forEach(it => this.insertBefore(it));
}
loadAfter(elements) {
this.afterList = elements.concat(this.afterList);
elements.forEach(it => this.insertAfter(it));
}
setLoading(value) {
this.loading = value;
} }
} }
\ No newline at end of file
class Context { class Context extends Component {
constructor(message, beforeList = [], afterList = []) { constructor(message, beforeList = [], afterList = []) {
super();
this.message = message; this.message = message;
this.beforeList = beforeList; this.beforeList = beforeList;
this.afterList = afterList; this.afterList = afterList;
this.render(); this.render();
this.insertAfterTarget = this.loadAfterBtn; this.insertAfterTarget = this.loadAfterBtn.elem;
this.beforeList.forEach(this.insertBefore); this.beforeList.forEach((it) => this.insertBefore(it));
this.afterList.forEach(this.insertAfter); this.afterList.forEach((it) => this.insertAfter(it));
this.message.addEventListener("focus", () => this.focus());
this.anchorBefore = this.message.id;
this.anchorAfter = this.message.id;
this.loading = false;
} }
render() { render() {
...@@ -15,33 +24,63 @@ class Context { ...@@ -15,33 +24,63 @@ class Context {
<div className="context"> <div className="context">
{this.containerBefore = ( {this.containerBefore = (
<div className="container before"> <div className="container before">
{(this.loadBeforeBtn = new LoadMore(translation.context.load_earlier, this.loadBefore)).elem} {(this.loadBeforeBtn = new LoadMore(translation.context.load_earlier, () => this.triggerLoadBefore())).elem}
</div> </div>
)} )}
{this.message.elem} {this.message.elem}
{this.containerAfter = ( {this.containerAfter = (
<div className="container after"> <div className="container after">
{(this.loadAfterBtn = new LoadMore(translation.context.load_later, this.loadAfter)).elem} {(this.loadAfterBtn = new LoadMore(translation.context.load_later, () => this.triggerLoadAfter())).elem}
</div> </div>
)} )}
</div> </div>
); );
} }
loadBefore() { focus(focus) {
/* load data */ if (focus === undefined)
focus = !this.elem.classList.contains("focus");
if (this.anchorBefore === this.message.id && this.anchorAfter === this.message.id) {
this.triggerLoadBefore(true);
this.triggerLoadAfter(true);
}
this.elem.classList.toggle("focus", focus);
this.sendEvent("focus", focus);
} }
insertBefore(message) { insertBefore(message) {
this.containerBefore.insertBefore(message.elem, this.insertBeforeTarget); this.containerBefore.insertBefore(message.elem, this.insertBeforeTarget);
this.insertBeforeTarget = message.elem; this.insertBeforeTarget = message.elem;
} this.anchorBefore = message.id;
loadAfter() {
/* load data */
} }
insertAfter(message) { insertAfter(message) {
this.containerAfter.insertBefore(message.elem, this.insertAfterTarget); this.containerAfter.insertBefore(message.elem, this.insertAfterTarget);
this.anchorAfter = message.id;
}
triggerLoadBefore(initialLoad) {
this.sendEvent("loadBefore", [this, initialLoad === true]);
}
triggerLoadAfter(initialLoad) {
this.sendEvent("loadAfter", [this, initialLoad === true]);
}
loadBefore(elements) {
this.beforeList = elements.concat(this.beforeList);
elements.forEach((it) => this.insertBefore(it));
}
loadAfter(elements) {
this.afterList = elements.concat(this.afterList);
elements.forEach((it) => this.insertAfter(it));
}
setLoading(value) {
// Add UI indicator
this.loading = value;
} }
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ class LoadMore extends Component { ...@@ -2,6 +2,7 @@ class LoadMore extends Component {
constructor(text, eventListener) { constructor(text, eventListener) {
super(); super();
this.render(text); this.render(text);
this.addEventListener('click', eventListener);
} }
render(text) { render(text) {
return this.elem = function () { return this.elem = function () {
......
...@@ -2,6 +2,7 @@ class LoadMore extends Component { ...@@ -2,6 +2,7 @@ class LoadMore extends Component {
constructor(text, eventListener) { constructor(text, eventListener) {
super(); super();
this.render(text); this.render(text);
this.addEventListener("click", eventListener);
} }
render(text) { render(text) {
......
class Message { class Message extends Component {
constructor(id, time, sender, content) { constructor(id, time, sender, content, isAnchor) {
super();
this.id = id; this.id = id;
this.time = time; this.time = time;
this.sender = sender; this.sender = sender;
this.content = content; this.content = content;
this.isAnchor = isAnchor;
this.render(); this.render();
} }
render() { render() {
return this.elem = function () { return this.elem = function () {
var $$a = document.createElement('div'); var $$a = document.createElement('span');
$$a.setAttribute('class', 'message'); $$a.setAttribute('class', 'message');
var $$b = document.createElement('time'); var $$b = document.createElement('span');
$$a.appendChild($$b); $$a.appendChild($$b);
$$b.appendChildren(moment(new Date(this.time.replace(' ', 'T') + 'Z')).format('L LT')); var $$c = document.createElement('time');
var $$d = document.createElement('div'); $$b.appendChild($$c);
$$d.setAttribute('class', 'container'); $$c.appendChildren(this.formatTime());
$$a.appendChild($$d); var $$e = document.createElement('span');
var $$e = document.createElement('div'); $$e.setAttribute('class', 'container');
$$e.setAttribute('class', 'sender'); $$a.appendChild($$e);
$$e.setAttribute('data-sendercolor', SenderColorHandler.nickToColor(this.getNick())); var $$f = document.createElement('span');
$$d.appendChild($$e); $$f.setAttribute('class', 'sender');
$$e.appendChildren(this.getNick()); $$f.setAttribute('data-sendercolor', SenderColorHandler.nickToColor(this.getNick()));
var $$g = document.createElement('div'); $$e.appendChild($$f);
$$g.setAttribute('class', 'content'); var $$g = document.createElement('span');
$$d.appendChild($$g); $$g.setAttribute('class', 'invisible');
$$g.appendChildren(MircColorHandler.render(this.content)); $$f.appendChild($$g);
var $$h = document.createTextNode(' <');
$$g.appendChild($$h);
$$f.appendChildren(this.getNick());
var $$j = document.createElement('span');
$$j.setAttribute('class', 'invisible');
$$f.appendChild($$j);
var $$k = document.createTextNode('> ');
$$j.appendChild($$k);
var $$l = document.createElement('span');
$$l.setAttribute('class', 'content');
$$e.appendChild($$l);
$$l.appendChildren(MircColorHandler.render(this.content));
$$a.appendChildren(this.isAnchor ? function () {
var $$o = document.createElement('a');
$$o.setAttribute('class', 'more icon');
$$o.addEventListener('click', () => this.sendEvent('focus', []));
var $$p = document.createTextNode('list');
$$o.appendChild($$p);
return $$o;
}.call(this) : null);
return $$a; return $$a;
}.call(this); }.call(this);
} }
formatTime() {
const dateFormat = Storage.exists('dateformat') ? Storage.get('dateformat') : 'L';
const timeFormat = Storage.exists('timeformat') ? Storage.get('timeformat') : 'LT';
const dateTimeFormat = dateFormat + ' ' + timeFormat;
return moment(new Date(this.time.replace(' ', 'T') + 'Z')).format(dateTimeFormat);
}
getNick() { getNick() {
return this.sender.split('!')[0]; return this.sender.split('!')[0];
} }
......
class Message { class Message extends Component {
constructor(id, time, sender, content) { constructor(id, time, sender, content, isAnchor) {
super();
this.id = id; this.id = id;
this.time = time; this.time = time;
this.sender = sender; this.sender = sender;
this.content = content; this.content = content;
this.isAnchor = isAnchor;
this.render(); this.render();
} }
render() { render() {
return this.elem = ( return this.elem = (
<div className="message"> <span className="message">
<time>{moment(new Date(this.time.replace(" ", "T") + "Z")).format('L LT')}</time> <span><time>{this.formatTime()}</time></span>
<div className="container"> <span className="container">
<div className="sender" data-sendercolor={SenderColorHandler.nickToColor(this.getNick())}> <span className="sender" data-sendercolor={SenderColorHandler.nickToColor(this.getNick())}>
<span className="invisible"> &lt;</span>
{this.getNick()} {this.getNick()}
</div> <span className="invisible">&gt; </span>
<div className="content"> </span>
<span className="content">
{MircColorHandler.render(this.content)} {MircColorHandler.render(this.content)}
</div> </span>
</div> </span>
</div> {this.isAnchor ? (
<a className="more icon" onClick={() => this.sendEvent("focus", [])}>list</a>
) : null}
</span>
); );
} }
formatTime() {
const dateFormat = Storage.exists('dateformat') ? Storage.get('dateformat') : 'L';
const timeFormat = Storage.exists('timeformat') ? Storage.get('timeformat') : 'LT';
const dateTimeFormat = dateFormat + " " + timeFormat;
return moment(new Date(this.time.replace(" ", "T") + "Z")).format(dateTimeFormat);
}
getNick() { getNick() {
return this.sender.split("!")[0]; return this.sender.split("!")[0];
} }
......
class Storage {
static get(key) {
try {
return JSON.parse(localStorage.getItem(key));
} catch (e) {
return null;
}
}
static set(key, value) {
localStorage.setItem(key, JSON.stringify(value));
}
static exists(key) {
return !!Storage.get(key);
}
}
\ No newline at end of file
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
<script src="res/js/util/mirccolorhandler.js"></script> <script src="res/js/util/mirccolorhandler.js"></script>
<script src="res/js/util/sendercolorhandler.js"></script> <script src="res/js/util/sendercolorhandler.js"></script>
<script src="res/js/util/statehandler.js"></script> <script src="res/js/util/statehandler.js"></script>
<script src="res/js/util/storage.js"></script>
<script src="res/js/component/nohistoryelement.js"></script> <script src="res/js/component/nohistoryelement.js"></script>
<script src="res/js/component/historyelement.js"></script> <script src="res/js/component/historyelement.js"></script>
<script src="res/js/component/history.js"></script> <script src="res/js/component/history.js"></script>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment