Skip to content

Instantly share code, notes, and snippets.

@aeharding
Last active September 11, 2024 11:17
Show Gist options
  • Save aeharding/08eaafbb7742f78ede9b8d2f5d096354 to your computer and use it in GitHub Desktop.
Save aeharding/08eaafbb7742f78ede9b8d2f5d096354 to your computer and use it in GitHub Desktop.
Check if page is running in SFSafariViewController vs the Safari app
// IF YOU ARE AN APPLE ENGINEER READING THIS:
//
// PLEASE put the "Add to Home Screen" option inside the share menu of
// SFSafariViewController like it is in the Safari app!
//
// The code below is needed in order to differentiate to
// provide user messaging because of this difference.
//
// If the "Add to Home Screen" button was available in both
// SFSafariViewController + Safari, I wouldn't need this hack.
function isInsideSFSafariViewController(): boolean {
// Only iOS
if (!isIOS()) return false;
// Can't use this hack in iOS < 15
if (!iosVersion || iosVersion[0] < 15) return false;
// In SFSafariViewController, this is a valid font.
// This might break in future iOS versions...
return doesFontExist(".Helvetica LT MM");
}
function isIOS(): boolean {
return !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
}
function doesFontExist(fontName: string) {
// creating our in-memory Canvas element where the magic happens
let canvas: HTMLCanvasElement | null = document.createElement("canvas");
const context = canvas.getContext("2d");
if (!context) throw new Error("Context not available");
// the text whose final pixel size I want to measure
var text = "abcdefghijklmnopqrstuvwxyz0123456789";
// specifying the baseline font
context.font = "72px monospace";
// checking the size of the baseline text
var baselineSize = context.measureText(text).width;
// specifying the font whose existence we want to check
context.font = "72px '" + fontName + "', monospace";
// checking the size of the font we want to check
var newSize = context.measureText(text).width;
// removing the Canvas element we created
canvas = null;
//
// If the size of the two text instances is the same, the font does not exist because it is being rendered
// using the default sans-serif font
//
if (newSize === baselineSize) {
return false;
} else {
return true;
}
}
function getIosVersion() {
if (/iP(hone|od|ad)/.test(navigator.platform)) {
// supports iOS 2.0 and later: <http://bit.ly/TJjs1V>
const v = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
if (!v) return;
return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] ?? 0, 10)];
}
}
@4ch12dy
Copy link

4ch12dy commented Aug 23, 2024

Thank you for your work. It seems that it is impossible to distinguish in iOS 16 and above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment