Skip to content

Commit 7a77672

Browse files
authored
Merge pull request #9 from managedcode/codex/remove-obs-go-live-streaming-modules
Codex/remove obs go live streaming modules
2 parents 92fb2b9 + b1e5229 commit 7a77672

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2104
-139
lines changed

AGENTS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,9 @@ Repo-specific design rules:
352352
- CI or deployment work is not done when GitHub Actions is merely green; the deployed GitHub Pages app MUST be opened and verified to boot without shell errors.
353353
- GitHub Pages deployment for `prompter.managed-code.com` MUST serve from the custom-domain root with `<base href="/">`; repo-name path prefixes are forbidden.
354354
- Version text shown in the app must come from automated build or release metadata, never from manually edited About copy.
355-
- The runtime must negotiate browser language from supported cultures and default to English.
356-
- Supported runtime cultures are English, Ukrainian, French, Spanish, Portuguese, and Italian.
355+
- The runtime must negotiate the initial language from the browser's supported cultures, fall back to English when there is no supported match, and persist the user's explicit language choice in user settings for later sessions.
356+
- UI localization in Blazor must use resource-based localization with shared catalogs and named culture constants instead of screen-local hardcoded strings.
357+
- Supported runtime cultures are English, Ukrainian, French, Spanish, Portuguese, Italian, and German.
357358
- Russian must never be added as a supported runtime culture.
358359

359360
### Critical

docs/Architecture.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ flowchart LR
100100
| `Storage` | Browser persistence and cloud transfer orchestration | Keeps scripts and settings local-first while exposing provider-backed import/export | `src/PrompterOne.Shared/Storage`, `src/PrompterOne.Shared/Library/Services/Storage` | browser `IStorage` and VFS registration, authoritative browser repositories for scripts/folders, provider credential persistence, scripts/settings snapshot transfer | routed page layout, teleprompter rendering, video-stream upload workflows |
101101
| `Cross-Tab Messaging` | Same-origin browser runtime coordination | Lets separate WASM tabs coordinate browser-owned state without a backend | `src/PrompterOne.Shared/AppShell/Services`, `src/PrompterOne.Shared/Settings/Services`, `src/PrompterOne.Shared/wwwroot/app` | `BroadcastChannel` bridge, typed envelopes, settings fan-out, same-origin tab sync | server state, cross-origin transport, collaborative editor conflict resolution |
102102
| `Diagnostics` | Error and operation feedback layer | Makes recoverable and fatal issues visible in the shell | `src/PrompterOne.Shared/Diagnostics` | banners, error boundary reporting, operation status wiring | owning business logic of the failing feature |
103-
| `Localization` | Culture and UI text contract | Keeps supported runtime languages consistent and browser-driven | `src/PrompterOne.Shared/Localization`, `src/PrompterOne.Core/Localization` | text catalogs, culture bootstrap, supported culture rules | feature behavior or screen-specific layout ownership |
103+
| `Localization` | Culture and UI text contract | Keeps supported runtime languages consistent, browser-driven, and user-overridable through persisted settings | `src/PrompterOne.Shared/Localization`, `src/PrompterOne.Core/Localization` | shared resource catalogs, startup culture bootstrap, browser-language negotiation, persisted user language override, supported culture rules | feature behavior or screen-specific layout ownership |
104104
| `Workspace` | Active script/session state model | Gives editor, learn, read, and go-live one shared script context | `src/PrompterOne.Core/Workspace` | loaded script state, previews, estimated duration, active session metadata | feature-specific rendering details |
105105
| `Media` | Browser media and scene domain | Models cameras, microphones, transforms, and audio bus state | `src/PrompterOne.Core/Media`, `src/PrompterOne.Shared/Media` | media device models, scene state, browser media interop | routed screen layout ownership |
106106
| `Streaming` | Program capture, transport, and target routing domain | Defines how one composed program feed is described, which source/output modules can attach to it, and which external targets are genuinely reachable without a PrompterOne backend | `src/PrompterOne.Core/Streaming` | program-capture profiles, source/output module contracts, transport connection profiles, downstream target descriptors, routing normalization, standalone transport constraints | Razor UI or page layout concerns |
@@ -397,6 +397,7 @@ If a native embedded browser host returns later, media access must not rely on s
397397
- standalone Blazor WebAssembly host
398398
- serves the app shell and static asset references
399399
- applies browser-language culture selection before the WASM runtime starts rendering routed UI
400+
- falls back to the persisted user language override from typed settings before browser negotiation, with English as the final fallback
400401
- must stay free of server-only runtime dependencies
401402

402403
### `src/PrompterOne.Shared`
@@ -407,7 +408,7 @@ If a native embedded browser host returns later, media access must not rely on s
407408
- exact design shell and imported `design` assets
408409
- shared UI localization catalog for supported browser cultures
409410
- browser interop and app DI wiring
410-
- browser-backed `IUserSettingsStore` wiring for persisted reader, theme, scene, and studio preferences
411+
- browser-backed `IUserSettingsStore` wiring for persisted reader, theme, language, scene, and studio preferences
411412
- dynamic library folder components and folder/document browser storage adapters
412413
- UI diagnostics banner and global error boundary
413414
- debounced editor autosave and body-only TPS source authoring
@@ -547,7 +548,7 @@ flowchart LR
547548
- The runtime must remain backend-free.
548549
- `Go Live` may operate multiple concurrent browser publish transports when the operator explicitly arms them, but every active transport must still consume the same canonical browser-owned program feed.
549550
- `Go Live` must not require any PrompterOne-owned backend, relay, ingest layer, or media server; only third-party browser-facing transport infrastructure is allowed.
550-
- Browser-language localization must default to English and support `en`, `uk`, `fr`, `es`, `pt`, and `it`.
551+
- Browser-language localization must default to English, must allow a persisted user override, and must support `en`, `uk`, `fr`, `es`, `it`, `de`, and `pt`.
551552
- Russian is intentionally unsupported and must fall back to English.
552553
- Visual fidelity should prefer copying the exact design classes and structure over inventing replacements.
553554
- Browser tests require Playwright Chromium to be installed locally.

src/PrompterOne.App/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using Microsoft.AspNetCore.Components.Web;
22
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
3-
using Microsoft.JSInterop;
43
using PrompterOne.App;
54
using PrompterOne.App.Services;
5+
using PrompterOne.Shared.Localization;
66
using PrompterOne.Shared.Services;
77
using PrompterOne.Shared.Settings.Services;
88

@@ -22,5 +22,5 @@
2222
builder.Services.AddPrompterOneShared();
2323

2424
var host = builder.Build();
25-
await BrowserCultureRuntime.ApplyPreferredCultureAsync(host.Services.GetRequiredService<IJSRuntime>());
25+
await host.Services.GetRequiredService<AppCulturePreferenceService>().InitializeAsync();
2626
await host.RunAsync();

src/PrompterOne.App/Services/BrowserCultureRuntime.cs

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/PrompterOne.App/wwwroot/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
1010
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&family=Playfair+Display:ital,wght@0,700;0,800;0,900;1,700;1,800&display=swap" rel="stylesheet" />
1111
<link rel="icon" type="image/png" href="_content/PrompterOne.Shared/favicon.png" />
12+
<script src="_content/PrompterOne.Shared/localization/browser-culture.js"></script>
1213
<script src="_content/PrompterOne.Shared/theme/browser-theme.js"></script>
1314
<link rel="stylesheet" href="_content/PrompterOne.Shared/design/tokens.css" />
1415
<link rel="stylesheet" href="_content/PrompterOne.Shared/design/components.css" />

src/PrompterOne.Core/Localization/AppCultureCatalog.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,45 @@ public static class AppCultureCatalog
99
public const string UkrainianCultureName = "uk";
1010
public const string FrenchCultureName = "fr";
1111
public const string SpanishCultureName = "es";
12+
public const string GermanCultureName = "de";
1213
public const string PortugueseCultureName = "pt";
1314
public const string ItalianCultureName = "it";
1415

1516
private const char CultureSeparator = '-';
1617
private const char AlternateCultureSeparator = '_';
18+
private const string EnglishDisplayName = "English";
19+
private const string FrenchDisplayName = "Français";
20+
private const string GermanDisplayName = "Deutsch";
21+
private const string ItalianDisplayName = "Italiano";
22+
private const string PortugueseDisplayName = "Português";
1723
private const string RussianLanguageName = "ru";
24+
private const string SpanishDisplayName = "Español";
25+
private const string UkrainianDisplayName = "Українська";
26+
27+
private static readonly IReadOnlyList<AppCultureDefinition> SupportedCultureDefinitions =
28+
[
29+
new(EnglishCultureName, EnglishDisplayName),
30+
new(UkrainianCultureName, UkrainianDisplayName),
31+
new(FrenchCultureName, FrenchDisplayName),
32+
new(SpanishCultureName, SpanishDisplayName),
33+
new(ItalianCultureName, ItalianDisplayName),
34+
new(GermanCultureName, GermanDisplayName),
35+
new(PortugueseCultureName, PortugueseDisplayName)
36+
];
1837

1938
private static readonly HashSet<string> SupportedCultures = new(StringComparer.OrdinalIgnoreCase)
2039
{
2140
EnglishCultureName,
2241
UkrainianCultureName,
2342
FrenchCultureName,
2443
SpanishCultureName,
44+
GermanCultureName,
2545
PortugueseCultureName,
2646
ItalianCultureName
2747
};
2848

49+
public static IReadOnlyList<AppCultureDefinition> SupportedCultureDefinitionsInDisplayOrder => SupportedCultureDefinitions;
50+
2951
public static IReadOnlyCollection<string> SupportedCultureNames => SupportedCultures;
3052

3153
public static string ResolvePreferredCulture(IEnumerable<string?> requestedCultures)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace PrompterOne.Core.Localization;
2+
3+
public sealed record AppCultureDefinition(string CultureName, string DisplayName);

src/PrompterOne.Shared/AppShell/Layout/MainLayout.razor.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ namespace PrompterOne.Shared.Layout;
1313
public partial class MainLayout : LayoutComponentBase, IDisposable
1414
{
1515
private const string GoLiveWidgetIdleElapsed = "00:00:00";
16-
private const string GoLiveWidgetLiveStateLabel = "Live";
17-
private const string GoLiveWidgetRecordingStateLabel = "Rec";
18-
private const string GoLiveWidgetStreamingRecordingStateLabel = "Live + Rec";
1916
private const string RouteChangedLogTemplate = "Route changed to {Location}.";
2017

2118
[Inject] private AppBootstrapper Bootstrapper { get; set; } = null!;
@@ -64,9 +61,9 @@ public partial class MainLayout : LayoutComponentBase, IDisposable
6461

6562
private string GoLiveIndicatorCopy => GoLiveIndicatorState switch
6663
{
67-
RecordingStateValue => "Recording active",
68-
StreamingStateValue => "Stream active",
69-
_ => "Ready"
64+
RecordingStateValue => Text(UiTextKey.HeaderGoLiveIndicatorRecording),
65+
StreamingStateValue => Text(UiTextKey.HeaderGoLiveIndicatorStreaming),
66+
_ => Text(UiTextKey.HeaderGoLiveIndicatorReady)
7067
};
7168

7269
private string GoLiveIndicatorState => GoLiveSessionState.IsRecordingActive
@@ -87,9 +84,9 @@ public partial class MainLayout : LayoutComponentBase, IDisposable
8784

8885
private string GoLiveWidgetStateLabel => (GoLiveSessionState.IsStreamActive, GoLiveSessionState.IsRecordingActive) switch
8986
{
90-
(true, true) => GoLiveWidgetStreamingRecordingStateLabel,
91-
(true, false) => GoLiveWidgetLiveStateLabel,
92-
(false, true) => GoLiveWidgetRecordingStateLabel,
87+
(true, true) => Text(UiTextKey.HeaderGoLiveWidgetLiveRecording),
88+
(true, false) => Text(UiTextKey.HeaderGoLiveWidgetLive),
89+
(false, true) => Text(UiTextKey.HeaderGoLiveWidgetRecording),
9390
_ => GoLiveIndicatorCopy
9491
};
9592

src/PrompterOne.Shared/AppShell/Services/PrompterOneServiceCollectionExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using PrompterOne.Core.Services.Rsvp;
1111
using PrompterOne.Core.Services.Streaming;
1212
using PrompterOne.Core.Services.Workspace;
13+
using PrompterOne.Shared.Localization;
1314
using PrompterOne.Shared.Services.Diagnostics;
1415
using PrompterOne.Shared.Services.Editor;
1516
using PrompterOne.Shared.Settings.Services;
@@ -64,6 +65,7 @@ public static IServiceCollection AddPrompterOneShared(this IServiceCollection se
6465
services.AddScoped<BrowserCloudStorageStore>();
6566
services.AddScoped<BrowserFileStorageStore>();
6667
services.AddScoped<BrowserThemeService>();
68+
services.AddScoped<AppCulturePreferenceService>();
6769
services.AddScoped<CloudStorageProviderFactory>();
6870
services.AddScoped<CloudStorageTransferService>();
6971
services.AddScoped<StudioSettingsStore>();

src/PrompterOne.Shared/Contracts/UiTestIds.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ public static class Settings
218218
public const string AboutVersion = "settings-about-version";
219219
public const string AppearancePanel = "settings-appearance-panel";
220220
public const string AiPanel = "settings-ai-panel";
221+
public const string LanguageSelect = "settings-language-select";
221222
public const string CameraFrameRate = "settings-camera-frame-rate";
222223
public const string CameraPreviewCard = "settings-camera-preview-card";
223224
public const string CameraPreviewEmpty = "settings-camera-preview-empty";
@@ -256,6 +257,7 @@ public static class Settings
256257
public const string NoiseSuppression = "settings-noise-suppression";
257258
public const string Page = "settings-page";
258259
public const string PrimaryMic = "settings-primary-mic";
260+
public const string Title = "settings-title";
259261
public const string RecordingAudioBitrate = "settings-recording-audio-bitrate";
260262
public const string RecordingAutoRecord = "settings-recording-auto-record";
261263
public const string RecordingPanel = "settings-recording-panel";

0 commit comments

Comments
 (0)