Commit 002cd1df authored by Cédric F.'s avatar Cédric F.

Improve responsiveness

parent c416e2fa
Pipeline #14388459 (#) passed with stage
in 1 minute and 28 seconds
......@@ -44,7 +44,6 @@
body {
font-family: 'Inconsolata', monospace;
font-size: 1.25rem;
}
hr {
......@@ -61,21 +60,25 @@
background-color: #000;
}
.amount {
white-space: nowrap;
}
.glow {
transition: all 1s;
background: orange;
box-shadow: 0 0 10px 5px orange;
}
.fetching {
opacity: 0.5;
}
.rotate {
animation: spin 2s linear infinite;
}
@keyframes spin { 100% { transform:rotate(360deg); } }
@media (min-width: 768px) {
body { font-size: 1.25rem; }
}
</style>
</head>
<body class="bg-black text-white">
......@@ -89,7 +92,7 @@
<script>
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '.amount::after { content: " ' + coin + '" };';
style.innerHTML = '.amount::after { content: "' + '\u00a0' + coin + '" };';
document.getElementsByTagName('head')[0].appendChild(style);
</script>
......@@ -107,13 +110,7 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js"></script>
<script>
//particlesJS.load('particles-js', 'assets/js/particles.json', function() {
//console.log('callback - particles.js config loaded');
//});
window.addEventListener('load', () => {
const elmAppDiv = document.querySelector('#elm-app');
const elmApp = Elm.Trappisto.embed(elmAppDiv, { coin: coin });
......@@ -144,6 +141,12 @@
}
break;
case 'particles':
particlesJS.load('particles-js', 'assets/js/particles.json', () => {
alert('Congrats, you found the easter egg! Particles are coming at you at supersonic speed!');
});
break;
default:
console.error('Unhandled command: ' + command);
}
......@@ -174,5 +177,7 @@
// setTimeout(() => { logo.classList.remove('glow'); }, 1000);
});
</script>
<script src="https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js" async defer></script>
</body>
</html>
......@@ -83,10 +83,10 @@ view model now =
(\tx ->
tr []
[ td [] [ queryLink tx.hash (shortHash tx.hash) [] ]
, td [] [ text tx.type_ ]
, td [ class "d-none d-sm-block" ] [ text tx.type_ ]
, td []
[ Transaction.vInToAddress model.address tx |> formatAmount ]
, td [] [ Transaction.formatTime tx now ]
[ Transaction.sentToAddress model.address tx |> formatAmount ]
, td [ class "d-none d-sm-block" ] [ Transaction.formatTime tx now ]
, td [] [ text <| toString tx.confirmations ]
]
)
......@@ -94,8 +94,9 @@ view model now =
div [ class "row" ]
[ div [ class "col" ]
[ div [ class "card bg-dark" ]
[ h5 [ class "card-header" ]
[ span [] [ text <| "Address " ++ model.address ]
[ h5 [ class "card-header d-flex justify-content-between" ]
[ span [ class "d-inline d-lg-none align-self-center" ] [ text <| "Address " ++ (shortAddress model.address) ]
, span [ class "d-none d-lg-inline align-self-center" ] [ text <| "Address " ++ model.address ]
, dcrDataLink <| "address/" ++ model.address
]
, div [ class "card-body" ]
......@@ -114,9 +115,9 @@ view model now =
[ thead []
[ tr []
[ th [] [ text "hash" ]
, th [] [ text "type" ]
, th [] [ text "credit" ]
, th [] [ text "time" ]
, th [ class "d-none d-sm-block" ] [ text "type" ]
, th [] [ text "received" ]
, th [ class "d-none d-sm-block" ] [ text "time" ]
, th []
[ abbr [ title "confirmations" ] [ text "conf." ] ]
]
......@@ -220,7 +221,7 @@ decodeSearchRawTransactions address =
maxTransactionCount : Int
maxTransactionCount =
500
250
missingTransactions : Model -> Bool
......
......@@ -99,7 +99,7 @@ view model now =
let
( label, classes ) =
if direction == "right" then
( "Next block", " float-right ml-2" )
( "Next block", " ml-2" )
else
( "Previous block", "" )
in
......@@ -136,16 +136,20 @@ view model now =
_ ->
[ ( "transactions", transactions model.transactions "light" ) ]
in
div [ class "row align-items-center" ]
div [ class "row" ]
[ div [ class "col" ]
[ div
[ class "card bg-dark" ]
[ h5 [ class "card-header" ]
[ sibbling model.previousBlockHash "left"
, span [ class "ml-4" ]
[ text <| "Block " ++ model.hash ]
, sibbling model.nextBlockHash "right"
, dcrDataLink <| "block/" ++ model.hash
[ h5 [ class "card-header d-flex justify-content-between" ]
[ span []
[ sibbling model.previousBlockHash "left"
, span [ class "d-inline d-lg-none ml-2 align-self-start" ] [ text <| "Block " ++ (shortHash model.hash) ]
, span [ class "d-none d-lg-inline ml-2 align-self-start" ] [ text <| "Block " ++ model.hash ]
]
, span []
[ dcrDataLink <| "block/" ++ model.hash
, sibbling model.nextBlockHash "right"
]
]
, div [ class "card-body" ]
[ p [ class "card-text" ]
......
......@@ -124,10 +124,10 @@ view model now =
queryLink hash (shortHash hash) []
( Nothing, Just height ) ->
queryLink (toString height) (toString height) []
queryLink (formatNumber height) (toString height) []
( Just hash, Just height ) ->
queryLink hash (toString height) []
queryLink hash (formatNumber height) []
formatFees model =
case model.config.coin of
......@@ -151,19 +151,33 @@ view model now =
_ ->
[]
formatAddresses scriptPubKey =
div [] <|
(List.map
(\address -> div [] [ queryLink address address [] ])
scriptPubKey.addresses
)
formatAddresses maybe =
case maybe of
Nothing ->
span [] []
Just wrapper ->
div [] <|
(List.map
(\address ->
div []
[ queryLink address
(shortAddress address)
[ class "d-inline d-xs-none" ]
, queryLink address
address
[ class "d-none d-xs-inline" ]
]
)
wrapper.addresses
)
formatVIn vIn =
vIn
|> List.map
(\vIn ->
li [ class "list-group-item bg-secondary" ]
[ span [ class "badge badge-info" ]
[ span [ class "badge badge-info mr-2" ]
[ text
(if vIn.coinbase /= Nothing then
"coinbase"
......@@ -179,15 +193,16 @@ view model now =
else
span [] []
]
, div [ class "clearfix" ] []
, div []
[ (case vIn.txId of
(case vIn.txId of
Just hash ->
queryLink hash ("Transaction " ++ shortHash hash) []
[ queryLink hash (shortHash hash) [] ]
Nothing ->
span [] []
)
]
[ span [] [] ]
)
, formatAddresses vIn.prevOut
]
)
......@@ -196,9 +211,10 @@ view model now =
|> List.map
(\vOut ->
li [ class "list-group-item bg-secondary" ]
[ span [ class "badge badge-info" ] [ text vOut.scriptPubKey.type_ ]
[ span [ class "badge badge-info mr-2" ] [ text vOut.scriptPubKey.type_ ]
, span [ class "float-right" ] [ formatAmount vOut.value ]
, formatAddresses vOut.scriptPubKey
, div [ class "clearfix" ] []
, formatAddresses (Just vOut.scriptPubKey)
, code [ class "mt-2" ] [ text vOut.scriptPubKey.asm ]
]
)
......@@ -207,8 +223,9 @@ view model now =
[ div [ class "col" ]
[ div
[ class "card bg-dark" ]
[ h5 [ class "card-header" ]
[ span [] [ text <| "Transaction " ++ model.hash ]
[ h5 [ class "card-header d-flex justify-content-between" ]
[ span [ class "d-inline d-lg-none align-self-center" ] [ text <| "Transaction " ++ (shortHash model.hash) ]
, span [ class "d-none d-lg-inline align-self-center" ] [ text <| "Transaction " ++ model.hash ]
, dcrDataLink <| "tx/" ++ model.hash
]
, div [ class "card-body" ]
......@@ -236,7 +253,7 @@ view model now =
]
, hr [] []
, div [ class "row" ]
[ div [ class "col" ]
[ div [ class "col mb-3" ]
[ h4 [ class "text-center" ]
[ span [ class "badge badge-pill badge-info" ]
[ text <| pluralize (List.length model.vIn) "input" ]
......@@ -244,7 +261,7 @@ view model now =
, ul [ class "list-group list-group-flush" ] <|
formatVIn model.vIn
]
, div [ class "col" ]
, div [ class "col mb-3" ]
[ h4 [ class "text-center" ]
[ span [ class "badge badge-pill badge-info" ]
[ text <| pluralize (List.length model.vOut) "output" ]
......@@ -311,7 +328,11 @@ decodeGetRawTransaction prefix =
|> Pipeline.requiredAt (path "hex") Decode.string
|> Pipeline.optionalAt (path "confirmations") Decode.int 0
|> Pipeline.optionalAt (path "blockhash") (Decode.maybe Decode.string) Nothing
|> Pipeline.optionalAt (path "blockheight") (Decode.maybe Decode.int) Nothing
|> Pipeline.optionalAt (path "blockheight")
(Decode.maybe Decode.int
|> Decode.andThen (\height -> zeroToNothing height |> Decode.succeed)
)
Nothing
|> Pipeline.optionalAt (path "time") (Decode.maybe Decode.int) Nothing
|> Pipeline.requiredAt (path "vin") (Decode.list decodeVIn)
|> Pipeline.requiredAt (path "vout") (Decode.list decodeVOut)
......@@ -327,11 +348,26 @@ decodeVIn =
)
Nothing
|> Pipeline.optionalAt [ "coinbase" ] (Decode.maybe Decode.string) Nothing
|> Pipeline.optionalAt [ "amountin" ] Decode.float -1
|> Pipeline.requiredAt [ "amountin" ] decodeAmountIn
|> Pipeline.optionalAt [ "blockheight" ] (Decode.maybe Decode.int) Nothing
|> Pipeline.optionalAt [ "prevOut" ] (Decode.maybe decodePrevOut) Nothing
decodeAmountIn : Decode.Decoder Float
decodeAmountIn =
Decode.float
|> Decode.andThen
(\float ->
if float > 0 then
Decode.succeed float
else if float == -1.0e-8 then
--- XXX: unconfirmed txs will return -1 atom as placeholder
Decode.succeed 0
else
Debug.crash <| "Unknown amountin: " ++ (toString float)
)
decodePrevOut : Decode.Decoder PrevOut
decodePrevOut =
Pipeline.decode PrevOut
......@@ -446,7 +482,6 @@ vInToAddress address model =
)
|> List.map .amountIn
|> List.sum
|> negate
vOutToAddress : String -> Model -> Float
......@@ -458,6 +493,11 @@ vOutToAddress address model =
|> List.sum
sentToAddress : String -> Model -> Float
sentToAddress address model =
vOutToAddress address model - vInToAddress address model
totalVIn : Model -> Float
totalVIn model =
List.map .amountIn model.vIn |> List.sum
......
......@@ -50,6 +50,11 @@ formatNumber int =
toString int |> split |> List.reverse |> String.join ","
shortAddress : String -> String
shortAddress address =
String.concat [ String.left 4 address, "...", String.right 4 address ]
shortHash : String -> String
shortHash hash =
String.concat [ String.left 2 hash, "...", String.right 2 hash ]
......@@ -65,8 +70,8 @@ dlBuilder list =
Just value ->
Just <|
[ dt [ class "col-3 text-right" ] [ text label ]
, dd [ class "col-9" ] [ value ]
[ dt [ class "col-6 col-sm-4 col-md-3 text-right" ] [ text label ]
, dd [ class "col-6 col-sm-8 col-md-9" ] [ value ]
]
in
dl [ class "row" ] (List.concat <| List.filterMap filter list)
......@@ -87,7 +92,7 @@ queryLink query label attributes =
dcrDataLink : String -> Html msg
dcrDataLink path =
a
[ class "btn btn-secondary float-right"
[ class "btn btn-secondary"
, target "_blank"
, title "Open on dcrdata.org"
, href <| "https://explorer.dcrdata.org/explorer/" ++ path
......@@ -95,6 +100,19 @@ dcrDataLink path =
[ span [ class "oi oi-external-link" ] [] ]
zeroToNothing : Maybe Int -> Maybe Int
zeroToNothing maybe =
case maybe of
Just int ->
if int == 0 then
Nothing
else
maybe
Nothing ->
Nothing
zeroesToNothing : Maybe String -> Maybe String
zeroesToNothing maybe =
let
......
......@@ -79,7 +79,6 @@ type Msg
| KeyChange Bool Keyboard.KeyCode
| Resize Window.Size
| Tick Time
| GetBestBlockx
| GetBestBlockResult (Result Http.Error BestBlock)
......
......@@ -189,13 +189,6 @@ update action model =
)
|> updateUrl
GetBestBlockx ->
let
updatedModel =
{ model | fetching = True }
in
( updatedModel, getBestBlock updatedModel )
GetBestBlockResult result ->
case result of
Ok bestBlock ->
......
......@@ -51,9 +51,10 @@ errorView model =
Just error ->
div [ class "row" ]
[ div [ class "col-6 offset-3" ]
[ div [ class "col-12 col-lg-6 offset-lg-3" ]
[ div
[ class "text-center alert alert-danger"
, style [ ( "overflow", "hidden" ) ]
, HtmlAttributesExtra.innerHtml error
]
[]
......@@ -66,20 +67,20 @@ searchView model =
let
search model =
div [ class "row align-items-center" ]
[ div [ class "col-2" ] [ logo model ]
, div [ class "col-8" ]
[ div [ class "col-4 col-lg-3" ] [ logo model ]
, div [ class "col-4 col-lg-6" ]
[ input
[ id "query"
, name "query"
, class "form-control form-control-lg text-center mt-2 mb-4"
, class "form-control form-control-lg text-center mt-2 mb-2"
, placeholder
"Search for blocks, transactions, addresses, particles, etc."
"Search for blocks, transactions, addresses, etc."
, onInput Query
, value model.query
]
[]
]
, div [ class "col-2" ] [ statusView model ]
, div [ class "col-4 col-lg-3" ] [ statusView model ]
]
vim =
......@@ -98,9 +99,9 @@ searchView model =
[ img
[ class
(if isFetching model then
"rotate"
"img-fluid rotate"
else
""
"img-fluid"
)
, src "assets/images/decred.png"
, alt "logo"
......@@ -136,16 +137,19 @@ statusView model =
in
div [ class "text-center" ]
[ span
[ class "badge badge-dark" ]
[ h5 []
[ span [] [ text "Last block:" ]
, br [] []
, lastBlock
]
[ class "w-100 badge badge-dark" ]
[ span [ class "oi oi-spreadsheet" ] []
, span [] [ text " " ]
, span [ class "d-none d-sm-inline" ] [ text "Last block: " ]
, lastBlock
]
, span
[ class <| "badge badge-pill badge-" ++ wsClass ]
[ text <| "Live updating: " ++ wsStatus ]
[ class <| "w-100 badge badge-" ++ wsClass ]
[ span [ class "oi oi-cloud-download" ] []
, span [] [ text " " ]
, span [ class "d-none d-sm-inline" ] [ text "Live updating: " ]
, span [] [ text wsStatus ]
]
]
......@@ -168,14 +172,17 @@ view : Model -> Html Msg
view model =
let
ascii =
div [ class "row text-center mt-3" ]
[ div [ class "col" ]
[ pre [ id "logo", class "text-white" ]
[ text
" ______ _______ _______ _______ _______ ______ \n( __ \\ ( ____ \\( ____ \\( ____ )( ____ \\( __ \\ \n| ( \\ )| ( \\/| ( \\/| ( )|| ( \\/| ( \\ )\n| | ) || (__ | | | (____)|| (__ | | ) |\n| | | || __) | | | __)| __) | | | |\n| | ) || ( | | | (\\ ( | ( | | ) |\n| (__/ )| (____/\\| (____/\\| ) \\ \\__| (____/\\| (__/ )\n(______/ (_______/(_______/|/ \\__/(_______/(______/ \n"
if List.isEmpty model.lastTransactions then
div [ class "row text-center mt-3 d-none d-sm-block" ]
[ div [ class "col" ]
[ pre [ id "logo", class "text-white" ]
[ text
" ______ _______ _______ _______ _______ ______ \n( __ \\ ( ____ \\( ____ \\( ____ )( ____ \\( __ \\ \n| ( \\ )| ( \\/| ( \\/| ( )|| ( \\/| ( \\ )\n| | ) || (__ | | | (____)|| (__ | | ) |\n| | | || __) | | | __)| __) | | | |\n| | ) || ( | | | (\\ ( | ( | | ) |\n| (__/ )| (____/\\| (____/\\| ) \\ \\__| (____/\\| (__/ )\n(______/ (_______/(_______/|/ \\__/(_______/(______/ \n"
]
]
]
]
else
span [] []
lastTransactions =
if List.isEmpty model.lastTransactions then
......@@ -245,15 +252,12 @@ view model =
wrapper model =
[ div [ class "row" ]
[ div
[ class <|
"col"
++ (if isFetching model then
" fetching"
else
""
)
]
content
[ class "col" ]
(if isFetching model then
[ searchView model ]
else
content
)
]
]
......
......@@ -81,13 +81,18 @@ suite =
Decode.decodeString
(Transaction.decodeGetRawTransaction True)
getRawTransactionUnconfirmedFixture
in
case result of
Ok jsonModel ->
Expect.pass
Err error ->
Expect.fail error
model =
case result of
Ok jsonModel ->
Transaction.modelFromJson
jsonModel
testConfig
Err error ->
Debug.crash error
in
Expect.equal [ 0 ] <| List.map .amountIn model.vIn
, test "computeVote" <|
\() ->
let
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment