在Mobile Safari中反应PWA图片上传会中断应用程序?

Won*_*nka 7 safari mobile-safari ios reactjs progressive-web-apps

令我们感到惊讶的是,我们在网上的任何地方都找不到任何提及此事的消息,因此我们在这里发布,希望找到解决方案。

当我们遇到此问题时,请在下面运行2个易于遵循的测试,以解决问题,使用iPhone,一种有效,一种无效。

这是链接 https://pwa-react.netlify.com/

这是我们运行的2个测试(均在链接中列出),一个在非PWA模式下有效,另一个在PWA模式下失败。

测试#1:完美运行(预期行为)

Visit https://pwa-react.netlify.com/ from iPhone in mobile safari
1. Make sure you have google drive on the phone but not logged in.
2. Click "Choose File". It will show you the list of options to choose from.
3. Click "Browse" to look for the photo.
4. Click "Cancel" and you're back here.
5. Click "Choose File" it will still show you the list of options to choose from.
   This works perfectly in mobile safari but NOT in PWA mode below.
Run Code Online (Sandbox Code Playgroud)

测试#2:不起作用(意外行为)(PWA)

Visit https://pwa-react.netlify.com/ from iPhone in mobile safari, hit the share
button, then add to home screen. This will add the PWA app on your phone. Open App.
1. Make sure you have google drive on the phone but not logged in.
2. Click "Choose File". It will show you the list of options to choose from.
3. Click "Browse" to look for the photo.
4. When it shows you the Google Drive logo with Sign In, double click the home 
   button, then go back to the PWA.
5. Click "Choose File" it will NOT show you the list of options to choose from. 
   This is now 100% broken.
   The ONLY way to fix it is to go to Settings>Safari>Clear History and Website Data (all the way down)
   How can we fix this so when the user hits "Choose File" it shows the list of 
   options to choose from in the PWA?
Run Code Online (Sandbox Code Playgroud)

屏幕截图1:这些是出现在测试1中并停止出现在测试2中的选项

在此处输入图片说明

屏幕截图2:此屏幕允许我们在测试1中取消,但在测试2中消失

在此处输入图片说明

知道如何通过允许我们在不破坏应用程序的情况下选择如屏幕截图1中的上传选项而使测试2正常工作,而不必去野生动物园设置清除历史记录和网站数据才能使其再次运行吗?

PS-这是存储库文件pwa-react / src / App.js

Par*_*elf 5

我们在 PWA 中遇到了几乎完全相同的问题,因此首先我要感谢您帮助我们缩小了问题范围。

在回顾了 iOS PWA 生命周期(此处的文章)以及几个小时令人发狂的试验和错误之后,我找到了一个半可接受的解决方案。

我的猜测是,当您在上传过程中离开应用程序(测试#2)时,会发生什么情况是,iOS 如何处理未重置的 PWA 存在一些内部上下文,因此当您返回并尝试再次上传文件时,它会发生变化。认为上传对话框已经打开。

文章提到,打开外部链接而不使用target=_blank会导致 PWA 上下文被删除,因此当应用内浏览器关闭时,PWA 页面会在独立窗口中重新加载。我认为这可能会重置“分离上传”上下文,并且最终成功了。

因此,我创建了一个托管在另一个域上的页面,并在 PWA 中的上传按钮下方链接到该页面:

// not sure the target={'_self'} is necessary but not risking it
<a href={'https://externalDomain.com/reset'} target={'_self'}>
    Having Issues? Reset Upload
</a>
Run Code Online (Sandbox Code Playgroud)

这工作得很好,除了一个问题。当您单击此链接时,它会打开应用程序内浏览器,但没有“完成”按钮或导航工具供用户知道如何退出。链接回 PWA 不起作用,因为 iOS 会检测到这一点并且不会重置应用程序上下文。我注意到的是,如果我从第一个外部页面导航到另一个页面(我最初只是使用 google.com 进行了测试),则会显示“完成”按钮,从而清楚地显示如何退出。

有了这些知识,我猜想你可能可以window.history.pushState达到相同的效果,这是有效的。我的最终解决方案如下。当用户从应用程序内浏览器中按“完成”时,它会导致整个应用程序重新加载,但在我看来,这比将它们重新添加到主屏幕要好得多。

const Reset: React.FC = props => {
    React.useEffect(() => {
        // Redirect any wayward users who find this page from outside the PWA
        if (!window.matchMedia('(display-mode: standalone)').matches) {
            navigate('/');
        }
        // push an additional page into history
        const newUrl = `${window.location.href}?reset`;
        window.history.pushState({ path: newUrl }, '', newUrl);
    }, []);
    return (
        <Grid container>
            <ArrowUpIcon />
            <Typography variant={'h5'}>Press done above to return to App</Typography>
            <Typography variant={'body1'}>Sorry for the inconvenience!</Typography>
        </Grid>
    );
};
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!很想知道它是否适合您。

生产测试后编辑: 另一个重要的注意事项是您的“重置”页面必须位于完全不同的域上才能正常工作。今天在生产中遇到了这个问题,因为我们的重置页面位于与 PWA 具有相同根的子域上,iOS 并没有重置整个 PWA 生命周期。

概括

关键的问题:

  1. 在任何“文件上传”对话框打开(“拍照”、“照片库”或“浏览”)时离开 iOS PWA 会破坏 iOS PWA 生命周期。这种破坏使用户无法打开任何“文件”单击文件输入时出现“上传”对话框。
  2. 为了解决此问题,必须完全重置 PWA 上下文。
  3. 似乎重置 PWA 上下文的唯一方法是重新启动手机、删除应用程序并将其重新添加到主屏幕,或者打开外部链接。
  4. 打开外部链接时,关闭 iOS PWA 嵌入式浏览器的“完成”按钮不会显示在初始页面上。用户必须导航到其他外部页面才能显示“完成”按钮。
  5. 外部链接在有 时不会触发 PWA 上下文重置target="_blank"

解决方案:

为了让用户能够再次上传文件,必须重置 PWA 上下文。最简单的方法(在我看来)是要求他们打开外部链接。

  1. (在 PWA 中):向用户提供一个链接以修复上传对话框未显示的问题。链接目标必须是完全不相关的域(不是子域)并且必须具有target="_self"(问题#5)。
  2. (外部页面):一旦用户单击链接并打开外部页面,将没有可见的方式离开该页面(问题#4)。要解决此问题,您可以使用history.pushState模拟导航到其他页面。
  3. (外部页面 - 奖励):为了让用户清楚问题已得到解决,请在左上角添加一个指向“完成”按钮的箭头(如我的屏幕截图所示)。