diff --git a/frontend/src/app/components/difficulty-mining/difficulty-mining.component.ts b/frontend/src/app/components/difficulty-mining/difficulty-mining.component.ts
index c23d7d4b9..c1283b8b1 100644
--- a/frontend/src/app/components/difficulty-mining/difficulty-mining.component.ts
+++ b/frontend/src/app/components/difficulty-mining/difficulty-mining.component.ts
@@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
-import { combineLatest, Observable, timer } from 'rxjs';
-import { map, switchMap } from 'rxjs/operators';
+import { combineLatest, Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
import { StateService } from '../../services/state.service';
interface EpochProgress {
@@ -15,6 +15,7 @@ interface EpochProgress {
previousRetarget: number;
blocksUntilHalving: number;
timeUntilHalving: number;
+ timeAvg: number;
}
@Component({
@@ -26,6 +27,9 @@ interface EpochProgress {
export class DifficultyMiningComponent implements OnInit {
isLoadingWebSocket$: Observable;
difficultyEpoch$: Observable;
+ blocksUntilHalving: number | null = null;
+ timeUntilHalving = 0;
+ now = new Date().getTime();
@Input() showProgress = true;
@Input() showHalving = false;
@@ -64,8 +68,9 @@ export class DifficultyMiningComponent implements OnInit {
colorPreviousAdjustments = '#ffffff66';
}
- const blocksUntilHalving = 210000 - (maxHeight % 210000);
- const timeUntilHalving = new Date().getTime() + (blocksUntilHalving * 600000);
+ this.blocksUntilHalving = 210000 - (maxHeight % 210000);
+ this.timeUntilHalving = new Date().getTime() + (this.blocksUntilHalving * 600000);
+ this.now = new Date().getTime();
const data = {
base: `${da.progressPercent.toFixed(2)}%`,
@@ -77,8 +82,9 @@ export class DifficultyMiningComponent implements OnInit {
newDifficultyHeight: da.nextRetargetHeight,
estimatedRetargetDate: da.estimatedRetargetDate,
previousRetarget: da.previousRetarget,
- blocksUntilHalving,
- timeUntilHalving,
+ blocksUntilHalving: this.blocksUntilHalving,
+ timeUntilHalving: this.timeUntilHalving,
+ timeAvg: da.timeAvg,
};
return data;
})
diff --git a/frontend/src/app/components/time/time.component.ts b/frontend/src/app/components/time/time.component.ts
index 2febf6238..679604ff5 100644
--- a/frontend/src/app/components/time/time.component.ts
+++ b/frontend/src/app/components/time/time.component.ts
@@ -10,7 +10,6 @@ import { dates } from '../../shared/i18n/dates';
export class TimeComponent implements OnInit, OnChanges, OnDestroy {
interval: number;
text: string;
- units: string[] = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'];
precisionThresholds = {
year: 100,
month: 18,
@@ -29,6 +28,8 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
@Input() fixedRender = false;
@Input() relative = false;
@Input() precision: number = 0;
+ @Input() numUnits: number = 1;
+ @Input() units: string[] = ['year', 'month', 'week', 'day', 'hour', 'minute', 'second'];
@Input() minUnit: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' = 'second';
@Input() fractionDigits: number = 0;
@@ -94,6 +95,8 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
}
let counter: number;
+ const result = [];
+ let usedUnits = 0;
for (const [index, unit] of this.units.entries()) {
let precisionUnit = this.units[Math.min(this.units.length - 1, index + this.precision)];
counter = Math.floor(seconds / this.intervals[unit]);
@@ -105,107 +108,126 @@ export class TimeComponent implements OnInit, OnChanges, OnDestroy {
counter = Math.max(1, counter);
}
if (counter > 0) {
- let rounded = Math.round(seconds / this.intervals[precisionUnit]);
- if (this.fractionDigits) {
- const roundFactor = Math.pow(10,this.fractionDigits);
+ let rounded;
+ const roundFactor = Math.pow(10,this.fractionDigits || 0);
+ if (this.kind === 'until' && usedUnits < this.numUnits) {
+ rounded = Math.floor((seconds / this.intervals[precisionUnit]) * roundFactor) / roundFactor;
+ } else {
rounded = Math.round((seconds / this.intervals[precisionUnit]) * roundFactor) / roundFactor;
}
- const dateStrings = dates(rounded);
- switch (this.kind) {
- case 'since':
- if (rounded === 1) {
- switch (precisionUnit) { // singular (1 day)
- case 'year': return $localize`:@@time-since:${dateStrings.i18nYear}:DATE: ago`; break;
- case 'month': return $localize`:@@time-since:${dateStrings.i18nMonth}:DATE: ago`; break;
- case 'week': return $localize`:@@time-since:${dateStrings.i18nWeek}:DATE: ago`; break;
- case 'day': return $localize`:@@time-since:${dateStrings.i18nDay}:DATE: ago`; break;
- case 'hour': return $localize`:@@time-since:${dateStrings.i18nHour}:DATE: ago`; break;
- case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinute}:DATE: ago`; break;
- case 'second': return $localize`:@@time-since:${dateStrings.i18nSecond}:DATE: ago`; break;
- }
- } else {
- switch (precisionUnit) { // plural (2 days)
- case 'year': return $localize`:@@time-since:${dateStrings.i18nYears}:DATE: ago`; break;
- case 'month': return $localize`:@@time-since:${dateStrings.i18nMonths}:DATE: ago`; break;
- case 'week': return $localize`:@@time-since:${dateStrings.i18nWeeks}:DATE: ago`; break;
- case 'day': return $localize`:@@time-since:${dateStrings.i18nDays}:DATE: ago`; break;
- case 'hour': return $localize`:@@time-since:${dateStrings.i18nHours}:DATE: ago`; break;
- case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinutes}:DATE: ago`; break;
- case 'second': return $localize`:@@time-since:${dateStrings.i18nSeconds}:DATE: ago`; break;
- }
- }
- break;
- case 'until':
- if (rounded === 1) {
- switch (precisionUnit) { // singular (In ~1 day)
- case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYear}:DATE:`; break;
- case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonth}:DATE:`; break;
- case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeek}:DATE:`; break;
- case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDay}:DATE:`; break;
- case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHour}:DATE:`; break;
- case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinute}:DATE:`;
- case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSecond}:DATE:`;
- }
- } else {
- switch (precisionUnit) { // plural (In ~2 days)
- case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYears}:DATE:`; break;
- case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonths}:DATE:`; break;
- case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeeks}:DATE:`; break;
- case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDays}:DATE:`; break;
- case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHours}:DATE:`; break;
- case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinutes}:DATE:`; break;
- case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSeconds}:DATE:`; break;
- }
- }
- break;
- case 'span':
- if (rounded === 1) {
- switch (precisionUnit) { // singular (1 day)
- case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYear}:DATE:`; break;
- case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonth}:DATE:`; break;
- case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeek}:DATE:`; break;
- case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDay}:DATE:`; break;
- case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHour}:DATE:`; break;
- case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinute}:DATE:`; break;
- case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSecond}:DATE:`; break;
- }
- } else {
- switch (precisionUnit) { // plural (2 days)
- case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYears}:DATE:`; break;
- case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonths}:DATE:`; break;
- case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeeks}:DATE:`; break;
- case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDays}:DATE:`; break;
- case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHours}:DATE:`; break;
- case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinutes}:DATE:`; break;
- case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSeconds}:DATE:`; break;
- }
- }
- break;
- default:
- if (rounded === 1) {
- switch (precisionUnit) { // singular (1 day)
- case 'year': return dateStrings.i18nYear; break;
- case 'month': return dateStrings.i18nMonth; break;
- case 'week': return dateStrings.i18nWeek; break;
- case 'day': return dateStrings.i18nDay; break;
- case 'hour': return dateStrings.i18nHour; break;
- case 'minute': return dateStrings.i18nMinute; break;
- case 'second': return dateStrings.i18nSecond; break;
- }
- } else {
- switch (precisionUnit) { // plural (2 days)
- case 'year': return dateStrings.i18nYears; break;
- case 'month': return dateStrings.i18nMonths; break;
- case 'week': return dateStrings.i18nWeeks; break;
- case 'day': return dateStrings.i18nDays; break;
- case 'hour': return dateStrings.i18nHours; break;
- case 'minute': return dateStrings.i18nMinutes; break;
- case 'second': return dateStrings.i18nSeconds; break;
- }
- }
+ if (this.kind !== 'until' || this.numUnits === 1) {
+ return this.formatTime(this.kind, precisionUnit, rounded);
+ } else {
+ if (!usedUnits) {
+ result.push(this.formatTime(this.kind, precisionUnit, rounded));
+ } else {
+ result.push(this.formatTime('', precisionUnit, rounded));
+ }
+ seconds -= (rounded * this.intervals[precisionUnit]);
+ usedUnits++;
+ if (usedUnits >= this.numUnits) {
+ return result.join(', ');
+ }
}
}
}
+ return result.join(', ');
}
+ private formatTime(kind, unit, number): string {
+ const dateStrings = dates(number);
+ switch (kind) {
+ case 'since':
+ if (number === 1) {
+ switch (unit) { // singular (1 day)
+ case 'year': return $localize`:@@time-since:${dateStrings.i18nYear}:DATE: ago`; break;
+ case 'month': return $localize`:@@time-since:${dateStrings.i18nMonth}:DATE: ago`; break;
+ case 'week': return $localize`:@@time-since:${dateStrings.i18nWeek}:DATE: ago`; break;
+ case 'day': return $localize`:@@time-since:${dateStrings.i18nDay}:DATE: ago`; break;
+ case 'hour': return $localize`:@@time-since:${dateStrings.i18nHour}:DATE: ago`; break;
+ case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinute}:DATE: ago`; break;
+ case 'second': return $localize`:@@time-since:${dateStrings.i18nSecond}:DATE: ago`; break;
+ }
+ } else {
+ switch (unit) { // plural (2 days)
+ case 'year': return $localize`:@@time-since:${dateStrings.i18nYears}:DATE: ago`; break;
+ case 'month': return $localize`:@@time-since:${dateStrings.i18nMonths}:DATE: ago`; break;
+ case 'week': return $localize`:@@time-since:${dateStrings.i18nWeeks}:DATE: ago`; break;
+ case 'day': return $localize`:@@time-since:${dateStrings.i18nDays}:DATE: ago`; break;
+ case 'hour': return $localize`:@@time-since:${dateStrings.i18nHours}:DATE: ago`; break;
+ case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinutes}:DATE: ago`; break;
+ case 'second': return $localize`:@@time-since:${dateStrings.i18nSeconds}:DATE: ago`; break;
+ }
+ }
+ break;
+ case 'until':
+ if (number === 1) {
+ switch (unit) { // singular (In ~1 day)
+ case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYear}:DATE:`; break;
+ case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonth}:DATE:`; break;
+ case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeek}:DATE:`; break;
+ case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDay}:DATE:`; break;
+ case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHour}:DATE:`; break;
+ case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinute}:DATE:`;
+ case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSecond}:DATE:`;
+ }
+ } else {
+ switch (unit) { // plural (In ~2 days)
+ case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYears}:DATE:`; break;
+ case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonths}:DATE:`; break;
+ case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeeks}:DATE:`; break;
+ case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDays}:DATE:`; break;
+ case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHours}:DATE:`; break;
+ case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinutes}:DATE:`; break;
+ case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSeconds}:DATE:`; break;
+ }
+ }
+ break;
+ case 'span':
+ if (number === 1) {
+ switch (unit) { // singular (1 day)
+ case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYear}:DATE:`; break;
+ case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonth}:DATE:`; break;
+ case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeek}:DATE:`; break;
+ case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDay}:DATE:`; break;
+ case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHour}:DATE:`; break;
+ case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinute}:DATE:`; break;
+ case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSecond}:DATE:`; break;
+ }
+ } else {
+ switch (unit) { // plural (2 days)
+ case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYears}:DATE:`; break;
+ case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonths}:DATE:`; break;
+ case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeeks}:DATE:`; break;
+ case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDays}:DATE:`; break;
+ case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHours}:DATE:`; break;
+ case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinutes}:DATE:`; break;
+ case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSeconds}:DATE:`; break;
+ }
+ }
+ break;
+ default:
+ if (number === 1) {
+ switch (unit) { // singular (1 day)
+ case 'year': return dateStrings.i18nYear; break;
+ case 'month': return dateStrings.i18nMonth; break;
+ case 'week': return dateStrings.i18nWeek; break;
+ case 'day': return dateStrings.i18nDay; break;
+ case 'hour': return dateStrings.i18nHour; break;
+ case 'minute': return dateStrings.i18nMinute; break;
+ case 'second': return dateStrings.i18nSecond; break;
+ }
+ } else {
+ switch (unit) { // plural (2 days)
+ case 'year': return dateStrings.i18nYears; break;
+ case 'month': return dateStrings.i18nMonths; break;
+ case 'week': return dateStrings.i18nWeeks; break;
+ case 'day': return dateStrings.i18nDays; break;
+ case 'hour': return dateStrings.i18nHours; break;
+ case 'minute': return dateStrings.i18nMinutes; break;
+ case 'second': return dateStrings.i18nSeconds; break;
+ }
+ }
+ }
+ }
}