123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- import { DeviceType } from "cc";
- export default class DeviceM {
- private static _ins: DeviceM;
- public static get ins(): DeviceM {
- return (DeviceM._ins ??= new DeviceM());
- }
- public async isMobile(): Promise<boolean> {
- // 檢查是否在瀏覽器環境中
- if (typeof window === "undefined") {
- return false;
- }
- // 方法1: 檢查 User Agent
- const userAgent = navigator.userAgent.toLowerCase();
- const mobileKeywords = [
- "android",
- "iphone",
- "ipad",
- "ipod",
- "blackberry",
- "windows phone",
- "mobile",
- "tablet",
- "opera mini",
- "opera mobi",
- ];
- const isMobileByUserAgent = mobileKeywords.some((keyword) =>
- userAgent.includes(keyword)
- );
- // 方法2: 檢查螢幕尺寸
- const isMobileByScreen =
- window.innerWidth <= 768 || window.innerHeight <= 768;
- // 方法3: 檢查觸控支援
- const isMobileByTouch =
- "ontouchstart" in window || navigator.maxTouchPoints > 0;
- // 方法4: 檢查設備像素比
- const isMobileByPixelRatio = window.devicePixelRatio > 1;
- // 綜合判斷:如果任一條件成立,則認為是移動端
- return (
- isMobileByUserAgent ||
- (isMobileByScreen && isMobileByTouch) ||
- isMobileByPixelRatio
- );
- }
- /**
- * 檢查瀏覽器是否支持打開新標籤頁面
- * @returns Promise<boolean>
- */
- public async supportsNewTab(): Promise<boolean> {
- // 檢查是否在瀏覽器環境中
- if (typeof window === "undefined") {
- return false;
- }
- // 檢查是否在 iframe 中(iframe 通常無法打開新標籤頁)
- if (window.self !== window.top) {
- return false;
- }
- // 檢查是否在彈出視窗中(彈出視窗通常無法打開新標籤頁)
- if (window.opener) {
- return false;
- }
- // 檢查是否在 WebView 中(某些 WebView 可能不支持新標籤頁)
- const userAgent = navigator.userAgent.toLowerCase();
- const webViewKeywords = [
- "webview",
- "wv",
- "mobile safari",
- "chrome mobile",
- "firefox mobile",
- "opera mobile",
- ];
- const isInWebView = webViewKeywords.some((keyword) =>
- userAgent.includes(keyword)
- );
- // 檢查是否在無頭瀏覽器中(如 Puppeteer、Selenium 等)
- const isHeadless =
- userAgent.includes("headless") ||
- userAgent.includes("phantomjs") ||
- userAgent.includes("selenium");
- // 檢查是否支持 window.open 方法
- const supportsWindowOpen = typeof window.open === "function";
- // 綜合判斷:支持新標籤頁的條件
- return supportsWindowOpen && !isInWebView && !isHeadless;
- }
- /**
- * 嘗試打開新標籤頁
- * @param url 要打開的 URL
- * @param target 目標視窗(默認為 '_blank')
- * @returns Promise<boolean> 是否成功打開
- */
- public async openNewTab(
- url: string,
- target: string = "_blank"
- ): Promise<boolean> {
- try {
- // 首先檢查是否支持新標籤頁
- const canOpen = await this.supportsNewTab();
- if (!canOpen) {
- console.warn("當前環境不支持打開新標籤頁");
- return false;
- }
- // 嘗試打開新標籤頁
- const newWindow = window.open(url, target);
- // 檢查是否成功打開
- if (newWindow && !newWindow.closed) {
- return true;
- } else {
- console.warn("無法打開新標籤頁,可能被瀏覽器阻擋");
- return false;
- }
- } catch (error) {
- console.error("打開新標籤頁時發生錯誤:", error);
- return false;
- }
- }
- }
|