<commit_before>{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}

module Unison.Explorer where

import Data.Functor
import Data.List
import Data.Maybe
import Data.Semigroup
import Reflex.Dom
import Unison.Dimensions (X(..),Y(..))
import qualified Unison.Signals as Signals

modal :: (MonadWidget t m, Reflex t) => Dynamic t Bool -> a -> m a -> m (Dynamic t a)
modal switch off on = do
  initial <- sample (current switch)
  let choose b = if b then on else pure off
  widgetHold (choose initial) (fmap choose (updated switch))

joinModal :: (MonadWidget t m, Reflex t) => Dynamic t Bool -> a -> m (Dynamic t a) -> m (Dynamic t a)
joinModal switch off on = holdDyn off never >>= \off -> joinDyn <$> modal switch off on

explorer :: forall t m k s a . (Reflex t, MonadWidget t m, Eq k, Semigroup s)
         => Event t Int
         -> (s -> String -> Action m s k a)
         -> Event t (m ()) -- loaded asynchronously on open of explorer
         -> Dynamic t s
         -> m (Dynamic t s, Event t (Maybe a))
explorer keydown processQuery topContent s0 = do
  let extractReq a = case a of Request r _ -> Just r; _ -> Nothing
  let validAttrs = "class" =: "explorer valid"
  let invalidAttrs = "class" =: "explorer invalid"
  rec
    attrs <- holdDyn ("class" =: "explorer") (fmap (\l -> if null l then invalidAttrs else validAttrs) valids)
    (valids, updatedS, closings) <- elDynAttr "div" attrs $ mdo
      searchbox <- textInput def
      elClass "div" "top-separator" $ pure ()
      _ <- elClass "div" "top-content" $ widgetHold (pure ()) topContent -- todo: perhaps a spinner
      s <- sample (current s0)
      s' <- foldDyn (<>) s (updated responses)
      actions <- do
        t <- Signals.prepend "" (updated $ _textInput_value searchbox)
        pure $ pushAlways (\txt -> processQuery <$> sample (current s') <*> pure txt) t
      responses <- widgetHold (pure s) $ fmapMaybe extractReq actions
      list <- holdDyn [] $
        let f a = case a of Request _ l -> Just l; Results l -> Just l; _ -> Nothing
        in fmapMaybe f actions
      keys <- mapDyn (mapMaybe (\(k,b,_) -> if b then Just k else Nothing)) list
      valids <- holdDyn [] $ fmap (mapMaybe (\(k,b,v) -> if b then Just (k,v) else Nothing)) (updated list)
      invalids <- mapDyn (mapMaybe (\(_,b,v) -> if not b then Just v else Nothing)) list<commit_msg>disable up/down events going to text box in explorer<commit_after>{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleContexts #-}

module Unison.Explorer where

import Data.Functor
import Data.List
import Data.Maybe
import Data.Semigroup
import Reflex.Dom
import Unison.Dimensions (X(..),Y(..))
import GHCJS.DOM.EventM (preventDefault)
import GHCJS.DOM.Element (elementOnkeydown)
import qualified Unison.Signals as Signals

modal :: (MonadWidget t m, Reflex t) => Dynamic t Bool -> a -> m a -> m (Dynamic t a)
modal switch off on = do
  initial <- sample (current switch)
  let choose b = if b then on else pure off
  widgetHold (choose initial) (fmap choose (updated switch))

joinModal :: (MonadWidget t m, Reflex t) => Dynamic t Bool -> a -> m (Dynamic t a) -> m (Dynamic t a)
joinModal switch off on = holdDyn off never >>= \off -> joinDyn <$> modal switch off on

explorer :: forall t m k s a . (Reflex t, MonadWidget t m, Eq k, Semigroup s)
         => Event t Int
         -> (s -> String -> Action m s k a)
         -> Event t (m ()) -- loaded asynchronously on open of explorer
         -> Dynamic t s
         -> m (Dynamic t s, Event t (Maybe a))
explorer keydown processQuery topContent s0 = do
  let extractReq a = case a of Request r _ -> Just r; _ -> Nothing
  let validAttrs = "class" =: "explorer valid"
  let invalidAttrs = "class" =: "explorer invalid"
  rec
    attrs <- holdDyn ("class" =: "explorer") (fmap (\l -> if null l then invalidAttrs else validAttrs) valids)
    (valids, updatedS, closings) <- elDynAttr "div" attrs $ mdo
      searchbox <- textInput def
      -- disable up/down keyboard events inside of text box; they are used for controlling what item is selected
      let isArrow i = i == 38 || i == 40
      let tweak e = e >>= \i -> if isArrow i then i <$ preventDefault else pure i
      tweakedKeydown <- wrapDomEvent (_textInput_element searchbox) elementOnkeydown (tweak getKeyEvent)
      performEvent_ (fmap (const (pure ())) tweakedKeydown)
      elClass "div" "top-separator" $ pure ()
      _ <- elClass "div" "top-content" $ widgetHold (pure ()) topContent -- todo: perhaps a spinner
      s <- sample (current s0)
      s' <- foldDyn (<>) s (updated responses)
      actions <- do
        t <- Signals.prepend "" (updated $ _textInput_value searchbox)
        pure $ pushAlways (\txt -> processQuery <$> sample (current s') <*> pure txt) t
      responses <- widgetHold (pure s) $ fmapMaybe extractReq actions
      list <- holdDyn [] $
        let f a = case a of Request _ l -> Just l; Results l -> Just l; _ -> Nothing
        in fmapMaybe f actions
      keys <- mapDyn (mapMaybe (\(k,b,_) -> if b then Just k else Nothing)) list
      valids <- holdDyn [] $ fmap (mapMaybe (\(k,b,v) -> if b then Just (k,v) else Nothing)) (updated list)
      invalids <- mapDyn (mapMaybe (\(_,b,v) -> if not b then Just v else Nothing)) list
{'fraction_non_alphanumeric': 0.12349117920148561, 'fraction_numerical': 0.0014856081708449396, 'mean_word_length': 2.8776097912167025, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 70, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5369316', 'n_tokens_mistral': 1769, 'n_tokens_neox': 1700, 'n_words': 679}