import {ChangeLog, ChangeSetEntry} from "../update/ChangeLog"; import * as loader from "tc-loader"; import {Stage} from "tc-loader"; import {setUIUpdater} from "../update/index"; import {Updater} from "../update/Updater"; import {LogCategory, logError} from "../log"; const ChangeLogContents: string = require("../../../ChangeLog.md"); const EntryRegex = /^\* \*\*([0-9]{2})\.([0-9]{2})\.([0-9]{2})\*\*$/m; const TimeStampRegex = /^([0-9]{2})\.([0-9]{2})\.([0-9]{2})$/m; function parseChangeLogEntry(lines: string[], index: number) : { entries: ChangeSetEntry[], index: number } { const entryDepth = lines[index].indexOf("-"); if(entryDepth === -1) { throw "missing entry depth for line " + index; } let entries = [] as ChangeSetEntry[]; let currentEntry; while(index < lines.length && !lines[index].match(EntryRegex)) { let trimmed = lines[index].trim(); if(trimmed.length === 0) { index++; continue; } if(trimmed[0] === '-') { const depth = lines[index].indexOf('-'); if(depth > entryDepth) { if(typeof currentEntry === "undefined") throw "missing change child entries parent at line " + index; const result = parseChangeLogEntry(lines, index); entries.push({ changes: result.entries, title: currentEntry }); index = result.index; } else if(depth < entryDepth) { /* we're done with our block */ break; } else { /* new entry */ if(typeof currentEntry === "string") entries.push(currentEntry); currentEntry = trimmed.substr(1).trim(); } } else { currentEntry += "\n" + trimmed; } index++; } if(typeof currentEntry === "string") entries.push(currentEntry); return { index: index, entries: entries }; } function parseUIChangeLog() : ChangeLog { let result: ChangeLog = { currentVersion: "unknown", changes: [] } const lines = ChangeLogContents.split("\n"); let index = 0; while(index < lines.length && !lines[index].match(EntryRegex)) index++; while(index < lines.length) { const [ _, day, month, year ] = lines[index].match(EntryRegex); const entry = parseChangeLogEntry(lines, index + 1); result.changes.push({ timestamp: day + "." + month + "." + year, changes: entry.entries }); index = entry.index; } return result; } const kLastUsedVersionKey = "updater-used-version-web"; class WebUpdater implements Updater { private readonly changeLog: ChangeLog; private readonly currentVersion: string; constructor() { this.changeLog = parseUIChangeLog(); const currentBuildTimestamp = new Date(__build.timestamp * 1000); this.currentVersion = ("00" + currentBuildTimestamp.getUTCDate()).substr(-2) + "." + ("00" + currentBuildTimestamp.getUTCMonth()).substr(-2) + "." + currentBuildTimestamp.getUTCFullYear().toString().substr(2); } getChangeLog(): ChangeLog { return this.changeLog; } getChangeList(oldVersion: string): ChangeLog { let changes = { changes: [], currentVersion: this.currentVersion } as ChangeLog; try { const [ _, oldDay, oldMonth, oldYear ] = oldVersion.match(TimeStampRegex); const oldDate = new Date(parseInt(oldYear), parseInt(oldMonth), parseInt(oldDay)); for(const change of this.getChangeLog().changes) { const [ _, currentDay, currentMonth, currentYear ] = change.timestamp.match(TimeStampRegex); const currentDate = new Date(parseInt(currentYear), parseInt(currentMonth), parseInt(currentDay)); if(currentDate.getTime() <= oldDate.getTime()) break; changes.changes.push(change); } } catch (error) { logError(LogCategory.GENERAL, tr("Failed to gather a change list from version %s: %o"), oldVersion, error); return this.getChangeLog(); } return changes; } getCurrentVersion(): string { return this.currentVersion; } getLastUsedVersion(): string { return localStorage.getItem(kLastUsedVersionKey) || "08.08.20"; } updateUsedVersion() { localStorage.setItem(kLastUsedVersionKey, this.getCurrentVersion()); } } loader.register_task(Stage.JAVASCRIPT_INITIALIZING, { name: "web updater init", function: async () => { setUIUpdater(new WebUpdater()); }, priority: 50 });