feat(privacy): add personalized ads toggle in settings

- Add PrivacySettings schema with can_sell field (default: false)
- Move privacy toggle to GeneralSettingsScreen with clear labeling
- Update l10n for zh/en/zh_hant with user-friendly copy
- Clean up redundant PrivacyNotificationSettingsScreen
- Update profile-protocol.md to reflect new privacy schema
- Fix basedpyright warnings in user.py
This commit is contained in:
qzl
2026-04-17 13:11:09 +08:00
parent be30eb6eab
commit 913ed26f8d
17 changed files with 417 additions and 163 deletions
+15 -4
View File
@@ -27,7 +27,7 @@ class PreferenceSettings(BaseModel):
@classmethod
def validate_timezone(cls, value: str) -> str:
try:
ZoneInfo(value)
_ = ZoneInfo(value)
except ZoneInfoNotFoundError as exc:
raise ValueError("timezone must be a valid IANA timezone") from exc
return value
@@ -52,10 +52,15 @@ class DivinationTutorialSettings(BaseModel):
manual_divination_shown: bool = False
class PrivacySettings(BaseModel):
can_sell: bool = False
profile_visibility: str = "public"
class ProfileSettingsV1(BaseModel):
version: Literal[1] = 1
preferences: PreferenceSettings = Field(default_factory=PreferenceSettings)
privacy: dict[str, object] = Field(default_factory=dict)
privacy: PrivacySettings = Field(default_factory=PrivacySettings)
notification: NotificationSettings = Field(default_factory=NotificationSettings)
divination_tutorial: DivinationTutorialSettings = Field(
default_factory=DivinationTutorialSettings
@@ -67,7 +72,13 @@ ProfileSettingsUnion = ProfileSettingsV1
def parse_profile_settings(raw: dict[str, object] | None) -> ProfileSettingsUnion:
payload = dict(raw or {})
payload.setdefault("version", 1)
_ = payload.setdefault("version", 1)
if "privacy" in payload:
privacy_data = payload["privacy"]
if isinstance(privacy_data, dict):
payload["privacy"] = PrivacySettings.model_validate(privacy_data)
return ProfileSettingsV1.model_validate(payload)
@@ -76,7 +87,7 @@ def upgrade_to_latest(settings: ProfileSettingsUnion) -> ProfileSettingsV1:
class UserContext(BaseModel):
model_config = ConfigDict(from_attributes=True)
model_config = ConfigDict(from_attributes=True) # pyright: ignore[reportUnannotatedClassAttribute]
id: str
username: str