Skip to content

Commit 51f389a

Browse files
authored
feat: explorer display block hash with middle ellipsis
1 parent c0fcf04 commit 51f389a

File tree

6 files changed

+53
-13
lines changed

6 files changed

+53
-13
lines changed

.changeset/thin-doors-notice.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'explorer': minor
3+
---
4+
5+
Block hashes now show both leading and ending characters to improve legibility. Closes https://github.com/SiaFoundation/web/issues/451

apps/explorer/components/Block/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export function Block({ block }: Props) {
1616
const list: DatumProps[] = [
1717
{
1818
label: 'Block hash',
19-
value: block.id,
19+
entityType: 'blockHash',
20+
entityValue: block.id,
2021
},
2122
{
2223
label: 'Miner payout address',
@@ -64,6 +65,7 @@ export function Block({ block }: Props) {
6465
<EntityList
6566
title={`Transactions (${block.transactions?.length || 0})`}
6667
dataset={block.transactions?.map((tx) => ({
68+
type: 'transaction',
6769
hash: tx.id,
6870
label: 'transaction',
6971
initials: 'T',

apps/explorer/components/ExplorerDatum.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { getHref } from '../lib/utils'
1313
export type DatumProps = {
1414
label: string
1515
value?: React.ReactNode
16+
displayValue?: string
1617
entityType?: EntityType
1718
entityValue?: string
1819
sc?: BigNumber
@@ -27,6 +28,7 @@ export function ExplorerDatum({
2728
entityValue,
2829
copyable = true,
2930
value,
31+
displayValue,
3032
sc,
3133
sf,
3234
comment,
@@ -47,14 +49,10 @@ export function ExplorerDatum({
4749
(entityValue ? (
4850
<ValueCopyable
4951
scaleSize="18"
50-
label={entityType}
5152
href={getHref(entityType, entityValue)}
5253
value={entityValue}
53-
displayValue={
54-
entityType === 'block' && entityValue
55-
? Number(entityValue).toLocaleString()
56-
: entityValue
57-
}
54+
type={entityType}
55+
displayValue={displayValue}
5856
// className="relative top-0.5"
5957
/>
6058
) : (

apps/explorer/lib/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { Metadata } from 'next'
44
import { siteName } from '../config'
55

66
export function getHref(type: EntityType, value: string) {
7-
return routes[type].view.replace(':id', value)
7+
// block accepts blockhash as a value.
8+
const coercedType = type === 'blockHash' ? 'block' : type
9+
return routes[coercedType].view.replace(':id', value)
810
}
911

1012
export function buildMetadata({

libs/design-system/src/components/ValueCopyable.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
getEntityDisplayLength,
1313
getEntitySiascanUrl,
1414
getEntityTypeCopyLabel,
15+
formatEntityValue,
16+
defaultFormatValue,
1517
} from '../lib/entityTypes'
1618
import { cx } from 'class-variance-authority'
1719
import {
@@ -56,11 +58,11 @@ export function ValueCopyable({
5658
const label = customLabel || getEntityTypeCopyLabel(type)
5759
const maxLength = customMaxLength || getEntityDisplayLength(type)
5860
const cleanValue = stripPrefix(value)
59-
const renderValue = displayValue || cleanValue
60-
61-
const text = `${renderValue?.slice(0, maxLength)}${
62-
(renderValue?.length || 0) > maxLength ? '...' : ''
63-
}`
61+
// If we pass a defaultValue, use it. An entityType? Format it.
62+
const renderValue =
63+
displayValue || (type && formatEntityValue(type, cleanValue, maxLength))
64+
// If we don't yet have a renderValue, apply some general formatting.
65+
const text = renderValue || defaultFormatValue(cleanValue, maxLength)
6466

6567
return (
6668
<div className={cx('flex items-center', className)}>

libs/design-system/src/lib/entityTypes.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type EntityType =
1111
| 'hostIp'
1212
| 'hostPublicKey'
1313
| 'contract'
14+
| 'blockHash'
1415

1516
export type TxType =
1617
| 'siacoin'
@@ -119,6 +120,7 @@ const entityLabels: Record<EntityType, string> = {
119120
hostIp: 'host',
120121
hostPublicKey: 'host',
121122
ip: 'IP',
123+
blockHash: 'block hash',
122124
}
123125

124126
const entityCopyLabels: Record<EntityType, string> = {
@@ -130,6 +132,7 @@ const entityCopyLabels: Record<EntityType, string> = {
130132
hostIp: 'host address',
131133
hostPublicKey: 'host public key',
132134
ip: 'IP',
135+
blockHash: 'block hash',
133136
}
134137

135138
const txTypeMap: Record<TxType, string> = {
@@ -200,3 +203,31 @@ export function getEntitySiascanUrl(
200203
return ''
201204
}
202205
}
206+
207+
export function defaultFormatValue(text: string, maxLength: number) {
208+
return `${text?.slice(0, maxLength)}${
209+
(text?.length || 0) > maxLength ? '...' : ''
210+
}`
211+
}
212+
213+
export function formatEntityValue(
214+
type: EntityType,
215+
text: string,
216+
maxLength: number
217+
) {
218+
switch (type) {
219+
case 'blockHash': {
220+
const halfMax = maxLength / 2
221+
// Floor and ceil here to handle odd maxLengths.
222+
// .slice() will round down on floats.
223+
const firstHalf = text.slice(0, Math.floor(halfMax))
224+
const lastHalf = text.slice(text.length - Math.ceil(halfMax))
225+
return firstHalf + '...' + lastHalf
226+
}
227+
default: {
228+
// We could also return null here, forcing the issue of defining
229+
// formats for the missing cases in the switch above.
230+
return defaultFormatValue(text, maxLength)
231+
}
232+
}
233+
}

0 commit comments

Comments
 (0)