diff --git a/assets/js/app.ts b/assets/js/app.ts index 75a585d5..da6f9cdd 100644 --- a/assets/js/app.ts +++ b/assets/js/app.ts @@ -397,6 +397,36 @@ const Hooks = { }); }, }, + LiveBillboard: { + setup() { + const urls = JSON.parse(this.el.dataset.urls); + const [img1, img2] = this.el.querySelectorAll("img"); + let currentIndex = 0; + let nextIndex = Math.min(1, urls.length - 1); + img2.src = urls[nextIndex]; + + clearInterval(this.interval); + if (urls.length > 1) { + this.interval = setInterval(() => { + const nextImg = currentIndex % 2 === 0 ? img2 : img1; + const currentImg = currentIndex % 2 === 0 ? img1 : img2; + + nextImg.src = urls[nextIndex]; + nextImg.classList.remove("opacity-0"); + currentImg.classList.add("opacity-0"); + + currentIndex = nextIndex; + nextIndex = (nextIndex + 1) % urls.length; + }, 5000); + } + }, + mounted() { + this.setup(); + }, + updated() { + this.setup(); + }, + }, } satisfies Record & Record>; // Accessible focus handling diff --git a/lib/algora/admin.ex b/lib/algora/admin.ex index b7c401eb..d542bd4b 100644 --- a/lib/algora/admin.ex +++ b/lib/algora/admin.ex @@ -10,6 +10,49 @@ defmodule Algora.Admin do video: "g3cFdmlkZW8.m3u8" } + def kill_ad_overlay_processes do + find_ad_overlay_processes() |> Enum.each(&Process.exit(&1, :kill)) + end + + def find_ad_overlay_processes do + nodes() + |> Enum.flat_map(fn node -> + :rpc.call(node, __MODULE__, :find_local_ad_overlay_processes, []) + end) + end + + def kill_local_ad_overlay_processes do + find_local_ad_overlay_processes() |> Enum.each(&Process.exit(&1, :kill)) + end + + def find_liveview_processes(module, function \\ :mount, arity \\ 3) do + nodes() + |> Enum.flat_map(fn node -> + :rpc.call(node, __MODULE__, :find_local_liveview_processes, [module, function, arity]) + end) + end + + def find_local_liveview_processes(module, function \\ :mount, arity \\ 3) do + :erlang.processes() + |> Enum.filter(&local_process_matches?(&1, [{module, function, arity}])) + end + + def find_local_ad_overlay_processes do + find_local_liveview_processes(AlgoraWeb.AdOverlayLive) + end + + defp local_process_matches?(pid, match_patterns) do + case Process.info(pid, [:dictionary]) do + [dictionary: dict] -> + dict + |> Keyword.get(:"$initial_call") + |> then(&Enum.any?(match_patterns, fn pattern -> pattern == &1 end)) + + _ -> + false + end + end + def whoami(), do: {System.get_env("FLY_REGION"), Node.self()} defp get(url) do @@ -197,7 +240,7 @@ defmodule Algora.Admin do {:ok, _} = Accounts.update_settings(user, %{channel_tagline: title}) end - def nodes(), do: [Node.self() | Node.list()] + def nodes(), do: Node.list([:this, :visible]) def pipelines() do nodes() |> Enum.flat_map(&Membrane.Pipeline.list_pipelines/1) diff --git a/lib/algora/ads/ad.ex b/lib/algora/ads/ad.ex index e78a53c5..62203249 100644 --- a/lib/algora/ads/ad.ex +++ b/lib/algora/ads/ad.ex @@ -8,7 +8,7 @@ defmodule Algora.Ads.Ad do field :status, Ecto.Enum, values: [:inactive, :active] field :verified, :boolean, default: false field :website_url, :string - field :composite_asset_url, :string + field :composite_asset_urls, {:array, :string} field :asset_url, :string field :logo_url, :string field :qrcode_url, :string @@ -33,7 +33,7 @@ defmodule Algora.Ads.Ad do :name, :verified, :website_url, - :composite_asset_url, + :composite_asset_urls, :asset_url, :logo_url, :qrcode_url, @@ -49,7 +49,6 @@ defmodule Algora.Ads.Ad do |> validate_required([ :slug, :website_url, - :composite_asset_url, :border_color ]) |> validate_format(:border_color, ~r/^#([0-9A-F]{3}){1,2}$/i, diff --git a/lib/algora_web/components/core_components.ex b/lib/algora_web/components/core_components.ex index 6d698002..6ff1d755 100644 --- a/lib/algora_web/components/core_components.ex +++ b/lib/algora_web/components/core_components.ex @@ -178,6 +178,34 @@ defmodule AlgoraWeb.CoreComponents do """ end + attr :ad, :any, required: true + attr :id, :string, required: true + attr :class, :string, default: nil + + def live_billboard(assigns) do + ~H""" +
+ {@ad.website_url} + {@ad.website_url} +
+ """ + end + attr :class, :string, default: nil def logo(assigns) do diff --git a/lib/algora_web/live/ad_live/analytics.html.heex b/lib/algora_web/live/ad_live/analytics.html.heex index 55c21bd6..3dca0b41 100644 --- a/lib/algora_web/live/ad_live/analytics.html.heex +++ b/lib/algora_web/live/ad_live/analytics.html.heex @@ -16,12 +16,7 @@ - {@ad.website_url} + <.live_billboard ad={@ad} id={"ad-banner-#{@ad.id}"} /> - {ad.website_url} + <.live_billboard ad={ad} id={"ad-banner-#{ad.id}"} /> <:action :let={{_id, ad}}>
diff --git a/lib/algora_web/live/ad_live/schedule.html.heex b/lib/algora_web/live/ad_live/schedule.html.heex index dda0c867..73c4fb08 100644 --- a/lib/algora_web/live/ad_live/schedule.html.heex +++ b/lib/algora_web/live/ad_live/schedule.html.heex @@ -31,11 +31,6 @@
- {ad.website_url} + <.live_billboard ad={ad} id={"ad-banner-#{ad.id}"} /> diff --git a/lib/algora_web/live/ad_live/show.html.heex b/lib/algora_web/live/ad_live/show.html.heex index 6d03ac15..4e6711c0 100644 --- a/lib/algora_web/live/ad_live/show.html.heex +++ b/lib/algora_web/live/ad_live/show.html.heex @@ -11,7 +11,7 @@ <.list> <:item title="Verified"><%= @ad.verified %> <:item title="Website url"><%= @ad.website_url %> - <:item title="Composite asset url"><%= @ad.composite_asset_url %> + <:item title="Composite asset url"><%= @ad.composite_asset_urls |> Enum.join(", ") %> <:item title="Asset url"><%= @ad.asset_url %> <:item title="Logo url"><%= @ad.logo_url %> <:item title="Qrcode url"><%= @ad.qrcode_url %> diff --git a/lib/algora_web/live/ad_overlay_live.ex b/lib/algora_web/live/ad_overlay_live.ex index 7aabb6a8..230d672c 100644 --- a/lib/algora_web/live/ad_overlay_live.ex +++ b/lib/algora_web/live/ad_overlay_live.ex @@ -9,17 +9,12 @@ defmodule AlgoraWeb.AdOverlayLive do ~H""" <%= if @ads && length(@ads) > 0 do %>
- {@current_ad.website_url} - {@next_ad.website_url} + <.live_billboard ad={@next_ad} id="ad-banner-1" class="opacity-0 pointer-events-none" />
<% end %> """ diff --git a/priv/repo/migrations/20240926172045_rename_composite_asset_url_to_composite_asset_urls.exs b/priv/repo/migrations/20240926172045_rename_composite_asset_url_to_composite_asset_urls.exs new file mode 100644 index 00000000..f879d5c2 --- /dev/null +++ b/priv/repo/migrations/20240926172045_rename_composite_asset_url_to_composite_asset_urls.exs @@ -0,0 +1,35 @@ +defmodule Algora.Repo.Local.Migrations.RenameCompositeAssetUrlToCompositeAssetUrls do + use Ecto.Migration + + def up do + alter table(:ads) do + add :composite_asset_urls, {:array, :string}, default: [] + end + + execute """ + UPDATE ads + SET composite_asset_urls = ARRAY[composite_asset_url] + WHERE composite_asset_url IS NOT NULL + """ + + alter table(:ads) do + remove :composite_asset_url + end + end + + def down do + alter table(:ads) do + add :composite_asset_url, :string + end + + execute """ + UPDATE ads + SET composite_asset_url = composite_asset_urls[1] + WHERE composite_asset_urls IS NOT NULL + """ + + alter table(:ads) do + remove :composite_asset_urls + end + end +end