Sync text zoom preference through the account instead of local settings

Local user://settings.cfg meant zoom level didn't follow a student
across devices/browsers. Question bank and CCS text scale now live on
the user's study profile in Mongo (QuestionTextScale/CcsTextScale),
synced through a new PUT /api/profile/me/text-scale endpoint and the
existing preferences GET/cache already used for study preferences.

Both question_player.gd and ccs_service.gd read the synced value at
startup and react to AccountProfileService.profile_changed so a value
pulled down after login (or changed from another session) applies
without a restart. Backend validates the 0.85-1.35 range and updates
only the field(s) provided via a targeted $set, so it can't clobber
the other scale or the unrelated study-profile preferences.
This commit is contained in:
hz
2026-07-23 03:59:02 -05:00
parent b88f38f29b
commit d69a1fd0e3
10 changed files with 124 additions and 36 deletions
@@ -13,6 +13,8 @@ public sealed class UserStudyProfile
public string PreparationStage { get; set; } = "pre_dedicated";
public int WeeklyGoalHours { get; set; } = 10;
public string PreferredStudyMode { get; set; } = "mixed";
public double QuestionTextScale { get; set; } = 1.0;
public double CcsTextScale { get; set; } = 1.0;
public int Revision { get; set; }
public DateTime UpdatedUtc { get; set; } = DateTime.UtcNow;
}
@@ -25,6 +27,12 @@ public sealed class UpdateUserStudyProfileRequest
public string PreferredStudyMode { get; set; } = "mixed";
}
public sealed class UpdateTextScaleRequest
{
public double? QuestionTextScale { get; set; }
public double? CcsTextScale { get; set; }
}
public sealed class DeletedUserTombstone
{
[BsonId]
@@ -48,3 +56,18 @@ public static class UserStudyProfileValidator
return null;
}
}
public static class UpdateTextScaleRequestValidator
{
private const double Min = 0.85;
private const double Max = 1.35;
public static string? Validate(UpdateTextScaleRequest request)
{
if (request.QuestionTextScale is { } questionScale && (questionScale < Min || questionScale > Max))
return "Question text scale must be between 0.85 and 1.35.";
if (request.CcsTextScale is { } ccsScale && (ccsScale < Min || ccsScale > Max))
return "CCS text scale must be between 0.85 and 1.35.";
return null;
}
}