Add multi-language audio tracks and self-hosted flag-icons
Introduce per-video language support and multiple audio tracks (VideoAudioTrack model + migrations for language, description, title), a reusable language-select component, and a track-editor form. Bundle the self-hosted flag-icons v7.2.3 library and a NAS auto-sync command. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
1 parent
f8d13457fa
commit
66fd78c10f
314 files changed
+16507
-3172
No files matched your search
@@ -1,13 +1,13 @@
|
||||
# Reusable Select Component Usage
|
||||
|
||||
This file tracks every page/partial that uses `<x-phone-code-select>`, `<x-country-select>`, or `<x-timezone-select>`.
|
||||
This file tracks every page/partial that uses `<x-phone-code-select>`, `<x-country-select>`, `<x-timezone-select>`, or `<x-language-select>`.
|
||||
**Update this file whenever you add or remove a component from a view.**
|
||||
|
||||
When modifying any component or its data source (`app/Data/Countries.php`), check all pages in the relevant section below and verify the change works correctly in each context.
|
||||
When modifying any component or its data source, check all pages in the relevant section below and verify the change works correctly in each context.
|
||||
|
||||
---
|
||||
|
||||
## Data source
|
||||
## Data sources
|
||||
|
||||
**`app/Data/Countries.php`** — `App\Data\Countries`
|
||||
|
||||
@@ -20,18 +20,30 @@ When modifying any component or its data source (`app/Data/Countries.php`), chec
|
||||
|
||||
Adding or renaming a field in `Countries::all()` requires updating the corresponding `for*()` method too.
|
||||
|
||||
**`app/Data/Languages.php`** — `App\Data\Languages`
|
||||
|
||||
| Method | Used by component |
|
||||
|---|---|
|
||||
| `Languages::forLanguage()` | `<x-language-select>` |
|
||||
| `Languages::all()` | Via `forLanguage()` |
|
||||
|
||||
Arabic and English are pinned to the top of the list; all others are sorted alphabetically by English name. Stored value is the ISO 639-1 code (e.g. `"ar"`, `"en"`).
|
||||
|
||||
---
|
||||
|
||||
## Shared CSS / JS
|
||||
|
||||
The `.csd-*` CSS rules and the `window.CSD` class are duplicated across all three component files inside `@once` guards. If you change the look or behaviour of the dropdown, **update all three component files**:
|
||||
The `.csd-*` CSS rules and the `window.CSD` class are duplicated across all four component files inside `@once` guards. If you change the look or behaviour of the dropdown, **update all four component files**:
|
||||
|
||||
- `resources/views/components/phone-code-select.blade.php`
|
||||
- `resources/views/components/country-select.blade.php`
|
||||
- `resources/views/components/timezone-select.blade.php`
|
||||
- `resources/views/components/language-select.blade.php`
|
||||
|
||||
The `@once` Blade directive ensures the browser only receives one copy of the CSS/JS even when multiple components are on the same page.
|
||||
|
||||
`language-select` also emits an extra `@once('lsd-badge-styles')` block for the `.lsd-code` ISO badge that appears in place of a flag emoji.
|
||||
|
||||
---
|
||||
|
||||
## `<x-video-insights>`
|
||||
@@ -88,7 +100,7 @@ The `@once` Blade directive ensures the browser only receives one copy of the CS
|
||||
| `resources/views/user/channel.blade.php` | `avatar` — circle 300×300 | Owner only; `update-url = profile.updateAvatar`; callback `onAvatarSaved` |
|
||||
| `resources/views/user/channel.blade.php` | `banner` — square 500×160 | Owner only; `update-url = profile.updateBanner`; callback `onBannerSaved` |
|
||||
| `resources/views/layouts/partials/upload-modal.blade.php` | `thumb_upload` — square 448×252 | Form mode; `target-input=thumbnail-modal`; output 1280px |
|
||||
| `resources/views/layouts/partials/edit-video-modal.blade.php` | `thumb_edit` — square 448×252 | Form mode; `target-input=edit-thumbnail-input`; output 1280px |
|
||||
| `resources/views/layouts/partials/edit-video-modal.blade.php` | `thumb_edit` — square 448×252 | Form mode; `target-input=edit-t1-thumbnail-input`; output 1280px |
|
||||
| `resources/views/videos/create.blade.php` | `thumb_create_mobile` — square 448×252 | Mobile; `target-input=thumbnail`; output 1280px |
|
||||
| `resources/views/videos/edit.blade.php` | `thumb_edit_mobile` — square 448×252 | Mobile; `target-input=edit-thumbnail`; output 1280px |
|
||||
| `resources/views/playlists/index.blade.php` | `thumb_pl_create` — square 448×252 | Form mode; `target-input=playlist-thumbnail-input`; output 1280px |
|
||||
@@ -140,6 +152,38 @@ Stored value: IANA timezone string (e.g. `"Asia/Bahrain"`).
|
||||
|
||||
---
|
||||
|
||||
## `<x-track-editor-form>`
|
||||
|
||||
**File:** `resources/views/components/track-editor-form.blade.php`
|
||||
**Props:** `prefix` (default `'t1'`), `isPrimary` (bool, default `false`), `languageName`, `languageId`, `titleName`, `titleId`, `descName`, `descId`, `videoFileInputId`.
|
||||
**Behaviour:** Renders the full track editor form panel shown inside the Track Editor popup. Contains: optional Primary Track banner (when `:is-primary="true"`), language dropdown (`<x-language-select>`), title input, description textarea, video+thumbnail zone (hidden, shown for video/match type via `_editApplyMode`), and audio+slides zone (hidden, shown for music type). All element IDs are prefixed with `edit-{prefix}-*`. JS functions `editHandleThumbnail(input, prefix)`, `editRemoveThumbnail(event, prefix)`, `editSlidesZoneClick(event, tid)`, `editHandleSlides(files, tid)`, `editClearSlides(event, tid)` all accept the prefix/tid param.
|
||||
|
||||
| View file | Prefix used | Notes |
|
||||
|---|---|---|
|
||||
| `resources/views/layouts/partials/edit-video-modal.blade.php` | `t1` | Primary track only; secondary tracks are built via JS (`_editAddExistingTrack`) |
|
||||
|
||||
---
|
||||
|
||||
## `<x-language-select>`
|
||||
|
||||
**File:** `resources/views/components/language-select.blade.php`
|
||||
**Data source:** `app/Data/Languages.php` — `Languages::forLanguage()`
|
||||
**Stored value:** ISO 639-1 code (e.g. `"ar"`, `"en"`, `"fr"`).
|
||||
**Props:** `name`, `id`, `value`, `label`, `placeholder`, `required`, `class`, `style`.
|
||||
**Icon:** 2-letter uppercase ISO code rendered as a monospace badge (`.lsd-code`) — no flag emoji.
|
||||
**Arabic and English are always pinned to the top** of the list; all other languages are alphabetical by English name.
|
||||
|
||||
**Rule:** This component must be used for every language picker in the application. Never build a custom `<select>` or inline list for language selection.
|
||||
|
||||
| View file | Field name | Notes |
|
||||
|---|---|---|
|
||||
| `resources/views/layouts/partials/upload-modal.blade.php` | `primary_language` | Inside accordion track 1 body (`id="lang-tracks-section-modal"`); extra track language rows use `LANG_OPTIONS_MODAL` JS constant for inline dynamic CSD |
|
||||
| `resources/views/videos/create.blade.php` | `primary_language` | Inside accordion track 1 body (`id="lang-tracks-section-create"`); extra track language rows use `LANG_OPTIONS_CREATE` JS constant for inline dynamic CSD |
|
||||
| `resources/views/components/track-editor-form.blade.php` | `$languageName` (prop) | Rendered inside the track editor form; used for primary track in edit-video-modal (prefix `t1`) |
|
||||
| `resources/views/videos/edit.blade.php` | `primary_language` | Inside `@else` (audio only) block; pre-populated with `value="{{ $video->language ?? '' }}"` |
|
||||
|
||||
---
|
||||
|
||||
## Usage example
|
||||
|
||||
```blade
|
||||
@@ -171,6 +215,15 @@ Stored value: IANA timezone string (e.g. `"Asia/Bahrain"`).
|
||||
value="{{ old('timezone', $user->timezone ?? 'Asia/Bahrain') }}"
|
||||
required
|
||||
/>
|
||||
|
||||
{{-- Language --}}
|
||||
<x-language-select
|
||||
name="language"
|
||||
label="Language"
|
||||
placeholder="Select language"
|
||||
value="{{ old('language', $video->language ?? '') }}"
|
||||
required
|
||||
/>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in new issue
Block a user