Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .github/workflows/fcx-web.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: fcx-web

on:
push:
pull_request:

# Cancel superseded runs on the same ref so rapid pushes don't pile up.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
MIX_ENV: test

jobs:
# Formatting is version-independent, so check it once instead of per matrix cell.
lint:
name: Lint
runs-on: ubuntu-latest
env:
ELIXIR_VERSION: "1.15"
OTP_VERSION: "25"
defaults:
run:
working-directory: fcx-web
steps:
- uses: actions/checkout@v6

- name: Set up Elixir / OTP
uses: erlef/setup-beam@v1
with:
otp-version: ${{ env.OTP_VERSION }}
elixir-version: ${{ env.ELIXIR_VERSION }}

- name: Cache deps and _build
uses: actions/cache@v5
with:
path: |
fcx-web/deps
fcx-web/_build
key: ${{ runner.os }}-mix-lint-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('fcx-web/mix.lock') }}
restore-keys: ${{ runner.os }}-mix-lint-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-

- name: Install dependencies
run: mix deps.get

# Compile before format so all dependency apps are loaded.
- name: Compile
run: mix compile

- name: Check formatting
run: mix format --check-formatted

test:
name: fcx-web tests (Elixir ${{ matrix.elixir }} / OTP ${{ matrix.otp }})
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
- elixir: "1.15"
otp: "25"
- elixir: "1.16"
otp: "26"
- elixir: "1.17"
otp: "27"
- elixir: "1.18"
otp: "27"
- elixir: "1.19"
otp: "28"

defaults:
run:
working-directory: fcx-web

steps:
- uses: actions/checkout@v6

- name: Set up Elixir / OTP
uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}

- name: Cache deps and _build
uses: actions/cache@v5
with:
path: |
fcx-web/deps
fcx-web/_build
key: ${{ runner.os }}-mix-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('fcx-web/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-${{ matrix.otp }}-${{ matrix.elixir }}-

- name: Install dependencies
run: mix deps.get

- name: Compile (warnings as errors)
run: mix compile --warnings-as-errors

# SQLite test DB — no database service required.
- name: Run tests
run: mix test
3 changes: 2 additions & 1 deletion fcx-web/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ config :fullcontrol_x,
namespace: FullControlX,
ecto_repos: [FullControlX.Repo],
fcxd_path: "../zig-out/bin/FullControlX",
files_path: "priv/static/assets"
files_path: "priv/static/assets",
start_driver: true

# Configures the endpoint
config :fullcontrol_x, FullControlXWeb.Endpoint,
Expand Down
3 changes: 2 additions & 1 deletion fcx-web/config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Config
# manifest is generated by the `mix phx.digest` task,
# which you should run after static files are built and
# before starting your production server.
config :fullcontrol_x, FullControlXWeb.Endpoint, cache_static_manifest: "priv/static/cache_manifest.json"
config :fullcontrol_x, FullControlXWeb.Endpoint,
cache_static_manifest: "priv/static/cache_manifest.json"

# Do not print debug messages in production
config :logger, level: :info
Expand Down
5 changes: 4 additions & 1 deletion fcx-web/config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ config :fullcontrol_x, FullControlXWeb.Endpoint,
secret_key_base: "EgTKrB+SZcnfHfZUYem501WigH0KvvCe5J6YSP6JfwxM7aKjQ2BQWw2SaCUegyhS",
server: false

# No native fcxd binary in test; don't start the driver.
config :fullcontrol_x, start_driver: false

# Print only warnings and errors during test
config :logger, level: :warn
config :logger, level: :warning

# Initialize plugs at runtime for faster test compilation
config :phoenix, :plug_init_mode, :runtime
37 changes: 23 additions & 14 deletions fcx-web/lib/fullcontrol_x/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,36 @@ defmodule FullControlX.Application do
def start(_type, _args) do
FullControlX.print_connection_qrcode()

children = [
# Start the Ecto repository
FullControlX.Repo,
# Start the Telemetry supervisor
FullControlXWeb.Telemetry,
# Start the PubSub system
{Phoenix.PubSub, name: FullControlX.PubSub},
# Start the Endpoint (http/https)
FullControlXWeb.Endpoint,
# Start a worker by calling: FullControlX.Worker.start_link(arg)
# {FullControlX.Worker, arg}
{FullControlX.Driver,
name: FullControlX.Driver, fcxd_path: Application.get_env(:fullcontrol_x, :fcxd_path)}
]
children =
[
# Start the Ecto repository
FullControlX.Repo,
# Start the Telemetry supervisor
FullControlXWeb.Telemetry,
# Start the PubSub system
{Phoenix.PubSub, name: FullControlX.PubSub},
# Start the Endpoint (http/https)
FullControlXWeb.Endpoint
] ++ driver_children()

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: FullControlX.Supervisor]
Supervisor.start_link(children, opts)
end

# Skip the driver where its native fcxd binary isn't built (e.g. test).
defp driver_children do
if Application.get_env(:fullcontrol_x, :start_driver, true) do
[
{FullControlX.Driver,
name: FullControlX.Driver, fcxd_path: Application.get_env(:fullcontrol_x, :fcxd_path)}
]
else
[]
end
end

# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
@impl true
Expand Down
3 changes: 2 additions & 1 deletion fcx-web/lib/fullcontrol_x_web/commands_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ defmodule FullControlXWeb.CommandsLive do
~H"""
<.header title="FullControlX" />
<div class="grow"></div>

<ul class="flex gap-2 overflow-x-scroll scrollbar-hidden scroll-smooth">
<%= for app <- @apps do %>
<li class={app_class(app)}>
<%= "#{Map.get(app, "localized_name")}" %>
{"#{Map.get(app, "localized_name")}"}
</li>
<% end %>
</ul>
Expand Down
3 changes: 1 addition & 2 deletions fcx-web/lib/fullcontrol_x_web/components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ defmodule FullControlXWeb.Components do
def switch(assigns) do
~H"""
<label class="switch">
<input type="checkbox" checked />
<span class="slider"></span>
<input type="checkbox" checked /> <span class="slider"></span>
</label>
"""
end
Expand Down
28 changes: 23 additions & 5 deletions fcx-web/lib/fullcontrol_x_web/info_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,49 @@ defmodule FullControlXWeb.InfoLive do
<div class="m-auto flex flex-col gap-4 justify-start items-start p-4 max-w-xl">
<div>
<h2>Host</h2>

<div>
<%= for {key, value} <- @info do %>
<div>
<%= "#{key}: #{value}" %>
{"#{key}: #{value}"}
</div>
<% end %>
</div>
</div>

<div>
<h2>URLs</h2>

<ul>
<%= for url <- @urls do %>
<li><a href={url} target="_blank"><%= url %></a></li>
<li><a href={url} target="_blank">{url}</a></li>
<% end %>
</ul>
</div>

<div>
<h2>QR code</h2>
<p><%= @url_in_qrcode %></p>

<p>{@url_in_qrcode}</p>
<img src={@qrcode_svg_url} />
</div>

<div>
<h2>FullControlX</h2>
<p>FullControlX is the official Open Source "spinoff" of the commercial app <a href="https://fullcontrol.cescobaz.com" target="_blank">FullControl</a>.</p>
<p>Developed and maintained by Francesco Burelli. More info at <a href="https://github.com/cescobaz/FullControlX" target="_blank">Github Project Homepage</a>.</p>

<p>
FullControlX is the official Open Source "spinoff" of the commercial app <a
href="https://fullcontrol.cescobaz.com"
target="_blank"
>FullControl</a>.
</p>

<p>
Developed and maintained by Francesco Burelli. More info at <a
href="https://github.com/cescobaz/FullControlX"
target="_blank"
>Github Project Homepage</a>.
</p>
</div>
</div>
"""
Expand Down
3 changes: 3 additions & 0 deletions fcx-web/lib/fullcontrol_x_web/tools_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,19 @@ defmodule FullControlXWeb.ToolsLive do
<._button title={button.title} value={button.value} icon={button.icon} />
<% end %>
</div>

<div class="flex justify-center gap-4">
<%= for button <- @arrows_buttons do %>
<._button title={button.title} value={button.value} icon={button.icon} />
<% end %>
</div>

<div class="flex justify-center gap-4">
<%= for button <- @media_buttons do %>
<._button title={button.title} value={button.value} icon={button.icon} />
<% end %>
</div>

<div class="flex justify-center gap-4">
<%= for button <- @audio_buttons do %>
<._button title={button.title} value={button.value} icon={button.icon} />
Expand Down
14 changes: 13 additions & 1 deletion fcx-web/lib/fullcontrol_x_web/trackpad_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,24 @@ defmodule FullControlXWeb.TrackpadLive do
<div id="placeholder" class="w-full h-full flex flex-col items-center justify-center">
<div class="p-4">
<p><span class="font-semibold">Left click</span>: one tap</p>

<p><span class="font-semibold">Right click</span>: one tap with two fingers</p>

<p><span class="font-semibold">Scroll</span>: drag with two fingers</p>

<p><span class="font-semibold">Drag</span>: one tap and drag or drag with three fingers</p>
</div>
</div>
<div id="trackpad" class="absolute left-0 top-0 h-full w-full" phx-touchstart="touchstart" phx-touchmove="touchmove" phx-touchend="touchend" phx-touchcancel="touchcancel" phx-hook="Trackpad">

<div
id="trackpad"
class="absolute left-0 top-0 h-full w-full"
phx-touchstart="touchstart"
phx-touchmove="touchmove"
phx-touchend="touchend"
phx-touchcancel="touchcancel"
phx-hook="Trackpad"
>
</div>
</div>
"""
Expand Down
2 changes: 1 addition & 1 deletion fcx-web/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule FullControlX.MixProject do
[
app: :fullcontrol_x,
version: "0.1.0",
elixir: "~> 1.14",
elixir: "~> 1.15",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
Expand Down
14 changes: 7 additions & 7 deletions fcx-web/test/fullcontrol_x_web/views/error_view_test.exs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
defmodule FullControlXWeb.ErrorViewTest do
use FullControlXWeb.ConnCase, async: true

# Bring render/3 and render_to_string/3 for testing custom views
import Phoenix.View

test "renders 404.html" do
assert render_to_string(FullControlXWeb.ErrorView, "404.html", []) == "Not Found"
# ErrorView has no templates, so it falls back to template_not_found/2,
# which returns the status message for the requested template.
test "renders the 404 status message" do
assert FullControlXWeb.ErrorView.template_not_found("404.html", %{}) == "Not Found"
end

test "renders 500.html" do
assert render_to_string(FullControlXWeb.ErrorView, "500.html", []) == "Internal Server Error"
test "renders the 500 status message" do
assert FullControlXWeb.ErrorView.template_not_found("500.html", %{}) ==
"Internal Server Error"
end
end