145 lines
4.1 KiB
TypeScript
Raw Normal View History

import TxSprite from './tx-sprite'
import { FastVertexArray } from './fast-vertex-array'
import { TransactionStripped } from 'src/app/interfaces/websocket.interface';
import { SpriteUpdateParams, Square, Color, ViewUpdateParams } from './sprite-types'
import { feeLevels, mempoolFeeColors } from 'src/app/app.constants';
const hoverTransitionTime = 300
const defaultHoverColor = hexToColor('1bd8f4')
// convert from this class's update format to TxSprite's update format
function toSpriteUpdate(params : ViewUpdateParams): SpriteUpdateParams {
return {
start: (params.start || performance.now()) + (params.delay || 0),
duration: params.duration,
minDuration: params.minDuration,
...params.display.position,
...params.display.color,
adjust: params.adjust
}
}
export default class TxView implements TransactionStripped {
txid: string;
fee: number;
vsize: number;
value: number;
feerate: number;
initialised: boolean;
vertexArray: FastVertexArray;
hover: boolean;
sprite: TxSprite;
hoverColor: Color | void;
screenPosition: Square;
gridPosition : Square | void;
dirty: boolean;
constructor (tx: TransactionStripped, vertexArray: FastVertexArray) {
this.txid = tx.txid
this.fee = tx.fee
this.vsize = tx.vsize
this.value = tx.value
this.feerate = tx.fee / tx.vsize
this.initialised = false
this.vertexArray = vertexArray
this.hover = false
this.screenPosition = { x: 0, y: 0, s: 0 }
this.dirty = true
}
destroy (): void {
if (this.sprite) {
this.sprite.destroy()
this.sprite = null
this.initialised = false
}
}
applyGridPosition (position: Square): void {
if (!this.gridPosition) this.gridPosition = { x: 0, y: 0, s: 0 }
if (this.gridPosition.x != position.x || this.gridPosition.y != position.y || this.gridPosition.s != position.s) {
this.gridPosition.x = position.x
this.gridPosition.y = position.y
this.gridPosition.s = position.s
this.dirty = true
}
}
/*
display: defines the final appearance of the sprite
position: { x, y, s } (coordinates & size)
color: { r, g, b, a} (color channels & alpha)
duration: of the tweening animation from the previous display state
start: performance.now() timestamp, when to start the transition
delay: additional milliseconds to wait before starting
jitter: if set, adds a random amount to the delay,
adjust: if true, modify an in-progress transition instead of replacing it
*/
update (params: ViewUpdateParams): void {
if (params.jitter) params.delay += (Math.random() * params.jitter)
if (!this.initialised || !this.sprite) {
this.initialised = true
this.sprite = new TxSprite(
toSpriteUpdate(params),
this.vertexArray
)
// apply any pending hover event
if (this.hover) {
this.sprite.update({
...this.hoverColor,
duration: hoverTransitionTime,
adjust: false,
temp: true
})
}
} else {
this.sprite.update(
toSpriteUpdate(params)
)
}
this.dirty = false
}
// Temporarily override the tx color
setHover (hoverOn: boolean, color: Color | void = defaultHoverColor): void {
if (hoverOn) {
this.hover = true
this.hoverColor = color
this.sprite.update({
...this.hoverColor,
duration: hoverTransitionTime,
adjust: false,
temp: true
})
} else {
this.hover = false
this.hoverColor = null
if (this.sprite) this.sprite.resume(hoverTransitionTime)
}
this.dirty = false
}
getColor (): Color {
let feeLevelIndex = feeLevels.slice().reverse().findIndex((feeLvl) => (this.feerate || 1) >= feeLvl);
feeLevelIndex = feeLevelIndex >= 0 ? feeLevels.length - feeLevelIndex : feeLevelIndex;
return hexToColor(mempoolFeeColors[feeLevelIndex - 1] || mempoolFeeColors[mempoolFeeColors.length - 1])
}
}
function hexToColor (hex: string): Color {
return {
r: parseInt(hex.slice(0,2), 16) / 255,
g: parseInt(hex.slice(2,4), 16) / 255,
b: parseInt(hex.slice(4,6), 16) / 255,
a: 1
}
}