Skip to content

Commit 8434337

Browse files
committed
add debouncing in ref
1 parent ffcb748 commit 8434337

1 file changed

Lines changed: 33 additions & 23 deletions

File tree

src/Select.purs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ import Control.Monad.Free (Free, foldFree, liftF)
1313
import Data.Array (length, (!!))
1414
import Data.Maybe (Maybe(..), fromMaybe)
1515
import Data.Time.Duration (Milliseconds(..))
16-
import Data.Traversable (for_, traverse_)
16+
import Data.Traversable (for_, traverse, traverse_)
1717
import Effect.Aff (Fiber, delay, error, forkAff, killFiber)
1818
import Effect.Aff.AVar (AVar)
1919
import Effect.Aff.AVar as AVar
2020
import Effect.Aff.Class (class MonadAff)
21+
import Effect.Ref (Ref)
22+
import Effect.Ref as Ref
2123
import Halogen as H
2224
import Halogen.HTML as HH
2325
import Renderless.State (getState, modifyState_, modifyStore)
@@ -30,22 +32,18 @@ import Web.UIEvent.MouseEvent as ME
3032
-- Component Types
3133

3234
-- | A useful shorthand for the Halogen component type
33-
type Component o item m
34-
= H.Component HH.HTML (Query o item) (Input o item) (Message o item) m
35+
type Component o item m = H.Component HH.HTML (Query o item) (Input o item) (Message o item) m
3536

3637
-- | A useful shorthand for the Halogen component HTML type
37-
type ComponentHTML o item
38-
= H.ComponentHTML (Query o item)
38+
type ComponentHTML o item = H.ComponentHTML (Query o item)
3939

4040
-- | A useful shorthand for the Halogen component DSL type
41-
type ComponentDSL o item m
42-
= H.ComponentDSL (StateStore o item) (Query o item) (Message o item) m
41+
type ComponentDSL o item m = H.ComponentDSL (StateStore o item) (Query o item) (Message o item) m
4342

4443
-- | The component's state type, wrapped in `Store`. The state and result of the
4544
-- | render function are stored so that `extract` from `Control.Comonad` can be
4645
-- | used to pull out the render function.
47-
type StateStore o item
48-
= Store (State item) (ComponentHTML o item)
46+
type StateStore o item = Store (State item) (ComponentHTML o item)
4947

5048
----------
5149
-- Core Constructors
@@ -72,6 +70,7 @@ data QueryF o item a
7270
| GetVisibility (Visibility -> a)
7371
| ReplaceItems (Array item) a
7472
| Raise (o Unit) a
73+
| Initialize a
7574
| Receive (Input o item) a
7675

7776
type Query o item = Free (QueryF o item)
@@ -138,6 +137,10 @@ raise o = liftF (Raise o unit)
138137
receive :: o item . Input o item -> Query o item Unit
139138
receive i = liftF (Receive i unit)
140139

140+
-- | Initializes the component on mount.
141+
initialize :: o item. Query o item Unit
142+
initialize = liftF (Initialize unit)
143+
141144
-- | Represents a way to navigate on `Highlight` events: to the previous
142145
-- | item, next item, or the item at a particular index.
143146
data Target = Prev | Next | Index Int
@@ -183,8 +186,8 @@ data InputType
183186
-- | they have typed on the toggle.
184187
-- | - `debounceTime`: How long, in milliseconds, before events should occur based
185188
-- | on user searches.
186-
-- | - `debouncer`: A representation of a running timer that, when it expires, will
187-
-- | trigger debounced events.
189+
-- | - `debounceRef`: A representation of a running timer that, when it expires, will
190+
-- | trigger debounced events.
188191
-- | - `inputElement`: A reference to the toggle or input element.
189192
-- | - `items`: An array of user-provided `item`s.
190193
-- | - `visibility`: Whether the array of items should be considered visible or not.
@@ -196,7 +199,7 @@ type State item =
196199
{ inputType :: InputType
197200
, search :: String
198201
, debounceTime :: Milliseconds
199-
, debouncer :: Maybe Debouncer
202+
, debounceRef :: Maybe (Ref (Maybe Debouncer))
200203
, items :: Array item
201204
, visibility :: Visibility
202205
, highlightedIndex :: Maybe Int
@@ -207,7 +210,8 @@ type State item =
207210
-- | .cts.
208211
type Debouncer =
209212
{ var :: AVar Unit
210-
, fiber :: Fiber Unit }
213+
, fiber :: Fiber Unit
214+
}
211215

212216
-- | The component's input type, which includes the component's render function. This
213217
-- | render function can also be used to share data with the parent component, as every
@@ -234,22 +238,22 @@ data Message o item
234238
| VisibilityChanged Visibility
235239
| Emit (o Unit)
236240

237-
component :: o item m
238-
. MonadAff m
239-
=> Component o item m
241+
component :: o item m. MonadAff m => Component o item m
240242
component =
241-
H.component
243+
H.lifecycleComponent
242244
{ initialState
243245
, render: extract
244246
, eval: eval'
245247
, receiver: Just <<< receive
248+
, initializer: Just initialize
249+
, finalizer: Nothing
246250
}
247251
where
248252
initialState i = store i.render
249253
{ inputType: i.inputType
250254
, search: fromMaybe "" i.initialSearch
251255
, debounceTime: fromMaybe (Milliseconds 0.0) i.debounceTime
252-
, debouncer: Nothing
256+
, debounceRef: Nothing
253257
, items: i.items
254258
, highlightedIndex: Nothing
255259
, visibility: Off
@@ -267,27 +271,33 @@ component =
267271
-- Just the normal Halogen eval
268272
eval :: QueryF o item ~> ComponentDSL o item m
269273
eval = case _ of
274+
Initialize a -> a <$ do
275+
ref <- H.liftEffect $ Ref.new Nothing
276+
modifyState_ _ { debounceRef = Just ref }
277+
270278
Search str a -> a <$ do
271279
st <- getState
280+
ref :: Maybe Debouncer <- H.liftEffect $ map join $ traverse Ref.read st.debounceRef
272281
modifyState_ _ { search = str }
273282
setVis On
274283

275-
case st.inputType, st.debouncer of
284+
case st.inputType, ref of
276285
TextInput, Nothing -> unit <$ do
277286
var <- H.liftAff AVar.empty
278287
fiber <- H.liftAff $ forkAff do
279288
delay st.debounceTime
280289
AVar.put unit var
281290

282291
-- This compututation will fork and run in the background. When the
283-
-- var is finally filled, the .ct will run (raise a new search)
292+
-- var is finally filled, the action will run (raise a new search)
284293
_ <- H.fork do
285294
_ <- H.liftAff $ AVar.take var
286-
modifyState_ _ { debouncer = Nothing, highlightedIndex = Just 0 }
295+
void $ H.liftEffect $ traverse_ (Ref.write Nothing) st.debounceRef
296+
modifyState_ _ { highlightedIndex = Just 0 }
287297
newState <- getState
288298
H.raise $ Searched newState.search
289299

290-
modifyState_ _ { debouncer = Just { var, fiber } }
300+
void $ H.liftEffect $ traverse_ (Ref.write $ Just { var, fiber }) st.debounceRef
291301

292302
TextInput, Just debouncer -> do
293303
let var = debouncer.var
@@ -296,7 +306,7 @@ component =
296306
delay st.debounceTime
297307
AVar.put unit var
298308

299-
modifyState_ _ { debouncer = Just { var, fiber } }
309+
void $ H.liftEffect $ traverse_ (Ref.write $ Just { var, fiber }) st.debounceRef
300310

301311
-- Key stream is not yet implemented. However, this should capture user
302312
-- key events and expire their search after a set number of milliseconds.

0 commit comments

Comments
 (0)