Current section
Files
Jump to
Current section
Files
lib/adapters/session/session.ex
defmodule NavEx.Adapters.Session do
@moduledoc """
NavEx.Adapters.Session is adapter for keeping user's navigation history
utilizing Plug.Conn session. **Doesn't support LiveView sockets.**
## Adapter config
adapter_config: %{
history_key: "nav_ex_history" # name of the key in session where navigation history is saved
}
## This adapter supports only Plug.Conn - no LiveView support due to session usage.
For LiveView sockets you have to use NavEx.Adapters.ETS.
"""
@behaviour NavEx.Adapter
import Plug.Conn
@session_key Application.compile_env(:nav_ex, :adapter_config)[:history_key] || "nav_ex_history"
@history_length (Application.compile_env(:nav_ex, :history_length) || 10) + 1
@excluded_paths Application.compile_env(:nav_ex, :excluded_paths) || ["/exclude"]
@impl NavEx.Adapter
def children, do: []
@impl NavEx.Adapter
def insert(%Plug.Conn{request_path: request_path} = conn) do
if Enum.any?(@excluded_paths, &String.starts_with?(request_path, &1)) do
{:ok, conn}
else
do_insert(conn, request_path)
end
end
defp do_insert(conn, request_path) do
case get_session(conn, @session_key) do
nil ->
{:ok, put_session(conn, @session_key, [request_path])}
history ->
{:ok, handle_history(conn, history, request_path)}
end
end
@impl NavEx.Adapter
def insert(%Phoenix.LiveView.Socket{} = _socket, _path) do
raise ArgumentError,
"NavEx.Adapters.Session doesn't support LiveView sockets. Please use Plug.Conn instead."
end
@impl NavEx.Adapter
def list(%Plug.Conn{} = conn) do
case get_session(conn, @session_key) do
nil ->
{:error, :not_found}
history ->
{:ok, history}
end
end
@impl NavEx.Adapter
def list(%Phoenix.LiveView.Socket{} = _socket) do
raise ArgumentError,
"NavEx.Adapters.Session doesn't support LiveView sockets. Please use Plug.Conn instead."
end
@impl NavEx.Adapter
def last_path(%Plug.Conn{} = conn) do
case get_session(conn, @session_key) do
nil ->
{:error, :not_found}
history when length(history) > 1 ->
{:ok, Enum.at(history, 1)}
_history ->
{:ok, nil}
end
end
@impl NavEx.Adapter
def last_path(%Phoenix.LiveView.Socket{} = _socket) do
raise ArgumentError,
"NavEx.Adapters.Session doesn't support LiveView sockets. Please use Plug.Conn instead."
end
@impl NavEx.Adapter
def path_at(%Plug.Conn{} = conn, n) do
case get_session(conn, @session_key) do
nil ->
{:error, :not_found}
history ->
{:ok, Enum.at(history, n)}
end
end
@impl NavEx.Adapter
def path_at(%Phoenix.LiveView.Socket{} = _socket, _n) do
raise ArgumentError,
"NavEx.Adapters.Session doesn't support LiveView sockets. Please use Plug.Conn instead."
end
###
defp handle_history(conn, history, path) do
if length(history) < @history_length do
put_session(conn, @session_key, [path | history])
else
[_last | cut_navigation_history] = Enum.reverse(history)
to_be_stored = Enum.reverse(cut_navigation_history)
put_session(conn, @session_key, [path | to_be_stored])
end
end
end