add timeformatter, shared between all view models

This commit is contained in:
Bruno Windels 2022-11-25 16:13:22 +01:00
parent 9c2c5af291
commit c4e239a401
5 changed files with 86 additions and 8 deletions

View File

@ -29,6 +29,7 @@ import type {ILogger} from "../logging/types";
import type {Navigation} from "./navigation/Navigation";
import type {SegmentType} from "./navigation/index";
import type {IURLRouter} from "./navigation/URLRouter";
import type { ITimeFormatter } from "../platform/types/types";
export type Options<T extends object = SegmentType> = {
platform: Platform;
@ -145,4 +146,8 @@ export class ViewModel<N extends object = SegmentType, O extends Options<N> = Op
// typescript needs a little help here
return this._options.navigation as unknown as Navigation<N>;
}
get timeFormatter(): ITimeFormatter {
return this._options.platform.timeFormatter;
}
}

View File

@ -48,13 +48,7 @@ export class DateTile extends ViewModel implements ITile<BaseEventEntry> {
get date(): string {
if (!this._dateString) {
const date = new Date(this.refEntry.timestamp);
this._dateString = date.toLocaleDateString({}, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
this._dateString = this.timeFormatter.formatRelativeDate(new Date(this.refEntry.timestamp));
}
return this._dateString;
}

View File

@ -16,7 +16,7 @@ limitations under the License.
import type {RequestResult} from "../web/dom/request/fetch.js";
import type {RequestBody} from "../../matrix/net/common";
import type {ILogItem} from "../../logging/types";
import type { BaseObservableValue } from "../../observable/ObservableValue";
export interface IRequestOptions {
uploadProgress?: (loadedBytes: number) => void;
@ -43,3 +43,7 @@ export type File = {
readonly name: string;
readonly blob: IBlobHandle;
}
export interface ITimeFormatter {
formatRelativeDate(date: Date): string;
}

View File

@ -39,6 +39,7 @@ import {Disposables} from "../../utils/Disposables";
import {parseHTML} from "./parsehtml.js";
import {handleAvatarError} from "./ui/avatar";
import {ThemeLoader} from "./theming/ThemeLoader";
import {TimeFormatter} from "./dom/TimeFormatter";
function addScript(src) {
return new Promise(function (resolve, reject) {
@ -139,6 +140,7 @@ export class Platform {
this._createLogger(options?.development);
this.history = new History();
this.onlineStatus = new OnlineStatus();
this.timeFormatter = new TimeFormatter();
this._serviceWorkerHandler = null;
if (assetPaths.serviceWorker && "serviceWorker" in navigator) {
this._serviceWorkerHandler = new ServiceWorkerHandler();

View File

@ -0,0 +1,73 @@
/*
Copyright 2022 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import type { ITimeFormatter } from "../../types/types";
import {Clock} from "./Clock";
enum TimeScope {
Minute = 60 * 1000,
Day = 24 * 60 * 60 * 1000,
}
export class TimeFormatter implements ITimeFormatter {
private todayMidnight: Date;
private relativeDayFormatter: Intl.RelativeTimeFormat;
private weekdayFormatter: Intl.DateTimeFormat;
private currentYearFormatter: Intl.DateTimeFormat;
private otherYearFormatter: Intl.DateTimeFormat;
constructor(private clock: Clock) {
// don't use the clock time here as the DOM relative formatters don't support setting the reference date anyway
this.todayMidnight = new Date();
this.todayMidnight.setHours(0, 0, 0, 0);
this.relativeDayFormatter = new Intl.RelativeTimeFormat(undefined, {numeric: "auto"});
this.weekdayFormatter = new Intl.DateTimeFormat(undefined, {weekday: 'long'});
this.currentYearFormatter = new Intl.DateTimeFormat(undefined, {
weekday: 'long',
month: 'long',
day: 'numeric'
});
this.otherYearFormatter = new Intl.DateTimeFormat(undefined, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
formatRelativeDate(date: Date): string {
let daysDiff = Math.floor((date.getTime() - this.todayMidnight.getTime()) / TimeScope.Day);
console.log("formatRelativeDate daysDiff", daysDiff, date);
if (daysDiff >= -1 && daysDiff <= 1) {
// Tomorrow, Today, Yesterday
return capitalizeFirstLetter(this.relativeDayFormatter.format(daysDiff, "day"));
} else if (daysDiff > -7 && daysDiff < 0) {
// Wednesday
return this.weekdayFormatter.format(date);
} else if (this.todayMidnight.getFullYear() === date.getFullYear()) {
// Friday, November 6
return this.currentYearFormatter.format(date);
} else {
// Friday, November 5, 2021
return this.otherYearFormatter.format(date);
}
}
}
function capitalizeFirstLetter(str: string) {
return str.slice(0, 1).toLocaleUpperCase() + str.slice(1);
}