Last active
January 16, 2016 13:06
-
-
Save danyx23/c80ad1791544101c08b0 to your computer and use it in GitHub Desktop.
Dealing with ports as part of the Elm Architecture
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type PortAction | |
= StartAudioPlayback AudioPlaybackMessage | |
| StopAudioPlayback | |
| DecodeAudioData AudioRawDataMessage | |
| NoopPortAction | |
update : Action -> Model -> (Model, Effects Action, PortAction) | |
app : App Model MainActions.PortAction | |
app = | |
start | |
{ init = (Types.init seed0, Effects.none, MainActions.NoopPortAction) | |
, update = update | |
, view = view | |
, inputs = [Signal.map audioClipLoadedAction audioClipLoaded] | |
} | |
-- outgoing port | |
port startAudioPlayback : Signal AudioPlaybackMessage | |
port startAudioPlayback = | |
Signal.filterMap filterStartPlayback (AudioPlaybackMessage (AssetId -1) 0.0) app.portActions | |
filterStartPlayback : MainActions.PortAction -> Maybe AudioPlaybackMessage | |
filterStartPlayback portAction = | |
case portAction of | |
MainActions.StartAudioPlayback info -> | |
Just info | |
_ -> | |
Nothing | |
-- incoming port | |
port audioClipLoaded : Signal AudioDurationMessage |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module CustomAppStart | |
( start | |
, App | |
, Config | |
) | |
where | |
import Html exposing (Html) | |
import Effects exposing (Effects, Never) | |
import Task | |
type alias Config model action portAction = | |
{ init : (model, Effects action, portAction) | |
, update : action -> model -> (model, Effects action, Maybe portAction) | |
, view : Signal.Address action -> model -> Html | |
, inputs : List (Signal.Signal action) | |
} | |
type alias App model portAction = | |
{ html : Signal Html | |
, model : Signal model | |
, tasks : Signal (Task.Task Never ()) | |
, portActions : Signal portAction | |
} | |
{-| Copy from StartApp but with folp' instead of foldp | |
Start an application. It requires a bit of wiring once you have created an | |
`App`. It should pretty much always look like this: | |
app = | |
start { init = init, view = view, update = update, inputs = [] } | |
main = | |
app.html | |
port tasks : Signal (Task.Task Never ()) | |
port tasks = | |
app.tasks | |
So once we start the `App` we feed the HTML into `main` and feed the resulting | |
tasks into a `port` that will run them all. | |
-} | |
start : Config model action portAction -> App model portAction | |
start config = | |
let | |
fst3 (a, _, _) = a | |
snd3 (_, b, _) = b | |
thrd3 (_, _, c) = c | |
singleton action = [ action ] | |
-- messages : Signal.Mailbox (List action) | |
messages = Signal.mailbox [] | |
-- address : Signal.Address action | |
address = Signal.forwardTo messages.address singleton | |
-- updateStep : action -> (model, Effects action, Maybe portAction) -> (model, Effects action, Maybe portAction) | |
updateStep action (oldModel, accumulatedEffects, _) = | |
let | |
(newModel, additionalEffects, maybePortAction) = config.update action oldModel | |
in | |
(newModel, Effects.batch [accumulatedEffects, additionalEffects], maybePortAction) | |
-- update : List action -> (model, Effects action, Maybe portAction) -> (model, Effects action, Maybe portAction) | |
update actions (model, _, _) = | |
List.foldl updateStep (model, Effects.none, Nothing) actions | |
-- inputs : Signal (List action) | |
inputs = Signal.mergeMany (messages.signal :: List.map (Signal.map singleton) config.inputs) | |
-- effectsAndModel : Signal (model, Effects action, Maybe portAction) | |
modelEffectsPortActions = Signal.foldp update (config.init |> maybefy) inputs | |
model = Signal.map fst3 modelEffectsPortActions | |
tasks = Signal.map (Effects.toTask messages.address << snd3) modelEffectsPortActions | |
portActions = Signal.filterMap identity (config.init |> thrd3) <| Signal.map thrd3 modelEffectsPortActions | |
in | |
{ html = Signal.map (config.view address) model | |
, model = model | |
, tasks = tasks | |
, portActions = portActions | |
} | |
maybefy : (model, Effects action, portAction) -> (model, Effects action, Maybe portAction) | |
maybefy (model, action, portAction) = | |
(model, action, Just portAction) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment