@x-edu/live-player 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +10 -10
- package/.eslintignore +8 -8
- package/.eslintrc.js +26 -26
- package/.gem-mine +11 -11
- package/.postcssrc.js +6 -6
- package/README.md +145 -145
- package/babel.config.js +33 -33
- package/doc/develop.md +23 -23
- package/gem-mine.config.js +86 -86
- package/jest.config.js +9 -9
- package/jsconfig.json +15 -15
- package/mock/helper.js +8 -8
- package/mock/index.js +34 -34
- package/package.json +99 -99
- package/public/3rd/ali-player/alipayercomponents-1.0.8.min.js +26 -26
- package/public/3rd/ali-player/aliplayer-hls-min.js +27 -27
- package/public/3rd/ali-player/aliplayer-min.js +1 -1
- package/public/3rd/im-web-push/index.umd.js +14 -14
- package/public/JsBridge.js +1602 -1602
- package/public/fish/editor/themes/default/css/ueditor.css +1905 -1905
- package/public/fish/editor/third-party/codemirror/codemirror.css +104 -104
- package/public/fish/editor/third-party/codemirror/codemirror.js +3581 -3581
- package/public/fish/editor/third-party/zeroclipboard/ZeroClipboard.js +1255 -1255
- package/public/fish/editor/ueditor.all.min.js +16 -16
- package/public/fish/editor/ueditor.config.js +467 -467
- package/public/fish/icon/umd-4.1.2.js +1 -1
- package/public/fish/video/videoplayer.min.css +6 -6
- package/public/fish/video/videoplayer.min.js +31 -31
- package/public/fish/video/zh-CN.js +82 -82
- package/public/icon/demo.css +539 -539
- package/public/icon/demo_index.html +2189 -2189
- package/public/icon/iconfont.css +363 -363
- package/public/icon/iconfont.json +618 -618
- package/public/index.html +50 -50
- package/script/image/readme.md +77 -77
- package/script/postcss.js +48 -48
- package/src/App.jsx +24 -24
- package/src/asset/img/course/playing.svg +21 -21
- package/src/asset/img/icon-course-white.svg +3 -3
- package/src/asset/img/icon-course.svg +3 -3
- package/src/asset/img/icon-eye-white.svg +4 -4
- package/src/asset/img/icon-eye.svg +4 -4
- package/src/asset/img/icon-school-white.svg +3 -3
- package/src/asset/img/icon-school.svg +3 -3
- package/src/asset/img/loading.svg +52 -52
- package/src/asset/img/video-play.svg +6 -6
- package/src/asset/style/background.less +19 -19
- package/src/asset/style/banner.less +36 -36
- package/src/asset/style/base.less +74 -74
- package/src/asset/style/index.less +114 -114
- package/src/asset/style/reset-theme.less +141 -141
- package/src/asset/style/theme/index.less +55 -55
- package/src/asset/style/theme/party/global.less +20 -20
- package/src/asset/style/theme/party/override.less +57 -57
- package/src/asset/style/theme/test/global.less +18 -18
- package/src/asset/style/theme/test/override.less +45 -45
- package/src/asset/style/variable.less +12 -12
- package/src/component/AliPlayer/index.jsx +49 -49
- package/src/component/Avatar/index.jsx +50 -50
- package/src/component/Empty/index.jsx +34 -34
- package/src/component/Empty/index.module.less +37 -37
- package/src/component/IMChatroom/component/status/403.jsx +13 -13
- package/src/component/IMChatroom/component/status/404.jsx +13 -13
- package/src/component/IMChatroom/component/status/Error.jsx +23 -23
- package/src/component/IMChatroom/component/status/Loading.jsx +5 -5
- package/src/component/IMChatroom/config/app/config.js +118 -118
- package/src/component/IMChatroom/config/app/index.js +60 -60
- package/src/component/IMChatroom/config/env.js +5 -5
- package/src/component/IMChatroom/config/index.js +3 -3
- package/src/component/IMChatroom/config/request/config/base.js +124 -124
- package/src/component/IMChatroom/config/request/config/chatroom.js +26 -26
- package/src/component/IMChatroom/config/request/config/imCoreApi.js +21 -21
- package/src/component/IMChatroom/config/request/index.js +21 -21
- package/src/component/IMChatroom/config/request/proxy.js +39 -39
- package/src/component/IMChatroom/config/url.js +7 -7
- package/src/component/IMChatroom/constants/errorCode.js +9 -9
- package/src/component/IMChatroom/constants/index.js +84 -84
- package/src/component/IMChatroom/constants/origin.js +27 -27
- package/src/component/IMChatroom/context/chatroom.js +154 -154
- package/src/component/IMChatroom/context/connect.js +28 -28
- package/src/component/IMChatroom/i18n/en/index.json +73 -73
- package/src/component/IMChatroom/i18n/index.jsx +14 -14
- package/src/component/IMChatroom/i18n/language.js +9 -9
- package/src/component/IMChatroom/i18n/zh-CN/index.json +73 -73
- package/src/component/IMChatroom/index.jsx +49 -49
- package/src/component/IMChatroom/page/chat/index.jsx +27 -27
- package/src/component/IMChatroom/page/chat/messageEditor/index.jsx +375 -375
- package/src/component/IMChatroom/page/chat/messageList/index.jsx +354 -354
- package/src/component/IMChatroom/page/chat/stickedMessage/index.jsx +59 -59
- package/src/component/IMChatroom/page/chat/stickedMessage/style/index.module.less +7 -7
- package/src/component/IMChatroom/page/chat/style/index.module.less +51 -51
- package/src/component/IMChatroom/page/home/connect/index.jsx +188 -188
- package/src/component/IMChatroom/page/home/connect/status.jsx +124 -124
- package/src/component/IMChatroom/page/home/context/cmd.jsx +37 -37
- package/src/component/IMChatroom/page/home/context/index.jsx +67 -67
- package/src/component/IMChatroom/page/home/index.jsx +164 -164
- package/src/component/IMChatroom/page/home/notice/index.jsx +123 -123
- package/src/component/IMChatroom/page/home/notice/style/index.module.less +49 -49
- package/src/component/IMChatroom/page/home/style/index.module.less +110 -110
- package/src/component/IMChatroom/page/member/index.jsx +15 -15
- package/src/component/IMChatroom/page/member/memberCount/index.jsx +44 -44
- package/src/component/IMChatroom/page/member/memberList/index.jsx +121 -121
- package/src/component/IMChatroom/page/member/style/index.module.less +2 -2
- package/src/component/IMChatroom/sdk/bridge.js +39 -39
- package/src/component/IMChatroom/sdk/cs/constants.js +20 -20
- package/src/component/IMChatroom/sdk/cs/index.js +101 -101
- package/src/component/IMChatroom/sdk/imChatroom.js +15 -15
- package/src/component/IMChatroom/sdk/imcore/constants.js +128 -128
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomDestroyed.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomInfoGetFail.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomKickedByAdmin.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomKickedBySelf.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomLoginFail.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomLoginSuccess.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomMemberLogin.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/chatroomMemberLogout.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/connectionConnected.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/connectionConnecting.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/connectionDisconnect.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/emitters/index.js +57 -57
- package/src/component/IMChatroom/sdk/imcore/emitters/messageReceive.js +36 -36
- package/src/component/IMChatroom/sdk/imcore/index.js +178 -178
- package/src/component/IMChatroom/sdk/imcore/interceptors/request.js +7 -7
- package/src/component/IMChatroom/sdk/imcore/interceptors/response.js +5 -5
- package/src/component/IMChatroom/sdk/imcore/plugins/getAuth.js +64 -64
- package/src/component/IMChatroom/sdk/imcore/plugins/getConversationId.js +20 -20
- package/src/component/IMChatroom/sdk/imcore/plugins/getExtInfo.js +10 -10
- package/src/component/IMChatroom/sdk/imcore/plugins/getLoginInfo.js +48 -48
- package/src/component/IMChatroom/sdk/imcore/plugins/getPlatformType.js +12 -12
- package/src/component/IMChatroom/sdk/imcore/plugins/index.js +22 -22
- package/src/component/IMChatroom/sdk/imcore/util/format.js +177 -177
- package/src/component/IMChatroom/sdk/imcore/util/parser.js +35 -35
- package/src/component/IMChatroom/sdk/oms.js +18 -18
- package/src/component/IMChatroom/sdk/uc.js +3 -3
- package/src/component/IMChatroom/subscription/channel/app.js +5 -5
- package/src/component/IMChatroom/subscription/channel/ctl.js +22 -22
- package/src/component/IMChatroom/subscription/channel/member.js +40 -40
- package/src/component/IMChatroom/subscription/channel/message.js +13 -13
- package/src/component/IMChatroom/subscription/channel/ntf.js +86 -86
- package/src/component/IMChatroom/subscription/channel/tel.js +5 -5
- package/src/component/IMChatroom/subscription/channel/websocket.js +5 -5
- package/src/component/IMChatroom/subscription/event.js +37 -37
- package/src/component/IMChatroom/subscription/index.js +19 -19
- package/src/component/IMChatroom/util/account.js +8 -8
- package/src/component/IMChatroom/util/chatroom.js +255 -255
- package/src/component/IMChatroom/util/jsonBigInt.js +5 -5
- package/src/component/IMChatroom/util/location.js +12 -12
- package/src/component/Icon/index.jsx +16 -16
- package/src/component/Icon/index.module.less +2 -2
- package/src/component/Pagination/LocalPagination.jsx +27 -27
- package/src/component/Pagination/RemotePagination.jsx +32 -32
- package/src/component/Pagination/index.jsx +32 -31
- package/src/component/Pagination/index.module.less +117 -110
- package/src/component/PlayerTip/index.jsx +34 -34
- package/src/component/VideoBase/index.jsx +242 -242
- package/src/component/VideoBase/style.less +65 -65
- package/src/component/VideoBase/utils.js +81 -81
- package/src/component/mixin.less +9 -9
- package/src/component/status/403.jsx +15 -15
- package/src/component/status/404/index.jsx +73 -73
- package/src/component/status/404/index.module.less +36 -36
- package/src/component/status/Error/error.module.less +13 -13
- package/src/component/status/Error/index.jsx +47 -47
- package/src/component/status/Loading/img/loading.svg +52 -52
- package/src/component/status/Loading/index.jsx +31 -31
- package/src/component/status/Loading/index.less +56 -56
- package/src/component/status/None/index.jsx +20 -20
- package/src/component/status/None/index.module.less +35 -35
- package/src/component/status/Status/index.jsx +26 -26
- package/src/component/status/Status/index.module.less +8 -8
- package/src/config/constant/commonUrl.js +2 -2
- package/src/config/constant/user.js +6 -6
- package/src/config/context/site-config.js +48 -48
- package/src/config/env/index.js +5 -5
- package/src/config/env/local/index.js +13 -13
- package/src/config/env/ncet-xedu/api.js +175 -175
- package/src/config/env/ncet-xedu/app.js +12 -12
- package/src/config/env/ncet-xedu/cs.js +8 -8
- package/src/config/env/ncet-xedu/index.js +14 -14
- package/src/config/env/ncet-xedu/push.js +5 -5
- package/src/config/env/preproduction/api.js +144 -144
- package/src/config/env/preproduction/app.js +12 -12
- package/src/config/env/preproduction/cs.js +8 -8
- package/src/config/env/preproduction/index.js +14 -14
- package/src/config/env/preproduction/push.js +5 -5
- package/src/config/env/product/api.js +113 -113
- package/src/config/env/product/app.js +12 -12
- package/src/config/env/product/cs.js +5 -5
- package/src/config/env/product/index.js +14 -14
- package/src/config/env/product/push.js +5 -5
- package/src/config/live.js +80 -80
- package/src/config/publicLive.js +53 -53
- package/src/config/request/assessments.js +24 -24
- package/src/config/request/config-center.js +8 -8
- package/src/config/request/helper.js +166 -166
- package/src/config/request/im-broadcasts.js +12 -12
- package/src/config/request/live-activity-gateway.js +8 -8
- package/src/config/request/live-activity.js +13 -13
- package/src/config/request/raw.js +6 -6
- package/src/config/request/x-cloud-web.js +13 -13
- package/src/config/request/x-proxy.js +34 -34
- package/src/demo/Detail.jsx +11 -11
- package/src/demo/List.jsx +66 -64
- package/src/demo/index.jsx +17 -17
- package/src/detail/LineSwitch/index.jsx +71 -71
- package/src/detail/LiveCountDown/index.jsx +44 -44
- package/src/detail/LiveCountDown/index.module.less +31 -31
- package/src/detail/LiveOnlineCount/img/icon.svg +15 -15
- package/src/detail/LiveOnlineCount/index.jsx +68 -68
- package/src/detail/LiveOnlineCount/index.module.less +34 -34
- package/src/detail/LiveOnlineCount/util.js +74 -74
- package/src/detail/LiveStatus/AnchorOnTheWay.jsx +88 -88
- package/src/detail/LiveStatus/index.jsx +202 -202
- package/src/detail/LiveStatus/index.module.less +192 -192
- package/src/detail/LiveVideo/config.js +37 -37
- package/src/detail/LiveVideo/index.jsx +188 -188
- package/src/detail/LiveVideo/index.module.less +41 -41
- package/src/detail/NotLoginChatroom/index.jsx +37 -37
- package/src/detail/NotLoginChatroom/index.module.less +46 -46
- package/src/detail/RecordVideo/index.jsx +150 -150
- package/src/detail/RecordVideo/index.module.less +31 -31
- package/src/detail/ReplayVideo/index.jsx +93 -93
- package/src/detail/ReplayVideo/index.module.less +65 -65
- package/src/detail/const.js +20 -20
- package/src/detail/hook/usePullSource.js +82 -82
- package/src/detail/hook/usePullState.js +51 -51
- package/src/detail/index.jsx +482 -482
- package/src/detail/index.module.less +188 -188
- package/src/hook/useAsync.js +84 -84
- package/src/hook/useGoToPage.js +83 -83
- package/src/hook/useInterval.js +28 -28
- package/src/hook/useIsMounted.js +17 -17
- package/src/hook/useModuleByRole.js +53 -53
- package/src/hook/usePageScrollable.js +52 -52
- package/src/hook/usePortal.js +83 -83
- package/src/hook/useScrollRestore/index.js +32 -32
- package/src/hook/useScrollRestore/scrollContext.js +20 -20
- package/src/hook/useTrackRef.js +11 -11
- package/src/hook/useWindowSize.js +28 -28
- package/src/hook/useZoom.js +47 -47
- package/src/index.js +10 -10
- package/src/lib/getLiveOnlineCount.js +10 -10
- package/src/lib/getServiceConfig.js +102 -102
- package/src/list/Empty/index.jsx +20 -20
- package/src/list/Empty/index.module.less +23 -23
- package/src/list/ListItem/Action/index.jsx +100 -98
- package/src/list/ListItem/Action/index.module.less +19 -21
- package/src/list/ListItem/img/play.svg +15 -15
- package/src/list/ListItem/img/video.svg +3 -0
- package/src/list/ListItem/index.jsx +46 -28
- package/src/list/ListItem/index.module.less +152 -146
- package/src/list/index.module.less +35 -35
- package/src/service/common.js +73 -73
- package/src/service/content-mgr.js +73 -73
- package/src/service/im-group.js +12 -12
- package/src/service/im.js +7 -7
- package/src/service/imBroadcasts.js +33 -33
- package/src/service/like.js +134 -134
- package/src/service/manageApi.js +7 -7
- package/src/service/managePortal.js +6 -6
- package/src/service/myStudyRecord.js +93 -93
- package/src/service/navigation.js +47 -47
- package/src/service/ndMeeting.js +10 -10
- package/src/service/ndr.js +122 -122
- package/src/service/news.js +93 -93
- package/src/service/personalCenter.js +270 -270
- package/src/service/qualityCourse.js +31 -31
- package/src/service/recommend.js +81 -81
- package/src/service/school.js +323 -323
- package/src/service/search.js +170 -170
- package/src/service/site-config.js +7 -7
- package/src/service/socialCensor.js +45 -45
- package/src/service/specialEdu.js +31 -31
- package/src/service/suggestion.js +85 -85
- package/src/service/syncClassroom.js +321 -321
- package/src/service/tCourse.js +204 -204
- package/src/service/tchTraining.js +37 -37
- package/src/service/uc.js +45 -45
- package/src/util/app.js +1 -1
- package/src/util/array.js +3 -3
- package/src/util/auth/func.js +57 -57
- package/src/util/date.js +53 -53
- package/src/util/env.js +9 -9
- package/src/util/getTimestamp.js +10 -10
- package/src/util/hof.js +105 -105
- package/src/util/live/index.js +42 -42
- package/src/util/netUrl.js +35 -35
- package/src/util/object.js +13 -13
- package/src/util/push/index.js +58 -58
- package/src/util/request.js +227 -227
- package/src/util/type.js +17 -17
- package/src/util/url.js +203 -203
- package/src/util/video.js +26 -26
- package/test/setup.js +21 -21
- package/test/unit/component/header/logo.spec.jsx +8 -8
- package/test/unit/helper.jsx +25 -25
- package/test/unit/util/date.spec.js +40 -40
- package/dist/XEduLivePlayer.common.js +0 -72605
- package/dist/XEduLivePlayerPre.common.js +0 -72625
package/src/hook/useGoToPage.js
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import { useHistory } from 'react-router-dom'
|
|
2
|
-
|
|
3
|
-
const smartcan = window.Bridge && window.navigator.userAgent.indexOf('SmartCanWebView') !== -1
|
|
4
|
-
|
|
5
|
-
// function getQueryVariable(variable, path) {
|
|
6
|
-
// const vars = path.split('&')
|
|
7
|
-
// for (let i = 0; i < vars.length; i++) {
|
|
8
|
-
// const pair = vars[i].split('=')
|
|
9
|
-
// if (pair[0] === variable) {
|
|
10
|
-
// return pair[1]
|
|
11
|
-
// }
|
|
12
|
-
// }
|
|
13
|
-
// return null
|
|
14
|
-
// }
|
|
15
|
-
|
|
16
|
-
export default function useGoToPage() {
|
|
17
|
-
const history = useHistory()
|
|
18
|
-
return async (subPath, {
|
|
19
|
-
useBridge = false,
|
|
20
|
-
newPage
|
|
21
|
-
} = {}) => {
|
|
22
|
-
if (smartcan && useBridge) {
|
|
23
|
-
let targetPath
|
|
24
|
-
// url 是cmp地址,直接跳转
|
|
25
|
-
if (subPath?.startsWith('cmp://')) {
|
|
26
|
-
targetPath = subPath
|
|
27
|
-
} else if (subPath.indexOf('http') === 0) {
|
|
28
|
-
targetPath = subPath
|
|
29
|
-
} else if (subPath.substr(0, 1) === '/') {
|
|
30
|
-
targetPath = `${window.location.origin}${subPath}`
|
|
31
|
-
} else {
|
|
32
|
-
targetPath = `${window.location.href}${subPath.substr(1)}`
|
|
33
|
-
}
|
|
34
|
-
// const title = getQueryVariable('_maf_webview_title', targetPath) || '国家智慧教育读书平台'
|
|
35
|
-
targetPath = addQuery(targetPath, {
|
|
36
|
-
_maf_menu_ids: getMenuIds(subPath),
|
|
37
|
-
_maf_show_progress_bar: false,
|
|
38
|
-
_maf_need_decode: true
|
|
39
|
-
})
|
|
40
|
-
const appfactory = window.Bridge.require('sdp.appfactory').promise()
|
|
41
|
-
const result = await appfactory.goPage({
|
|
42
|
-
page: targetPath
|
|
43
|
-
})
|
|
44
|
-
return result
|
|
45
|
-
} else if (window.parent === window.self) {
|
|
46
|
-
if (newPage) {
|
|
47
|
-
window.open(subPath, '_blank')
|
|
48
|
-
} else if (subPath.indexOf('http') === 0) {
|
|
49
|
-
window.location.href = subPath
|
|
50
|
-
} else {
|
|
51
|
-
const [
|
|
52
|
-
pathname,
|
|
53
|
-
search
|
|
54
|
-
] = subPath.split('?')
|
|
55
|
-
history.push({
|
|
56
|
-
pathname,
|
|
57
|
-
search: search && `?${search}`
|
|
58
|
-
})
|
|
59
|
-
}
|
|
60
|
-
} else {
|
|
61
|
-
window.open(subPath, '_blank')
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const ShowIdsSubPath = [
|
|
67
|
-
'/teacherTraining?firstLevel=t_type_M52vKqPtOQ'
|
|
68
|
-
]
|
|
69
|
-
|
|
70
|
-
function getMenuIds(subPath) {
|
|
71
|
-
const needMenu = ShowIdsSubPath.some((t) => subPath.indexOf(t) === 0)
|
|
72
|
-
return needMenu ? 'all' : 'none'
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function addQuery(url, params) {
|
|
76
|
-
const paramStr = Object.keys(params).map((key) => {
|
|
77
|
-
const value = params[key]
|
|
78
|
-
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
79
|
-
}).join('&')
|
|
80
|
-
return url.indexOf('?') > 0
|
|
81
|
-
? `${url}&${paramStr}`
|
|
82
|
-
: `${url}?${paramStr}`
|
|
83
|
-
}
|
|
1
|
+
import { useHistory } from 'react-router-dom'
|
|
2
|
+
|
|
3
|
+
const smartcan = window.Bridge && window.navigator.userAgent.indexOf('SmartCanWebView') !== -1
|
|
4
|
+
|
|
5
|
+
// function getQueryVariable(variable, path) {
|
|
6
|
+
// const vars = path.split('&')
|
|
7
|
+
// for (let i = 0; i < vars.length; i++) {
|
|
8
|
+
// const pair = vars[i].split('=')
|
|
9
|
+
// if (pair[0] === variable) {
|
|
10
|
+
// return pair[1]
|
|
11
|
+
// }
|
|
12
|
+
// }
|
|
13
|
+
// return null
|
|
14
|
+
// }
|
|
15
|
+
|
|
16
|
+
export default function useGoToPage() {
|
|
17
|
+
const history = useHistory()
|
|
18
|
+
return async (subPath, {
|
|
19
|
+
useBridge = false,
|
|
20
|
+
newPage
|
|
21
|
+
} = {}) => {
|
|
22
|
+
if (smartcan && useBridge) {
|
|
23
|
+
let targetPath
|
|
24
|
+
// url 是cmp地址,直接跳转
|
|
25
|
+
if (subPath?.startsWith('cmp://')) {
|
|
26
|
+
targetPath = subPath
|
|
27
|
+
} else if (subPath.indexOf('http') === 0) {
|
|
28
|
+
targetPath = subPath
|
|
29
|
+
} else if (subPath.substr(0, 1) === '/') {
|
|
30
|
+
targetPath = `${window.location.origin}${subPath}`
|
|
31
|
+
} else {
|
|
32
|
+
targetPath = `${window.location.href}${subPath.substr(1)}`
|
|
33
|
+
}
|
|
34
|
+
// const title = getQueryVariable('_maf_webview_title', targetPath) || '国家智慧教育读书平台'
|
|
35
|
+
targetPath = addQuery(targetPath, {
|
|
36
|
+
_maf_menu_ids: getMenuIds(subPath),
|
|
37
|
+
_maf_show_progress_bar: false,
|
|
38
|
+
_maf_need_decode: true
|
|
39
|
+
})
|
|
40
|
+
const appfactory = window.Bridge.require('sdp.appfactory').promise()
|
|
41
|
+
const result = await appfactory.goPage({
|
|
42
|
+
page: targetPath
|
|
43
|
+
})
|
|
44
|
+
return result
|
|
45
|
+
} else if (window.parent === window.self) {
|
|
46
|
+
if (newPage) {
|
|
47
|
+
window.open(subPath, '_blank')
|
|
48
|
+
} else if (subPath.indexOf('http') === 0) {
|
|
49
|
+
window.location.href = subPath
|
|
50
|
+
} else {
|
|
51
|
+
const [
|
|
52
|
+
pathname,
|
|
53
|
+
search
|
|
54
|
+
] = subPath.split('?')
|
|
55
|
+
history.push({
|
|
56
|
+
pathname,
|
|
57
|
+
search: search && `?${search}`
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
window.open(subPath, '_blank')
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const ShowIdsSubPath = [
|
|
67
|
+
'/teacherTraining?firstLevel=t_type_M52vKqPtOQ'
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
function getMenuIds(subPath) {
|
|
71
|
+
const needMenu = ShowIdsSubPath.some((t) => subPath.indexOf(t) === 0)
|
|
72
|
+
return needMenu ? 'all' : 'none'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function addQuery(url, params) {
|
|
76
|
+
const paramStr = Object.keys(params).map((key) => {
|
|
77
|
+
const value = params[key]
|
|
78
|
+
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
79
|
+
}).join('&')
|
|
80
|
+
return url.indexOf('?') > 0
|
|
81
|
+
? `${url}&${paramStr}`
|
|
82
|
+
: `${url}?${paramStr}`
|
|
83
|
+
}
|
package/src/hook/useInterval.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { useEffect, useRef } from 'react'
|
|
2
|
-
|
|
3
|
-
function useInterval(
|
|
4
|
-
callback,
|
|
5
|
-
delay
|
|
6
|
-
) {
|
|
7
|
-
const savedCallback = useRef(callback)
|
|
8
|
-
|
|
9
|
-
// Remember the latest callback if it changes.
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
savedCallback.current = callback
|
|
12
|
-
}, [callback])
|
|
13
|
-
|
|
14
|
-
// Set up the interval.
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
// Don't schedule if no delay is specified.
|
|
17
|
-
// Note: 0 is a valid value for delay.
|
|
18
|
-
if (!delay && delay !== 0) {
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const id = setInterval(() => savedCallback.current(), delay)
|
|
23
|
-
|
|
24
|
-
return () => clearInterval(id)
|
|
25
|
-
}, [delay])
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default useInterval
|
|
1
|
+
import { useEffect, useRef } from 'react'
|
|
2
|
+
|
|
3
|
+
function useInterval(
|
|
4
|
+
callback,
|
|
5
|
+
delay
|
|
6
|
+
) {
|
|
7
|
+
const savedCallback = useRef(callback)
|
|
8
|
+
|
|
9
|
+
// Remember the latest callback if it changes.
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
savedCallback.current = callback
|
|
12
|
+
}, [callback])
|
|
13
|
+
|
|
14
|
+
// Set up the interval.
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
// Don't schedule if no delay is specified.
|
|
17
|
+
// Note: 0 is a valid value for delay.
|
|
18
|
+
if (!delay && delay !== 0) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const id = setInterval(() => savedCallback.current(), delay)
|
|
23
|
+
|
|
24
|
+
return () => clearInterval(id)
|
|
25
|
+
}, [delay])
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export default useInterval
|
package/src/hook/useIsMounted.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react'
|
|
2
|
-
|
|
3
|
-
function useIsMounted() {
|
|
4
|
-
const isMounted = useRef(false)
|
|
5
|
-
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
isMounted.current = true
|
|
8
|
-
|
|
9
|
-
return () => {
|
|
10
|
-
isMounted.current = false
|
|
11
|
-
}
|
|
12
|
-
}, [])
|
|
13
|
-
|
|
14
|
-
return useCallback(() => isMounted.current, [])
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default useIsMounted
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react'
|
|
2
|
+
|
|
3
|
+
function useIsMounted() {
|
|
4
|
+
const isMounted = useRef(false)
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
isMounted.current = true
|
|
8
|
+
|
|
9
|
+
return () => {
|
|
10
|
+
isMounted.current = false
|
|
11
|
+
}
|
|
12
|
+
}, [])
|
|
13
|
+
|
|
14
|
+
return useCallback(() => isMounted.current, [])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default useIsMounted
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import { useContext, useEffect, useState } from 'react'
|
|
2
|
-
import { USER_IDENTITY } from '@/config/live'
|
|
3
|
-
import UserContext from '@/component/Login/UserContext'
|
|
4
|
-
|
|
5
|
-
// 四个模块
|
|
6
|
-
export const Module = {
|
|
7
|
-
SYNC_CLASSROOM_PICKED: 'SYNC_CLASSROOM_PICKED', // 首页精选课
|
|
8
|
-
TCH_TRAINING: 'TCH_TRAINING',
|
|
9
|
-
FAMILY_EDU: 'FAMILY_EDU',
|
|
10
|
-
EVO_EXP: 'EVO_EXP',
|
|
11
|
-
STUDIO: 'STUDIO' // 工作室
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 每个角色不可见的模块
|
|
15
|
-
export const inaccessible = {
|
|
16
|
-
[USER_IDENTITY.TEACHER]: [],
|
|
17
|
-
[USER_IDENTITY.STUDENT]: [Module.SYNC_CLASSROOM_PICKED, Module.TCH_TRAINING, Module.FAMILY_EDU, Module.EVO_EXP, Module.STUDIO],
|
|
18
|
-
[USER_IDENTITY.GUARDIAN]: [Module.SYNC_CLASSROOM_PICKED, Module.TCH_TRAINING, Module.EVO_EXP, Module.STUDIO],
|
|
19
|
-
[USER_IDENTITY.ACADEMIC_STAFF]: [],
|
|
20
|
-
[USER_IDENTITY.ELECTRIC_TEACHER]: [],
|
|
21
|
-
[USER_IDENTITY.EDU_ADMIN]: [],
|
|
22
|
-
[USER_IDENTITY.SOCIAL_LEARNER]: []
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// 四个模块可见性(默认都可见)
|
|
26
|
-
const moduleVisible = {
|
|
27
|
-
[Module.SYNC_CLASSROOM_PICKED]: true,
|
|
28
|
-
[Module.TCH_TRAINING]: true,
|
|
29
|
-
[Module.FAMILY_EDU]: true,
|
|
30
|
-
[Module.EVO_EXP]: true,
|
|
31
|
-
[Module.STUDIO]: true
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default function useModuleByRole() {
|
|
35
|
-
const { userInfo, userRole, loginStatus } = useContext(UserContext)
|
|
36
|
-
const [visibleModule, setVisibleModule] = useState(moduleVisible)
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (userInfo && userRole) {
|
|
40
|
-
Object.keys(moduleVisible).forEach((key) => {
|
|
41
|
-
moduleVisible[key] = !inaccessible[userRole].includes(key)
|
|
42
|
-
})
|
|
43
|
-
setVisibleModule({
|
|
44
|
-
...moduleVisible
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
}, [userInfo, userRole])
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
visibleModule,
|
|
51
|
-
loginStatus
|
|
52
|
-
}
|
|
53
|
-
}
|
|
1
|
+
import { useContext, useEffect, useState } from 'react'
|
|
2
|
+
import { USER_IDENTITY } from '@/config/live'
|
|
3
|
+
import UserContext from '@/component/Login/UserContext'
|
|
4
|
+
|
|
5
|
+
// 四个模块
|
|
6
|
+
export const Module = {
|
|
7
|
+
SYNC_CLASSROOM_PICKED: 'SYNC_CLASSROOM_PICKED', // 首页精选课
|
|
8
|
+
TCH_TRAINING: 'TCH_TRAINING',
|
|
9
|
+
FAMILY_EDU: 'FAMILY_EDU',
|
|
10
|
+
EVO_EXP: 'EVO_EXP',
|
|
11
|
+
STUDIO: 'STUDIO' // 工作室
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 每个角色不可见的模块
|
|
15
|
+
export const inaccessible = {
|
|
16
|
+
[USER_IDENTITY.TEACHER]: [],
|
|
17
|
+
[USER_IDENTITY.STUDENT]: [Module.SYNC_CLASSROOM_PICKED, Module.TCH_TRAINING, Module.FAMILY_EDU, Module.EVO_EXP, Module.STUDIO],
|
|
18
|
+
[USER_IDENTITY.GUARDIAN]: [Module.SYNC_CLASSROOM_PICKED, Module.TCH_TRAINING, Module.EVO_EXP, Module.STUDIO],
|
|
19
|
+
[USER_IDENTITY.ACADEMIC_STAFF]: [],
|
|
20
|
+
[USER_IDENTITY.ELECTRIC_TEACHER]: [],
|
|
21
|
+
[USER_IDENTITY.EDU_ADMIN]: [],
|
|
22
|
+
[USER_IDENTITY.SOCIAL_LEARNER]: []
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 四个模块可见性(默认都可见)
|
|
26
|
+
const moduleVisible = {
|
|
27
|
+
[Module.SYNC_CLASSROOM_PICKED]: true,
|
|
28
|
+
[Module.TCH_TRAINING]: true,
|
|
29
|
+
[Module.FAMILY_EDU]: true,
|
|
30
|
+
[Module.EVO_EXP]: true,
|
|
31
|
+
[Module.STUDIO]: true
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default function useModuleByRole() {
|
|
35
|
+
const { userInfo, userRole, loginStatus } = useContext(UserContext)
|
|
36
|
+
const [visibleModule, setVisibleModule] = useState(moduleVisible)
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (userInfo && userRole) {
|
|
40
|
+
Object.keys(moduleVisible).forEach((key) => {
|
|
41
|
+
moduleVisible[key] = !inaccessible[userRole].includes(key)
|
|
42
|
+
})
|
|
43
|
+
setVisibleModule({
|
|
44
|
+
...moduleVisible
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
}, [userInfo, userRole])
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
visibleModule,
|
|
51
|
+
loginStatus
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createContext,
|
|
3
|
-
useContext,
|
|
4
|
-
useLayoutEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState
|
|
7
|
-
} from 'react'
|
|
8
|
-
import { useLocation } from 'react-router-dom'
|
|
9
|
-
import { isInElectron } from '@/util/env'
|
|
10
|
-
|
|
11
|
-
export function usePageScrollableRoot() {
|
|
12
|
-
const location = useLocation()
|
|
13
|
-
const [pageScrollable, setPageScrollable] = useState(!isInElectron)
|
|
14
|
-
const pageScrollableRef = useRef(pageScrollable)
|
|
15
|
-
|
|
16
|
-
const setCurrentPageScrollable = (value) => {
|
|
17
|
-
setPageScrollable(value)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
useLayoutEffect(() => {
|
|
21
|
-
// page不变,是location发生变化
|
|
22
|
-
if (pageScrollableRef.current === pageScrollable) {
|
|
23
|
-
if (!pageScrollable) {
|
|
24
|
-
if (!isInElectron) {
|
|
25
|
-
setPageScrollable(true)
|
|
26
|
-
pageScrollableRef.current = true
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
} else {
|
|
30
|
-
// 是page发生变化则同步更新
|
|
31
|
-
pageScrollableRef.current = pageScrollable
|
|
32
|
-
}
|
|
33
|
-
}, [location.key, pageScrollable])
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
pageScrollable,
|
|
37
|
-
setCurrentPageScrollable
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const PageScrollableContext = createContext()
|
|
42
|
-
/**
|
|
43
|
-
*
|
|
44
|
-
* @typedef {Object} UsePageScrollable
|
|
45
|
-
* @property {Boolean} pageScrollable 页面是否可以滚动,默认可以滚动
|
|
46
|
-
* @property {(isPageScrollable: Boolean) => void} setCurrentPageScrollable 设置当前页面是否可以滚动,设置仅对当前路由有效,切换则设置恢复滚动
|
|
47
|
-
*/
|
|
48
|
-
/**
|
|
49
|
-
* 用于React组件下获取siteConfig,注意siteConfig本身是异步获取,所以同步获取的值只能用于React组件渲染
|
|
50
|
-
* @returns {UsePageScrollable}
|
|
51
|
-
*/
|
|
52
|
-
export const usePageScrollable = () => useContext(PageScrollableContext)
|
|
1
|
+
import {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useLayoutEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
useState
|
|
7
|
+
} from 'react'
|
|
8
|
+
import { useLocation } from 'react-router-dom'
|
|
9
|
+
import { isInElectron } from '@/util/env'
|
|
10
|
+
|
|
11
|
+
export function usePageScrollableRoot() {
|
|
12
|
+
const location = useLocation()
|
|
13
|
+
const [pageScrollable, setPageScrollable] = useState(!isInElectron)
|
|
14
|
+
const pageScrollableRef = useRef(pageScrollable)
|
|
15
|
+
|
|
16
|
+
const setCurrentPageScrollable = (value) => {
|
|
17
|
+
setPageScrollable(value)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
useLayoutEffect(() => {
|
|
21
|
+
// page不变,是location发生变化
|
|
22
|
+
if (pageScrollableRef.current === pageScrollable) {
|
|
23
|
+
if (!pageScrollable) {
|
|
24
|
+
if (!isInElectron) {
|
|
25
|
+
setPageScrollable(true)
|
|
26
|
+
pageScrollableRef.current = true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
// 是page发生变化则同步更新
|
|
31
|
+
pageScrollableRef.current = pageScrollable
|
|
32
|
+
}
|
|
33
|
+
}, [location.key, pageScrollable])
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
pageScrollable,
|
|
37
|
+
setCurrentPageScrollable
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const PageScrollableContext = createContext()
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @typedef {Object} UsePageScrollable
|
|
45
|
+
* @property {Boolean} pageScrollable 页面是否可以滚动,默认可以滚动
|
|
46
|
+
* @property {(isPageScrollable: Boolean) => void} setCurrentPageScrollable 设置当前页面是否可以滚动,设置仅对当前路由有效,切换则设置恢复滚动
|
|
47
|
+
*/
|
|
48
|
+
/**
|
|
49
|
+
* 用于React组件下获取siteConfig,注意siteConfig本身是异步获取,所以同步获取的值只能用于React组件渲染
|
|
50
|
+
* @returns {UsePageScrollable}
|
|
51
|
+
*/
|
|
52
|
+
export const usePageScrollable = () => useContext(PageScrollableContext)
|
package/src/hook/usePortal.js
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import { useRef, useEffect } from 'react'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates DOM element to be used as React root.
|
|
5
|
-
* @returns {HTMLElement}
|
|
6
|
-
*/
|
|
7
|
-
function createRootElement(id) {
|
|
8
|
-
const rootContainer = document.createElement('div')
|
|
9
|
-
rootContainer.setAttribute('id', id)
|
|
10
|
-
return rootContainer
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Appends element as last child of body.
|
|
15
|
-
* @param {HTMLElement} rootElem
|
|
16
|
-
*/
|
|
17
|
-
function addRootElement(rootElem) {
|
|
18
|
-
document.body.insertBefore(
|
|
19
|
-
rootElem,
|
|
20
|
-
document.body.lastElementChild.nextElementSibling
|
|
21
|
-
)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Hook to create a React Portal.
|
|
26
|
-
* Automatically handles creating and tearing-down the root elements (no SRR
|
|
27
|
-
* makes this trivial), so there is no need to ensure the parent target already
|
|
28
|
-
* exists.
|
|
29
|
-
* @example
|
|
30
|
-
* const target = usePortal(id, [id]);
|
|
31
|
-
* return createPortal(children, target);
|
|
32
|
-
* @param {String} selector The selector of the target container, e.g '#modal' or '.spotlight'
|
|
33
|
-
* @param {containerClass} containerClass
|
|
34
|
-
* @returns {HTMLElement} The DOM node to use as the Portal target.
|
|
35
|
-
*/
|
|
36
|
-
function usePortal(selector, containerClass) {
|
|
37
|
-
const rootElemRef = useRef(null)
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
// Look for existing target dom element to append to
|
|
41
|
-
const existingParent = document.querySelector(selector)
|
|
42
|
-
// Parent is either a new root or the existing dom element
|
|
43
|
-
const parentElem = existingParent || createRootElement(selector)
|
|
44
|
-
|
|
45
|
-
// If there is no existing DOM element, add a new one.
|
|
46
|
-
if (!existingParent) {
|
|
47
|
-
addRootElement(parentElem)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Add the detached element to the parent
|
|
51
|
-
parentElem.appendChild(rootElemRef.current)
|
|
52
|
-
|
|
53
|
-
return function removeElement() {
|
|
54
|
-
rootElemRef.current.remove()
|
|
55
|
-
if (!parentElem.childElementCount) {
|
|
56
|
-
parentElem.remove()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}, [selector])
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* It's important we evaluate this lazily:
|
|
63
|
-
* - We need first render to contain the DOM element, so it shouldn't happen
|
|
64
|
-
* in useEffect. We would normally put this in the constructor().
|
|
65
|
-
* - We can't do 'const rootElemRef = useRef(document.createElement('div))',
|
|
66
|
-
* since this will run every single render (that's a lot).
|
|
67
|
-
* - We want the ref to consistently point to the same DOM element and only
|
|
68
|
-
* ever run once.
|
|
69
|
-
* @link https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily
|
|
70
|
-
*/
|
|
71
|
-
function getRootElem() {
|
|
72
|
-
if (!rootElemRef.current) {
|
|
73
|
-
const div = document.createElement('div')
|
|
74
|
-
div.classList.add(containerClass)
|
|
75
|
-
rootElemRef.current = div
|
|
76
|
-
}
|
|
77
|
-
return rootElemRef.current
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return getRootElem()
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export default usePortal
|
|
1
|
+
import { useRef, useEffect } from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates DOM element to be used as React root.
|
|
5
|
+
* @returns {HTMLElement}
|
|
6
|
+
*/
|
|
7
|
+
function createRootElement(id) {
|
|
8
|
+
const rootContainer = document.createElement('div')
|
|
9
|
+
rootContainer.setAttribute('id', id)
|
|
10
|
+
return rootContainer
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Appends element as last child of body.
|
|
15
|
+
* @param {HTMLElement} rootElem
|
|
16
|
+
*/
|
|
17
|
+
function addRootElement(rootElem) {
|
|
18
|
+
document.body.insertBefore(
|
|
19
|
+
rootElem,
|
|
20
|
+
document.body.lastElementChild.nextElementSibling
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Hook to create a React Portal.
|
|
26
|
+
* Automatically handles creating and tearing-down the root elements (no SRR
|
|
27
|
+
* makes this trivial), so there is no need to ensure the parent target already
|
|
28
|
+
* exists.
|
|
29
|
+
* @example
|
|
30
|
+
* const target = usePortal(id, [id]);
|
|
31
|
+
* return createPortal(children, target);
|
|
32
|
+
* @param {String} selector The selector of the target container, e.g '#modal' or '.spotlight'
|
|
33
|
+
* @param {containerClass} containerClass
|
|
34
|
+
* @returns {HTMLElement} The DOM node to use as the Portal target.
|
|
35
|
+
*/
|
|
36
|
+
function usePortal(selector, containerClass) {
|
|
37
|
+
const rootElemRef = useRef(null)
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
// Look for existing target dom element to append to
|
|
41
|
+
const existingParent = document.querySelector(selector)
|
|
42
|
+
// Parent is either a new root or the existing dom element
|
|
43
|
+
const parentElem = existingParent || createRootElement(selector)
|
|
44
|
+
|
|
45
|
+
// If there is no existing DOM element, add a new one.
|
|
46
|
+
if (!existingParent) {
|
|
47
|
+
addRootElement(parentElem)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Add the detached element to the parent
|
|
51
|
+
parentElem.appendChild(rootElemRef.current)
|
|
52
|
+
|
|
53
|
+
return function removeElement() {
|
|
54
|
+
rootElemRef.current.remove()
|
|
55
|
+
if (!parentElem.childElementCount) {
|
|
56
|
+
parentElem.remove()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}, [selector])
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* It's important we evaluate this lazily:
|
|
63
|
+
* - We need first render to contain the DOM element, so it shouldn't happen
|
|
64
|
+
* in useEffect. We would normally put this in the constructor().
|
|
65
|
+
* - We can't do 'const rootElemRef = useRef(document.createElement('div))',
|
|
66
|
+
* since this will run every single render (that's a lot).
|
|
67
|
+
* - We want the ref to consistently point to the same DOM element and only
|
|
68
|
+
* ever run once.
|
|
69
|
+
* @link https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily
|
|
70
|
+
*/
|
|
71
|
+
function getRootElem() {
|
|
72
|
+
if (!rootElemRef.current) {
|
|
73
|
+
const div = document.createElement('div')
|
|
74
|
+
div.classList.add(containerClass)
|
|
75
|
+
rootElemRef.current = div
|
|
76
|
+
}
|
|
77
|
+
return rootElemRef.current
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return getRootElem()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default usePortal
|