From f591939ccde74d08fa088ddfb521292e5d7a633c Mon Sep 17 00:00:00 2001
From: "Luna D." <luna@nighty.cloud>
Date: Tue, 30 Apr 2024 16:40:09 +0200
Subject: [PATCH] prelim work on vite reload

---
 assets/js/app.js                                  |  3 +++
 config/dev.exs                                    |  4 ++--
 config/runtime.exs                                |  6 ++++++
 docker-compose.yml                                |  2 ++
 docker/app/Dockerfile                             |  3 ++-
 .../plugs/content_security_policy_plug.ex         |  5 +++--
 lib/philomena_web/templates/layout/app.html.slime | 15 ++++++++++-----
 lib/philomena_web/views/layout_view.ex            |  4 ++++
 8 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/assets/js/app.js b/assets/js/app.js
index a64ec696..018200ff 100644
--- a/assets/js/app.js
+++ b/assets/js/app.js
@@ -8,3 +8,6 @@
 // Our code
 import './ujs';
 import './when-ready';
+
+// Fallback on the dark theme for now
+import '../css/themes/dark.scss';
diff --git a/config/dev.exs b/config/dev.exs
index 90d6d4db..9f613906 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -17,10 +17,10 @@ config :philomena, PhilomenaWeb.Endpoint,
   watchers: [
     node: [
       "node_modules/vite/bin/vite.js",
-      "build",
       "--mode",
       "development",
-      "--watch",
+      "--host",
+      "0.0.0.0",
       "--config",
       "vite.config.ts",
       cd: Path.expand("../assets", __DIR__)
diff --git a/config/runtime.exs b/config/runtime.exs
index 3f911fa5..b7a71c3e 100644
--- a/config/runtime.exs
+++ b/config/runtime.exs
@@ -137,6 +137,9 @@ if config_env() == :prod do
 
   # Do not relax CSP in production
   config :philomena, csp_relaxed: false
+
+  # Disable Vite HMR in prod
+  config :philomena, vite_reload: false
 else
   # Don't send email in development
   config :philomena, Philomena.Mailer, adapter: Bamboo.LocalAdapter
@@ -146,4 +149,7 @@ else
 
   # Relax CSP rules in development and test servers
   config :philomena, csp_relaxed: true
+
+  # Enable Vite HMR
+  config :philomena, vite_reload: true
 end
diff --git a/docker-compose.yml b/docker-compose.yml
index 84d25060..8e644165 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -48,6 +48,8 @@ services:
       - postgres
       - elasticsearch
       - redis
+    ports:
+      - '5173:5173'
 
   postgres:
     image: postgres:16.2-alpine
diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile
index 7f620d52..fb76abbc 100644
--- a/docker/app/Dockerfile
+++ b/docker/app/Dockerfile
@@ -1,4 +1,4 @@
-FROM elixir:1.16.1-alpine
+FROM elixir:1.16.2-alpine
 
 ADD https://api.github.com/repos/philomena-dev/FFmpeg/git/refs/heads/release/6.1 /tmp/ffmpeg_version.json
 RUN (echo "https://github.com/philomena-dev/prebuilt-ffmpeg/raw/master"; cat /etc/apk/repositories) > /tmp/repositories \
@@ -24,4 +24,5 @@ COPY docker/app/run-test /usr/local/bin/run-test
 COPY docker/app/safe-rsvg-convert /usr/local/bin/safe-rsvg-convert
 COPY docker/app/purge-cache /usr/local/bin/purge-cache
 ENV PATH=$PATH:/root/.cargo/bin
+EXPOSE 5173
 CMD run-development
diff --git a/lib/philomena_web/plugs/content_security_policy_plug.ex b/lib/philomena_web/plugs/content_security_policy_plug.ex
index 58a18ac2..d85b1046 100644
--- a/lib/philomena_web/plugs/content_security_policy_plug.ex
+++ b/lib/philomena_web/plugs/content_security_policy_plug.ex
@@ -24,8 +24,9 @@ defmodule PhilomenaWeb.ContentSecurityPolicyPlug do
 
       csp_config = [
         {:default_src, ["'self'"]},
-        {:script_src, ["'self'" | script_src]},
-        {:style_src, ["'self'" | style_src]},
+        {:script_src, ["'self' localhost:5173" | script_src]},
+        {:connect_src, ["'self' ws://localhost:5173 localhost:5173"]},
+        {:style_src, ["'self' 'unsafe-inline'" | style_src]},
         {:object_src, ["'none'"]},
         {:frame_ancestors, ["'none'"]},
         {:frame_src, frame_src || ["'none'"]},
diff --git a/lib/philomena_web/templates/layout/app.html.slime b/lib/philomena_web/templates/layout/app.html.slime
index be918a5e..58ebd057 100644
--- a/lib/philomena_web/templates/layout/app.html.slime
+++ b/lib/philomena_web/templates/layout/app.html.slime
@@ -10,18 +10,23 @@ html lang="en"
         ' - Derpibooru
       - else
         ' Derpibooru
-    link rel="stylesheet" href=stylesheet_path(@conn, @current_user)
-    = if is_nil(@current_user) do
-      link rel="stylesheet" href=dark_stylesheet_path(@conn) media="(prefers-color-scheme: dark)"
     link rel="icon" href="/favicon.ico" type="image/x-icon"
     link rel="icon" href="/favicon.svg" type="image/svg+xml"
     meta name="generator" content="philomena"
     meta name="theme-color" content="#618fc3"
     meta name="format-detection" content="telephone=no"
     = csrf_meta_tag()
-    script type="module" src=Routes.static_path(@conn, "/js/app.js") async="async"
+
+    = if vite_reload?() do
+      script type="module" src="http://localhost:5173/@vite/client"
+      script type="module" src="http://localhost:5173/js/app.js"
+    - else
+      link rel="stylesheet" href=stylesheet_path(@conn, @current_user)
+      = if is_nil(@current_user) do
+        link rel="stylesheet" href=dark_stylesheet_path(@conn) media="(prefers-color-scheme: dark)"
+      script type="text/javascript" src=Routes.static_path(@conn, "/js/app.js") async="async"
     = render PhilomenaWeb.LayoutView, "_opengraph.html", assigns
-  body data-theme=theme_name(@current_user)
+  body data-theme=theme_name(@current_user) data-vite-reload=to_string(vite_reload?())
     = render PhilomenaWeb.LayoutView, "_burger.html", assigns
     #container class=container_class(@current_user)
       = render PhilomenaWeb.LayoutView, "_header.html", assigns
diff --git a/lib/philomena_web/views/layout_view.ex b/lib/philomena_web/views/layout_view.ex
index 261bb571..3ea772a7 100644
--- a/lib/philomena_web/views/layout_view.ex
+++ b/lib/philomena_web/views/layout_view.ex
@@ -22,6 +22,10 @@ defmodule PhilomenaWeb.LayoutView do
     Application.get_env(:philomena, :cdn_host)
   end
 
+  def vite_reload? do
+    Application.get_env(:philomena, :vite_reload)
+  end
+
   defp ignored_tag_list(nil), do: []
   defp ignored_tag_list([]), do: []
   defp ignored_tag_list([{tag, _body, _dnp_entries}]), do: [tag.id]