fix: sync Android default theme installs

This commit is contained in:
iamxvbaba 2026-07-30 20:13:22 +08:00
parent 80c36a8ab4
commit 0d917ef87e
8 changed files with 263 additions and 7 deletions

View file

@ -38,6 +38,18 @@ func LookupWallPaper(input tg.InputWallPaperClass) (tg.WallPaperClass, bool) {
return DefaultWallPaper(wallpaper), true
}
}
// account.getThemes/account.getChatThemes also advertise wallpapers nested
// in ThemeSettings. The default getWallPapers export is a filtered list and
// does not contain every nested entry, so these identities must remain part
// of the same lookup boundary or Android can render a theme that it cannot
// subsequently install.
for _, theme := range catalog.ChatThemes {
for _, settings := range theme.Settings {
if inputWallPaperMatches(input, settings.Wallpaper) {
return DefaultWallPaper(settings.Wallpaper), true
}
}
}
return nil, false
}

View file

@ -182,6 +182,31 @@ func DefaultThemeList() []tg.Theme {
return themes
}
// LookupDefaultTheme resolves an InputTheme against the exact identity emitted
// by DefaultThemeList. ID references must carry the matching access hash; slug
// references are public and match by their exact non-empty slug.
//
// These themes are an immutable server catalog rather than rows in the custom
// cloud-theme store. RPCs which accept a Theme returned by account.getThemes
// use this lookup before consulting that store.
func LookupDefaultTheme(input tg.InputThemeClass) (tg.Theme, bool) {
for _, theme := range DefaultThemeList() {
switch in := input.(type) {
case *tg.InputTheme:
if in.ID == theme.ID && in.AccessHash == theme.AccessHash {
return theme, true
}
case *tg.InputThemeSlug:
if in.Slug != "" && in.Slug == theme.Slug {
return theme, true
}
default:
return tg.Theme{}, false
}
}
return tg.Theme{}, false
}
func UniqueGiftChatThemes(hash int64) tg.AccountChatThemesClass {
if hash == uniqueGiftChatThemesHash {
return &tg.AccountChatThemesNotModified{}

View file

@ -216,6 +216,35 @@ func TestDefaultThemesAreDefaultFlaggedForPicker(t *testing.T) {
}
}
func TestLookupDefaultThemeValidatesIdentity(t *testing.T) {
themes := DefaultThemeList()
if len(themes) == 0 {
t.Fatal("DefaultThemeList is empty")
}
for _, theme := range themes {
byID, ok := LookupDefaultTheme(&tg.InputTheme{
ID: theme.ID,
AccessHash: theme.AccessHash,
})
if !ok || byID.ID != theme.ID {
t.Fatalf("lookup id %d = id %d ok=%v, want exact theme", theme.ID, byID.ID, ok)
}
bySlug, ok := LookupDefaultTheme(&tg.InputThemeSlug{Slug: theme.Slug})
if !ok || bySlug.ID != theme.ID {
t.Fatalf("lookup slug %q = id %d ok=%v, want %d", theme.Slug, bySlug.ID, ok, theme.ID)
}
if _, ok := LookupDefaultTheme(&tg.InputTheme{
ID: theme.ID,
AccessHash: theme.AccessHash + 1,
}); ok {
t.Fatalf("lookup id %d accepted forged access hash", theme.ID)
}
}
if _, ok := LookupDefaultTheme(&tg.InputThemeSlug{}); ok {
t.Fatal("lookup accepted empty slug")
}
}
func TestUniqueGiftChatThemesIsEmptyHashableStub(t *testing.T) {
got, ok := UniqueGiftChatThemes(0).(*tg.AccountChatThemes)
if !ok {
@ -299,6 +328,50 @@ func TestLookupWallPaperByIDAndSlug(t *testing.T) {
}
}
func TestDefaultThemeWallpaperReferencesResolve(t *testing.T) {
themes := DefaultThemeList()
var checked int
for _, theme := range themes {
settings, ok := theme.GetSettings()
if !ok {
continue
}
for i, setting := range settings {
wallpaperClass, ok := setting.GetWallpaper()
if !ok {
continue
}
wallpaper, ok := wallpaperClass.(*tg.WallPaper)
if !ok {
continue
}
checked++
byID, ok := LookupWallPaper(&tg.InputWallPaper{
ID: wallpaper.ID,
AccessHash: wallpaper.AccessHash,
})
if !ok {
t.Fatalf("theme %d settings[%d] wallpaper id %d was not resolvable", theme.ID, i, wallpaper.ID)
}
gotByID, ok := byID.(*tg.WallPaper)
if !ok || gotByID.ID != wallpaper.ID || gotByID.AccessHash != wallpaper.AccessHash {
t.Fatalf("theme %d settings[%d] wallpaper id lookup = %#v", theme.ID, i, byID)
}
bySlug, ok := LookupWallPaper(&tg.InputWallPaperSlug{Slug: wallpaper.Slug})
if !ok {
t.Fatalf("theme %d settings[%d] wallpaper slug %q was not resolvable", theme.ID, i, wallpaper.Slug)
}
gotBySlug, ok := bySlug.(*tg.WallPaper)
if !ok || gotBySlug.Slug != wallpaper.Slug {
t.Fatalf("theme %d settings[%d] wallpaper slug lookup = %#v", theme.ID, i, bySlug)
}
}
}
if checked == 0 {
t.Fatal("default themes exposed no file wallpapers")
}
}
func TestStarsRevenueStatsIsZeroBalanceCompatStub(t *testing.T) {
got := StarsRevenueStats(false)
if got == nil {