Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
3676362
Add front page and clarify loading message
raphaelscholle Aug 21, 2025
d090bf3
Merge pull request #21 from OpenHD/codex/add-frontpage-and-loading-ex…
raphaelscholle Aug 21, 2025
1e62293
test: restore app component spec
raphaelscholle Aug 21, 2025
ae09182
Revert "Add front page and clarify loading message"
raphaelscholle Aug 21, 2025
c9236e8
Merge pull request #22 from OpenHD/codex/add-frontpage-and-loading-ex…
raphaelscholle Aug 21, 2025
62e250e
Update nav-menu.component.html
raphaelscholle Aug 21, 2025
daccb2e
Add settings page and theme support
raphaelscholle Aug 21, 2025
de93a4d
Merge pull request #24 from OpenHD/codex/adjust-colorscheme-and-desig…
raphaelscholle Aug 21, 2025
d643335
Update favicon.ico
raphaelscholle Aug 21, 2025
3c6271c
TESTING
raphaelscholle Aug 22, 2025
b221951
logo tests
raphaelscholle Aug 22, 2025
cfc094a
Update nav-menu.component.css
raphaelscholle Aug 22, 2025
171610f
Update styles.css
raphaelscholle Aug 22, 2025
cccd0c6
Add dark mode switch and center layout
raphaelscholle Aug 22, 2025
3176eea
Merge pull request #25 from OpenHD/codex/add-dark-mode-features-and-s…
raphaelscholle Aug 22, 2025
08aa80d
Update nav-menu.component.html
raphaelscholle Aug 22, 2025
f4d7a8e
Default to dark theme and expand layout width
raphaelscholle Aug 22, 2025
b68d2c9
Merge pull request #26 from OpenHD/codex/make-dark-mode-default-and-a…
raphaelscholle Aug 22, 2025
a248a13
a few more styling changes
raphaelscholle Aug 22, 2025
1b826f9
feat: redesign frontpage
raphaelscholle Aug 22, 2025
be2d819
Merge branch 'master' into codex/set-body-background-color-to-pink-in…
raphaelscholle Aug 22, 2025
5f92b7e
Merge pull request #27 from OpenHD/codex/set-body-background-color-to…
raphaelscholle Aug 22, 2025
b750b7d
look and feel
raphaelscholle Aug 22, 2025
e6abc29
feat(theme): expand dark skin variables
raphaelscholle Aug 22, 2025
8b925cb
Merge pull request #28 from OpenHD/codex/add-text-color-variables-for…
raphaelscholle Aug 22, 2025
8c3f5e5
mods
raphaelscholle Aug 22, 2025
5681f2e
feat: use theme-aware text colors
raphaelscholle Aug 22, 2025
9ded03f
Merge pull request #30 from OpenHD/codex/add-dark-theme-styles-for-h3…
raphaelscholle Aug 22, 2025
96e1b85
feat: add terminal and material system page
raphaelscholle Aug 22, 2025
aaf51c9
Merge pull request #31 from OpenHD/codex/improve-system-app-with-mate…
raphaelscholle Aug 22, 2025
27ba532
Update global.json
raphaelscholle Aug 22, 2025
eaf8852
fix: clean up system terminal integration
raphaelscholle Aug 22, 2025
7af426a
Merge pull request #32 from OpenHD/codex/improve-system-app-with-mate…
raphaelscholle Aug 22, 2025
71cdd54
Update angular.json
raphaelscholle Aug 22, 2025
60855c9
Update control.template
raphaelscholle Aug 23, 2025
a458c00
Update styles.css
raphaelscholle Aug 23, 2025
50af9c0
styling
raphaelscholle Aug 23, 2025
9860cd7
refactor login and toggle terminal
raphaelscholle Aug 23, 2025
23546b7
Merge pull request #33 from OpenHD/codex/remove-login-sidebar-and-add…
raphaelscholle Aug 23, 2025
c9bb76f
Redesign system page layout
raphaelscholle Aug 23, 2025
70fd465
Merge pull request #35 from OpenHD/codex/redesign-system-page-layout
raphaelscholle Aug 23, 2025
6811590
feat(settings): add network interface management
raphaelscholle Aug 23, 2025
35fd08a
Merge pull request #36 from OpenHD/codex/add-wifi-and-ethernet-settin…
raphaelscholle Aug 23, 2025
c7567de
Revert "Update global.json"
raphaelscholle Aug 23, 2025
d587a0c
Revert "Merge pull request #36 from OpenHD/codex/add-wifi-and-etherne…
raphaelscholle Aug 23, 2025
a745170
Reapply "Merge pull request #36 from OpenHD/codex/add-wifi-and-ethern…
raphaelscholle Aug 23, 2025
f289910
Update global.json
raphaelscholle Sep 14, 2025
4836cb5
feat: add OpenHD settings editor
raphaelscholle Sep 26, 2025
b877c94
Merge pull request #39 from OpenHD/codex/improve-settings-menu-to-edi…
raphaelscholle Sep 26, 2025
454adae
Update Build.cs
raphaelscholle Sep 26, 2025
96b02cd
Refine network settings presentation
raphaelscholle Sep 26, 2025
9adb53d
Merge pull request #42 from OpenHD/codex/improve-design-and-readabili…
raphaelscholle Sep 26, 2025
fe0bb28
Upload deb artifacts even on Cloudsmith failure
raphaelscholle Sep 26, 2025
b0caefb
Merge pull request #43 from OpenHD/codex/modify-runner-to-upload-deb-…
raphaelscholle Sep 26, 2025
d8f205b
Improve settings JSON discovery and validation
raphaelscholle Sep 26, 2025
bb6ae9e
Merge pull request #44 from OpenHD/codex/fix-json-settings-reading-an…
raphaelscholle Sep 26, 2025
ecd9f08
feat: improve desktop responsiveness
raphaelscholle Sep 26, 2025
2d9eaf1
Merge pull request #45 from OpenHD/codex/update-design-for-responsive…
raphaelscholle Sep 26, 2025
3ccd29a
Revert "feat: improve desktop responsiveness"
raphaelscholle Sep 26, 2025
8d0a302
Add interactive controls to settings editor
raphaelscholle Sep 26, 2025
cec943b
Merge pull request #46 from OpenHD/codex/enhance-settings-menu-for-be…
raphaelscholle Sep 26, 2025
1df138c
Fix Angular build issues and capture CI logs
raphaelscholle Sep 26, 2025
9261baa
Merge pull request #47 from OpenHD/codex/fix-build-and-upload-error-log
raphaelscholle Sep 26, 2025
b9f9f19
Add docs fallback to local mirror
raphaelscholle Sep 26, 2025
1474860
Make dark theme settings headers white
raphaelscholle Sep 27, 2025
98d2253
Merge pull request #57 from OpenHD/codex/add-text-colors-for-dark-and…
raphaelscholle Sep 27, 2025
3173c90
Adjust dark theme text colors for toggles
raphaelscholle Sep 27, 2025
085c740
Merge pull request #58 from OpenHD/codex/set-toggle-field-title-file-…
raphaelscholle Sep 27, 2025
23ab64e
Update README.md
raphaelscholle Jan 7, 2026
4db6439
status page
raphaelscholle Jan 7, 2026
c2db830
remove home screen replace with status
raphaelscholle Jan 7, 2026
ed4dd7e
improve status and terminal
raphaelscholle Jan 7, 2026
89f5fe9
Merge branch 'master' into development
raphaelscholle Jan 7, 2026
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
4 changes: 2 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
*.sh text=auto eol=lf # linux line-endings
postinst text=auto eol=lf # linux line-endings
*.sh text=auto eol=lf
postinst text=auto eol=lf
###############################################################################
# Set default behavior for command prompt diff.
#
Expand Down
18 changes: 17 additions & 1 deletion .github/workflows/continuous.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ jobs:
~/.nuget/packages
key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj', '**/Directory.Packages.props') }}
- name: 'Run: Clean, CloudsmithPublish'
run: ./build.cmd Clean CloudsmithPublish
run: |
set -o pipefail
./build.cmd Clean CloudsmithPublish 2>&1 | tee build.log
env:
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
- name: 'Upload build log'
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: build-log
path: build.log
if-no-files-found: warn
- name: 'Upload deb artifacts'
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: deb-packages
path: out/deb/*.deb
if-no-files-found: warn
2 changes: 1 addition & 1 deletion build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public Build()

IReadOnlyCollection<string> Rids;

const string PackageName = "open-hd-web-ui";
const string PackageName = "openhd-web-ui";

protected override void OnBuildInitialized()
{
Expand Down
2 changes: 1 addition & 1 deletion control.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ Priority: optional
Architecture: {{architecture}}
Maintainer: Roman Buldygin <froooks@gmail.com>
Description: Web UI for OpenHD
Depends: libgcc1, libicu | libicu72 | libicu71 | libicu70 | libicu69 | libicu68 | libicu67 | libicu66 | libicu65 | libicu63 | libicu60 | libicu57 | libicu55 | libicu52, libc6, libssl1.0.0 | libssl1.0.2 | libssl1.1 | libssl3, zlib1g, libstdc++6, libgssapi-krb5-2
Depends: libgcc1, libicu | libicu74 | libicu72 | libicu71 | libicu70 | libicu69 | libicu68 | libicu67 | libicu66 | libicu65 | libicu63 | libicu60 | libicu57 | libicu55 | libicu52, libc6, libssl1.0.0 | libssl1.0.2 | libssl1.1 | libssl3, zlib1g, libstdc++6, libgssapi-krb5-2
Binary file added example.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "9.0.200"
"version": "9.0.201"
}
}
2 changes: 2 additions & 0 deletions src/OpenHdWebUi.Server/Configuration/ServiceConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class ServiceConfiguration

public List<SystemFileConfiguration> SystemFiles { get; set; }

public List<string> SettingsDirectories { get; set; }

public UpdateFileConfiguration UpdateConfig { get; set; }
}

Expand Down
63 changes: 63 additions & 0 deletions src/OpenHdWebUi.Server/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Mvc;
using OpenHdWebUi.Server.Models;

namespace OpenHdWebUi.Server.Controllers;

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
[HttpPost("login")]
public IActionResult Login([FromBody] LoginRequest request)
{
if (LinuxPasswordValidator.Validate(request.Username, request.Password))
{
return Ok();
}

return Unauthorized();
}
}

static class LinuxPasswordValidator
{
[DllImport("libc", SetLastError = true)]
private static extern IntPtr crypt(string key, string salt);

public static bool Validate(string username, string password)
{
try
{
foreach (var line in System.IO.File.ReadLines("/etc/shadow"))
{
if (!line.StartsWith(username + ":", StringComparison.Ordinal))
{
continue;
}

var parts = line.Split(':');
var hash = parts.Length > 1 ? parts[1] : string.Empty;
if (string.IsNullOrEmpty(hash) || hash == "!" || hash == "*")
{
return false;
}

var ptr = crypt(password, hash);
if (ptr == IntPtr.Zero)
{
return false;
}

var result = Marshal.PtrToStringAnsi(ptr);
return string.Equals(result, hash, StringComparison.Ordinal);
}
}
catch
{
// ignored
}

return false;
}
}
54 changes: 54 additions & 0 deletions src/OpenHdWebUi.Server/Controllers/DocsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Mvc;

namespace OpenHdWebUi.Server.Controllers;

[ApiController]
[Route("api/[controller]")]
public class DocsController : ControllerBase
{
private const string RemoteDocsUrl = "https://openhdfpv.org/introduction/";
private const string LocalDocsPath = "/docs/introduction/index.html";

private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<DocsController> _logger;

public DocsController(IHttpClientFactory httpClientFactory, ILogger<DocsController> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}

[HttpGet("link")]
public async Task<ActionResult<DocsLinkResponse>> GetDocsLink(CancellationToken cancellationToken)
{
if (await RemoteDocsReachable(cancellationToken))
{
return Ok(new DocsLinkResponse(RemoteDocsUrl));
}

return Ok(new DocsLinkResponse(LocalDocsPath));
}

private async Task<bool> RemoteDocsReachable(CancellationToken cancellationToken)
{
try
{
var client = _httpClientFactory.CreateClient();
client.Timeout = TimeSpan.FromSeconds(5);

using var request = new HttpRequestMessage(HttpMethod.Head, RemoteDocsUrl);
request.Headers.UserAgent.Add(new ProductInfoHeaderValue("OpenHdWebUi", "1.0"));

using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
return response.IsSuccessStatusCode;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Unable to reach remote documentation at {RemoteDocsUrl}", RemoteDocsUrl);
return false;
}
}

public record DocsLinkResponse(string Url);
}
31 changes: 31 additions & 0 deletions src/OpenHdWebUi.Server/Controllers/NetworkController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.AspNetCore.Mvc;
using OpenHdWebUi.Server.Models;
using OpenHdWebUi.Server.Services.Network;
using System.Threading.Tasks;

namespace OpenHdWebUi.Server.Controllers;

[ApiController]
[Route("api/[controller]")]
public class NetworkController : ControllerBase
{
private readonly NetworkInfoService _service;

public NetworkController(NetworkInfoService service)
{
_service = service;
}

[HttpGet("info")]
public NetworkInfoDto GetInfo()
{
return _service.GetNetworkInfo();
}

[HttpPost("ethernet")]
public async Task<IActionResult> SetEthernet([FromBody] SetIpRequest request)
{
await _service.SetEthernetIpAsync(request.Interface, request.Ip, request.Netmask);
return Ok();
}
}
68 changes: 68 additions & 0 deletions src/OpenHdWebUi.Server/Controllers/SettingsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Microsoft.AspNetCore.Mvc;
using OpenHdWebUi.Server.Models;
using OpenHdWebUi.Server.Services.Settings;

namespace OpenHdWebUi.Server.Controllers;

[ApiController]
[Route("api/[controller]")]
public class SettingsController : ControllerBase
{
private readonly SettingsService _settingsService;

public SettingsController(SettingsService settingsService)
{
_settingsService = settingsService;
}

[HttpGet]
public ActionResult<IReadOnlyCollection<SettingFileSummaryDto>> GetSettings()
{
var summaries = _settingsService.GetSettingFiles();
return Ok(summaries);
}

[HttpGet("{id}")]
public ActionResult<SettingFileDto> GetSetting(string id)
{
var file = _settingsService.GetSettingFile(id);
if (file == null)
{
return NotFound();
}

return Ok(file);
}

[HttpPut("{id}")]
public IActionResult UpdateSetting(string id, [FromBody] UpdateSettingFileRequest request)
{
if (request == null)
{
return BadRequest();
}

var updated = _settingsService.TrySaveSettingFile(id, request.Content, out var file, out var notFound, out var invalidJson);
if (!updated)
{
if (notFound)
{
return NotFound();
}

if (invalidJson)
{
return BadRequest("The provided settings file is not valid JSON.");
}

return Problem("Unable to save the requested settings file.");
}

if (file == null)
{
return Problem("Unable to reload the settings file after saving.");
}

return Ok(file);
}
}
29 changes: 29 additions & 0 deletions src/OpenHdWebUi.Server/Controllers/StatusController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Mvc;
using OpenHdWebUi.Server.Models;
using OpenHdWebUi.Server.Services.Status;

namespace OpenHdWebUi.Server.Controllers;

[Route("api/status")]
[ApiController]
public class StatusController : ControllerBase
{
private readonly SysutilStatusService _statusService;

public StatusController(SysutilStatusService statusService)
{
_statusService = statusService;
}

[HttpGet]
public Task<OpenHdStatusDto> GetStatus(CancellationToken cancellationToken)
{
return _statusService.GetStatusAsync(cancellationToken);
}

[HttpGet("stream")]
public Task<OpenHdStatusDto> GetStatusStream([FromQuery] long since, CancellationToken cancellationToken)
{
return _statusService.WaitForStatusChangeAsync(since, cancellationToken);
}
}
23 changes: 21 additions & 2 deletions src/OpenHdWebUi.Server/Controllers/SystemController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using OpenHdWebUi.Server.Models;
using OpenHdWebUi.Server.Services.Commands;
using OpenHdWebUi.Server.Services.Files;
using System.Diagnostics;

namespace OpenHdWebUi.Server.Controllers;

Expand Down Expand Up @@ -44,13 +45,13 @@ public async Task RunCommand([FromBody] RunCommandRequest request)
[HttpGet("get-files")]
public IReadOnlyCollection<SystemFileDto> GetFiles()
{
return _systemFilesService.GetAllCommands()
return _systemFilesService.GetAllFiles()
.Select(c => new SystemFileDto(c.Id, c.DisplayName))
.ToArray();
}

[HttpGet("get-file/{id}")]
public async Task<IActionResult> RunCommand([FromRoute]string id)
public async Task<IActionResult> GetFile([FromRoute] string id)
{
var (found, content) = await _systemFilesService.TryGetFileContentAsync(id);
if (found)
Expand All @@ -60,5 +61,23 @@ public async Task<IActionResult> RunCommand([FromRoute]string id)

return NoContent();
}

[HttpPost("run-terminal")]
public async Task<string> RunTerminal([FromBody] RunTerminalCommandRequest request)
{
var psi = new ProcessStartInfo
{
FileName = "/bin/bash",
ArgumentList = { "-c", request.Command },
RedirectStandardOutput = true,
RedirectStandardError = true
};

using var process = Process.Start(psi);
var output = await process!.StandardOutput.ReadToEndAsync();
var error = await process.StandardError.ReadToEndAsync();
await process.WaitForExitAsync();
return output + error;
}
}

Loading