Skip to content

Commit

Permalink
implement user session storage for liveviews
Browse files Browse the repository at this point in the history
taken fromhttps://fly.io/phoenix-files/saving-and-restoring-liveview-state/
  • Loading branch information
electronicbites committed Aug 15, 2024
1 parent 222732f commit 129ad28
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
23 changes: 23 additions & 0 deletions assets/js/hooks/local_state_store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// JS Hook for storing some state in sessionStorage in the browser.
// The server requests stored data and clears it when requested.
// Code taken from fly.io blog post: https://fly.io/phoenix-files/saving-and-restoring-liveview-state/
export const hooks = {
mounted() {
this.handleEvent("store", (obj) => this.store(obj));
this.handleEvent("clear", (obj) => this.clear(obj));
this.handleEvent("restore", (obj) => this.restore(obj));
},

store(obj) {
sessionStorage.setItem(obj.key, obj.data);
},

restore(obj) {
var data = sessionStorage.getItem(obj.key);
this.pushEvent(obj.event, data);
},

clear(obj) {
sessionStorage.removeItem(obj.key);
},
};
47 changes: 47 additions & 0 deletions lib/radiator_web/live/episode_live/index.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ defmodule RadiatorWeb.EpisodeLive.Index do
Dispatch.subscribe(episode.id)
end

socket =
if connected?(socket) do
# This represents some meaningful key to your LiveView that you can
# store and restore state using. Perhaps an ID from the page
# the user is visiting?
my_storage_key = "a-relevant-value-from-somewhere"
# For handle_params, it could be
# my_storage_key = params["id"]

socket
|> assign(:my_storage_key, my_storage_key)
# request the browser to restore any state it has for this key.
|> push_event("restore", %{key: my_storage_key, event: "restoreSettings"})
else
socket
end

socket
|> assign(:selected_episode, episode)
|> push_event("list", %{nodes: nodes})
Expand Down Expand Up @@ -72,6 +89,36 @@ defmodule RadiatorWeb.EpisodeLive.Index do
|> reply(:noreply)
end

# Pushed from JS hook. Server requests it to send up any
# stored settings for the key.
def handle_event("restoreSettings", token_data, socket) when is_binary(token_data) do
socket =
case restore_from_token(token_data) do
{:ok, nil} ->
# do nothing with the previous state
socket

{:ok, restored} ->
socket
|> assign(:state, restored)

{:error, reason} ->
# We don't continue checking. Display error.
# Clear the token so it doesn't keep showing an error.
socket
|> put_flash(:error, reason)
|> clear_browser_storage()
end

{:noreply, socket}
end

def handle_event("restoreSettings", _token_data, socket) do
# No expected token data received from the client
Logger.debug("No LiveView SessionStorage state to restore")
{:noreply, socket}
end

def handle_event("create_node", params, socket) do
user = socket.assigns.current_user
episode = socket.assigns.selected_episode
Expand Down

0 comments on commit 129ad28

Please sign in to comment.