Last active
April 20, 2017 06:55
-
-
Save gutchom/f34c293188c6689d63736aa016ff969f to your computer and use it in GitHub Desktop.
オブジェクトを与えることで画面の状態や操作の履歴を保存したり復元したりしてくれるよ。
This file contains hidden or 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
interface HistoryLogger { | |
readonly current: any | |
readonly stamp: number | |
jump(stamp: number): void | |
undo(): void | |
redo(): void | |
clear(): void | |
record(record: any): void | |
restore(): void | |
} |
This file contains hidden or 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
import moment from 'moment' | |
const PREFIX = 'log-' | |
export default class Logger implements HistoryLogger { | |
version: string | |
name: string | |
history: any[] = [] // index1番が最古の状態。this.history.length - 1が最新。 | |
retroactDepth = 0 // this.history.lengthが最大値。 | |
restorableDepth: number | |
marks: { timestamp: number, position: number }[] = [] | |
noStorage: boolean = false | |
constructor(version: string, name: string, restorableDepth: number) { | |
this.version = version | |
this.name = name | |
this.restorableDepth = restorableDepth | |
try { | |
if (typeof window.sessionStorage === 'undefined') this.noStorage = true | |
const x = '__storage_test__' | |
localStorage.setItem(x, x) | |
localStorage.removeItem(x) | |
this.noStorage = false | |
} | |
catch (err) { | |
this.noStorage = true | |
} | |
} | |
private get minDepth(): number { return 0 } | |
private get maxDepth(): number { return this.history.length - 1 } | |
private get depth(): number { return this.retroactDepth } | |
private set depth(num: number) { | |
this.retroactDepth = num <= this.minDepth | |
? this.minDepth | |
: num >= this.maxDepth | |
? this.maxDepth | |
: num | |
this.marks = this.marks.filter(mark => mark.position < this.history.length) | |
} | |
get current(): any { return this.history[this.history.length - this.depth - 1] } | |
get stamp(): number { | |
const timestamp = Date.now() | |
const position = this.history.length - this.depth | |
this.marks.push({ timestamp, position }) | |
return timestamp | |
} | |
undo(): void { this.depth++ } | |
redo(): void { this.depth-- } | |
clear(): void { | |
this.history = [] | |
this.depth = this.minDepth | |
} | |
jump(stamp: number): void { | |
const mark = this.marks.find(mark => mark.timestamp === stamp) | |
if (!mark) throw new Error('Assigned stamp to logger is outdated.') | |
this.depth = this.history.length - mark.position | |
} | |
record(data: any): void { | |
const index = this.history.length - this.depth | |
this.history.splice(index, this.depth, data) | |
if (this.noStorage) return | |
const depth = - (this.depth + this.restorableDepth) | |
const log = { | |
version: this.version, | |
timestamp: moment().format(), | |
depth: this.retroactDepth, | |
data: this.history.slice(depth), | |
} | |
localStorage.setItem(PREFIX + this.name, JSON.stringify(log)) | |
} | |
restore(): void { | |
if (this.noStorage) return | |
const json = localStorage.getItem(PREFIX + this.name) | |
if (!json) return | |
const restored = JSON.parse(json) | |
if (restored.version !== this.version) return | |
if (moment().diff(moment(restored.timestamp), 'hours', true) > 3) return | |
this.depth = restored.depth | |
this.history = restored.data | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment