package rte import ( "fmt" "regexp" "time" "drmdecryption/adb" "drmdecryption/uiflow" ) // tapChipThenPlay is this app's navigation idiom: on the Live tab, tap the // channel chip, then the large hero Play button that appears. If the hero button // is already on screen, tap it directly. func (a *App) tapChipThenPlay(c *adb.Client, ch Channel) error { playPats := uiflow.CompileRes(ch.PlayDesc) chipPats := uiflow.CompileRes(ch.ChipDesc) nodes, err := c.DumpUI(a.CacheDir()) if err != nil { return err } if cand := a.findHeroPlay(nodes, playPats); cand != nil { fmt.Printf("[*] tap Play @ %d,%d\n", cand.CX(), cand.CY()) return c.Tap(cand.CX(), cand.CY()) } chip := adb.FindSmallest(nodes, chipPats) if chip == nil { chip, err = c.WaitFor(a.CacheDir(), nil, chipPats, time.Duration(a.cfg.Timeouts.ChipWait)) if err != nil { return fmt.Errorf("chip not found: %w", err) } } fmt.Printf("[*] tap chip @ %d,%d\n", chip.CX(), chip.CY()) _ = c.Tap(chip.CX(), chip.CY()) time.Sleep(time.Duration(a.cfg.Timeouts.AfterChip)) deadline := time.Now().Add(time.Duration(a.cfg.Timeouts.PlayWait)) for time.Now().Before(deadline) { nodes, err = c.DumpUI(a.CacheDir()) if err == nil { if cand := a.findHeroPlay(nodes, playPats); cand != nil { fmt.Printf("[*] tap Play @ %d,%d\n", cand.CX(), cand.CY()) return c.Tap(cand.CX(), cand.CY()) } } time.Sleep(700 * time.Millisecond) } return fmt.Errorf("Play button did not appear") } // findHeroPlay accepts a Play match only if it is big enough to be the hero // button rather than a small list-item play icon. func (a *App) findHeroPlay(nodes []adb.Node, playPats []*regexp.Regexp) *adb.Node { cand := adb.FindLargest(nodes, nil, playPats) if cand == nil || cand.Area() < a.cfg.HeroMinArea { return nil } return cand }