@@ -12,6 +12,8 @@ import qualified Data.ByteString.Lazy as BL
12
12
#endif
13
13
import qualified Data.List.NonEmpty as NonEmpty
14
14
import qualified Data.Map as Map
15
+ import qualified Data.Text as T
16
+ import qualified Data.Version as Version
15
17
import Functora.Money
16
18
import Functora.Prelude as Prelude
17
19
import Functora.Rates
@@ -27,7 +29,8 @@ import qualified Material.Theme as Theme
27
29
import qualified Material.Typography as Typography
28
30
import Miso hiding (view )
29
31
import qualified Miso
30
- import Miso.String hiding (cons , foldl , null , reverse )
32
+ import Miso.String hiding (cons , foldl , intercalate , null , reverse )
33
+ import qualified Paths_app as Paths
31
34
import qualified Text.Fuzzy as Fuzzy
32
35
33
36
#ifndef __GHCJS__
@@ -61,12 +64,18 @@ data Model = Model
61
64
modelMarket :: MVar Market ,
62
65
modelCurrencies :: NonEmpty CurrencyInfo ,
63
66
modelSnackbarQueue :: Snackbar. Queue Action ,
64
- modelProducerQueue :: TChan (Model -> Model ),
65
- modelConsumerQueue :: TChan (Model -> Model ),
67
+ modelProducerQueue :: TChan (ChanItem ( Model -> Model ) ),
68
+ modelConsumerQueue :: TChan (ChanItem ( Model -> Model ) ),
66
69
modelUpdatedAt :: UTCTime
67
70
}
68
71
deriving stock (Eq , Generic )
69
72
73
+ data ChanItem a = ChanItem
74
+ { chanItemDelay :: Natural ,
75
+ chanItemValue :: a
76
+ }
77
+ deriving stock (Eq , Ord , Show , Read , Data , Generic )
78
+
70
79
data TopOrBottom
71
80
= Top
72
81
| Bottom
@@ -191,15 +200,17 @@ data Action
191
200
| InitUpdate
192
201
| TimeUpdate
193
202
| ChanUpdate Model
194
- | PushUpdate (JSM () ) (Model -> Model )
203
+ | PushUpdate (JSM () ) (ChanItem ( Model -> Model ) )
195
204
196
205
--
197
206
-- NOTE : In most cases we don't need JSM.
198
207
--
199
- pureUpdate :: (Model -> Model ) -> Action
200
- pureUpdate = PushUpdate $ pure ()
208
+ pureUpdate :: Natural -> (Model -> Model ) -> Action
209
+ pureUpdate delay =
210
+ PushUpdate (pure () )
211
+ . ChanItem delay
201
212
202
- pushActionQueue :: (MonadIO m ) => Model -> (Model -> Model ) -> m ()
213
+ pushActionQueue :: (MonadIO m ) => Model -> ChanItem (Model -> Model ) -> m ()
203
214
pushActionQueue st =
204
215
liftIO
205
216
. atomically
@@ -255,7 +266,7 @@ updateModel InitUpdate prevSt = do
255
266
{ modelProducerQueue = prod,
256
267
modelConsumerQueue = cons
257
268
}
258
- pushActionQueue nextSt (& # modelHide .~ False )
269
+ pushActionQueue nextSt $ ChanItem 0 (& # modelHide .~ False )
259
270
pure $ ChanUpdate nextSt
260
271
]
261
272
updateModel TimeUpdate st = do
@@ -266,7 +277,9 @@ updateModel TimeUpdate st = do
266
277
pure TimeUpdate ,
267
278
do
268
279
ct <- getCurrentTime
269
- unless (upToDate ct $ st ^. # modelUpdatedAt) $ pushActionQueue st id
280
+ unless (upToDate ct $ st ^. # modelUpdatedAt)
281
+ . pushActionQueue st
282
+ $ ChanItem 0 id
270
283
pure Noop
271
284
]
272
285
updateModel (ChanUpdate prevSt) _ = do
@@ -291,19 +304,25 @@ updateModel (PushUpdate runJSM updater) st = do
291
304
pure Noop
292
305
]
293
306
294
- drainTChan :: (MonadIO m ) => TChan a -> m [a ]
307
+ drainTChan :: (MonadIO m ) => TChan ( ChanItem a ) -> m [a ]
295
308
drainTChan chan = do
296
309
item <- liftIO . atomically $ readTChan chan
297
310
liftIO
298
- . fmap ((item : ) . reverse )
299
- $ drainInto [] False
311
+ . fmap ((chanItemValue item : ) . reverse )
312
+ . drainInto []
313
+ $ chanItemDelay item
300
314
where
301
- drainInto acc debounced = do
315
+ drainInto acc delay = do
302
316
item <- atomically $ tryReadTChan chan
303
317
case item of
304
- Nothing | debounced -> pure acc
305
- Nothing -> sleepMilliSeconds 300 >> drainInto acc True
306
- Just next -> drainInto (next : acc) False
318
+ Nothing | delay == 0 -> pure acc
319
+ Nothing -> do
320
+ sleepMilliSeconds $ from @ Natural @ Integer delay
321
+ drainInto acc 0
322
+ Just next ->
323
+ drainInto (chanItemValue next : acc)
324
+ . max delay
325
+ $ chanItemDelay next
307
326
308
327
syncInputs :: Model -> JSM ()
309
328
syncInputs st =
@@ -342,10 +361,9 @@ updateSnackbar ::
342
361
) =>
343
362
(Snackbar. Queue Action -> Snackbar. Queue Action ) ->
344
363
a ->
345
- Model ->
346
- Model
364
+ ChanItem (Model -> Model )
347
365
updateSnackbar before x =
348
- (& # modelSnackbarQueue %~ (Snackbar. addMessage msg . before))
366
+ ChanItem 0 (& # modelSnackbarQueue %~ (Snackbar. addMessage msg . before))
349
367
where
350
368
msg =
351
369
inspect x
@@ -527,7 +545,7 @@ amountWidget st loc =
527
545
(parseMoney input == Just output)
528
546
|| (input == inspectMoneyAmount output)
529
547
onBlurAction =
530
- pureUpdate $ \ st' ->
548
+ pureUpdate 0 $ \ st' ->
531
549
if valid
532
550
then st'
533
551
else
@@ -546,9 +564,10 @@ amountWidget st loc =
546
564
<> inspect loc
547
565
<> " ').getElementsByTagName('input')[0].blur();"
548
566
)
549
- id
567
+ ( ChanItem 300 id
568
+ )
550
569
onInputAction txt =
551
- pureUpdate $ \ st' ->
570
+ pureUpdate 300 $ \ st' ->
552
571
st'
553
572
& # modelData
554
573
. getMoneyOptic loc
@@ -565,7 +584,8 @@ amountWidget st loc =
565
584
. getMoneyOptic loc
566
585
. # modelMoneyAmountInput
567
586
)
568
- id
587
+ ( ChanItem 0 id
588
+ )
569
589
onClearAction =
570
590
PushUpdate
571
591
( do
@@ -576,7 +596,7 @@ amountWidget st loc =
576
596
<> inspect loc
577
597
<> " '); if (el) el.value = '';"
578
598
)
579
- ( \ st' ->
599
+ ( ChanItem 300 $ \ st' ->
580
600
st'
581
601
& # modelData
582
602
. getMoneyOptic loc
@@ -668,14 +688,14 @@ currencyWidget st loc =
668
688
]
669
689
where
670
690
search input =
671
- pureUpdate $ \ st' ->
691
+ pureUpdate 0 $ \ st' ->
672
692
st'
673
693
& # modelData
674
694
. getMoneyOptic loc
675
695
. # modelMoneyCurrencySearch
676
696
.~ from @ String @ Text input
677
697
opened =
678
- pureUpdate $ \ st' ->
698
+ pureUpdate 0 $ \ st' ->
679
699
st'
680
700
& # modelData
681
701
. getMoneyOptic loc
@@ -686,7 +706,7 @@ currencyWidget st loc =
686
706
. # modelMoneyCurrencySearch
687
707
.~ mempty
688
708
closed =
689
- pureUpdate $ \ st' ->
709
+ pureUpdate 0 $ \ st' ->
690
710
st'
691
711
& # modelData
692
712
. getMoneyOptic loc
@@ -735,7 +755,7 @@ currencyListItemWidget loc current item =
735
755
else Nothing
736
756
)
737
757
& ListItem. setOnClick
738
- ( pureUpdate $ \ st ->
758
+ ( pureUpdate 0 $ \ st ->
739
759
st
740
760
& # modelData
741
761
. getMoneyOptic loc
@@ -773,7 +793,7 @@ swapAmountsWidget =
773
793
" Swap amounts"
774
794
where
775
795
onClickAction =
776
- pureUpdate $ \ st ->
796
+ pureUpdate 0 $ \ st ->
777
797
let baseInput =
778
798
st ^. # modelData . # modelDataTopMoney . # modelMoneyAmountInput
779
799
baseOutput =
@@ -819,7 +839,7 @@ swapCurrenciesWidget =
819
839
" Swap currencies"
820
840
where
821
841
onClickAction =
822
- pureUpdate $ \ st ->
842
+ pureUpdate 0 $ \ st ->
823
843
let baseCurrency =
824
844
st ^. # modelData . # modelDataTopMoney . # modelMoneyCurrencyInfo
825
845
quoteCurrency =
@@ -851,12 +871,13 @@ copyright =
851
871
a_ [href_ " license.html" ] [Miso. text " Terms and Conditions" ],
852
872
Miso. text " and " ,
853
873
a_ [href_ " privacy.html" ] [Miso. text " Privacy Policy" ],
854
- Miso. text " ."
874
+ Miso. text " . " ,
875
+ Miso. text . ms $ " Version " <> vsn <> " ."
855
876
]
856
877
857
878
snackbarClosed :: Snackbar. MessageId -> Action
858
879
snackbarClosed msg =
859
- pureUpdate (& # modelSnackbarQueue %~ Snackbar. close msg)
880
+ pureUpdate 0 (& # modelSnackbarQueue %~ Snackbar. close msg)
860
881
861
882
inspectMoneyAmount :: (MoneyTags tags , From String a ) => Money tags -> a
862
883
inspectMoneyAmount =
@@ -867,3 +888,9 @@ upToDate lhs rhs =
867
888
diff < 3600
868
889
where
869
890
diff = abs . toRational $ diffUTCTime lhs rhs
891
+
892
+ vsn :: Text
893
+ vsn =
894
+ T. intercalate " ."
895
+ . fmap inspect
896
+ $ Version. versionBranch Paths. version
0 commit comments