-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
76 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,83 @@ | ||
import {Component, Input} from '@angular/core'; | ||
import {ChangeDetectorRef, Component, inject, Inject, Input, NgZone, OnDestroy, PLATFORM_ID} from '@angular/core'; | ||
import {TooltipComponent} from "../text/tooltip.component"; | ||
import {isPlatformBrowser} from "@angular/common"; | ||
|
||
@Component({ | ||
selector: 'app-date', | ||
standalone: true, | ||
imports: [ | ||
TooltipComponent | ||
], | ||
template: ` | ||
<!-- | ||
for some stupid fucking reason we need to defer this, | ||
because otherwise this breaks the layout when SSR renders this component | ||
--> | ||
@defer { | ||
<app-tooltip [text]="getFormattedDate()" class> | ||
{{ getMoment() }} | ||
</app-tooltip> | ||
} @placeholder { | ||
<span>{{ recentText }}</span> | ||
} | ||
` | ||
selector: 'app-date', | ||
standalone: true, | ||
imports: [ | ||
TooltipComponent | ||
], | ||
template: ` | ||
<app-tooltip [text]="formattedDate">{{ moment }}</app-tooltip> | ||
` | ||
}) | ||
export class DateComponent { | ||
private _date: Date = new Date(); | ||
|
||
protected recentText = "just now"; | ||
|
||
@Input({required: true, alias: "date"}) | ||
set date(value: Date) { | ||
this._date = new Date(value); | ||
} | ||
|
||
getMoment(): string { | ||
const now = new Date(); | ||
const seconds = Math.floor((now.getTime() - this._date.getTime()) / 1000); | ||
|
||
const intervals: { [key: string]: number } = { | ||
year: 31536000, | ||
month: 2592000, | ||
week: 604800, | ||
day: 86400, | ||
hour: 3600, | ||
minute: 60, | ||
second: 1, | ||
}; | ||
|
||
for (const interval in intervals) { | ||
const time = Math.floor(seconds / intervals[interval]); | ||
if (time >= 1) { | ||
return `${time} ${interval}${time > 1 ? 's' : ''} ago`; | ||
} | ||
export class DateComponent implements OnDestroy { | ||
private _date: Date = new Date(); | ||
private intervalId: any; | ||
|
||
constructor(@Inject(PLATFORM_ID) private platformId: string, private changeDetector: ChangeDetectorRef) { | ||
if (!this.isBrowser) return; | ||
|
||
inject(NgZone).runOutsideAngular(() => { | ||
this.intervalId = setInterval(() => { | ||
// console.log("tick", this.intervalId) | ||
this.changeDetector.detectChanges(); | ||
}, 1000); | ||
}) | ||
} | ||
|
||
get isBrowser(): boolean { | ||
return isPlatformBrowser(this.platformId); | ||
} | ||
|
||
protected recentText = "just now"; | ||
|
||
// this setter is actually required to be here; this is not a hold-over from the old site | ||
// for some reason, javascript's date parser doesn't create a full Date object. | ||
// so we need to do this horse-shit. | ||
@Input({required: true, alias: "date"}) | ||
set date(value: Date) { | ||
this._date = new Date(value); | ||
} | ||
|
||
return this.recentText; | ||
} | ||
get moment(): string { | ||
const now = new Date(); | ||
const totalSeconds = Math.floor((now.getTime() - this._date.getTime()) / 1000); | ||
|
||
getFormattedDate(): string { | ||
return `${this._date.toLocaleDateString()} @ ${this._date.toLocaleTimeString()}`; | ||
} | ||
const intervals: { [key: string]: number } = { | ||
year: 31536000, | ||
month: 2592000, | ||
week: 604800, | ||
day: 86400, | ||
hour: 3600, | ||
minute: 60, | ||
second: 1, | ||
}; | ||
|
||
if (totalSeconds < 20) | ||
return this.recentText; | ||
|
||
for (const interval in intervals) { | ||
const time = Math.floor(totalSeconds / intervals[interval]); | ||
if (time > 1) { | ||
return `${time} ${interval}s ago`; | ||
} else if (time == 1) { | ||
return `a${interval == "hour" ? 'n' : ''} ${interval} ago`; | ||
} | ||
} | ||
|
||
return this.recentText; | ||
} | ||
|
||
get formattedDate(): string { | ||
return `${this._date.toLocaleDateString()} @ ${this._date.toLocaleTimeString()}`; | ||
} | ||
|
||
ngOnDestroy() { | ||
if (this.intervalId) { | ||
// console.log("unsubscribe", this.intervalId) | ||
clearInterval(this.intervalId); | ||
} | ||
} | ||
} |