diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index dc06b413..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2018 Nicolas Constant
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/src/app/components/stream/status/status.component.html b/src/app/components/stream/status/status.component.html
index 024746ea..5a189ed6 100644
--- a/src/app/components/stream/status/status.component.html
+++ b/src/app/components/stream/status/status.component.html
@@ -1,5 +1,9 @@
-
-
-
@
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/app/components/stream/status/status.component.scss b/src/app/components/stream/status/status.component.scss
index 20278222..aebb10d8 100644
--- a/src/app/components/stream/status/status.component.scss
+++ b/src/app/components/stream/status/status.component.scss
@@ -1,47 +1,56 @@
-.toot {
- border: solid #06070b;
- border-width: 0 0 1px 0;
+@import "variables";
+.status {
margin: 0;
padding: 0;
width: calc(100%);
min-height: 70px;
overflow: hidden;
+ position: relative;
&__avatar {
- margin: 10px 0 0 10px;
+ position: absolute;
+ top: 10px;
+ left: 10px; // margin: 10px 0 0 10px;
/* margin: 0; */
width: 50px;
- height: 50px;
- float: left;
+ height: 50px; // float: left;
+ border-radius: 2px;
}
&__fullname {
- color: white;
+ display: block;
+ color: $status-primary-color;
}
&__profile-link {
- color: #353e64;
+ color: $status-secondary-color;
margin: 7px 0 0 70px;
display: block;
+ text-decoration: none;
+ overflow: hidden;
}
&__content {
/*width: calc(100% - 50px);*/
- margin: 10px 10px 10px 70px;
+ margin: 0px 10px 10px 70px;
}
&__content p {
margin: 0;
font-size: 0.85em;
}
+ &__created-at {
+ color: $status-secondary-color;
+ position: absolute;
+ top: 5px;
+ right: 10px;
+ }
}
-// #toot-avatar img {
-// width: 50px;
-// height: 50px;
-// border-radius: 2px;
-// margin: 0;
-// }
-/* #toot-username {
- color: grey;
-} */
-
-/* ::ng-deep .invisible {
- display: inline;
- color: red;
-} */
\ No newline at end of file
+//Mastodon styling
+:host ::ng-deep .status__content {
+ color: $status-primary-color;
+ & a,
+ .mention,
+ .ellipsis {
+ color: $status-links-color;
+ }
+ & .invisible {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/src/app/components/stream/status/status.component.ts b/src/app/components/stream/status/status.component.ts
index 3a4c9304..34d2b6d4 100644
--- a/src/app/components/stream/status/status.component.ts
+++ b/src/app/components/stream/status/status.component.ts
@@ -1,18 +1,36 @@
-import { Component, OnInit, Input } from "@angular/core";
+import { Component, OnInit, Input, Inject, LOCALE_ID } from "@angular/core";
import { Status } from "../../../services/models/mastodon.interfaces";
+import { formatDate } from '@angular/common';
@Component({
- selector: "app-status",
- templateUrl: "./status.component.html",
- styleUrls: ["./status.component.scss"]
+ selector: "app-status",
+ templateUrl: "./status.component.html",
+ styleUrls: ["./status.component.scss"]
})
export class StatusComponent implements OnInit {
- @Input() status: Status;
+ @Input() status: Status;
- constructor() { }
+ constructor(@Inject(LOCALE_ID) private locale: string) { }
- ngOnInit() {
- }
+ ngOnInit() {
+ }
+ getCompactRelativeTime(d: string): string {
+ const date = (new Date(d)).getTime();
+ const now = Date.now();
+ const timeDelta = (now - date) / (1000);
+
+ if (timeDelta < 60) {
+ return `${timeDelta | 0}s`;
+ } else if (timeDelta < 60 * 60) {
+ return `${timeDelta / 60 | 0}m`;
+ } else if (timeDelta < 60 * 60 * 24) {
+ return `${timeDelta / (60 * 60)| 0}h`;
+ } else if (timeDelta < 60 * 60 * 24 * 31) {
+ return `${timeDelta / (60 * 60 * 24) | 0}d`;
+ }
+
+ return formatDate(date, 'MM/dd', this.locale);
+ }
}
diff --git a/src/app/components/stream/stream.component.html b/src/app/components/stream/stream.component.html
index 884b57dd..fbfd0357 100644
--- a/src/app/components/stream/stream.component.html
+++ b/src/app/components/stream/stream.component.html
@@ -3,7 +3,7 @@
{{ streamElement.name.toUpperCase() }}
-
diff --git a/src/app/components/stream/stream.component.scss b/src/app/components/stream/stream.component.scss
index 7e52b612..a179cc8d 100644
--- a/src/app/components/stream/stream.component.scss
+++ b/src/app/components/stream/stream.component.scss
@@ -1,33 +1,32 @@
@import "variables";
.stream-column {
- width: $stream-column-width;
- height: calc(100%);
-
- background-color: #0f111a;
- margin: 0 0 0 $stream-column-separator;
-
- &__stream-header {
- width: calc(100%);
- height: 30px;
-
- background-color: black;
-
- border-bottom: 1px solid black;
-
- & h1 {
- color: whitesmoke;
- font-size: 0.8em;
- font-weight: normal;
- margin: 0;
- padding: 8px 0 0 10px;
+ width: $stream-column-width;
+ height: calc(100%);
+ background-color: #0f111a;
+ margin: 0 0 0 $stream-column-separator;
+ &__stream-header {
+ width: calc(100%);
+ height: 30px;
+ background-color: black;
+ border-bottom: 1px solid black;
+ & h1 {
+ color: whitesmoke;
+ font-size: 0.8em;
+ font-weight: normal;
+ margin: 0;
+ padding: 8px 0 0 10px;
+ }
}
- }
}
.stream-toots {
- height: calc(100% - 30px);
- width: 320px;
- overflow: auto;
+ height: calc(100% - 30px);
+ width: 320px;
+ overflow: auto;
+ &__status:not(:last-child) {
+ border: solid #06070b;
+ border-width: 0 0 1px 0;
+ }
}
.flexcroll {
diff --git a/src/app/components/stream/stream.component.ts b/src/app/components/stream/stream.component.ts
index 3df37602..bb1d433d 100644
--- a/src/app/components/stream/stream.component.ts
+++ b/src/app/components/stream/stream.component.ts
@@ -18,6 +18,8 @@ export class StreamComponent implements OnInit {
private websocketStreaming: StreamingWrapper;
statuses: Status[] = [];
+ private bufferStream: Status[] = [];
+ private bufferWasCleared: boolean;
@Input()
set streamElement(streamElement: StreamElement) {
@@ -28,7 +30,7 @@ export class StreamComponent implements OnInit {
const instance = splitedUserName[1];
this.account = this.getRegisteredAccounts().find(x => x.username == user && x.instance == instance);
- this.retrieveToots(); //TODO change this for WebSockets
+ this.retrieveToots();
this.launchWebsocket();
}
@@ -47,6 +49,10 @@ export class StreamComponent implements OnInit {
@ViewChild('statusstream') public statustream: ElementRef;
goToTop(): boolean {
+ this.loadBuffer();
+ if (this.statuses.length > 40) {
+ this.statuses.length = 40;
+ }
const stream = this.statustream.nativeElement as HTMLElement;
stream.scrollTo({
top: 0,
@@ -56,25 +62,58 @@ export class StreamComponent implements OnInit {
}
private streamPositionnedAtTop: boolean = true;
- private streamPositionnedAtBottom: boolean;
+ private isProcessingInfiniteScroll: boolean;
onScroll() {
var element = this.statustream.nativeElement as HTMLElement;
- const atBottom = element.scrollHeight - element.scrollTop === element.clientHeight;
+ const atBottom = element.scrollHeight <= element.clientHeight + element.scrollTop + 500;
const atTop = element.scrollTop === 0;
this.streamPositionnedAtTop = false;
- this.streamPositionnedAtBottom = false;
-
- if (atBottom) {
- console.log('Bottom reached!!');
- this.streamPositionnedAtBottom = true;
+ if (atBottom && !this.isProcessingInfiniteScroll) {
+ this.scrolledToBottom();
} else if (atTop) {
- console.log('Top reached!!');
- this.streamPositionnedAtTop = true;
+ this.scrolledToTop();
}
}
+ private scrolledToTop() {
+ this.streamPositionnedAtTop = true;
+
+ this.loadBuffer();
+ }
+
+ private loadBuffer(){
+ if(this.bufferWasCleared) {
+ this.statuses.length = 0;
+ this.bufferWasCleared = false;
+ }
+
+ for (const status of this.bufferStream) {
+ this.statuses.unshift(status);
+ }
+
+ this.bufferStream.length = 0;
+ }
+
+ private scrolledToBottom() {
+ this.isProcessingInfiniteScroll = true;
+
+ const lastStatus = this.statuses[this.statuses.length - 1];
+ this.mastodonService.getTimeline(this.account, this._streamElement.type, lastStatus.id)
+ .then((status: Status[]) => {
+ for (const s of status) {
+ this.statuses.push(s);
+ }
+ })
+ .catch(err => {
+ console.error(err);
+ })
+ .then(() => {
+ this.isProcessingInfiniteScroll = false;
+ });
+ }
+
private getRegisteredAccounts(): AccountInfo[] {
var regAccounts =
this.store.snapshot().registeredaccounts.accounts;
return regAccounts;
@@ -95,7 +134,11 @@ export class StreamComponent implements OnInit {
if (update) {
if (update.type === EventEnum.update) {
if (!this.statuses.find(x => x.id == update.status.id)) {
- this.statuses.unshift(update.status);
+ if (this.streamPositionnedAtTop) {
+ this.statuses.unshift(update.status);
+ } else {
+ this.bufferStream.push(update.status);
+ }
}
}
}
@@ -104,11 +147,16 @@ export class StreamComponent implements OnInit {
});
}
+
private checkAndCleanUpStream(): void {
if (this.streamPositionnedAtTop && this.statuses.length > 60) {
- console.log(`clean up start! ${this.statuses.length}`);
this.statuses.length = 40;
- console.log(`clean up ends! ${this.statuses.length}`);
+ }
+
+ if (this.bufferStream.length > 60) {
+ this.bufferWasCleared = true;
+ this.bufferStream.length = 40;
+
}
}
}
\ No newline at end of file
diff --git a/src/sass/_variables.scss b/src/sass/_variables.scss
index 29797028..370d9515 100644
--- a/src/sass/_variables.scss
+++ b/src/sass/_variables.scss
@@ -10,6 +10,11 @@ $color-secondary: #090b10;
$default-font-size: 15px;
$small-font-size: 12px;
+$status-primary-color: #fff;
+$status-secondary-color: #353e64;
+$status-secondary-color: #4e5572;
+$status-links-color: #d9e1e8;
+
// Block dispositions
$stream-selector-height: 30px;
diff --git a/src/sass/styles.scss b/src/sass/styles.scss
index 524815e2..c39de373 100644
--- a/src/sass/styles.scss
+++ b/src/sass/styles.scss
@@ -28,16 +28,16 @@ html, body {
background-color: $color-primary;
}
- .invisible {
- display: none;
- }
+// .invisible {
+// display: none;
+// }
/* .ellipsis {
} */
- #toot-content p {
- margin-bottom: 0 !important;
- }
+// #toot-content p {
+// margin-bottom: 0 !important;
+// }
- #toot-content a {
- color: #bec3d8;
- }
\ No newline at end of file
+// #toot-content a {
+// color: #bec3d8;
+// }
\ No newline at end of file