Skip to content

Commit

Permalink
use age instead of time column for recent matches (since time is hard…
Browse files Browse the repository at this point in the history
… to make sense of when matches aren't happening constantly all the time), but format it slightly differently from how it was
  • Loading branch information
norwnd committed Jan 10, 2025
1 parent b011042 commit a66bbae
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 66 deletions.
4 changes: 3 additions & 1 deletion client/asset/eth/multirpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,9 @@ func (p *provider) subscribeHeaders(ctx context.Context, sub ethereum.Subscripti
// will never return because geth does not use a timeout.
doneUnsubbing := make(chan struct{})
go func() {
sub.Unsubscribe()
if sub != nil {
sub.Unsubscribe()
}
close(doneUnsubbing)
}()
select {
Expand Down
4 changes: 4 additions & 0 deletions client/webserver/site/src/css/utilities.scss
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ sup.token-parent {
white-space: pre-line;
}

.preserve-spaces {
white-space:pre;
}

.vscroll {
@extend .stylish-overflow;

Expand Down
6 changes: 3 additions & 3 deletions client/webserver/site/src/html/markets.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -413,17 +413,17 @@
<span class="ico-arrowdown"></span>
<span id="qtyHdr"></span>
</th>
<th data-ordercol="time" class="text-end text-nowrap grey">
<th data-ordercol="age" class="text-end text-nowrap grey">
<span class="ico-arrowdown"></span>
<span id="timeHdr"></span>
<span id="ageHdr"></span>
</th>
</tr>
</thead>
<tbody id="recentMatchesLiveList">
<tr id="recentMatchesTemplate">
<td data-tmpl="price" class="text-start fs17"></td>
<td data-tmpl="qty" class="text-end fs17"></td>
<td data-tmpl="time" class="text-end fs17"></td>
<td data-tmpl="age" class="preserve-spaces text-end fs17"></td>
</tr>
</tbody>
</table>
Expand Down
8 changes: 0 additions & 8 deletions client/webserver/site/src/html/wallets.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,6 @@
<div class="d-flex justify-content-start align-items-stretch flex-column border-start col-sm-24 col-md-12 p-2" id="walletInfo">
<table id="walletInfoTable" class="w-100">
<tbody>
<tr id="statusLocked">
<td class="grey">[[[Status]]]</td>
<td><span class="ico-locked fs14 me-2"></span class="demi">[[[:title:locked]]]</td>
</tr>
<tr id="statusReady">
<td class="grey">[[[Status]]]</td>
<td class="demi"><span class="ico-unlocked fs14 me-2"></span>[[[:title:ready]]]</td>
</tr>
<tr id="statusOff">
<td class="grey">[[[Status]]]</td>
<td><span class="ico-sleeping fs14 me-2"></span class="demi">[[[:title:off]]]</td>
Expand Down
71 changes: 45 additions & 26 deletions client/webserver/site/src/js/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,8 @@ export default class Doc {
* ageSinceFromMs returns a string representation of the duration since the
* specified unix timestamp (milliseconds).
*/
static ageSinceFromMs (ms: number): string {
return Doc.formatDuration((new Date().getTime()) - ms)
static ageSinceFromMs (ms: number, trimSeconds?: boolean): string {
return Doc.formatDuration((new Date().getTime()) - ms, trimSeconds)
}

/*
Expand All @@ -696,9 +696,9 @@ export default class Doc {
}

/*
* hmsSinceFromS returns a time duration since the specified unix timestamp
* formatted as YYYY/MM/DD hh:mm.
*/
* hmsSinceFromS returns a time duration since the specified unix timestamp
* formatted as YYYY/MM/DD hh:mm.
*/
static ymdhmSinceFromMS (ms: number): string {
const date = new Date(ms)
const year = String(date.getFullYear())
Expand All @@ -710,29 +710,54 @@ export default class Doc {
}

/* formatDuration returns a string representation of the duration */
static formatDuration (dur: number): string {
static formatDuration (dur: number, trimSeconds?: boolean): string {
let seconds = Math.floor(dur)
let result = ''
let count = 0
const add = (n: number, s: string) => {
if (n > 0 || count > 0) count++
if (n > 0) result += `${n}${s} `
return count >= 2
// significantChunkCnt counts how many chunks (year, month, day, hour, minute) we've added to the result.
let significantChunkCnt = 0
const add = (n: number, s: string): boolean => {
if (n === 0 && significantChunkCnt === 0) {
// we haven't started building the result, so we aren't done yet
return false
}
significantChunkCnt++
let chunk = `${n}${s} `
if (n < 10) {
// gotta pad 1-digit number chunk so that it occupies the same amount of space as 2-digit chunk
chunk = ' ' + chunk // use a space that's of the same size as a digit
}
result += chunk
return significantChunkCnt >= 2 // we want to show 2 chunks (year, month, day, hour, minute) at most
}
let y, mo, d, h, m, s
[y, seconds] = timeMod(seconds, aYear)
if (add(y, 'y')) { return result }
[mo, seconds] = timeMod(seconds, aMonth)
if (add(mo, 'mo')) { return result }
[d, seconds] = timeMod(seconds, aDay)
if (add(d, 'd')) { return result }

const aYear = 31536000000
const aMonth = 2592000000
const aDay = 86400000
const anHour = 3600000
const aMinute = 60000
const aSecond = 1000

let Y, M, D, h, m, s
[Y, seconds] = timeMod(seconds, aYear)
if (add(Y, 'y')) { return result }
[M, seconds] = timeMod(seconds, aMonth)
if (add(M, 'm')) { return result }
[D, seconds] = timeMod(seconds, aDay)
if (add(D, 'd')) { return result }
[h, seconds] = timeMod(seconds, anHour)
if (add(h, 'h')) { return result }
if (trimSeconds) {
// show minutes chunk and be done with it
[m, seconds] = timeMod(seconds, aMinute)
add(m, 'm')
return result || '0m'
}
// show both minutes and seconds chunks then
[m, seconds] = timeMod(seconds, aMinute)
if (add(m, 'm')) { return result }
[s, seconds] = timeMod(seconds, 1000)
[s, seconds] = timeMod(seconds, aSecond)
add(s, 's')
return result.trimEnd() || '0s'
return result || '0s'
}

// showFormError can be used to set and display error message on forms.
Expand Down Expand Up @@ -875,12 +900,6 @@ function sleep (ms: number) {
return new Promise(resolve => setTimeout(resolve, ms))
}

const aYear = 31536000000
const aMonth = 2592000000
const aDay = 86400000
const anHour = 3600000
const aMinute = 60000

/* timeMod returns the quotient and remainder of t / dur. */
function timeMod (t: number, dur: number) {
const n = Math.floor(t / dur)
Expand Down
16 changes: 8 additions & 8 deletions client/webserver/site/src/js/markets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export default class MarketsPage extends BasePage {
this.recentMatches = []
this.hovers = []
// 'Recent Matches' list sort key and direction.
this.recentMatchesSortKey = 'time'
this.recentMatchesSortKey = 'age'
this.recentMatchesSortDirection = -1
// store original title so we can re-append it when updating market value.
this.ogTitle = document.title
Expand Down Expand Up @@ -449,8 +449,8 @@ export default class MarketsPage extends BasePage {
for (const mord of Object.values(this.recentlyActiveUserOrders)) {
mord.details.age.textContent = Doc.ageSinceFromMs(mord.ord.submitTime)
}
for (const td of Doc.applySelector(page.recentMatchesLiveList, '[data-tmpl=time]')) {
td.textContent = Doc.timeFromMs(parseFloat(td.dataset.timestampMs ?? '0'))
for (const td of Doc.applySelector(page.recentMatchesLiveList, '[data-tmpl=age]')) {
td.textContent = Doc.ageSinceFromMs(parseFloat(td.dataset.timestampMs ?? '0'), true)
}
}, 1000)

Expand Down Expand Up @@ -572,7 +572,7 @@ export default class MarketsPage extends BasePage {
return
}

const recentMatches = this.recentMatchesSorted('time', -1) // freshest first
const recentMatches = this.recentMatchesSorted('age', -1) // freshest first
if (recentMatches.length === 0) {
// not enough info to display current market price
setDummyValues()
Expand Down Expand Up @@ -1280,7 +1280,7 @@ export default class MarketsPage extends BasePage {

// update header for "matches" section
page.priceHdr.textContent = `Price (${Doc.shortSymbol(this.market.quote.symbol)})`
page.timeHdr.textContent = 'Time'
page.ageHdr.textContent = 'Age'
page.qtyHdr.textContent = `Size (${Doc.shortSymbol(this.market.base.symbol)})`
}

Expand Down Expand Up @@ -2661,7 +2661,7 @@ export default class MarketsPage extends BasePage {
return this.recentMatches.sort((a: RecentMatch, b: RecentMatch) => direction * (a.rate - b.rate))
case 'qty':
return this.recentMatches.sort((a: RecentMatch, b: RecentMatch) => direction * (a.qty - b.qty))
case 'time':
case 'age':
return this.recentMatches.sort((a: RecentMatch, b:RecentMatch) => direction * (a.stamp - b.stamp))
default:
return []
Expand Down Expand Up @@ -2691,8 +2691,8 @@ export default class MarketsPage extends BasePage {
tmpl.price.classList.add(match.sell ? 'sellcolor' : 'buycolor')
tmpl.qty.textContent = Doc.formatCoinAtomToLotSizeBaseCurrency(match.qty, mkt.baseUnitInfo, mkt.cfg.lotsize)
tmpl.qty.classList.add(match.sell ? 'sellcolor' : 'buycolor')
tmpl.time.textContent = Doc.timeFromMs(match.stamp)
tmpl.time.dataset.timestampMs = String(match.stamp)
tmpl.age.textContent = Doc.ageSinceFromMs(match.stamp, true)
tmpl.age.dataset.timestampMs = String(match.stamp)
page.recentMatchesLiveList.append(row)
}
}
Expand Down
22 changes: 2 additions & 20 deletions client/webserver/site/src/js/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,7 @@ export default class WalletsPage extends BasePage {
page.assetLogo.src = Doc.logoPath(symbol)
Doc.hide(
page.balanceBox, page.fiatBalanceBox, page.createWallet, page.walletDetails,
page.sendReceive, page.connectBttnBox, page.statusLocked, page.statusReady,
page.sendReceive, page.connectBttnBox,
page.statusOff, page.connectBttnBox, page.peerCountBox, page.syncProgressBox,
page.statusDisabled, page.tokenInfoBox, page.needsProviderBox, page.feeStateBox,
page.txSyncBox, page.txProgress, page.txFindingAddrs
Expand Down Expand Up @@ -1021,14 +1021,11 @@ export default class WalletsPage extends BasePage {
updateSyncAndPeers (assetID: number) {
const { page, selectedAssetID } = this
if (assetID !== selectedAssetID) return
const { peerCount, syncProgress, syncStatus, open, running } = app().walletMap[assetID]
const { peerCount, syncProgress, syncStatus, running } = app().walletMap[assetID]
if (!running) return
Doc.show(page.sendReceive, page.peerCountBox, page.syncProgressBox)
page.peerCount.textContent = String(peerCount)
page.syncProgress.textContent = `${(syncProgress * 100).toFixed(1)}%`
if (open) {
Doc.show(page.statusReady)
} else Doc.show(page.statusLocked) // wallet not unlocked
Doc.setVis(syncStatus.txs !== undefined, page.txSyncBox)
if (syncStatus.txs !== undefined) {
Doc.hide(page.txProgress, page.txFindingAddrs)
Expand Down Expand Up @@ -2007,21 +2004,6 @@ export default class WalletsPage extends BasePage {
this.showForm(this.page.recoverWalletConfirm)
}

/* Show the open wallet form if the password is not cached, and otherwise
* attempt to open the wallet.
*/
async openWallet (assetID: number) {
const open = {
assetID: assetID
}
const res = await postJSON('/api/openwallet', open)
if (!app().checkResponse(res)) {
console.error('openwallet error', res)
return
}
this.assetUpdated(assetID, undefined, intl.prep(intl.ID_WALLET_UNLOCKED))
}

/* Show the form used to change wallet configuration settings. */
async showReconfig (assetID: number, cfg?: reconfigSettings) {
const page = this.page
Expand Down

0 comments on commit a66bbae

Please sign in to comment.