Skip to content

Commit

Permalink
https://github.com/bonfire-networks/bonfire-app/issues/1031
Browse files Browse the repository at this point in the history
  • Loading branch information
mayel committed Oct 3, 2024
1 parent 2da2be5 commit 70a41ad
Show file tree
Hide file tree
Showing 13 changed files with 261 additions and 80 deletions.
2 changes: 1 addition & 1 deletion assets/static/images/icons/icons.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions assets/static/images/icons/vscode-icons/file-type-volt.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions lib/components/links/link_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ defmodule Bonfire.UI.Common.LinkLive do
@doc "What browser window/frame to target, eg. `_blank`"
prop target, :string, default: nil

prop external_link_warnings, :boolean, default: false

@doc """
Additional attributes to add onto the generated element
"""
Expand Down Expand Up @@ -71,6 +73,78 @@ defmodule Bonfire.UI.Common.LinkLive do
end
end

def render(%{to: "http" <> _, external_link_warnings: true} = assigns) do
~F"""
<p class="mb-4">This is an external link, please check where it leads before following it. If you have concerns it may be malicious you can check one of the URL reputation services below, or copy and paste the URL into a tool of your choice.</p>
<a
phx-hook="Copy"
id={"link_copy_url_#{@id || Text.random_string()}"}
href={@to}
class="float-right ml-4 flex items-center gap-2 btn btn-xs"
>
<#Icon iconify="ri:file-copy-line" class="w-4 h-4 shrink-0" />
<span data-role="label">{l("Copy")}</span>
</a>
<Link
to={@to}
class={@class}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
>
<#slot>{@label}</#slot>
</Link>
<p class="mt-4">
{#case URI.encode_www_form(@to)}
{#match url_encoded}
{!-- TODO: make these configurable --}
<Link
to={"https://transparencyreport.google.com/safe-browsing/search?url=#{url_encoded}"}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("Google Safe Browsing")}</Link>
<Link
to={"https://www.urlvoid.com/scan/#{url_encoded}"}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("URLvoid")}</Link>
<Link
to={"https://urlscan.io/search/#page.url.keyword:#{url_encoded}*"}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("URLscan")}</Link>
<Link
to={"https://www.virustotal.com/gui/search/#{url_encoded}"}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("VirusTotal")}</Link>
<Link
to={"https://sitecheck.sucuri.net/results/#{url_encoded}"}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("Sucuri")}</Link>
<Link
to={"https://safeweb.norton.com/report?url=#{url_encoded}"}
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("Norton")}</Link>
<Link
to="https://www.abuseipdb.com"
opts={@opts |> Keyword.merge("aria-label": @label, target: @target)}
class="btn btn-xs"
>{l("AbuseIPDB")}</Link>
{/case}
</p>
"""
end

def render(%{to: "http" <> _} = assigns) do
~F"""
<Link
Expand Down
10 changes: 10 additions & 0 deletions lib/components/modals/open_external_link_live.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
defmodule Bonfire.UI.Common.OpenExternalLinkLive do
@moduledoc """
TODOC
"""
use Bonfire.UI.Common.Web, :stateless_component

prop prompt_external_links, :boolean, default: false

slot default
end
34 changes: 34 additions & 0 deletions lib/components/modals/open_external_link_live.hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

let LinksClickPrompt = {
mounted() {
this.el.addEventListener("click", e => {
const link = e.target.closest('a');
if (!link) return;

e.preventDefault();
const url = window.prompt("Confirm or edit URL to follow:", link.href);

if (url) {
window.location.href = url;
}
});
}
};

let LinksDangerModal = {
mounted() {
this.el.addEventListener("click", e => {
const link = e.target.closest('a');
if (!link) return;

const url = link.href;

if (url && url.indexOf("/") != 0) {
e.preventDefault();
this.pushEvent("Bonfire.UI.Common.ReusableModalLive:prompt_external_link", { url: url })
}
});
}
};

export { LinksClickPrompt, LinksDangerModal };
3 changes: 3 additions & 0 deletions lib/components/modals/open_external_link_live.sface
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div id={@id} :hook={if @prompt_external_links, do: "LinksDangerModal"}>
<#slot />
</div>
60 changes: 6 additions & 54 deletions lib/components/modals/open_modal_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -106,51 +106,15 @@ defmodule Bonfire.UI.Common.OpenModalLive do

def open(reusable_modal_id \\ nil) do
debug("open!")
set([show: true], reusable_modal_id || @default_modal_id)
ReusableModalLive.set([show: true], reusable_modal_id)
end

def close(reusable_modal_id \\ nil) do
debug("close!")

set(
ReusableModalLive.set(
[show: false] ++ ReusableModalLive.default_assigns(),
reusable_modal_id || @default_modal_id
)
end

def set(assigns, reusable_modal_id \\ nil) do
maybe_set_assigns(
e(
assigns,
:reusable_modal_component,
ReusableModalLive
),
reusable_modal_id || e(assigns, :reusable_modal_id, nil) ||
if(e(assigns, :__context__, :sticky, nil),
do: "persistent_modal",
else: @default_modal_id
),
assigns
)

# case assigns[:root_assigns] do
# root_assigns when is_list(root_assigns) and root_assigns !=[] ->
# send_self(assigns[:root_assigns])

# _ -> nil
# end
end

def maybe_set_assigns(_component, "media_player_modal", assigns) do
# TODO: detect if we're already in the sticky view
Bonfire.UI.Common.PersistentLive.maybe_send(assigns, {:media_player, assigns})
end

def maybe_set_assigns(component, reusable_modal_id, assigns) do
maybe_send_update(
component,
reusable_modal_id,
assigns
reusable_modal_id
)
end

Expand All @@ -165,31 +129,19 @@ defmodule Bonfire.UI.Common.OpenModalLive do
)

# copy all of this component's assigns to the reusable modal (including slots!)
set(assigns(socket))
ReusableModalLive.set(assigns(socket))

{:noreply, socket}
end

def handle_event("close", _, socket) do
close(
e(assigns(socket), :reusable_modal_id, nil) ||
if(e(assigns(socket), :__context__, :sticky, nil),
do: "persistent_modal",
else: @default_modal_id
)
)
close(ReusableModalLive.modal_id(assigns(socket)))

{:noreply, socket}
end

def handle_event("set_value", %{"value" => value}, socket) do
close(
e(assigns(socket), :reusable_modal_id, nil) ||
if(e(assigns(socket), :__context__, :sticky, nil),
do: "persistent_modal",
else: @default_modal_id
)
)
close(ReusableModalLive.modal_id(assigns(socket)))

{:noreply, socket |> assign(:value, value)}
end
Expand Down
12 changes: 6 additions & 6 deletions lib/components/modals/open_preview_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ defmodule Bonfire.UI.Common.OpenPreviewLive do
"""
slot open_btn

def handle_event("close", _, socket) do
close()
{:noreply, assign(socket, show: false)}
end
# def handle_event("close", _, socket) do
# close()
# {:noreply, assign(socket, show: false)}
# end

# def handle_event("open", _, socket) do
# open()
Expand All @@ -45,7 +45,7 @@ defmodule Bonfire.UI.Common.OpenPreviewLive do
# def open() do
# debug("open!")

# Bonfire.UI.Common.OpenModalLive.set(
# Bonfire.UI.Common.ReusableModalLive.set(
# show: true,
# reusable_modal_component: Bonfire.UI.Common.PreviewContentLive,
# reusable_modal_id: "preview_content"
Expand All @@ -55,7 +55,7 @@ defmodule Bonfire.UI.Common.OpenPreviewLive do
def close() do
debug("close!")

Bonfire.UI.Common.OpenModalLive.set(
Bonfire.UI.Common.ReusableModalLive.set(
show: false,
reusable_modal_component: Bonfire.UI.Common.PreviewContentLive,
reusable_modal_id: "preview_content"
Expand Down
23 changes: 12 additions & 11 deletions lib/components/modals/preview_content_live.sface
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,25 @@
data-id="modal-contents"
>
<#slot>
{#if e(@modal_assigns, :preview_component_stateful?, nil) == true and
module_enabled?(@modal_assigns[:preview_component], @__context__)}
{!-- TODO: consolidate with ReusableModal and make modal_component & modal_view seperate props --}
{#if e(@modal_assigns, :modal_component_stateful?, nil) == true and
module_enabled?(@modal_assigns[:modal_component], @__context__)}
<StatefulComponent
id="preview_component"
module={@modal_assigns[:preview_component]}
id="modal_component"
module={@modal_assigns[:modal_component]}
{...@modal_assigns}
/>
{#elseif not is_nil(e(@modal_assigns, :preview_component, nil)) and
module_enabled?(@modal_assigns[:preview_component], @__context__)}
{#elseif not is_nil(e(@modal_assigns, :modal_component, nil)) and
module_enabled?(@modal_assigns[:modal_component], @__context__)}
<StatelessComponent
module={@modal_assigns[:preview_component]}
module={@modal_assigns[:modal_component]}
myself={@myself}
{...@modal_assigns}
/>
{#elseif not is_nil(e(@modal_assigns, :preview_view, nil)) and
module_enabled?(@modal_assigns[:preview_view], @__context__)}
{live_render(@socket, @modal_assigns[:preview_view],
id: "preview_view",
{#elseif not is_nil(e(@modal_assigns, :modal_view, nil)) and
module_enabled?(@modal_assigns[:modal_view], @__context__)}
{live_render(@socket, @modal_assigns[:modal_view],
id: "modal_view",
session: %{"params" => @modal_assigns}
)}
{#else}
Expand Down
Loading

0 comments on commit 70a41ad

Please sign in to comment.