static fe: proof of concept
authorWilliam Pitcock <nenolod@dereferenced.org>
Sat, 2 Mar 2019 14:17:55 +0000 (14:17 +0000)
committerPhil Hagelberg <phil@hagelb.org>
Sun, 10 Nov 2019 02:06:51 +0000 (18:06 -0800)
lib/pleroma/web/static_fe/static_fe_controller.ex [new file with mode: 0644]
lib/pleroma/web/static_fe/static_fe_view.ex [new file with mode: 0644]
lib/pleroma/web/templates/layout/static_fe.html.eex [new file with mode: 0644]
lib/pleroma/web/templates/static_fe/static_fe/notice.html.eex [new file with mode: 0644]
lib/pleroma/web/templates/static_fe/static_fe/user_card.html.eex [new file with mode: 0644]

diff --git a/lib/pleroma/web/static_fe/static_fe_controller.ex b/lib/pleroma/web/static_fe/static_fe_controller.ex
new file mode 100644 (file)
index 0000000..067af98
--- /dev/null
@@ -0,0 +1,42 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.StaticFE.StaticFEController do
+  use Pleroma.Web, :controller
+
+  alias Pleroma.Repo
+  alias Pleroma.Activity
+  alias Pleroma.Object
+  alias Pleroma.User
+  alias Pleroma.Web.ActivityPub.Visibility
+
+  require Logger
+
+  def show_notice(conn, %{"notice_id" => notice_id}) do
+    with %Activity{} = activity <- Repo.get(Activity, notice_id),
+         true <- Visibility.is_public?(activity),
+         %User{} = user <- User.get_or_fetch(activity.data["actor"]),
+         %Object{} = object <- Object.normalize(activity.data["object"]) do
+      conn
+      |> put_layout(:static_fe)
+      |> put_status(200)
+      |> put_view(Pleroma.Web.StaticFE.StaticFEView)
+      |> render("notice.html", %{notice: activity, object: object, user: user})
+    else
+      _ ->
+        conn
+        |> put_status(404)
+        |> text("Not found")
+    end
+  end
+
+  def show(%{path_info: ["notice", notice_id]} = conn, _params), do: show_notice(conn, %{"notice_id" => notice_id})
+
+  # Fallback for unhandled types
+  def show(conn, _params) do
+    conn
+    |> put_status(404)
+    |> text("Not found")
+  end
+end
diff --git a/lib/pleroma/web/static_fe/static_fe_view.ex b/lib/pleroma/web/static_fe/static_fe_view.ex
new file mode 100644 (file)
index 0000000..7f58e1b
--- /dev/null
@@ -0,0 +1,19 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.StaticFE.StaticFEView do
+  use Pleroma.Web, :view
+
+  alias Pleroma.User
+  alias Pleroma.Web.MediaProxy
+  alias Pleroma.Formatter
+
+  def emoji_for_user(%User{} = user) do
+    (user.info.source_data["tag"] || [])
+    |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
+    |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
+      {String.trim(name, ":"), url}
+    end)
+  end
+end
diff --git a/lib/pleroma/web/templates/layout/static_fe.html.eex b/lib/pleroma/web/templates/layout/static_fe.html.eex
new file mode 100644 (file)
index 0000000..c209581
--- /dev/null
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width,initial-scale=1,minimal-ui" />
+    <title>
+    <%= Application.get_env(:pleroma, :instance)[:name] %>
+    </title>
+    <style>
+      body {
+        background-color: #282c37;
+        font-family: sans-serif;
+        color: white;
+      }
+
+      .container {
+        margin: 50px auto;
+        max-width: 960px;
+        padding: 0;
+        padding: 40px 40px 40px 40px;
+        background-color: #313543;
+        border-radius: 4px;
+      }
+
+      .avatar {
+        cursor: pointer;
+      }
+
+      .avatar img {
+        float: left;
+        border-radius: 4px;
+        margin-right: 4px;
+      }
+
+      a {
+        color: white;
+      }
+
+      .h-card {
+        min-height: 48px;
+        margin-bottom: 8px;
+      }
+
+      .h-card a {
+        text-decoration: none;
+      }
+
+      .h-card a:hover {
+        text-decoration: underline;
+      }
+
+      .display-name {
+        padding-top: 4px;
+        display: block;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        color: white;
+      }
+
+      .display-name .nickname {
+        padding-top: 4px;
+        display: block;
+      }
+
+      .nickname:hover {
+        text-decoration: none;
+      }
+
+      h1 {
+        margin: 0;
+      }
+
+      h2 {
+        color: #9baec8;
+        font-weight: normal;
+        font-size: 20px;
+        margin-bottom: 40px;
+      }
+
+      form {
+        width: 100%;
+      }
+
+      input {
+        box-sizing: border-box;
+        width: 100%;
+        padding: 10px;
+        margin-top: 20px;
+        background-color: rgba(0,0,0,.1);
+        color: white;
+        border: 0;
+        border-bottom: 2px solid #9baec8;
+        font-size: 14px;
+      }
+
+      input:focus {
+        border-bottom: 2px solid #4b8ed8;
+      }
+
+      input[type="checkbox"] {
+        width: auto;
+      }
+
+      button {
+        box-sizing: border-box;
+        width: 100%;
+        color: white;
+        background-color: #419bdd;
+        border-radius: 4px;
+        border: none;
+        padding: 10px;
+        margin-top: 30px;
+        text-transform: uppercase;
+        font-weight: 500;
+        font-size: 16px;
+      }
+
+      .alert-danger {
+        box-sizing: border-box;
+        width: 100%;
+        color: #D8000C;
+        background-color: #FFD2D2;
+        border-radius: 4px;
+        border: none;
+        padding: 10px;
+        margin-top: 20px;
+        font-weight: 500;
+        font-size: 16px;
+      }
+
+      .alert-info {
+        box-sizing: border-box;
+        width: 100%;
+        color: #00529B;
+        background-color: #BDE5F8;
+        border-radius: 4px;
+        border: none;
+        padding: 10px;
+        margin-top: 20px;
+        font-weight: 500;
+        font-size: 16px;
+      }
+    </style>
+  </head>
+  <body>
+    <div class="container">
+      <%= render @view_module, @view_template, assigns %>
+    </div>
+  </body>
+</html>
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/notice.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/notice.html.eex
new file mode 100644 (file)
index 0000000..9957697
--- /dev/null
@@ -0,0 +1,6 @@
+<div class="activity">
+  <%= render("user_card.html", %{user: @user}) %>
+  <div class="activity-content">
+    <div class="e-content"><%= @object.data["content"] %></div>
+  </div>
+</div>
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/user_card.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/user_card.html.eex
new file mode 100644 (file)
index 0000000..8b397c6
--- /dev/null
@@ -0,0 +1,11 @@
+<div class="p-author h-card">
+  <a class="u-url" rel="author noopener" href="<%= User.profile_url(@user) %>">
+    <div class="avatar">
+      <img src="<%= User.avatar_url(@user) |> MediaProxy.url %>" width="48" height="48" alt="">
+    </div>
+    <span class="display-name">
+      <bdi><%= @user.name |> Formatter.emojify(emoji_for_user(@user)) %></bdi>
+      <span class="nickname"><%= @user.nickname %></span>
+    </span>
+  </a>
+</div>