fay-geoposition-0.1.0.1: src/Fay/GeoPosition.hs
{-|
Module : $Header$
Copyright : (c) 2015 Altera Praxis Pty Ltd
License : BSD
Maintainer : eocallaghan@alterapraxis.com
Stability : provisional
Portability : portable
This module encapsulates Fay Javascript for the
GeoPosition API specified as in the W3C spec.
-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE StandaloneDeriving #-}
module Fay.GeoPosition ( geoPositionErrorMessage
, geoPositionErrorCode
-- #ifdef FAY
, initGeoPosition
-- #endif
, GeoPositionCallbacks(..)
, GeoPositionOptions(..)
, GeoPosition(..)
, GeoCoordinates(..)
, GeoPositionError(..)
, GeoPositionErrorCode(..)
) where
import Fay.Text (Text,unpack)
-- #ifdef FAY
import FFI
import Data.Nullable (toNullable)
-- #endif
import Data.Time (UTCTime)
import Data.Data
import Prelude
-- #ifdef FAY
-- | Call to initialise GeoPosition API with callback
-- actions to be taken upon success or error.
initGeoPosition :: GeoPositionCallbacks Fay
-> Maybe GeoPositionOptions
-> Fay ()
initGeoPosition gpc gpo = do
getCurrentPosition' gpc's gpc'e gpc'o
where getCurrentPosition' :: (GeoPosition -> Fay ())
-> Nullable (GeoPositionError -> Fay ())
-> Nullable GeoPositionOptions
-> Fay ()
getCurrentPosition' = ffi "navigator.geolocation.getCurrentPosition(%1,%2,%3)"
gpc's = geoPositionCallback gpc
gpc'e = toNullable (geoPositionErrorCallback gpc)
gpc'o = toNullable gpo
-- #endif
-- | See section [5.1 - W3C Geolocation API]
-- Requires the monad type that the callbacks have action on
data GeoPositionCallbacks m = GeoPositionCallbacks { geoPositionCallback :: GeoPosition -> m ()
, geoPositionErrorCallback :: Maybe (GeoPositionError -> m ())
}
-- | See section [5.2 - W3C Geolocation API]
data GeoPositionOptions =
GeoPositionOptions { -- | Is a 'Bool' that indicates the application would
-- like to receive the best possible results.
enableHighAccuracy :: Bool
-- | Maximum length of time (in milliseconds) the device
-- is allowed to take in order to return a position.
, timeout :: Int
-- | Maximum age in milliseconds of a possible cached
-- position that is acceptable to return.
, maximumAge :: Int
} deriving Eq
-- | See section [5.3 - W3C Geolocation API]
data GeoPosition = GeoPosition { coords :: GeoCoordinates -- ^ Coordinates object defining the current location
, timestamp :: UTCTime -- ^ DOMTimeStamp, time at which location was retrieved
} deriving (Show,Data,Typeable)
-- | See section [5.4 - W3C Geolocation API]
data GeoCoordinates = GeoCoordinates { latitude :: Double -- ^ decimal degrees
, longitude :: Double -- ^ decimal degrees
, altitude :: Maybe Double -- ^ meters above the reference ellipsoid
, accuracy :: Double -- ^ meters
, altitudeAccuracy :: Maybe Double -- ^ meters
, heading :: Maybe Double -- ^ degrees clockwise from true north
, speed :: Maybe Double -- ^ meters/second
} deriving (Read,Show,Data,Typeable)
-- | See section [5.5 - W3C Geolocation API]
data GeoPositionError = GeoPositionError { code :: Int -- ^ Enumerated code, see 'GeoPositionErrorCode'
, message :: Text -- ^ Human readable 'UTF-16 DOMString' for debugging
} deriving (Read,Show,Data,Typeable)
-- | N.B. Fay does not support the Enum type class :(
-- Thus, use the 'geoPositionErrorCode' function to decode the value to the
-- 'GeoPositionErrorCode' type.
data GeoPositionErrorCode
-- | The acquisition of the geolocation information failed because the page
-- didn't have the permission to do it.
= PermissionDenied
-- | The acquisition of the geolocation failed because at least one internal
-- source of position returned an internal error.
| PositionUnavailable
-- | The time allowed to acquire the geolocation, defined by 'timeout'
-- information was reached before the information was obtained.
| Timeout
-- | Out of spec error code
| Unknown
deriving (Eq)
-- | Helper function extracts UTC-16 encoded error message
geoPositionErrorMessage :: GeoPositionError -> String
geoPositionErrorMessage = unpack . message
-- | Helper function decodes enumerated error 'code' into the 'GeoPositionErrorCode' type
geoPositionErrorCode :: GeoPositionError -> GeoPositionErrorCode
geoPositionErrorCode = decode . code
where decode e | e == 1 = PermissionDenied
| e == 2 = PositionUnavailable
| e == 3 = Timeout
| otherwise = Unknown