Skip to content

Commit

Permalink
Merge pull request #202 from AElfProject/feature/tg-acceleration
Browse files Browse the repository at this point in the history
fix/ismobile-check-and-typings
  • Loading branch information
work-kevin-flynn authored Dec 2, 2024
2 parents c5694b2 + 17ec80f commit f4329ae
Show file tree
Hide file tree
Showing 16 changed files with 403 additions and 222 deletions.
2 changes: 1 addition & 1 deletion packages/base/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aelf-web-login/wallet-adapter-base",
"version": "0.2.2-alpha.4",
"version": "0.2.2-alpha.5",
"type": "module",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
Expand Down
4 changes: 2 additions & 2 deletions packages/base/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { isMobile } from './isMobile';
import { isMobileDevices } from './isMobile';
import { getOriginalAddress } from './getOriginalAddress';
import { isPortkeyApp } from './isPortkeyApp';
import { sleep } from './sleep';
export default {
isMobile,
isMobileDevices,
getOriginalAddress,
isPortkeyApp,
sleep,
Expand Down
199 changes: 182 additions & 17 deletions packages/base/src/utils/isMobile.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,191 @@
const mobileRE =
/(android|bb\d+|meego).+mobile|armv7l|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series[46]0|samsungbrowser.*mobile|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i;
const notMobileRE = /CrOS/;
const appleIphone = /iPhone/i;
const appleIpod = /iPod/i;
const appleTablet = /iPad/i;
const appleUniversal = /\biOS-universal(?:.+)Mac\b/i;
const androidPhone = /\bAndroid(?:.+)Mobile\b/i; // Match 'Android' AND 'Mobile'
const androidTablet = /Android/i;
const amazonPhone = /(?:SD4930UR|\bSilk(?:.+)Mobile\b)/i; // Match 'Silk' AND 'Mobile'
const amazonTablet = /Silk/i;
const windowsPhone = /Windows Phone/i;
const windowsTablet = /\bWindows(?:.+)ARM\b/i; // Match 'Windows' AND 'ARM'
const otherBlackBerry = /BlackBerry/i;
const otherBlackBerry10 = /BB10/i;
const otherOpera = /Opera Mini/i;
const otherChrome = /\b(CriOS|Chrome)(?:.+)Mobile/i;
const otherFirefox = /Mobile(?:.+)Firefox\b/i; // Match 'Mobile' AND 'Firefox'

export function isMobile() {
if (typeof navigator === 'undefined') {
return false;
export type UserAgent = string;
export type Navigator = {
userAgent: string;
platform: string;
maxTouchPoints?: number;
};

const isAppleTabletOnIos13 = (navigator?: Navigator): boolean => {
return (
typeof navigator !== 'undefined' &&
navigator.platform === 'MacIntel' &&
typeof navigator.maxTouchPoints === 'number' &&
navigator.maxTouchPoints > 1
);
};

function createMatch(userAgent: UserAgent): (regex: RegExp) => boolean {
return (regex: RegExp): boolean => regex.test(userAgent);
}

export type isMobileResult = {
apple: {
phone: boolean;
ipod: boolean;
tablet: boolean;
universal: boolean;
device: boolean;
};
amazon: {
phone: boolean;
tablet: boolean;
device: boolean;
};
android: {
phone: boolean;
tablet: boolean;
device: boolean;
};
windows: {
phone: boolean;
tablet: boolean;
device: boolean;
};
other: {
blackberry: boolean;
blackberry10: boolean;
opera: boolean;
firefox: boolean;
chrome: boolean;
device: boolean;
};
phone: boolean;
tablet: boolean;
any: boolean;
};

export type IsMobileParameter = UserAgent | Navigator;

export function isMobile(param?: IsMobileParameter): isMobileResult {
let nav: Navigator = {
userAgent: '',
platform: '',
maxTouchPoints: 0,
};

if (!param && typeof navigator !== 'undefined') {
nav = {
userAgent: navigator.userAgent,
platform: navigator.platform,
maxTouchPoints: navigator.maxTouchPoints || 0,
};
} else if (typeof param === 'string') {
nav.userAgent = param;
} else if (param && param.userAgent) {
nav = {
userAgent: param.userAgent,
platform: param.platform,
maxTouchPoints: param.maxTouchPoints || 0,
};
}

const ua = navigator.userAgent;
if (typeof ua !== 'string') return false;
let userAgent = nav.userAgent;

let result = mobileRE.test(ua) && !notMobileRE.test(ua);
// Facebook mobile app's integrated browser adds a bunch of strings that
// match everything. Strip it out if it exists.
let tmp = userAgent.split('[FBAN');
if (typeof tmp[1] !== 'undefined') {
userAgent = tmp[0];
}

if (
!result &&
navigator &&
navigator.maxTouchPoints > 1 &&
ua.indexOf('Macintosh') !== -1 &&
ua.indexOf('Safari') !== -1
) {
result = true;
// Twitter mobile app's integrated browser on iPad adds a "Twitter for
// iPhone" string. Same probably happens on other tablet platforms.
// This will confuse detection so strip it out if it exists.
tmp = userAgent.split('Twitter');
if (typeof tmp[1] !== 'undefined') {
userAgent = tmp[0];
}

const match = createMatch(userAgent);

const result: isMobileResult = {
apple: {
phone: match(appleIphone) && !match(windowsPhone),
ipod: match(appleIpod),
tablet:
!match(appleIphone) &&
(match(appleTablet) || isAppleTabletOnIos13(nav)) &&
!match(windowsPhone),
universal: match(appleUniversal),
device:
(match(appleIphone) ||
match(appleIpod) ||
match(appleTablet) ||
match(appleUniversal) ||
isAppleTabletOnIos13(nav)) &&
!match(windowsPhone),
},
amazon: {
phone: match(amazonPhone),
tablet: !match(amazonPhone) && match(amazonTablet),
device: match(amazonPhone) || match(amazonTablet),
},
android: {
phone:
(!match(windowsPhone) && match(amazonPhone)) ||
(!match(windowsPhone) && match(androidPhone)),
tablet:
!match(windowsPhone) &&
!match(amazonPhone) &&
!match(androidPhone) &&
(match(amazonTablet) || match(androidTablet)),
device:
(!match(windowsPhone) &&
(match(amazonPhone) ||
match(amazonTablet) ||
match(androidPhone) ||
match(androidTablet))) ||
match(/\bokhttp\b/i),
},
windows: {
phone: match(windowsPhone),
tablet: match(windowsTablet),
device: match(windowsPhone) || match(windowsTablet),
},
other: {
blackberry: match(otherBlackBerry),
blackberry10: match(otherBlackBerry10),
opera: match(otherOpera),
firefox: match(otherFirefox),
chrome: match(otherChrome),
device:
match(otherBlackBerry) ||
match(otherBlackBerry10) ||
match(otherOpera) ||
match(otherFirefox) ||
match(otherChrome),
},
any: false,
phone: false,
tablet: false,
};

result.any =
result.apple.device || result.android.device || result.windows.device || result.other.device;
// excludes 'other' devices and ipods, targeting touchscreen phones
result.phone = result.apple.phone || result.android.phone || result.windows.phone;
result.tablet = result.apple.tablet || result.android.tablet || result.windows.tablet;

return result;
}

export function isMobileDevices() {
const isM = isMobile();
return isM.apple.device || isM.android.device;
}
4 changes: 2 additions & 2 deletions packages/bridge/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aelf-web-login/wallet-adapter-bridge",
"version": "0.2.2-alpha.4",
"version": "0.2.2-alpha.5",
"type": "module",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
Expand Down Expand Up @@ -33,14 +33,14 @@
},
"dependencies": {
"@aelf-web-login/wallet-adapter-base": "workspace:*",
"@aelf-web-login/tools": "workspace:*",
"@portkey/contracts": "^2.15.9",
"@portkey/services": "^2.15.9",
"@reduxjs/toolkit": "^2.2.3",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"babel-jest": "^29.7.0",
"@portkey/did-ui-react": "^2.15.9",
"@portkey/types": "^2.15.9",
"@portkey/utils": "^2.15.9",
Expand Down
9 changes: 4 additions & 5 deletions packages/bridge/src/__tests__/useVerifier.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import useVerifier from '../useVerifier';
import { did, ConfigProvider, useVerifyToken, IVerifier } from '@portkey/did-ui-react';
import { TChainId } from '@aelf-web-login/wallet-adapter-base';
import { OperationTypeEnum } from '@portkey/services';
import type { Mock } from 'vitest';

vi.mock('@portkey/did-ui-react', () => ({
did: {
Expand Down Expand Up @@ -52,11 +53,9 @@ describe('useVerifier', () => {
};

beforeEach(() => {
(did.services.getRecommendationVerifier as vi.Mock).mockReturnValue(
mockGetRecommendationVerifier,
);
(ConfigProvider.getSocialLoginConfig as vi.Mock).mockReturnValue(mockSocialLoginConfig);
(useVerifyToken as vi.Mock).mockReturnValue(mockVerifyToken);
(did.services.getRecommendationVerifier as Mock).mockReturnValue(mockGetRecommendationVerifier);
(ConfigProvider.getSocialLoginConfig as Mock).mockReturnValue(mockSocialLoginConfig);
(useVerifyToken as Mock).mockReturnValue(mockVerifyToken);
});

it('should return getRecommendationVerifier and verifySocialToken functions', () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/bridge/src/ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ interface ISignInModalProps {
wallets: WalletAdapter[];
baseConfig: IBaseConfig;
}
const { isMobile } = utils;
const { isMobileDevices } = utils;

const ConfirmLogoutDialog = (props: Partial<IConfirmLogoutDialogProps>) => {
const { title, subTitle, okTxt, cancelTxt, visible, onOk, onCancel, width, mobileWidth } = {
...defaultProps,
...props,
};
const isMobileDevice = isMobile();
const isMobileDevice = isMobileDevices();

return (
<Modal
Expand Down Expand Up @@ -160,7 +160,7 @@ const NestedModal = ({
design,
bridgeInstance,
}: INestedModalProps) => {
const isMobileDevice = isMobile();
const isMobileDevice = isMobileDevices();
const isWeb2Design = design === 'Web2Design';

const validWalletList = validWallets.map((wallet) => {
Expand Down Expand Up @@ -250,7 +250,7 @@ const SignInModal: React.FC<ISignInModalProps> = (props: ISignInModalProps) => {
const guardianList = JSON.parse(enhancedLocalStorage.getItem(GUARDIAN_LIST_FOR_LOGIN) || '[]');

const filteredWallets = wallets.filter((ele) => ele.name !== PORTKEYAA);
const isMobileDevice = isMobile();
const isMobileDevice = isMobileDevices();
const {
noCommonBaseModal = false,
SignInComponent,
Expand Down
21 changes: 21 additions & 0 deletions packages/react/jest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// In your own jest-setup.js (or any other name)
import '@testing-library/jest-dom';
global.fetch = require('node-fetch');
import { type IBridgeAPI } from '@aelf-web-login/wallet-adapter-bridge';

jest.mock('@aelf-web-login/wallet-adapter-bridge', () => ({
initBridge: jest.fn().mockReturnValue({
getSignIn: jest.fn((children) => children),
store: {
getState: () => null,
subscribe: () => null,
},
instance: {} as IBridgeAPI['instance'],
}),
}));

jest.mock('@aelf-web-login/wallet-adapter-portkey-aa', () => ({
PortkeyAAWallet: jest.fn(),
}));

jest.mock('vconsole');
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aelf-web-login/wallet-adapter-react",
"version": "0.2.2-alpha.4",
"version": "0.2.2-alpha.5",
"type": "module",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aelf-web-login/utils",
"version": "0.2.2-alpha.4",
"version": "0.2.2-alpha.5",
"type": "module",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
Expand Down
2 changes: 1 addition & 1 deletion packages/wallets/night-elf/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aelf-web-login/wallet-adapter-night-elf",
"version": "0.2.2-alpha.4",
"version": "0.2.2-alpha.5",
"type": "module",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
Expand Down
4 changes: 2 additions & 2 deletions packages/wallets/night-elf/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class NightElfWallet extends BaseWalletAdapter {
}

async login(): Promise<TWalletInfo> {
const { isMobile } = utils;
const { isMobileDevices } = utils;
try {
this._loginState = LoginStateEnum.CONNECTING;
const nodes = this._config.nodes;
Expand All @@ -91,7 +91,7 @@ export class NightElfWallet extends BaseWalletAdapter {
const result = await bridge.login({ chainId: node.chainId, payload: { method: 'LOGIN' } });
if (result.error) throw result.errorMessage || result;

if (isMobile()) {
if (isMobileDevices()) {
bridge?.connect!();
} else {
await Promise.all(Object.values(bridges).map((i) => i.chain.getChainStatus()));
Expand Down
6 changes: 3 additions & 3 deletions packages/wallets/night-elf/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import AelfBridgeCheck from './AelfBridgeCheck';
import NightElfCheck from './NightElfCheck';

export const getBridges = async (nodes: INightElfWalletAdapterConfig['nodes'], appName: string) => {
const { isMobile } = utils;
const { isMobileDevices } = utils;
try {
const isAElfBridge = isMobile() && !(window as any)?.NightElf;
const isAElfBridge = isMobileDevices() && !(window as any)?.NightElf;
console.log('aelf-wallet-debug----------1');
console.log(`isMobile(): ${isMobile()}`);
console.log(`isMobileDevices(): ${isMobileDevices()}`);
console.log(`(window as any)?.NightElf: ${(window as any)?.NightElf}`);

const connector = (
Expand Down
2 changes: 1 addition & 1 deletion packages/wallets/portkey-aa/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aelf-web-login/wallet-adapter-portkey-aa",
"version": "0.2.2-alpha.4",
"version": "0.2.2-alpha.5",
"type": "module",
"main": "dist/esm/index.js",
"module": "dist/esm/index.js",
Expand Down
Loading

0 comments on commit f4329ae

Please sign in to comment.