Okay, I figured this one out. It turns out that decoding a FileReader as an object1 with the key "0" works fine to get the first File object. I.e.
parseFilename = Json.at ["dataTransfer", "files"] <|
Json.object1 identity ("0" := (Json.object1 identity ("name" := Json.string)))
works just fine. It then took me a little while to figure out how to parse a List of filenames with the object keys set to 0 .. (length-1), but here is what I came up with in the end (I also decided to create a record that keeps the filename and the file blog itself as a Json.value so I can pass it to a port later on and feed that into a filereader.
type alias NativeFile =
{ name : String
, blob : Value
}
parseFilenameAt : Int -> Json.Decoder NativeFile
parseFilenameAt index = Json.at ["dataTransfer", "files"] <|
Json.object2 NativeFile ((toString index) := (Json.object1 identity ("name" := Json.string))) (toString index := Json.value)
parseFilenames : Int -> Json.Decoder (List NativeFile)
parseFilenames count =
case count of
0 ->
succeed []
_ ->
Json.object2 (::) (parseFilenameAt (count - 1)) (parseFilenames (count - 1))
parseLength : Json.Decoder Int
parseLength = Json.at ["dataTransfer", "files"] <| oneOf
[ Json.object1 identity ("length" := Json.int)
, null 0
]
onDrop : Signal.Address Action -> Attribute
onDrop address = onWithOptions "drop" {stopPropagation = True, preventDefault = True} (parseLength `andThen` parseFilenames) (\vals -> Signal.message address (Drop vals))
Once I have managed to load this file and upload it I will try to write up all of it in a blog post.
Cheers,
Daniel