Source access enforcement (the catalog): 10-source catalog + per-scene access matrix enforced by SceneAccessPolicy; Add-Source menu is one ItemsSource rebuilt per scene (Screen = Live-only, BG/Image/Text every scene), webcam row always present + greys out; Chatbox/Alerts/Socials are inert SourceType rows ready for their features; Text queued as a ship step (countdown + credits modes); Monetization notes socialBar free = YouTube + 1, unlimited with the paid key (79 tests passing)

This commit is contained in:
2026-08-10 12:17:03 -07:00
parent cc3b1c9234
commit ac22b1658f
8 changed files with 236 additions and 25 deletions
+31
View File
@@ -103,6 +103,7 @@ public class MainViewModel : ViewModelBase
public ObservableCollection<Scene> Scenes { get; } = new();
public ObservableCollection<ChatMessage> ChatMessages { get; } = new();
public ObservableCollection<DisplayInfo> Displays { get; } = new();
public ObservableCollection<SourceMenuItem> AddSourceMenuItems { get; } = new();
public string[] Visibilities { get; } = { "Public", "Unlisted", "Private" };
public Scene? ActiveScene
@@ -123,6 +124,7 @@ public class MainViewModel : ViewModelBase
OnPropertyChanged(nameof(CanShowWebcamInActiveScene));
UpdateActiveBackground();
UpdateBackdropImage();
RebuildAddSourceMenu();
}
}
}
@@ -1189,6 +1191,7 @@ public class MainViewModel : ViewModelBase
foreach (SceneElement element in e.OldItems)
element.PropertyChanged -= OnElementPropertyChanged;
OnPropertyChanged(nameof(CanAddWebcamToActiveScene));
RebuildAddSourceMenu();
ScheduleSave();
}
@@ -1245,6 +1248,34 @@ public class MainViewModel : ViewModelBase
ActiveScene = Scenes.FirstOrDefault();
}
// The Add-Source menu lists only what the active scene allows per the access
// matrix (SceneAccessPolicy). The webcam row is always present (webcams are
// allowed in every scene) but greys out once the active scene has one.
private void RebuildAddSourceMenu()
{
AddSourceMenuItems.Clear();
var sceneName = ActiveScene?.Name;
if (sceneName == null) return;
AddSourceMenuItems.Add(new SourceMenuItem(
"Webcam", AddWebcamCommand,
isEnabled: CanAddWebcamToActiveScene,
toolTip: "One webcam at a time — it's already in your stream"));
var menu = new[]
{
(Header: "Screen", Type: SourceType.DisplayCapture, Command: AddSourceCommand),
(Header: "Background", Type: SourceType.Background, Command: AddSourceCommand),
(Header: "Image", Type: SourceType.Image, Command: AddImageCommand),
(Header: "Text", Type: SourceType.TextOverlay, Command: AddSourceCommand),
};
foreach (var (header, type, command) in menu)
{
if (SceneAccessPolicy.Allows(sceneName, type))
AddSourceMenuItems.Add(new SourceMenuItem(header, command, type));
}
}
private void AddSource(object? parameter)
{
var scene = ActiveScene;