Add support modals (#65)
* Added fast indexing upgrade modal * Improved modal on smaller screens * Updated links to work again * Added donation modal * Reverted source fast index to 15 minutes * Removed unneeded HTML attributes from old alpine approach
This commit is contained in:
parent
816def21bb
commit
e1a5be8ef3
22 changed files with 218 additions and 68 deletions
|
|
@ -32,5 +32,6 @@ defmodule Pinchflat.StartupTasks do
|
||||||
|
|
||||||
defp apply_default_settings do
|
defp apply_default_settings do
|
||||||
Settings.fetch!(:onboarding, true)
|
Settings.fetch!(:onboarding, true)
|
||||||
|
Settings.fetch!(:pro_enabled, false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,9 @@ defmodule PinchflatWeb do
|
||||||
|
|
||||||
def live_view do
|
def live_view do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.LiveView,
|
use Phoenix.Component, global_prefixes: ~w(x-)
|
||||||
layout: {PinchflatWeb.Layouts, :app}
|
|
||||||
|
use Phoenix.LiveView
|
||||||
|
|
||||||
alias Pinchflat.Settings
|
alias Pinchflat.Settings
|
||||||
|
|
||||||
|
|
@ -75,7 +76,7 @@ defmodule PinchflatWeb do
|
||||||
|
|
||||||
def html do
|
def html do
|
||||||
quote do
|
quote do
|
||||||
use Phoenix.Component
|
use Phoenix.Component, global_prefixes: ~w(x-)
|
||||||
|
|
||||||
# Import convenience functions from controllers
|
# Import convenience functions from controllers
|
||||||
import Phoenix.Controller,
|
import Phoenix.Controller,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
"""
|
"""
|
||||||
attr :id, :string, required: true
|
attr :id, :string, required: true
|
||||||
attr :show, :boolean, default: false
|
attr :show, :boolean, default: false
|
||||||
|
attr :allow_close, :boolean, default: true
|
||||||
attr :on_cancel, JS, default: %JS{}
|
attr :on_cancel, JS, default: %JS{}
|
||||||
slot :inner_block, required: true
|
slot :inner_block, required: true
|
||||||
|
|
||||||
|
|
@ -50,9 +51,9 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
phx-mounted={@show && show_modal(@id)}
|
phx-mounted={@show && show_modal(@id)}
|
||||||
phx-remove={hide_modal(@id)}
|
phx-remove={hide_modal(@id)}
|
||||||
data-cancel={JS.exec(@on_cancel, "phx-remove")}
|
data-cancel={JS.exec(@on_cancel, "phx-remove")}
|
||||||
class="relative z-50 hidden"
|
class="relative z-99999 hidden"
|
||||||
>
|
>
|
||||||
<div id={"#{@id}-bg"} class="bg-zinc-50/90 fixed inset-0 transition-opacity" aria-hidden="true" />
|
<div id={"#{@id}-bg"} class="bg-black-2/80 fixed inset-0 transition-opacity" aria-hidden="true" />
|
||||||
<div
|
<div
|
||||||
class="fixed inset-0 overflow-y-auto"
|
class="fixed inset-0 overflow-y-auto"
|
||||||
aria-labelledby={"#{@id}-title"}
|
aria-labelledby={"#{@id}-title"}
|
||||||
|
|
@ -62,28 +63,28 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div class="flex min-h-full items-center justify-center">
|
<div class="flex min-h-full items-center justify-center">
|
||||||
<div class="w-full max-w-3xl p-4 sm:p-6 lg:py-8">
|
<div class="w-full max-w-3xl p-2 sm:p-6 lg:py-8">
|
||||||
<.focus_wrap
|
<div
|
||||||
id={"#{@id}-container"}
|
id={"#{@id}-container"}
|
||||||
phx-window-keydown={JS.exec("data-cancel", to: "##{@id}")}
|
phx-window-keydown={@allow_close && JS.exec("data-cancel", to: "##{@id}")}
|
||||||
phx-key="escape"
|
phx-key="escape"
|
||||||
phx-click-away={JS.exec("data-cancel", to: "##{@id}")}
|
phx-click-away={@allow_close && JS.exec("data-cancel", to: "##{@id}")}
|
||||||
class="shadow-zinc-700/10 ring-zinc-700/10 relative hidden rounded-2xl bg-white p-14 shadow-lg ring-1 transition"
|
class="shadow-zinc-700/10 ring-zinc-700/10 relative hidden rounded-2xl bg-graydark p-8 sm:p-14 shadow-lg ring-1 transition"
|
||||||
>
|
>
|
||||||
<div class="absolute top-6 right-5">
|
<div :if={@allow_close} class="absolute top-6 right-5">
|
||||||
<button
|
<button
|
||||||
phx-click={JS.exec("data-cancel", to: "##{@id}")}
|
phx-click={JS.exec("data-cancel", to: "##{@id}")}
|
||||||
type="button"
|
type="button"
|
||||||
class="-m-3 flex-none p-3 opacity-20 hover:opacity-40"
|
class="-m-3 flex-none p-3 opacity-60 hover:opacity-80"
|
||||||
aria-label={gettext("close")}
|
aria-label={gettext("close")}
|
||||||
>
|
>
|
||||||
<.icon name="hero-x-mark-solid" class="h-5 w-5" />
|
<.icon name="hero-x-mark-solid" class="h-5 w-5 text-white" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id={"#{@id}-content"}>
|
<div id={"#{@id}-content"}>
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
</div>
|
</div>
|
||||||
</.focus_wrap>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -243,6 +244,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
attr :id, :any, default: nil
|
attr :id, :any, default: nil
|
||||||
attr :name, :any
|
attr :name, :any
|
||||||
attr :label, :string, default: nil
|
attr :label, :string, default: nil
|
||||||
|
attr :label_suffix, :string, default: nil
|
||||||
attr :value, :any
|
attr :value, :any
|
||||||
attr :help, :string, default: nil
|
attr :help, :string, default: nil
|
||||||
|
|
||||||
|
|
@ -294,6 +296,7 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
{@rest}
|
{@rest}
|
||||||
/>
|
/>
|
||||||
<%= @label %>
|
<%= @label %>
|
||||||
|
<span :if={@label_suffix} class="text-xs text-bodydark"><%= @label_suffix %></span>
|
||||||
</label>
|
</label>
|
||||||
<.help :if={@help}><%= @help %></.help>
|
<.help :if={@help}><%= @help %></.help>
|
||||||
<.error :for={msg <- @errors}><%= msg %></.error>
|
<.error :for={msg <- @errors}><%= msg %></.error>
|
||||||
|
|
@ -309,7 +312,10 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
~H"""
|
~H"""
|
||||||
<div x-data={"{ enabled: #{@checked}}"}>
|
<div x-data={"{ enabled: #{@checked}}"}>
|
||||||
<.label for={@id}><%= @label %></.label>
|
<.label for={@id}>
|
||||||
|
<%= @label %>
|
||||||
|
<span :if={@label_suffix} class="text-xs text-bodydark"><%= @label_suffix %></span>
|
||||||
|
</.label>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<input type="hidden" name={@name} value="false" />
|
<input type="hidden" name={@name} value="false" />
|
||||||
<input
|
<input
|
||||||
|
|
@ -343,7 +349,9 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
def input(%{type: "select"} = assigns) do
|
def input(%{type: "select"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div phx-feedback-for={@name}>
|
||||||
<.label for={@id}><%= @label %></.label>
|
<.label for={@id}>
|
||||||
|
<%= @label %><span :if={@label_suffix} class="text-xs text-bodydark"><%= @label_suffix %></span>
|
||||||
|
</.label>
|
||||||
<select
|
<select
|
||||||
id={@id}
|
id={@id}
|
||||||
name={@name}
|
name={@name}
|
||||||
|
|
@ -367,7 +375,9 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
def input(%{type: "textarea"} = assigns) do
|
def input(%{type: "textarea"} = assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div phx-feedback-for={@name}>
|
||||||
<.label for={@id}><%= @label %></.label>
|
<.label for={@id}>
|
||||||
|
<%= @label %><span :if={@label_suffix} class="text-xs text-bodydark"><%= @label_suffix %></span>
|
||||||
|
</.label>
|
||||||
<textarea
|
<textarea
|
||||||
id={@id}
|
id={@id}
|
||||||
name={@name}
|
name={@name}
|
||||||
|
|
@ -390,7 +400,9 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
def input(assigns) do
|
def input(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div phx-feedback-for={@name}>
|
<div phx-feedback-for={@name}>
|
||||||
<.label for={@id}><%= @label %></.label>
|
<.label for={@id}>
|
||||||
|
<%= @label %><span :if={@label_suffix} class="text-xs text-bodydark"><%= @label_suffix %></span>
|
||||||
|
</.label>
|
||||||
<input
|
<input
|
||||||
type={@type}
|
type={@type}
|
||||||
name={@name}
|
name={@name}
|
||||||
|
|
@ -608,15 +620,15 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
<.back navigate={~p"/posts"}>Back to posts</.back>
|
<.back href={~p"/posts"}>Back to posts</.back>
|
||||||
"""
|
"""
|
||||||
attr :navigate, :any, required: true
|
attr :href, :any, required: true
|
||||||
slot :inner_block, required: true
|
slot :inner_block, required: true
|
||||||
|
|
||||||
def back(assigns) do
|
def back(assigns) do
|
||||||
~H"""
|
~H"""
|
||||||
<div class="mt-16">
|
<div class="mt-16">
|
||||||
<.link navigate={@navigate} class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700">
|
<.link href={@href} class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700">
|
||||||
<.icon name="hero-arrow-left-solid" class="h-3 w-3" />
|
<.icon name="hero-arrow-left-solid" class="h-3 w-3" />
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
</.link>
|
</.link>
|
||||||
|
|
@ -685,7 +697,6 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
)
|
)
|
||||||
|> show("##{id}-container")
|
|> show("##{id}-container")
|
||||||
|> JS.add_class("overflow-hidden", to: "body")
|
|> JS.add_class("overflow-hidden", to: "body")
|
||||||
|> JS.focus_first(to: "##{id}-content")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def hide_modal(js \\ %JS{}, id) do
|
def hide_modal(js \\ %JS{}, id) do
|
||||||
|
|
@ -697,7 +708,6 @@ defmodule PinchflatWeb.CoreComponents do
|
||||||
|> hide("##{id}-container")
|
|> hide("##{id}-container")
|
||||||
|> JS.hide(to: "##{id}", transition: {"block", "block", "hidden"})
|
|> JS.hide(to: "##{id}", transition: {"block", "block", "hidden"})
|
||||||
|> JS.remove_class("overflow-hidden", to: "body")
|
|> JS.remove_class("overflow-hidden", to: "body")
|
||||||
|> JS.pop_focus()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ defmodule PinchflatWeb.CustomComponents.ButtonComponents do
|
||||||
attr :color, :string, default: "bg-primary"
|
attr :color, :string, default: "bg-primary"
|
||||||
attr :rounding, :string, default: "rounded-sm"
|
attr :rounding, :string, default: "rounded-sm"
|
||||||
attr :class, :string, default: ""
|
attr :class, :string, default: ""
|
||||||
|
attr :type, :string, default: "submit"
|
||||||
attr :disabled, :boolean, default: false
|
attr :disabled, :boolean, default: false
|
||||||
|
attr :rest, :global
|
||||||
|
|
||||||
slot :inner_block, required: true
|
slot :inner_block, required: true
|
||||||
|
|
||||||
|
|
@ -26,9 +28,11 @@ defmodule PinchflatWeb.CustomComponents.ButtonComponents do
|
||||||
"#{@rounding} inline-flex items-center justify-center px-8 py-4",
|
"#{@rounding} inline-flex items-center justify-center px-8 py-4",
|
||||||
"#{@color}",
|
"#{@color}",
|
||||||
"hover:bg-opacity-90 lg:px-8 xl:px-10",
|
"hover:bg-opacity-90 lg:px-8 xl:px-10",
|
||||||
|
"disabled:bg-opacity-50 disabled:cursor-not-allowed disabled:text-gray-2",
|
||||||
@class
|
@class
|
||||||
]}
|
]}
|
||||||
disabled={@disabled}
|
disabled={@disabled}
|
||||||
|
{@rest}
|
||||||
>
|
>
|
||||||
<%= render_slot(@inner_block) %>
|
<%= render_slot(@inner_block) %>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,16 @@ defmodule PinchflatWeb.Layouts do
|
||||||
|
|
||||||
attr :icon, :string, required: true
|
attr :icon, :string, required: true
|
||||||
attr :text, :string, required: true
|
attr :text, :string, required: true
|
||||||
attr :navigate, :any, required: true
|
attr :href, :any, required: true
|
||||||
|
attr :target, :any, default: "_self"
|
||||||
|
|
||||||
def sidebar_item(assigns) do
|
def sidebar_item(assigns) do
|
||||||
# I'm testing out grouping classes here. Tentative order: font, layout, color, animation, state-modifiers
|
# I'm testing out grouping classes here. Tentative order: font, layout, color, animation, state-modifiers
|
||||||
~H"""
|
~H"""
|
||||||
<li>
|
<li>
|
||||||
<.link
|
<.link
|
||||||
navigate={@navigate}
|
href={@href}
|
||||||
|
target={@target}
|
||||||
class={[
|
class={[
|
||||||
"font-medium text-bodydark1",
|
"font-medium text-bodydark1",
|
||||||
"group relative flex items-center gap-2.5 rounded-sm px-4 py-2 duration-300 ease-in-out",
|
"group relative flex items-center gap-2.5 rounded-sm px-4 py-2 duration-300 ease-in-out",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<.modal id="donate-modal" allow_close={true}>
|
||||||
|
<section x-data="{ inputValue: '' }">
|
||||||
|
<h3 class="text-2xl text-white">Donate</h3>
|
||||||
|
<p class="text-sm">Thank you for your support :)</p>
|
||||||
|
<p class="mt-4">
|
||||||
|
If you find the project valuable and want to support its development, a
|
||||||
|
<.inline_link href="https://www.paypal.me/kieraneglin">donation</.inline_link>
|
||||||
|
would be greatly appreciated.
|
||||||
|
</p>
|
||||||
|
<p class="mt-4">
|
||||||
|
Plus, $5 USD from any donation over $10 USD will be donated to
|
||||||
|
<.inline_link href="https://www.eff.org/">The Electronic Frontier Foundation</.inline_link>
|
||||||
|
who defend your online liberties and backed
|
||||||
|
<.inline_code>youtube-dl</.inline_code>
|
||||||
|
when Google took them down<.inline_link href="https://github.com/github/dmca/blob/9a85e0f021f7967af80e186b890776a50443f06c/2020/11/2020-11-16-RIAA-reversal-effletter.pdf">
|
||||||
|
<.icon name="hero-arrow-top-right-on-square" class="h-3 w-3" />
|
||||||
|
</.inline_link>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<.link href="https://www.paypal.me/kieraneglin" target="_blank">
|
||||||
|
<.button color="bg-primary" class="w-full mt-8">
|
||||||
|
Donate
|
||||||
|
</.button>
|
||||||
|
</.link>
|
||||||
|
</section>
|
||||||
|
</.modal>
|
||||||
|
|
@ -1,31 +1,58 @@
|
||||||
<aside
|
<aside
|
||||||
x-bind:class="sidebarVisible ? 'translate-x-0' : '-translate-x-full'"
|
x-bind:class="sidebarVisible ? 'translate-x-0' : '-translate-x-full'"
|
||||||
class={[
|
class={[
|
||||||
"-translate-x-full absolute left-0 top-0 z-9999 flex h-screen w-60 flex-col overflow-y-hidden",
|
"-translate-x-full absolute left-0 top-0 z-9999 flex h-screen w-60 flex-col overflow-y-hidden justify-between",
|
||||||
"bg-black duration-300 ease-linear shadow-lg sm:shadow-none dark:bg-boxdark lg:static lg:translate-x-0"
|
"bg-black duration-300 ease-linear shadow-lg sm:shadow-none dark:bg-boxdark lg:static lg:translate-x-0"
|
||||||
]}
|
]}
|
||||||
@click.outside="sidebarVisible = false"
|
@click.outside="sidebarVisible = false"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-between gap-2 px-6 py-5.5 lg:py-6.5">
|
<section>
|
||||||
<a href="/" class="flex items-center">
|
<div class="flex items-center justify-between gap-2 px-6 py-5.5 lg:py-6.5">
|
||||||
<img src={~p"/images/logo.png?cachebust=2024-02-29"} alt="Pinchflat" class="w-9 h-9" />
|
<a href="/" class="flex items-center">
|
||||||
<h2 class="text-xl font-bold text-white pl-2">Pinchflat</h2>
|
<img src={~p"/images/logo.png?cachebust=2024-02-29"} alt="Pinchflat" class="w-9 h-9" />
|
||||||
</a>
|
<h2 class="text-xl font-bold text-white pl-2">Pinchflat</h2>
|
||||||
|
</a>
|
||||||
|
|
||||||
<button class="block lg:hidden" @click.stop="sidebarVisible = !sidebarVisible">
|
<button class="block lg:hidden" @click.stop="sidebarVisible = !sidebarVisible">
|
||||||
<.icon name="hero-arrow-left" class="fill-current" />
|
<.icon name="hero-arrow-left" class="fill-current" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="no-scrollbar flex flex-col overflow-y-auto duration-300 ease-linear">
|
<div class="no-scrollbar flex flex-col overflow-y-auto duration-300 ease-linear">
|
||||||
<nav class="mt-5 px-4 py-4 lg:mt-9 lg:px-6">
|
<nav class="mt-5 px-4 py-4 lg:mt-9 lg:px-6">
|
||||||
<div>
|
|
||||||
<h3 class="mb-4 ml-4 text-sm font-medium text-bodydark2">MENU</h3>
|
<h3 class="mb-4 ml-4 text-sm font-medium text-bodydark2">MENU</h3>
|
||||||
<ul class="mb-6 flex flex-col gap-1.5">
|
<div class="flex flex-col justify-between">
|
||||||
<.sidebar_item icon="hero-home" text="Home" navigate={~p"/"} />
|
<ul class="mb-6 flex flex-col gap-1.5">
|
||||||
<.sidebar_item icon="hero-tv" text="Sources" navigate={~p"/sources"} />
|
<.sidebar_item icon="hero-home" text="Home" href={~p"/"} />
|
||||||
<.sidebar_item icon="hero-adjustments-vertical" text="Media Profiles" navigate={~p"/media_profiles"} />
|
<.sidebar_item icon="hero-tv" text="Sources" href={~p"/sources"} />
|
||||||
</ul>
|
<.sidebar_item icon="hero-adjustments-vertical" text="Media Profiles" href={~p"/media_profiles"} />
|
||||||
</div>
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<nav class="mt-5 px-4 py-4 lg:mt-9 lg:px-6">
|
||||||
|
<ul class="mb-6 flex flex-col gap-1.5">
|
||||||
|
<.sidebar_item
|
||||||
|
icon="hero-code-bracket"
|
||||||
|
text="Github"
|
||||||
|
target="_blank"
|
||||||
|
href="https://github.com/kieraneglin/pinchflat"
|
||||||
|
/>
|
||||||
|
<li>
|
||||||
|
<span
|
||||||
|
class={[
|
||||||
|
"font-medium text-bodydark1",
|
||||||
|
"group relative flex items-center gap-2.5 rounded-sm px-4 py-2 duration-300 ease-in-out",
|
||||||
|
"duration-300 ease-in-out cursor-pointer",
|
||||||
|
"hover:bg-graydark dark:hover:bg-meta-4"
|
||||||
|
]}
|
||||||
|
phx-click={show_modal("donate-modal")}
|
||||||
|
>
|
||||||
|
<.icon name="hero-currency-dollar" /> Donate
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</section>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
defmodule Pinchflat.UpgradeButtonLive do
|
||||||
|
use PinchflatWeb, :live_view
|
||||||
|
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<form phx-change="check_matching_text">
|
||||||
|
<.input type="text" name="unlock-pro-textbox" value="" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<.button
|
||||||
|
class="w-full mt-4"
|
||||||
|
type="button"
|
||||||
|
disabled={@button_disabled}
|
||||||
|
phx-click={hide_modal("upgrade-modal")}
|
||||||
|
x-on:click="setTimeout(() => { proEnabled = true }, 200)"
|
||||||
|
>
|
||||||
|
Unlock Pro
|
||||||
|
</.button>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
def mount(_params, _session, socket) do
|
||||||
|
{:ok, assign(socket, :button_disabled, true)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("check_matching_text", %{"unlock-pro-textbox" => text}, socket) do
|
||||||
|
normalized_text =
|
||||||
|
text
|
||||||
|
|> String.trim()
|
||||||
|
|> String.downcase()
|
||||||
|
|
||||||
|
if normalized_text == "got it!" do
|
||||||
|
Settings.set!(:pro_enabled, true)
|
||||||
|
|
||||||
|
{:noreply, update(socket, :button_disabled, fn _ -> false end)}
|
||||||
|
else
|
||||||
|
{:noreply, update(socket, :button_disabled, fn _ -> true end)}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<.modal id="upgrade-modal" allow_close={false}>
|
||||||
|
<section>
|
||||||
|
<h3 class="text-2xl text-white">Pro Mode</h3>
|
||||||
|
<p class="text-sm">Don't worry - Pinchflat is completely free :)</p>
|
||||||
|
<p class="mt-4">
|
||||||
|
If you find the project valuable and want to support its development, a
|
||||||
|
<.inline_link href="https://www.paypal.me/kieraneglin">donation</.inline_link>
|
||||||
|
would be greatly appreciated.
|
||||||
|
</p>
|
||||||
|
<p class="mt-4">
|
||||||
|
Plus, $5 USD from any donation over $10 USD will be donated to
|
||||||
|
<.inline_link href="https://www.eff.org/">The Electronic Frontier Foundation</.inline_link>
|
||||||
|
who defend your online liberties and backed
|
||||||
|
<.inline_code>youtube-dl</.inline_code>
|
||||||
|
when Google took them down<.inline_link href="https://github.com/github/dmca/blob/9a85e0f021f7967af80e186b890776a50443f06c/2020/11/2020-11-16-RIAA-reversal-effletter.pdf">
|
||||||
|
<.icon name="hero-arrow-top-right-on-square" class="h-3 w-3" />
|
||||||
|
</.inline_link>. <strong>You do not need to donate to unlock Pro</strong>. It's just a way to say thanks!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="mt-4">
|
||||||
|
To unlock Pro, simply type
|
||||||
|
<.inline_code>got it!</.inline_code>
|
||||||
|
into the text box and press the button.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<%= live_render(@conn, Pinchflat.UpgradeButtonLive) %>
|
||||||
|
</section>
|
||||||
|
</.modal>
|
||||||
|
|
@ -12,7 +12,15 @@
|
||||||
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body x-data="{ sidebarVisible: false }" class="dark text-bodydark bg-boxdark-2">
|
<body
|
||||||
|
x-data={"{ sidebarVisible: false, proEnabled: #{Settings.get!(:pro_enabled)} }"}
|
||||||
|
class="dark text-bodydark bg-boxdark-2"
|
||||||
|
>
|
||||||
<%= @inner_content %>
|
<%= @inner_content %>
|
||||||
|
|
||||||
|
<.donate_modal conn={@conn} />
|
||||||
|
<template x-if="!proEnabled">
|
||||||
|
<.upgrade_modal conn={@conn} />
|
||||||
|
</template>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||||
<div class="flex gap-3 items-center">
|
<div class="flex gap-3 items-center">
|
||||||
<.link navigate={~p"/sources/#{@media_item.source_id}"}>
|
<.link href={~p"/sources/#{@media_item.source_id}"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||||
<.link navigate={~p"/media_profiles"}>
|
<.link href={~p"/media_profiles"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Media Profile</h2>
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Media Profile</h2>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Media Profiles
|
Media Profiles
|
||||||
</h2>
|
</h2>
|
||||||
<nav>
|
<nav>
|
||||||
<.link navigate={~p"/media_profiles/new"}>
|
<.link href={~p"/media_profiles/new"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full">
|
<.button color="bg-primary" rounding="rounded-full">
|
||||||
<span class="font-bold text-xl mx-2">+</span> New <span class="hidden sm:inline pl-1">Media Profile</span>
|
<span class="font-bold text-xl mx-2">+</span> New <span class="hidden sm:inline pl-1">Media Profile</span>
|
||||||
</.button>
|
</.button>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||||
<.link :if={!Settings.get!(:onboarding)} navigate={~p"/media_profiles"}>
|
<.link :if={!Settings.get!(:onboarding)} href={~p"/media_profiles"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Media Profile</h2>
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Media Profile</h2>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<.link navigate={~p"/media_profiles"}>
|
<.link href={~p"/media_profiles"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-2">
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-2">
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<.link navigate={~p"/media_profiles/#{@media_profile}/edit"}>
|
<.link href={~p"/media_profiles/#{@media_profile}/edit"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full">
|
<.button color="bg-primary" rounding="rounded-full">
|
||||||
<.icon name="hero-pencil-square" class="mr-2" />Edit <span class="hidden sm:inline pl-1">Media Profile</span>
|
<.icon name="hero-pencil-square" class="mr-2" />Edit <span class="hidden sm:inline pl-1">Media Profile</span>
|
||||||
</.button>
|
</.button>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<p class="text-md text-bodydark">Media Profiles set your preferences for fetching and downloading media.</p>
|
<p class="text-md text-bodydark">Media Profiles set your preferences for fetching and downloading media.</p>
|
||||||
<p class="text-md text-bodydark">Don't worry, you can create more Media Profiles later!</p>
|
<p class="text-md text-bodydark">Don't worry, you can create more Media Profiles later!</p>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<.link navigate={~p"/media_profiles/new"}>
|
<.link href={~p"/media_profiles/new"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full" disabled={@media_profiles_exist}>
|
<.button color="bg-primary" rounding="rounded-full" disabled={@media_profiles_exist}>
|
||||||
<span class="font-bold mx-2">+</span> New Media Profile
|
<span class="font-bold mx-2">+</span> New Media Profile
|
||||||
</.button>
|
</.button>
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
Each Media Profile can control many Sources so it's easy to add more content!
|
Each Media Profile can control many Sources so it's easy to add more content!
|
||||||
</p>
|
</p>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<.link navigate={~p"/sources/new"}>
|
<.link href={~p"/sources/new"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full" disabled={not @media_profiles_exist}>
|
<.button color="bg-primary" rounding="rounded-full" disabled={not @media_profiles_exist}>
|
||||||
<span class="font-bold mx-2">+</span> New Source
|
<span class="font-bold mx-2">+</span> New Source
|
||||||
</.button>
|
</.button>
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
</p>
|
</p>
|
||||||
<p class="text-md text-bodydark">Feel free to add more Media Profiles or Sources in the meantime!</p>
|
<p class="text-md text-bodydark">Feel free to add more Media Profiles or Sources in the meantime!</p>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<.link navigate={~p"/"}>
|
<.link href={~p"/"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full" disabled={not @sources_exist}>
|
<.button color="bg-primary" rounding="rounded-full" disabled={not @sources_exist}>
|
||||||
Let's Go <span class="font-bold mx-2">🚀</span>
|
Let's Go <span class="font-bold mx-2">🚀</span>
|
||||||
</.button>
|
</.button>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
</:col>
|
</:col>
|
||||||
<:col :let={result} label="" class="flex place-content-evenly">
|
<:col :let={result} label="" class="flex place-content-evenly">
|
||||||
<.link
|
<.link
|
||||||
navigate={~p"/sources/#{result.source_id}/media/#{result.id}"}
|
href={~p"/sources/#{result.source_id}/media/#{result.id}"}
|
||||||
class="hover:text-secondary duration-200 ease-in-out mx-0.5"
|
class="hover:text-secondary duration-200 ease-in-out mx-0.5"
|
||||||
>
|
>
|
||||||
<.icon name="hero-eye" />
|
<.icon name="hero-eye" />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||||
<.link navigate={~p"/sources"}>
|
<.link href={~p"/sources"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Source</h2>
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">Edit Source</h2>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white">Sources</h2>
|
<h2 class="text-title-md2 font-bold text-black dark:text-white">Sources</h2>
|
||||||
<nav>
|
<nav>
|
||||||
<.link navigate={~p"/sources/new"}>
|
<.link href={~p"/sources/new"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full">
|
<.button color="bg-primary" rounding="rounded-full">
|
||||||
<span class="font-bold mx-2">+</span> New <span class="hidden sm:inline pl-1">Source</span>
|
<span class="font-bold mx-2">+</span> New <span class="hidden sm:inline pl-1">Source</span>
|
||||||
</.button>
|
</.button>
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
</:col>
|
</:col>
|
||||||
<:col :let={source} label="Media Profile">
|
<:col :let={source} label="Media Profile">
|
||||||
<.link
|
<.link
|
||||||
navigate={~p"/media_profiles/#{source.media_profile_id}"}
|
href={~p"/media_profiles/#{source.media_profile_id}"}
|
||||||
class="hover:text-secondary duration-200 ease-in-out"
|
class="hover:text-secondary duration-200 ease-in-out"
|
||||||
>
|
>
|
||||||
<%= source.media_profile.name %>
|
<%= source.media_profile.name %>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center">
|
<div class="mb-6 flex gap-3 flex-row items-center">
|
||||||
<.link :if={!Settings.get!(:onboarding)} navigate={~p"/sources"}>
|
<.link :if={!Settings.get!(:onboarding)} href={~p"/sources"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Source</h2>
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">New Source</h2>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
<div class="mb-6 flex gap-3 flex-row items-center justify-between">
|
||||||
<div class="flex gap-3 items-center">
|
<div class="flex gap-3 items-center">
|
||||||
<.link navigate={~p"/sources"}>
|
<.link href={~p"/sources"}>
|
||||||
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
<.icon name="hero-arrow-left" class="w-10 h-10 hover:dark:text-white" />
|
||||||
</.link>
|
</.link>
|
||||||
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
<h2 class="text-title-md2 font-bold text-black dark:text-white ml-4">
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<.link navigate={~p"/sources/#{@source}/edit"}>
|
<.link href={~p"/sources/#{@source}/edit"}>
|
||||||
<.button color="bg-primary" rounding="rounded-full">
|
<.button color="bg-primary" rounding="rounded-full">
|
||||||
<.icon name="hero-pencil-square" class="mr-2" /> Edit <span class="hidden sm:inline pl-1">Source</span>
|
<.icon name="hero-pencil-square" class="mr-2" /> Edit <span class="hidden sm:inline pl-1">Source</span>
|
||||||
</.button>
|
</.button>
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,15 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<%!-- TODO: use Alpine to disable the index frequency when fast indexing is enabled --%>
|
<%!-- TODO: use Alpine to disable the index frequency when fast indexing is enabled --%>
|
||||||
<.input
|
<div phx-click={show_modal("upgrade-modal")}>
|
||||||
field={f[:fast_index]}
|
<.input
|
||||||
type="toggle"
|
field={f[:fast_index]}
|
||||||
label="Use Fast Indexing?"
|
type="toggle"
|
||||||
help="Experimental. Ignores 'Index Frequency'. Recommended for large channels that upload frequently. See below for more info"
|
label="Use Fast Indexing?"
|
||||||
/>
|
label_suffix="(pro)"
|
||||||
|
help="Experimental. Ignores 'Index Frequency'. Recommended for large channels that upload frequently. See below for more info"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
<h3 class="mt-8 text-2xl text-black dark:text-white">
|
||||||
Downloading Options
|
Downloading Options
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue