diff --git a/lib/aprsme/encoding_utils.ex b/lib/aprsme/encoding_utils.ex index 433f4b3..a49c768 100644 --- a/lib/aprsme/encoding_utils.ex +++ b/lib/aprsme/encoding_utils.ex @@ -56,8 +56,6 @@ defmodule Aprsme.EncodingUtils do def to_float(value) when is_integer(value) do if value >= -9.0e15 and value <= 9.0e15 do value * 1.0 - else - nil end end @@ -77,7 +75,6 @@ defmodule Aprsme.EncodingUtils do def to_float(_), do: nil - @doc """ Converts various types to Decimal for database storage. diff --git a/lib/aprsme_web/time_helpers.ex b/lib/aprsme_web/time_helpers.ex index dd6a3a6..960a9e5 100644 --- a/lib/aprsme_web/time_helpers.ex +++ b/lib/aprsme_web/time_helpers.ex @@ -7,6 +7,7 @@ defmodule AprsmeWeb.TimeHelpers do @doc """ Returns a human-readable string for how long ago the given DateTime was. """ + @spec time_ago_in_words(nil | NaiveDateTime.t() | DateTime.t()) :: String.t() def time_ago_in_words(nil), do: gettext("unknown time") <> " " <> gettext("ago") def time_ago_in_words(%NaiveDateTime{} = naive_datetime) do @@ -42,6 +43,7 @@ defmodule AprsmeWeb.TimeHelpers do Handles ISO 8601 strings, Unix timestamps in milliseconds, and existing DateTime or NaiveDateTime structs. """ + @spec to_datetime(String.t() | integer() | DateTime.t() | NaiveDateTime.t() | any()) :: DateTime.t() | nil def to_datetime(ts) do cond do is_binary(ts) -> diff --git a/lib/aprsme_web/user_auth.ex b/lib/aprsme_web/user_auth.ex index 3ced575..a224f56 100644 --- a/lib/aprsme_web/user_auth.ex +++ b/lib/aprsme_web/user_auth.ex @@ -10,6 +10,8 @@ defmodule AprsmeWeb.UserAuth do # Make the remember me cookie valid for 60 days. # If you want bump or reduce this value, also change # the token expiry itself in UserToken. + alias Phoenix.LiveView.Socket + @max_age 60 * 60 * 24 * 60 @remember_me_cookie "_aprs_web_user_remember_me" @remember_me_options [sign: true, max_age: @max_age, same_site: "Lax"] @@ -26,6 +28,7 @@ defmodule AprsmeWeb.UserAuth do disconnected on log out. The line can be safely removed if you are not using LiveView. """ + @spec log_in_user(Plug.Conn.t(), %Aprsme.Accounts.User{}, map()) :: Plug.Conn.t() def log_in_user(conn, user, params \\ %{}) do token = Accounts.generate_user_session_token(user) user_return_to = get_session(conn, :user_return_to) @@ -69,6 +72,7 @@ defmodule AprsmeWeb.UserAuth do It clears all session data for safety. See renew_session. """ + @spec log_out_user(Plug.Conn.t()) :: Plug.Conn.t() def log_out_user(conn) do user_token = get_session(conn, :user_token) user_token && Accounts.delete_user_session_token(user_token) @@ -87,6 +91,7 @@ defmodule AprsmeWeb.UserAuth do Authenticates the user by looking into the session and remember me token. """ + @spec fetch_current_user(Plug.Conn.t(), any()) :: Plug.Conn.t() def fetch_current_user(conn, _opts) do {user_token, conn} = ensure_user_token(conn) user = user_token && Accounts.get_user_by_session_token(user_token) @@ -144,6 +149,7 @@ defmodule AprsmeWeb.UserAuth do live "/profile", ProfileLive, :index end """ + @spec on_mount(atom(), map(), map(), Socket.t()) :: {:cont | :halt, Socket.t()} def on_mount(:mount_current_user, _params, session, socket) do {:cont, mount_current_user(session, socket)} end @@ -189,6 +195,7 @@ defmodule AprsmeWeb.UserAuth do @doc """ Used for routes that require the user to not be authenticated. """ + @spec redirect_if_user_is_authenticated(Plug.Conn.t(), any()) :: Plug.Conn.t() def redirect_if_user_is_authenticated(conn, _opts) do case conn.assigns[:current_user] do nil -> @@ -207,6 +214,7 @@ defmodule AprsmeWeb.UserAuth do If you want to enforce the user email is confirmed before they use the application at all, here would be a good place. """ + @spec require_authenticated_user(Plug.Conn.t(), any()) :: Plug.Conn.t() def require_authenticated_user(conn, _opts) do case conn.assigns[:current_user] do nil -> diff --git a/lib/aprsme_web/weather_units.ex b/lib/aprsme_web/weather_units.ex index fb392ec..d154dcd 100644 --- a/lib/aprsme_web/weather_units.ex +++ b/lib/aprsme_web/weather_units.ex @@ -10,6 +10,7 @@ defmodule AprsmeWeb.WeatherUnits do Determines the unit system based on locale. Returns :imperial for US, :metric for most other countries. """ + @spec unit_system(String.t() | nil | any()) :: :imperial | :metric def unit_system(locale) when is_binary(locale) do case locale do # Default to imperial for English @@ -32,6 +33,7 @@ defmodule AprsmeWeb.WeatherUnits do Converts temperature from Fahrenheit to Celsius if needed. Returns the temperature in the appropriate unit for the locale. """ + @spec format_temperature(number() | any(), String.t()) :: {number() | any(), String.t()} def format_temperature(temp, locale) when is_number(temp) do case unit_system(locale) do :imperial -> {temp, "°F"} @@ -45,6 +47,7 @@ defmodule AprsmeWeb.WeatherUnits do Converts wind speed from mph to km/h if needed. Returns the wind speed in the appropriate unit for the locale. """ + @spec format_wind_speed(number() | any(), String.t()) :: {number() | any(), String.t()} def format_wind_speed(speed, locale) when is_number(speed) do case unit_system(locale) do :imperial -> {speed, "mph"} @@ -58,6 +61,7 @@ defmodule AprsmeWeb.WeatherUnits do Converts rain from inches to mm if needed. Returns the rain amount in the appropriate unit for the locale. """ + @spec format_rain(number() | any(), String.t()) :: {number() | any(), String.t()} def format_rain(rain, locale) when is_number(rain) do case unit_system(locale) do :imperial -> {rain, "in"} @@ -70,6 +74,7 @@ defmodule AprsmeWeb.WeatherUnits do @doc """ Formats pressure (keeps hPa for all locales as it's standard). """ + @spec format_pressure(number() | any(), any()) :: {number() | any(), String.t()} def format_pressure(pressure, _locale) when is_number(pressure) do {pressure, "hPa"} end @@ -79,6 +84,12 @@ defmodule AprsmeWeb.WeatherUnits do @doc """ Gets the appropriate unit labels for the locale. """ + @spec unit_labels(String.t()) :: %{ + temperature: String.t(), + wind_speed: String.t(), + rain: String.t(), + pressure: String.t() + } def unit_labels(locale) do case unit_system(locale) do :imperial ->