node and browser bindings for gleam

bindings for geolocation getCurrentPosition

Changed files
+73 -1
src
+1 -1
gleam.toml
··· 1 1 name = "plinth" 2 - version = "0.4.5" 2 + version = "0.4.6" 3 3 description = "Bindings to Node.js and browser platform APIs" 4 4 target = "javascript" 5 5
+3
src/geolocation_ffi.mjs
··· 1 + export function getCurrentPosition(success, error) { 2 + globalThis.navigator.geolocation.getCurrentPosition(success, error) 3 + }
+69
src/plinth/browser/geolocation.gleam
··· 1 + import gleam/dynamic 2 + import gleam/javascript/promise 3 + import gleam/option.{type Option} 4 + import gleam/string 5 + 6 + pub type JSGeolocationPosition 7 + 8 + pub type JSGeolocationPositionError 9 + 10 + pub type GeolocationPosition { 11 + GeolocationPosition( 12 + latitude: Float, 13 + longitude: Float, 14 + altitude: Option(Float), 15 + accuracy: Float, 16 + altitude_accuracy: Option(Float), 17 + heading: Option(Float), 18 + speed: Option(Float), 19 + // separate timestamp field in native object 20 + timestamp: Float, 21 + ) 22 + } 23 + 24 + pub fn decode(raw) { 25 + dynamic.decode8( 26 + GeolocationPosition, 27 + dynamic.field("coords", dynamic.field("latitude", dynamic.float)), 28 + dynamic.field("coords", dynamic.field("longitude", dynamic.float)), 29 + dynamic.field( 30 + "coords", 31 + dynamic.field("altitude", dynamic.optional(dynamic.float)), 32 + ), 33 + dynamic.field("coords", dynamic.field("accuracy", dynamic.float)), 34 + dynamic.field( 35 + "coords", 36 + dynamic.field("altitudeAccuracy", dynamic.optional(dynamic.float)), 37 + ), 38 + dynamic.field( 39 + "coords", 40 + dynamic.field("heading", dynamic.optional(dynamic.float)), 41 + ), 42 + dynamic.field( 43 + "coords", 44 + dynamic.field("speed", dynamic.optional(dynamic.float)), 45 + ), 46 + dynamic.field("timestamp", dynamic.float), 47 + )(raw) 48 + } 49 + 50 + @external(javascript, "../../geolocation_ffi.mjs", "getCurrentPosition") 51 + pub fn get_current_position( 52 + success: fn(JSGeolocationPosition) -> Nil, 53 + error: fn(JSGeolocationPositionError) -> Nil, 54 + ) -> Nil 55 + 56 + pub fn current_position() { 57 + promise.new(fn(resolve) { 58 + get_current_position( 59 + fn(position) { 60 + case decode(dynamic.from(position)) { 61 + Ok(position) -> Ok(position) 62 + Error(reason) -> Error(string.inspect(reason)) 63 + } 64 + |> resolve() 65 + }, 66 + fn(error) { resolve(Error(string.inspect(error))) }, 67 + ) 68 + }) 69 + }