|
@@ -1,6 +1,7 @@
|
|
|
import cookies from 'js-cookie'
|
|
|
-import { COOKIE_ROOT_DOMAIN, COOKIE_APP_KEY, COOKIE_ACCESS_TOKEN_KEY, MSG_REQUIRE_LOGIN } from './constant'
|
|
|
-import { Notifier } from '../types/global'
|
|
|
+import semver from 'semver'
|
|
|
+import { COOKIE_ROOT_DOMAIN, COOKIE_APP_KEY, COOKIE_APP_EXTRA_KEY, COOKIE_ACCESS_TOKEN_KEY, MSG_REQUIRE_LOGIN, APP_INJECT_COOKIE_KEYS, DEF_SYNCED_COOKIE_EXP } from './constant'
|
|
|
+import { Notifier, SyncCookiesOptions } from '../types/global'
|
|
|
|
|
|
const parseJWT = (token: string): any => {
|
|
|
const payloadStr = token.split('.')[1]
|
|
@@ -19,10 +20,45 @@ const parseJWT = (token: string): any => {
|
|
|
return null
|
|
|
}
|
|
|
|
|
|
+const getAppInfo = () => {
|
|
|
+ const val = cookies.get(COOKIE_APP_KEY)
|
|
|
+ const matched = val && /^(ios|android)\ ((?:\d\.?)+)$/.exec(val)
|
|
|
+
|
|
|
+ if (!matched) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ os: matched[1],
|
|
|
+ version: matched[2]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const getAppExtra = (): any => {
|
|
|
+ const val = cookies.get(COOKIE_APP_EXTRA_KEY)
|
|
|
+ const segments = val && val.split(/\s+/)
|
|
|
+
|
|
|
+ if (!segments || !segments.length) {
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+
|
|
|
+ return segments.reduce((map, item) => {
|
|
|
+ const matched = /^([0-9a-zA-Z_-]+)\/(.+)$/.exec(item)
|
|
|
+
|
|
|
+ if (matched) {
|
|
|
+ map[matched[1]] = matched[2]
|
|
|
+ }
|
|
|
+
|
|
|
+ return map
|
|
|
+ }, {})
|
|
|
+}
|
|
|
+
|
|
|
+let cachedAppInfo: any
|
|
|
+let cachedappExtra: any
|
|
|
+
|
|
|
class ProginnBridge {
|
|
|
// @ts-ignore
|
|
|
- root = window.app_event
|
|
|
- isAndroid = /Android/.test(window.navigator.userAgent)
|
|
|
+ root = window.app_event || window.appBridge
|
|
|
|
|
|
private notifier?: Notifier
|
|
|
|
|
@@ -34,13 +70,38 @@ class ProginnBridge {
|
|
|
this.notifier = notifier
|
|
|
}
|
|
|
|
|
|
- get cookie() {
|
|
|
- return cookies.get()
|
|
|
+ get appInfo() {
|
|
|
+ cachedAppInfo = cachedAppInfo || getAppInfo()
|
|
|
+ return cachedAppInfo
|
|
|
+ }
|
|
|
+
|
|
|
+ get appExtra() {
|
|
|
+ cachedappExtra = cachedappExtra || getAppExtra()
|
|
|
+ return cachedappExtra
|
|
|
+ }
|
|
|
+
|
|
|
+ get appVersion() {
|
|
|
+ return this.appInfo?.version
|
|
|
+ }
|
|
|
+
|
|
|
+ get os() {
|
|
|
+ return this.appInfo?.os
|
|
|
}
|
|
|
|
|
|
get isInApp() {
|
|
|
- // @ts-ignore
|
|
|
- return !!(cookies.get(COOKIE_APP_KEY) || this.root || window.appBridge)
|
|
|
+ return !!(this.appInfo || this.root)
|
|
|
+ }
|
|
|
+
|
|
|
+ get isAndroid() {
|
|
|
+ return /Android/.test(window.navigator.userAgent) || this.os === 'android' || false
|
|
|
+ }
|
|
|
+
|
|
|
+ get isIos() {
|
|
|
+ return /iP(hone|ad|od)/.test(window.navigator.userAgent) || this.os === 'ios' || false
|
|
|
+ }
|
|
|
+
|
|
|
+ get cookie() {
|
|
|
+ return cookies.get()
|
|
|
}
|
|
|
|
|
|
get isLogined() {
|
|
@@ -59,32 +120,19 @@ class ProginnBridge {
|
|
|
window[root][name] = cb
|
|
|
}
|
|
|
|
|
|
- syncCookies() {
|
|
|
- const app = cookies.get(COOKIE_APP_KEY)
|
|
|
- const token = cookies.get(COOKIE_ACCESS_TOKEN_KEY)
|
|
|
- const opts = {
|
|
|
- domain: COOKIE_ROOT_DOMAIN,
|
|
|
- expires: 7200
|
|
|
- }
|
|
|
-
|
|
|
- if (app) {
|
|
|
- cookies.set(COOKIE_APP_KEY, app, opts)
|
|
|
- }
|
|
|
-
|
|
|
- if (token) {
|
|
|
- cookies.set(COOKIE_ACCESS_TOKEN_KEY, token, opts)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
invoke(fn: string, payload?: any) {
|
|
|
if (!this.root) {
|
|
|
// tslint:disable-next-line
|
|
|
console.warn(`Bridge invoke ${fn} skipped.`)
|
|
|
- return
|
|
|
+ return null
|
|
|
}
|
|
|
|
|
|
if (this.isAndroid) {
|
|
|
- return this.root[fn] && this.root[fn](payload)
|
|
|
+ if (typeof this.root[fn] === 'function') {
|
|
|
+ return payload ? this.root[fn](payload) : this.root[fn]()
|
|
|
+ } else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
} else {
|
|
|
return this.root(fn, payload)
|
|
|
}
|
|
@@ -102,6 +150,14 @@ class ProginnBridge {
|
|
|
window.location.href = url
|
|
|
}
|
|
|
|
|
|
+ open(url: string, title?: string) {
|
|
|
+ if (this.isInApp && (!this.isAndroid || this.compareAppVersion('gte', '4.20.0'))) {
|
|
|
+ url = `proginn://webview?url=${encodeURIComponent(url)}${title ? '&title=' + encodeURIComponent(title) : ''}`
|
|
|
+ }
|
|
|
+
|
|
|
+ this.load(url)
|
|
|
+ }
|
|
|
+
|
|
|
login() {
|
|
|
if (!this.isInApp) {
|
|
|
return
|
|
@@ -120,6 +176,54 @@ class ProginnBridge {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
+ compareAppVersion(operator: 'gt' | 'lt' | 'gte' | 'lte' | 'eq' | 'neq', version: string) {
|
|
|
+ return this.appVersion ? semver[operator](this.appVersion, version) : false
|
|
|
+ }
|
|
|
+
|
|
|
+ syncCookies(opts?: SyncCookiesOptions) {
|
|
|
+ opts = opts || {}
|
|
|
+ opts.domain = opts.domain || COOKIE_ROOT_DOMAIN
|
|
|
+ opts.expires = opts.expires || DEF_SYNCED_COOKIE_EXP
|
|
|
+
|
|
|
+ for (const key of APP_INJECT_COOKIE_KEYS) {
|
|
|
+ const val = cookies.get(key)
|
|
|
+
|
|
|
+ if (val) {
|
|
|
+ cookies.set(key, val, opts)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // generally to fix android webview cookies non-inject bug
|
|
|
+ cacheCookiesInStorage() {
|
|
|
+ for (const key of APP_INJECT_COOKIE_KEYS) {
|
|
|
+ const val = cookies.get(key)
|
|
|
+
|
|
|
+ if (val) {
|
|
|
+ window.localStorage.setItem(key, val)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ loadCookiesInStorage(opts?: SyncCookiesOptions) {
|
|
|
+ opts = opts || {}
|
|
|
+ opts.domain = opts.domain || COOKIE_ROOT_DOMAIN
|
|
|
+ opts.expires = opts.expires || DEF_SYNCED_COOKIE_EXP
|
|
|
+
|
|
|
+ for (const key of APP_INJECT_COOKIE_KEYS) {
|
|
|
+ // pass if already exists
|
|
|
+ if (cookies.get(key)) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ const val = window.localStorage.getItem(key)
|
|
|
+
|
|
|
+ if (val) {
|
|
|
+ cookies.set(key, val, opts)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
userLoad(userInfo: any) {
|
|
|
this.invoke('user_load', this.isAndroid ? userInfo : {
|
|
|
userInfo
|