Skip to content

Instantly share code, notes, and snippets.

View f0rest8's full-sized avatar

Mark f0rest8

View GitHub Profile
@f0rest8
f0rest8 / metamorphic_shared_avatars_html_snippet.html.heex
Created October 22, 2022 22:32
Metamorphic shared avatars html snippet
<div id={"avatar-[#{index}]-#{rel.id}"} class="flex-shrink-0" :if={not @avatar_loading || @avatar_loading_count != index}>
<.avatar name={live_decrypt(rel, nil, @current_user, @current_user_session_key, [is_payload_struct?: true, payload_ext: "name"])} src={get_shared_avatar(@current_user, rel, @current_user_session_key)} size="sm" random_color class="h-12 w-12 rounded-full" />
</div>
<div id={"avatar-[#{index}]-#{rel.id}"} class="flex-shrink-0" :if={@avatar_loading && @avatar_loading_count == index}>
<.spinner />
</div>
@f0rest8
f0rest8 / metamorphic_shared_avatars_helper_function.ex
Created October 22, 2022 22:29
Metamorphic shared avatars helper function
def get_shared_avatar(current_user, relationship, current_user_session_key) do
cond do
is_nil(relationship.user_avatar_url) && relationship.relation_id == current_user.id ->
""
is_nil(relationship.relation_avatar_url) && relationship.user_id == current_user.id ->
""
not is_nil(
avatar_binary =
@f0rest8
f0rest8 / metamorphic_shared_avatars_handle_info.ex
Last active October 23, 2022 00:40
Metamorphic shared avatars handle_info function
## Handle the specific shared_avatar async task
@impl true
def handle_info({_ref, {"get_shared_avatar", relationship_id}}, socket) do
cond do
socket.assigns.avatar_loading && socket.assigns.avatar_loading_count < Enum.count(socket.assigns.relationships) ->
socket =
socket
|> assign(:avatar_loading, false)
|> assign(:current_loading_avatar_rel_id, relationship_id)
|> assign(:avatar_loading_count, socket.assigns.avatar_loading_count + 1)
@f0rest8
f0rest8 / expanded_ux_index.ex
Created November 20, 2021 23:56
Quick and easy local time for clients (expanded ux)
defmodule YourAppWeb.DashboardLive.Index do
@moduledoc false
use YourAppWeb, :live_view
on_mount YourAppWeb.Hooks.LocalTimeZoneHook
@impl true
def mount(_params, session, socket) do
...
@f0rest8
f0rest8 / index.ex
Last active November 20, 2021 21:43
Quick and easy local time zone in your Elixir and Phoenix app
defmodule YourAppWeb.DashboardLive.Index do
@moduledoc false
use YourAppWeb, :live_view
on_mount YourAppWeb.Hooks.LocalTimeZoneHook
@impl true
def mount(_params, session, socket) do
...
@f0rest8
f0rest8 / plug_attack_fail2ban.ex
Last active November 13, 2021 04:14
Protect against bad actors while preservering their privacy with fail2ban
defmodule YourAppWeb.Plugs.PlugAttack do
@moduledoc false
use PlugAttack
import Plug.Conn
@alg :sha512
@ip_secret System.fetch_env!("PLUG_ATTACK_IP_SECRET")
rule "fail2ban by ip", conn do
fail2ban hash_ip(@alg, convert_ip(conn.remote_ip)),
@f0rest8
f0rest8 / plug_attack.ex
Last active November 13, 2021 03:30
Protect against bad actors while preserving their privacy
defmodule YourAppWeb.Plugs.PlugAttack do
@moduledoc false
use PlugAttack
import Plug.Conn
@alg :sha512
@ip_secret System.fetch_env!("PLUG_ATTACK_IP_SECRET")
rule "throttle by ip", conn do
throttle hash_ip(@alg, convert_ip(conn.remote_ip)),
@f0rest8
f0rest8 / revised_new.ex
Last active September 27, 2021 19:57
Person registration with live view implementation update for Phoenix 1.6
defmodule YourAppWeb.PersonRegistrationLive.New do
use Phoenix.LiveView
alias YourAppWeb.Router.Helpers, as: Routes
alias YourApp.Accounts
alias YourApp.Accounts.Person
def mount(_params, _session, socket) do
changeset = Accounts.change_person_registration(%Person{})
{:ok, assign(socket, changeset: changeset)}
defmodule YourAppWeb.PersonRegistrationLive.New do
use Phoenix.LiveView
alias YourAppWeb.Router.Helpers, as: Routes
alias YourApp.Accounts
alias YourApp.Accounts.Person
def mount(_params, _session, socket) do
changeset = Accounts.change_person_registration(%Person{})
{:ok,
def render(assigns) do
~H"""
<.form let={f} for={@changeset} url="#" phx_change="validate" phx_submit="save">
<div class={unless @current_step === 1, do: "hidden"}>
<!-- Step 1 form fields here -->
</div>
<div class={unless @current_step === 2, do: "hidden"}>
<!-- Step 2 form fields here -->
</div>