Allow changing of the console font (#1277)

* Custom Fonts

* Update app/Filament/Pages/Auth/EditProfile.php

Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com>

* wip

* wip

* Update app/Filament/Pages/Auth/EditProfile.php

Co-authored-by: Lance Pioch <git@lance.sh>

* Update app/helpers.php

Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com>

* update

* add fonts folder for docker

* Add default font

* Update server console to preload the font

* Update settings/trans

---------

Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com>
Co-authored-by: Lance Pioch <git@lance.sh>
This commit is contained in:
Charles 2025-05-01 09:47:59 -04:00 committed by GitHub
parent e354bc9be7
commit 3effd98013
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 79 additions and 26 deletions

1
.gitignore vendored
View File

@ -1,7 +1,6 @@
/.phpunit.cache
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/storage/pail

View File

@ -82,6 +82,7 @@ RUN chown root:www-data ./ \
&& ln -s /pelican-data/database/database.sqlite ./database/database.sqlite \
&& ln -sf /var/www/html/storage/app/public /var/www/html/public/storage \
&& ln -s /pelican-data/storage/avatars /var/www/html/storage/app/public/avatars \
&& ln -s /pelican-data/storage/fonts /var/www/html/storage/app/public/fonts \
# Allow www-data write permissions where necessary
&& chown -R www-data:www-data /pelican-data ./storage ./bootstrap/cache /var/run/supervisord /var/www/html/public/storage \
&& chmod -R u+rwX,g+rwX,o-rwx /pelican-data ./storage ./bootstrap/cache /var/run/supervisord

View File

@ -13,6 +13,7 @@ use Filament\Actions\Action;
use Filament\Forms\Components\Actions;
use Filament\Forms\Components\Actions\Action as FormAction;
use Filament\Forms\Components\Component;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Section;
@ -724,10 +725,17 @@ class Settings extends Page implements HasForms
->onColor('success')
->offColor('danger')
->live()
->columnSpanFull()
->columnSpan(1)
->formatStateUsing(fn ($state): bool => (bool) $state)
->afterStateUpdated(fn ($state, Set $set) => $set('PANEL_EDITABLE_SERVER_DESCRIPTIONS', (bool) $state))
->default(env('PANEL_EDITABLE_SERVER_DESCRIPTIONS', config('panel.editable_server_descriptions'))),
FileUpload::make('ConsoleFonts')
->hint(trans('admin/setting.misc.server.console_font_hint'))
->label(trans('admin/setting.misc.server.console_font_upload'))
->directory('fonts')
->columnSpan(1)
->maxFiles(1)
->preserveFilenames(),
]),
Section::make(trans('admin/setting.misc.webhook.title'))
->description(trans('admin/setting.misc.webhook.helper'))
@ -756,6 +764,7 @@ class Settings extends Page implements HasForms
{
try {
$data = $this->form->getState();
unset($data['ConsoleFonts']);
// Convert bools to a string, so they are correctly written to the .env file
$data = array_map(fn ($value) => is_bool($value) ? ($value ? 'true' : 'false') : $value, $data);

View File

@ -373,10 +373,35 @@ class EditProfile extends BaseEditProfile
->required()
->columnSpan(1)
->default(30),
// Select::make('console_font')
// ->label(trans('profile.font'))
// ->hidden() //TODO
// ->columnSpan(1),
Select::make('console_font')
->label(trans('profile.font'))
->options(fn () => get_fonts(storage_path('app\public\fonts')))
->reactive()
->afterStateUpdated(fn ($state, callable $set) => $set('font_preview', $state)),
Placeholder::make('font_preview')
->label('Preview')
->content(function (Get $get) {
$fontName = $get('console_font') ?? 'No font selected.';
$fontUrl = asset("fonts/{$fontName}.ttf");
$fontSize = $get('console_font_size') . 'px';
return new HtmlString(<<<HTML
<style>
@font-face {
font-family: "CustomPreviewFont";
src: url("$fontUrl");
}
.preview-text {
font-family: "CustomPreviewFont";
font-size: $fontSize;
margin-top: 10px;
display: block;
}
</style>
<span class="preview-text">The quick blue pelican jumps over the lazy pterodactyl. :)</span>
HTML);
}),
TextInput::make('console_font_size')
->label(trans('profile.font_size'))
->columnSpan(1)
@ -446,12 +471,13 @@ class EditProfile extends BaseEditProfile
protected function mutateFormDataBeforeSave(array $data): array
{
$moarbetterdata = [
'console_font' => $data['console_font'],
'console_font_size' => $data['console_font_size'],
'console_rows' => $data['console_rows'],
'dashboard_layout' => $data['dashboard_layout'],
];
unset($data['dashboard_layout'], $data['console_font_size'], $data['console_rows']);
unset($data['console_font'],$data['console_font_size'], $data['console_rows'], $data['dashboard_layout']);
$data['customization'] = json_encode($moarbetterdata);
return $data;
@ -461,6 +487,7 @@ class EditProfile extends BaseEditProfile
{
$moarbetterdata = json_decode($data['customization'], true);
$data['console_font'] = $moarbetterdata['console_font'] ?? 'ComicMono';
$data['console_font_size'] = $moarbetterdata['console_font_size'] ?? 14;
$data['console_rows'] = $moarbetterdata['console_rows'] ?? 30;
$data['dashboard_layout'] = $moarbetterdata['dashboard_layout'] ?? 'grid';

View File

@ -67,3 +67,17 @@ if (!function_exists('resolve_path')) {
return implode('/', $absolutes);
}
}
if (!function_exists('get_fonts')) {
/**
* @return array<string, string>
*/
function get_fonts(?string $directory = null): array
{
$directory ??= public_path('fonts');
return collect(glob($directory . '/*.ttf', GLOB_BRACE) ?: [])
->mapWithKeys(fn ($file) => [$name = pathinfo($file, PATHINFO_FILENAME) => $name])
->all();
}
}

View File

@ -23,7 +23,7 @@ else
echo -e "APP_INSTALLED=false" >> /pelican-data/.env
fi
mkdir -p /pelican-data/database /pelican-data/storage/avatars /var/www/html/storage/logs/supervisord 2>/dev/null
mkdir -p /pelican-data/database /pelican-data/storage/avatars /pelican-data/storage/fonts /var/www/html/storage/logs/supervisord 2>/dev/null
if ! grep -q "APP_KEY=" .env || grep -q "APP_KEY=$" .env; then
echo "Generating APP_KEY..."

View File

@ -137,6 +137,8 @@ return [
'title' => 'Servers',
'helper' => 'Settings for Servers',
'edit_server_desc' => 'Allow Users to edit Descriptions?',
'console_font_upload' => 'Console Font Upload',
'console_font_hint' => 'Only *.ttf fonts are supported. Mono fonts strongly recommended!',
],
'webhook' => [
'title' => 'Webhooks',

View File

@ -48,15 +48,3 @@
::-webkit-scrollbar-corner {
background: transparent;
}
@font-face {
font-family: Comic Mono;
font-weight: normal;
src: url('/fonts/ComicMono.ttf');
}
@font-face {
font-family: Comic Mono;
font-weight: bold;
src: url('/fonts/ComicMono-bold.ttf');
}

Binary file not shown.

View File

@ -1,12 +1,25 @@
<x-filament::widget>
@assets
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm/css/xterm.min.css">
@php
$userFont = auth()->user()->getCustomization()['console_font'] ?? 'ComicMono';
$userFontSize = auth()->user()->getCustomization()['console_font_size'] ?? 14;
$userRows = auth()->user()->getCustomization()['console_rows'] ?? 30;
@endphp
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm/lib/xterm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit/lib/addon-fit.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-web-links/lib/addon-web-links.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-search/lib/addon-search.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-search-bar/lib/xterm-addon-search-bar.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm/css/xterm.min.css">
<link rel="stylesheet" href="{{ asset('/css/filament/server/console.css') }}">
<link rel="preload" href="{{ asset("storage/fonts/{$userFont}.ttf") }}" as="font" crossorigin>
<style>
@font-face {
font-family: '{{ $userFont }}';
src: url('{{ asset("storage/fonts/{$userFont}.ttf") }}');
}
</style>
@endassets
<div id="terminal" wire:ignore></div>
@ -57,14 +70,14 @@
};
let options = {
fontSize: {{ auth()->user()->getCustomization()['console_font_size'] ?? 14 }},
fontFamily: 'Comic Mono, monospace',
fontSize: {{ $userFontSize }},
fontFamily: '{{ $userFont }}',
lineHeight: 1.2,
disableStdin: true,
cursorStyle: 'underline',
cursorInactiveStyle: 'underline',
allowTransparency: true,
rows: {{ auth()->user()->getCustomization()['console_rows'] ?? 30 }},
rows: {{ $userRows }},
theme: theme
};