CSS & JS Effect – Do something on enter/leave window tab

需求

我在做一个体验

当用户 submit enquiry 后会 window.open 开启 WhatsApp。而当用户关闭 WhatsApp 回来网站后,会 show 一个 feedback message。

 

实现思路

关键就在如何感知到,用户从 WhatsApp 切换回到了网站。

参考: Detect When Users Switch Tabs using JavaScript

监听 visibilitychange,然后通过 document.visibilityState 得知是 hidden or visible。

hidden 表示 leave tab,visible 表示 back to tab。

 

Android 鬼

本来是很简单的东西,但不知道是不是我手机的问题。Android 在开启 WhatsApp 的时候会触发 2 次。

Windows:open WhatsApp > hidden > close WhatsApp > visible

Android:open WhatsApp > hidden > visible > hidden > close WhatsApp > visible

显然 Windows 是正常的,Android 跑了多一次。

Workaround 就是尽可能判断出 Android 的情况,不要被它搞乱。我没有太认真去思考 right way,我觉得多半是一个 bug 来的,所以暂时解决就好了。

参考代码注释理解吧

复制代码
const beforeWindowOpenTime = performance.now();
window.open(generateWhatsAppLink(whatsAppNumberBS.value, message), '_blank');

// note 解忧:
// 这里有一个 user back from WhatsApp 后 show submitted feedback 的体验。
// 它比较复杂,因为手机有 bug,
// 正常情况下 visibilitychange 会 dispatch when user leave/enter tab,离开 state = hidden,回来 state = visible。
// so when window open WhatsApp, dispatch lever tab 咯, when user close WhatsApp, dispatch enter tab 咯.
// 但是我的 android 有鬼。
// when window open WhatsApp,它会先 leave + enter 1 次, 紧接着又 leave 1 次, 直到 user back
// 所以下面代码需要顾虑它第一轮假的 leave + enter
const [visible$, hidden$] = partition(
  fromEvent(window, 'visibilitychange').pipe(share()),
  () => document.visibilityState === 'visible',
);

// 监听第一次 visible
visible$.pipe(take(1)).subscribe(() => {
  const now = performance.now();
  // 如果第一次 visible 超过 1 秒
  if (now - beforeWindowOpenTime >= 1000) {
    // 直接 show feedback,因为 android 鬼是很快的,绝对不会超过 1 秒
    showSubmittedFeedback();
    return;
  }

  // 如果小于 1 秒,那可能是 android 鬼,或者 user 真的很快就 close WhatsApp
  // 我们尝试监听 hidden,如果是 android 鬼,那么 2 秒内会触发 hidden
  // 如果 2 秒后没有 hidden 那判定是 user close 很快。
  hidden$.pipe(take(1), timeout({ first: 2000 })).subscribe({
    next() {
      // android 鬼的话,等待下一次的 visible 表示 user close
      visible$.pipe(take(1)).subscribe(() => showSubmittedFeedback());
    },
    error() {
      // user close 的话,直接 show feedback
      showSubmittedFeedback();
    },
  });

  function showSubmittedFeedback() {
    setTimeout(() => {
      submitFeedbackReCaptchaContainer.submitFeedbackReCaptchaContainerController.showSubmittedFeedback();
    }, 1000);
  }
});
复制代码

 

posted @   兴杰  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
历史上的今天:
2022-10-05 Google – Reviews
2021-10-05 Figma 学习笔记 – Auto Layout
2021-10-05 Figma 学习笔记 – Scroll and Position Fixed
2021-10-05 Figma 学习笔记 – Constraints 约束
2021-10-05 Figma 学习笔记 – Align 对齐
2021-10-05 Figma 学习笔记 – Border
2021-10-05 Figma 学习笔记 – Comment
点击右上角即可分享
微信分享提示