From 2aabc6fd9c072cab905c0fd5b0b2892b79f7984a Mon Sep 17 00:00:00 2001 From: lyswhut Date: Sat, 15 May 2021 22:52:42 +0800 Subject: [PATCH] first commit --- .buckconfig | 6 + .editorconfig | 13 + .eslintrc.js | 26 + .flowconfig | 66 + .gitattributes | 3 + .github/ISSUE_TEMPLATE/----.md | 25 + .github/ISSUE_TEMPLATE/--bug.md | 42 + .github/workflows/beta-pack.yml | 80 + .github/workflows/release.yml | 109 + .gitignore | 60 + .prettierrc.js | 7 + .vscode/javascript.code-snippets | 52 + .vscode/settings.json | 11 + .watchmanconfig | 1 + CHANGELOG.md | 11 + FAQ.md | 66 + LICENSE | 201 + README.md | 57 + android/app/BUCK | 55 + android/app/build.gradle | 268 + android/app/build_defs.bzl | 19 + android/app/debug.keystore | Bin 0 -> 2257 bytes android/app/proguard-rules.pro | 10 + android/app/src/debug/AndroidManifest.xml | 13 + .../com/lxmusicmobile/ReactNativeFlipper.java | 72 + android/app/src/main/AndroidManifest.xml | 49 + .../app/src/main/assets/fonts/AntDesign.ttf | Bin 0 -> 70344 bytes .../assets/fonts/MaterialCommunityIcons.ttf | Bin 0 -> 899432 bytes android/app/src/main/assets/fonts/icomoon.ttf | Bin 0 -> 4356 bytes .../java/com/lxmusicmobile/MainActivity.java | 14 + .../com/lxmusicmobile/MainApplication.java | 86 + .../cache/CacheClearAsyncTask.java | 33 + .../com/lxmusicmobile/cache/CacheModule.java | 74 + .../com/lxmusicmobile/cache/CachePackage.java | 24 + .../java/com/lxmusicmobile/cache/Utils.java | 80 + .../com/lxmusicmobile/gzip/GzipModule.java | 103 + .../com/lxmusicmobile/gzip/GzipPackage.java | 24 + .../java/com/lxmusicmobile/gzip/Utils.java | 50 + .../com/lxmusicmobile/utils/UtilsModule.java | 100 + .../com/lxmusicmobile/utils/UtilsPackage.java | 24 + .../main/res/drawable-hdpi/launch_screen.png | Bin 0 -> 23184 bytes .../res/drawable-land-hdpi/launch_screen.png | Bin 0 -> 18933 bytes .../res/drawable-land-mdpi/launch_screen.png | Bin 0 -> 13902 bytes .../res/drawable-land-xhdpi/launch_screen.png | Bin 0 -> 29620 bytes .../drawable-land-xxhdpi/launch_screen.png | Bin 0 -> 46773 bytes .../drawable-land-xxxhdpi/launch_screen.png | Bin 0 -> 64037 bytes .../main/res/drawable-mdpi/launch_screen.png | Bin 0 -> 15655 bytes .../main/res/drawable-xhdpi/launch_screen.png | Bin 0 -> 37498 bytes .../res/drawable-xxhdpi/launch_screen.png | Bin 0 -> 60611 bytes .../res/drawable-xxxhdpi/launch_screen.png | Bin 0 -> 52296 bytes .../app/src/main/res/layout/launch_screen.xml | 11 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3033 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5024 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2339 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2858 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4537 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6814 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9027 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15523 bytes android/app/src/main/res/values/colors.xml | 4 + android/app/src/main/res/values/strings.xml | 3 + android/app/src/main/res/values/styles.xml | 17 + android/app/src/main/res/xml/file_paths.xml | 22 + .../main/res/xml/network_security_config.xml | 4 + android/build.gradle | 43 + android/gradle.properties | 37 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + android/gradlew | 185 + android/gradlew.bat | 89 + android/settings.gradle | 7 + app.json | 4 + babel.config.js | 29 + doc/images/icon.png | Bin 0 -> 6856 bytes index.js | 86 + jsconfig.json | 16 + metro.config.js | 17 + package.json | 123 + publish/changeLog.md | 3 + publish/index.js | 50 + publish/utils/index.js | 62 + publish/utils/updateChangeLog.js | 54 + publish/version.json | 5 + shim.js | 26 + src/components/ListItem/index.js | 71 + src/components/MusicAddModal.js | 112 + src/components/MusicMultiAddModal.js | 113 + .../OnlineList/ExitMultipleModeBar.js | 142 + src/components/OnlineList/Footer.js | 26 + src/components/OnlineList/ListItem.js | 130 + src/components/OnlineList/index.js | 279 + src/components/SearchInput.js | 35 + src/components/common/Badge.js | 46 + src/components/common/Button.js | 30 + src/components/common/CheckBox.js | 89 + src/components/common/ChoosePath/List.js | 128 + .../common/ChoosePath/components/Footer.js | 40 + .../common/ChoosePath/components/Header.js | 127 + .../common/ChoosePath/components/ListItem.js | 72 + .../common/ChoosePath/components/Main.js | 57 + src/components/common/ChoosePath/index.js | 78 + src/components/common/ConfirmAlert.js | 79 + src/components/common/Dialog.js | 84 + src/components/common/DorpDownMenu.js | 56 + src/components/common/DorpDownPanel/Panel.js | 98 + src/components/common/DorpDownPanel/index.js | 51 + src/components/common/Icon.js | 7 + src/components/common/Input.js | 113 + src/components/common/LoadingMask.js | 69 + src/components/common/Menu.js | 127 + src/components/common/Modal.js | 32 + src/components/layout/Header.js | 51 + src/components/player/Progress.js | 87 + src/components/searchTipList.js | 131 + src/config/constant.js | 25 + src/config/defaultSetting.js | 89 + src/config/globalData.js | 14 + src/config/index.js | 20 + src/config/setting.js | 42 + src/lang/Readme.md | 39 + src/lang/en_us.json | 173 + src/lang/index.js | 15 + src/lang/zh_cn.json | 173 + src/navigation/components/PactModal.js | 220 + src/navigation/components/Toast.js | 64 + src/navigation/components/VersionModal.js | 305 + src/navigation/index.js | 37 + src/navigation/navigation.js | 260 + src/navigation/registerScreens.js | 41 + src/navigation/screenNames.js | 6 + src/navigation/utils.js | 100 + src/plugins/i18n.js | 44 + src/plugins/lyric.js | 95 + src/plugins/player/Player.js | 0 src/plugins/player/hook.js | 104 + src/plugins/player/index.js | 46 + src/plugins/player/service.js | 245 + src/plugins/player/utils.js | 304 + src/plugins/storage.js | 93 + src/resources/fonts/icomoon.ttf | Bin 0 -> 4356 bytes src/resources/fonts/selection.json | 1 + src/resources/medias/Silence02s.mp3 | Bin 0 -> 2194 bytes src/screens/Home/Download/index.js | 15 + .../List/components/ExitMultipleModeBar.js | 142 + src/screens/Home/List/components/ListItem.js | 121 + .../List/components/MusicPositionModal.js | 92 + src/screens/Home/List/components/MyList.js | 259 + src/screens/Home/List/index.js | 354 + src/screens/Home/Search/components/Input.js | 82 + .../Home/Search/components/MusicList.js | 67 + .../Home/Search/components/SourceSelector.js | 40 + src/screens/Home/Search/components/TipList.js | 37 + src/screens/Home/Search/index.js | 87 + src/screens/Home/Setting/About.js | 112 + src/screens/Home/Setting/Backup/All.js | 0 src/screens/Home/Setting/Backup/Part.js | 157 + src/screens/Home/Setting/Backup/index.js | 17 + src/screens/Home/Setting/Basic/Language.js | 47 + src/screens/Home/Setting/Basic/Source.js | 54 + src/screens/Home/Setting/Basic/SourceName.js | 59 + src/screens/Home/Setting/Basic/Theme.js | 83 + src/screens/Home/Setting/Basic/index.js | 22 + src/screens/Home/Setting/Other/Cache.js | 70 + src/screens/Home/Setting/Other/index.js | 17 + .../Home/Setting/Player/IsPlayHighQuality.js | 20 + src/screens/Home/Setting/Player/MaxCache.js | 40 + src/screens/Home/Setting/Player/index.js | 51 + src/screens/Home/Setting/Version.js | 79 + src/screens/Home/Setting/components/Button.js | 31 + .../Home/Setting/components/CheckBoxItem.js | 22 + .../Home/Setting/components/InputItem.js | 53 + .../Home/Setting/components/Section.js | 32 + .../Home/Setting/components/SubTitle.js | 29 + src/screens/Home/Setting/index.js | 46 + src/screens/Home/SongList/List/List.js | 128 + src/screens/Home/SongList/List/ListItem.js | 57 + src/screens/Home/SongList/List/MenuBar.js | 31 + src/screens/Home/SongList/List/SortTab.js | 77 + .../Home/SongList/List/SourceSelector.js | 47 + src/screens/Home/SongList/List/Tag.js | 127 + src/screens/Home/SongList/List/index.js | 25 + .../Home/SongList/ListDetail/ButtonBar.js | 84 + .../Home/SongList/ListDetail/Header.js | 71 + src/screens/Home/SongList/ListDetail/List.js | 42 + src/screens/Home/SongList/ListDetail/index.js | 137 + src/screens/Home/SongList/index.js | 25 + src/screens/Home/Top/BoardsList.js | 77 + src/screens/Home/Top/LeftBar.js | 32 + src/screens/Home/Top/MusicList.js | 74 + src/screens/Home/Top/SourceSelector.js | 42 + src/screens/Home/Top/index.js | 26 + src/screens/Home/components/Aside.js | 172 + src/screens/Home/components/FooterPlayer.js | 11 + src/screens/Home/components/Header.js | 101 + src/screens/Home/components/Main.js | 215 + .../Home/components/PlayerLandscape.js | 125 + .../PlayerPortrait/components/ControlBtn.js | 90 + .../PlayerPortrait/components/Pic.js | 55 + .../PlayerPortrait/components/PlayInfo.js | 54 + .../PlayerPortrait/components/Status.js | 25 + .../PlayerPortrait/components/Title.js | 40 + .../Home/components/PlayerPortrait/index.js | 81 + src/screens/Home/index.js | 20 + src/screens/index.js | 6 + src/store/.bak/actions/common.js | 23 + src/store/.bak/actions/counts.js | 23 + src/store/.bak/actions/search.js | 76 + src/store/.bak/reducers/common.js | 34 + src/store/.bak/reducers/count.js | 19 + src/store/.bak/reducers/index.js | 19 + src/store/.bak/reducers/search.js | 220 + src/store/Provider/Provider.js | 32 + src/store/Provider/index.js | 1 + src/store/connect.js | 23 + src/store/index.js | 7 + src/store/modules/common/action.js | 238 + src/store/modules/common/getter.js | 50 + src/store/modules/common/index.js | 5 + src/store/modules/common/reducer.js | 244 + src/store/modules/index.js | 15 + src/store/modules/list/action.js | 262 + src/store/modules/list/getter.js | 25 + src/store/modules/list/index.js | 5 + src/store/modules/list/reducer.js | 281 + src/store/modules/player/action.js | 763 ++ src/store/modules/player/getter.js | 63 + src/store/modules/player/index.js | 7 + src/store/modules/player/reducer.js | 120 + src/store/modules/search/action.js | 88 + src/store/modules/search/getter.js | 33 + src/store/modules/search/index.js | 5 + src/store/modules/search/reducer.js | 248 + src/store/modules/songList/action.js | 217 + src/store/modules/songList/getter.js | 31 + src/store/modules/songList/index.js | 5 + src/store/modules/songList/reducer.js | 190 + src/store/modules/top/action.js | 158 + src/store/modules/top/getter.js | 24 + src/store/modules/top/index.js | 5 + src/store/modules/top/reducer.js | 82 + src/store/reducer.js | 27 + src/store/store.js | 48 + src/store/subscriber.js | 7 + src/store/useDispatch.js | 24 + src/store/useGetter.js | 23 + src/theme/Colors.js | 122 + src/theme/Typography.js | 50 + src/theme/index.js | 18 + src/theme/themes/blue.js | 39 + src/theme/themes/green.js | 39 + src/theme/themes/index.js | 3 + src/theme/themes/red.js | 39 + src/utils/cache.js | 6 + src/utils/common.js | 44 + src/utils/env.js | 5 + src/utils/fs.js | 53 + src/utils/gzip.js | 12 + src/utils/hooks/index.js | 6 + src/utils/hooks/useAssertApiSupport.js | 7 + src/utils/hooks/useDimensions.js | 21 + src/utils/hooks/useKeyboard.js | 32 + src/utils/hooks/useLayout.js | 16 + src/utils/hooks/usePlayTime.js | 19 + src/utils/index.js | 127 + src/utils/log.js | 58 + src/utils/message.js | 8 + src/utils/music/api-source-info.js | 26 + src/utils/music/api-source.js | 41 + src/utils/music/bd/api-test.js | 20 + src/utils/music/bd/hotSearch.js | 23 + src/utils/music/bd/index.js | 41 + src/utils/music/bd/leaderboard.js | 155 + src/utils/music/bd/musicInfo.js | 20 + src/utils/music/bd/musicSearch.js | 90 + src/utils/music/bd/songList.js | 266 + src/utils/music/index.js | 137 + src/utils/music/kg/api-test.js | 44 + src/utils/music/kg/comment.js | 79 + src/utils/music/kg/hotSearch.js | 33 + src/utils/music/kg/index.js | 36 + src/utils/music/kg/leaderboard.js | 210 + src/utils/music/kg/lyric.js | 138 + src/utils/music/kg/musicSearch.js | 105 + src/utils/music/kg/pic.js | 50 + src/utils/music/kg/songList.js | 590 ++ src/utils/music/kg/util.js | 22 + src/utils/music/kw/album.js | 101 + src/utils/music/kw/api-temp.js | 19 + src/utils/music/kw/api-test.js | 31 + src/utils/music/kw/comment.js | 61 + src/utils/music/kw/decodeLyric.js | 40 + src/utils/music/kw/hotSearch.js | 22 + src/utils/music/kw/index.js | 113 + src/utils/music/kw/leaderboard.js | 208 + src/utils/music/kw/lyric.js | 20 + src/utils/music/kw/musicSearch.js | 150 + src/utils/music/kw/pic.js | 9 + src/utils/music/kw/songList.js | 316 + src/utils/music/kw/tempSearch.js | 32 + src/utils/music/kw/util.js | 76 + src/utils/music/mg/album.js | 30 + src/utils/music/mg/api-test.js | 20 + src/utils/music/mg/comment.js | 95 + src/utils/music/mg/hotSearch.js | 18 + src/utils/music/mg/index.js | 30 + src/utils/music/mg/leaderboard.js | 212 + src/utils/music/mg/leaderboard2.js | 174 + src/utils/music/mg/lyric.js | 42 + src/utils/music/mg/musicSearch.js | 125 + src/utils/music/mg/pic.js | 21 + src/utils/music/mg/songList.js | 307 + src/utils/music/options.js | 9 + src/utils/music/tx/api-test.js | 25 + src/utils/music/tx/comment.js | 187 + src/utils/music/tx/hotSearch.js | 23 + src/utils/music/tx/index.js | 31 + src/utils/music/tx/leaderboard.js | 255 + src/utils/music/tx/lyric.js | 23 + src/utils/music/tx/musicSearch.js | 107 + src/utils/music/tx/songList.js | 302 + src/utils/music/tx/tipSearch.js | 30 + src/utils/music/utils.js | 21 + src/utils/music/wy/api-test.js | 44 + src/utils/music/wy/comment.js | 138 + src/utils/music/wy/hotSearch.js | 26 + src/utils/music/wy/index.js | 32 + src/utils/music/wy/leaderboard.js | 202 + src/utils/music/wy/lyric.js | 62 + src/utils/music/wy/musicDetail.js | 91 + src/utils/music/wy/musicInfo.js | 25 + src/utils/music/wy/musicSearch.js | 128 + src/utils/music/wy/songList.js | 282 + src/utils/music/wy/utils/crypto.js | 33 + src/utils/music/xm.js | 57 + src/utils/request.js | 194 + src/utils/tools.js | 186 + src/utils/utils.js | 9 + src/utils/version.js | 109 + track-player.json | 5 + yarn.lock | 9073 +++++++++++++++++ 342 files changed, 32986 insertions(+) create mode 100644 .buckconfig create mode 100644 .editorconfig create mode 100644 .eslintrc.js create mode 100644 .flowconfig create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/----.md create mode 100644 .github/ISSUE_TEMPLATE/--bug.md create mode 100644 .github/workflows/beta-pack.yml create mode 100644 .github/workflows/release.yml create mode 100644 .gitignore create mode 100644 .prettierrc.js create mode 100644 .vscode/javascript.code-snippets create mode 100644 .vscode/settings.json create mode 100644 .watchmanconfig create mode 100644 CHANGELOG.md create mode 100644 FAQ.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 android/app/BUCK create mode 100644 android/app/build.gradle create mode 100644 android/app/build_defs.bzl create mode 100644 android/app/debug.keystore create mode 100644 android/app/proguard-rules.pro create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/debug/java/com/lxmusicmobile/ReactNativeFlipper.java create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/assets/fonts/AntDesign.ttf create mode 100644 android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf create mode 100644 android/app/src/main/assets/fonts/icomoon.ttf create mode 100644 android/app/src/main/java/com/lxmusicmobile/MainActivity.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/MainApplication.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/cache/CacheClearAsyncTask.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/cache/CacheModule.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/cache/CachePackage.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/cache/Utils.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/gzip/GzipModule.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/gzip/GzipPackage.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/gzip/Utils.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/utils/UtilsModule.java create mode 100644 android/app/src/main/java/com/lxmusicmobile/utils/UtilsPackage.java create mode 100644 android/app/src/main/res/drawable-hdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-land-hdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-land-mdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-land-xhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-land-xxhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-land-xxxhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-mdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-xhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/launch_screen.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/launch_screen.png create mode 100644 android/app/src/main/res/layout/launch_screen.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 android/app/src/main/res/values/strings.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/main/res/xml/file_paths.xml create mode 100644 android/app/src/main/res/xml/network_security_config.xml create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100755 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/settings.gradle create mode 100644 app.json create mode 100644 babel.config.js create mode 100644 doc/images/icon.png create mode 100644 index.js create mode 100644 jsconfig.json create mode 100644 metro.config.js create mode 100644 package.json create mode 100644 publish/changeLog.md create mode 100644 publish/index.js create mode 100644 publish/utils/index.js create mode 100644 publish/utils/updateChangeLog.js create mode 100644 publish/version.json create mode 100644 shim.js create mode 100644 src/components/ListItem/index.js create mode 100644 src/components/MusicAddModal.js create mode 100644 src/components/MusicMultiAddModal.js create mode 100644 src/components/OnlineList/ExitMultipleModeBar.js create mode 100644 src/components/OnlineList/Footer.js create mode 100644 src/components/OnlineList/ListItem.js create mode 100644 src/components/OnlineList/index.js create mode 100644 src/components/SearchInput.js create mode 100644 src/components/common/Badge.js create mode 100644 src/components/common/Button.js create mode 100644 src/components/common/CheckBox.js create mode 100644 src/components/common/ChoosePath/List.js create mode 100644 src/components/common/ChoosePath/components/Footer.js create mode 100644 src/components/common/ChoosePath/components/Header.js create mode 100644 src/components/common/ChoosePath/components/ListItem.js create mode 100644 src/components/common/ChoosePath/components/Main.js create mode 100644 src/components/common/ChoosePath/index.js create mode 100644 src/components/common/ConfirmAlert.js create mode 100644 src/components/common/Dialog.js create mode 100644 src/components/common/DorpDownMenu.js create mode 100644 src/components/common/DorpDownPanel/Panel.js create mode 100644 src/components/common/DorpDownPanel/index.js create mode 100644 src/components/common/Icon.js create mode 100644 src/components/common/Input.js create mode 100644 src/components/common/LoadingMask.js create mode 100644 src/components/common/Menu.js create mode 100644 src/components/common/Modal.js create mode 100644 src/components/layout/Header.js create mode 100644 src/components/player/Progress.js create mode 100644 src/components/searchTipList.js create mode 100644 src/config/constant.js create mode 100644 src/config/defaultSetting.js create mode 100644 src/config/globalData.js create mode 100644 src/config/index.js create mode 100644 src/config/setting.js create mode 100644 src/lang/Readme.md create mode 100644 src/lang/en_us.json create mode 100644 src/lang/index.js create mode 100644 src/lang/zh_cn.json create mode 100644 src/navigation/components/PactModal.js create mode 100644 src/navigation/components/Toast.js create mode 100644 src/navigation/components/VersionModal.js create mode 100644 src/navigation/index.js create mode 100644 src/navigation/navigation.js create mode 100644 src/navigation/registerScreens.js create mode 100644 src/navigation/screenNames.js create mode 100644 src/navigation/utils.js create mode 100644 src/plugins/i18n.js create mode 100644 src/plugins/lyric.js create mode 100644 src/plugins/player/Player.js create mode 100644 src/plugins/player/hook.js create mode 100644 src/plugins/player/index.js create mode 100644 src/plugins/player/service.js create mode 100644 src/plugins/player/utils.js create mode 100644 src/plugins/storage.js create mode 100644 src/resources/fonts/icomoon.ttf create mode 100644 src/resources/fonts/selection.json create mode 100644 src/resources/medias/Silence02s.mp3 create mode 100644 src/screens/Home/Download/index.js create mode 100644 src/screens/Home/List/components/ExitMultipleModeBar.js create mode 100644 src/screens/Home/List/components/ListItem.js create mode 100644 src/screens/Home/List/components/MusicPositionModal.js create mode 100644 src/screens/Home/List/components/MyList.js create mode 100644 src/screens/Home/List/index.js create mode 100644 src/screens/Home/Search/components/Input.js create mode 100644 src/screens/Home/Search/components/MusicList.js create mode 100644 src/screens/Home/Search/components/SourceSelector.js create mode 100644 src/screens/Home/Search/components/TipList.js create mode 100644 src/screens/Home/Search/index.js create mode 100644 src/screens/Home/Setting/About.js create mode 100644 src/screens/Home/Setting/Backup/All.js create mode 100644 src/screens/Home/Setting/Backup/Part.js create mode 100644 src/screens/Home/Setting/Backup/index.js create mode 100644 src/screens/Home/Setting/Basic/Language.js create mode 100644 src/screens/Home/Setting/Basic/Source.js create mode 100644 src/screens/Home/Setting/Basic/SourceName.js create mode 100644 src/screens/Home/Setting/Basic/Theme.js create mode 100644 src/screens/Home/Setting/Basic/index.js create mode 100644 src/screens/Home/Setting/Other/Cache.js create mode 100644 src/screens/Home/Setting/Other/index.js create mode 100644 src/screens/Home/Setting/Player/IsPlayHighQuality.js create mode 100644 src/screens/Home/Setting/Player/MaxCache.js create mode 100644 src/screens/Home/Setting/Player/index.js create mode 100644 src/screens/Home/Setting/Version.js create mode 100644 src/screens/Home/Setting/components/Button.js create mode 100644 src/screens/Home/Setting/components/CheckBoxItem.js create mode 100644 src/screens/Home/Setting/components/InputItem.js create mode 100644 src/screens/Home/Setting/components/Section.js create mode 100644 src/screens/Home/Setting/components/SubTitle.js create mode 100644 src/screens/Home/Setting/index.js create mode 100644 src/screens/Home/SongList/List/List.js create mode 100644 src/screens/Home/SongList/List/ListItem.js create mode 100644 src/screens/Home/SongList/List/MenuBar.js create mode 100644 src/screens/Home/SongList/List/SortTab.js create mode 100644 src/screens/Home/SongList/List/SourceSelector.js create mode 100644 src/screens/Home/SongList/List/Tag.js create mode 100644 src/screens/Home/SongList/List/index.js create mode 100644 src/screens/Home/SongList/ListDetail/ButtonBar.js create mode 100644 src/screens/Home/SongList/ListDetail/Header.js create mode 100644 src/screens/Home/SongList/ListDetail/List.js create mode 100644 src/screens/Home/SongList/ListDetail/index.js create mode 100644 src/screens/Home/SongList/index.js create mode 100644 src/screens/Home/Top/BoardsList.js create mode 100644 src/screens/Home/Top/LeftBar.js create mode 100644 src/screens/Home/Top/MusicList.js create mode 100644 src/screens/Home/Top/SourceSelector.js create mode 100644 src/screens/Home/Top/index.js create mode 100644 src/screens/Home/components/Aside.js create mode 100644 src/screens/Home/components/FooterPlayer.js create mode 100644 src/screens/Home/components/Header.js create mode 100644 src/screens/Home/components/Main.js create mode 100644 src/screens/Home/components/PlayerLandscape.js create mode 100644 src/screens/Home/components/PlayerPortrait/components/ControlBtn.js create mode 100644 src/screens/Home/components/PlayerPortrait/components/Pic.js create mode 100644 src/screens/Home/components/PlayerPortrait/components/PlayInfo.js create mode 100644 src/screens/Home/components/PlayerPortrait/components/Status.js create mode 100644 src/screens/Home/components/PlayerPortrait/components/Title.js create mode 100644 src/screens/Home/components/PlayerPortrait/index.js create mode 100644 src/screens/Home/index.js create mode 100644 src/screens/index.js create mode 100644 src/store/.bak/actions/common.js create mode 100644 src/store/.bak/actions/counts.js create mode 100644 src/store/.bak/actions/search.js create mode 100644 src/store/.bak/reducers/common.js create mode 100644 src/store/.bak/reducers/count.js create mode 100644 src/store/.bak/reducers/index.js create mode 100644 src/store/.bak/reducers/search.js create mode 100644 src/store/Provider/Provider.js create mode 100644 src/store/Provider/index.js create mode 100644 src/store/connect.js create mode 100644 src/store/index.js create mode 100644 src/store/modules/common/action.js create mode 100644 src/store/modules/common/getter.js create mode 100644 src/store/modules/common/index.js create mode 100644 src/store/modules/common/reducer.js create mode 100644 src/store/modules/index.js create mode 100644 src/store/modules/list/action.js create mode 100644 src/store/modules/list/getter.js create mode 100644 src/store/modules/list/index.js create mode 100644 src/store/modules/list/reducer.js create mode 100644 src/store/modules/player/action.js create mode 100644 src/store/modules/player/getter.js create mode 100644 src/store/modules/player/index.js create mode 100644 src/store/modules/player/reducer.js create mode 100644 src/store/modules/search/action.js create mode 100644 src/store/modules/search/getter.js create mode 100644 src/store/modules/search/index.js create mode 100644 src/store/modules/search/reducer.js create mode 100644 src/store/modules/songList/action.js create mode 100644 src/store/modules/songList/getter.js create mode 100644 src/store/modules/songList/index.js create mode 100644 src/store/modules/songList/reducer.js create mode 100644 src/store/modules/top/action.js create mode 100644 src/store/modules/top/getter.js create mode 100644 src/store/modules/top/index.js create mode 100644 src/store/modules/top/reducer.js create mode 100644 src/store/reducer.js create mode 100644 src/store/store.js create mode 100644 src/store/subscriber.js create mode 100644 src/store/useDispatch.js create mode 100644 src/store/useGetter.js create mode 100644 src/theme/Colors.js create mode 100644 src/theme/Typography.js create mode 100644 src/theme/index.js create mode 100644 src/theme/themes/blue.js create mode 100644 src/theme/themes/green.js create mode 100644 src/theme/themes/index.js create mode 100644 src/theme/themes/red.js create mode 100644 src/utils/cache.js create mode 100644 src/utils/common.js create mode 100644 src/utils/env.js create mode 100644 src/utils/fs.js create mode 100644 src/utils/gzip.js create mode 100644 src/utils/hooks/index.js create mode 100644 src/utils/hooks/useAssertApiSupport.js create mode 100644 src/utils/hooks/useDimensions.js create mode 100644 src/utils/hooks/useKeyboard.js create mode 100644 src/utils/hooks/useLayout.js create mode 100644 src/utils/hooks/usePlayTime.js create mode 100644 src/utils/index.js create mode 100644 src/utils/log.js create mode 100644 src/utils/message.js create mode 100644 src/utils/music/api-source-info.js create mode 100644 src/utils/music/api-source.js create mode 100644 src/utils/music/bd/api-test.js create mode 100644 src/utils/music/bd/hotSearch.js create mode 100644 src/utils/music/bd/index.js create mode 100644 src/utils/music/bd/leaderboard.js create mode 100644 src/utils/music/bd/musicInfo.js create mode 100644 src/utils/music/bd/musicSearch.js create mode 100644 src/utils/music/bd/songList.js create mode 100644 src/utils/music/index.js create mode 100644 src/utils/music/kg/api-test.js create mode 100644 src/utils/music/kg/comment.js create mode 100644 src/utils/music/kg/hotSearch.js create mode 100644 src/utils/music/kg/index.js create mode 100644 src/utils/music/kg/leaderboard.js create mode 100644 src/utils/music/kg/lyric.js create mode 100644 src/utils/music/kg/musicSearch.js create mode 100644 src/utils/music/kg/pic.js create mode 100644 src/utils/music/kg/songList.js create mode 100644 src/utils/music/kg/util.js create mode 100644 src/utils/music/kw/album.js create mode 100644 src/utils/music/kw/api-temp.js create mode 100644 src/utils/music/kw/api-test.js create mode 100644 src/utils/music/kw/comment.js create mode 100644 src/utils/music/kw/decodeLyric.js create mode 100644 src/utils/music/kw/hotSearch.js create mode 100644 src/utils/music/kw/index.js create mode 100644 src/utils/music/kw/leaderboard.js create mode 100644 src/utils/music/kw/lyric.js create mode 100644 src/utils/music/kw/musicSearch.js create mode 100644 src/utils/music/kw/pic.js create mode 100644 src/utils/music/kw/songList.js create mode 100644 src/utils/music/kw/tempSearch.js create mode 100644 src/utils/music/kw/util.js create mode 100644 src/utils/music/mg/album.js create mode 100644 src/utils/music/mg/api-test.js create mode 100644 src/utils/music/mg/comment.js create mode 100644 src/utils/music/mg/hotSearch.js create mode 100644 src/utils/music/mg/index.js create mode 100644 src/utils/music/mg/leaderboard.js create mode 100644 src/utils/music/mg/leaderboard2.js create mode 100644 src/utils/music/mg/lyric.js create mode 100644 src/utils/music/mg/musicSearch.js create mode 100644 src/utils/music/mg/pic.js create mode 100644 src/utils/music/mg/songList.js create mode 100644 src/utils/music/options.js create mode 100644 src/utils/music/tx/api-test.js create mode 100644 src/utils/music/tx/comment.js create mode 100644 src/utils/music/tx/hotSearch.js create mode 100644 src/utils/music/tx/index.js create mode 100644 src/utils/music/tx/leaderboard.js create mode 100644 src/utils/music/tx/lyric.js create mode 100644 src/utils/music/tx/musicSearch.js create mode 100644 src/utils/music/tx/songList.js create mode 100644 src/utils/music/tx/tipSearch.js create mode 100644 src/utils/music/utils.js create mode 100644 src/utils/music/wy/api-test.js create mode 100644 src/utils/music/wy/comment.js create mode 100644 src/utils/music/wy/hotSearch.js create mode 100644 src/utils/music/wy/index.js create mode 100644 src/utils/music/wy/leaderboard.js create mode 100644 src/utils/music/wy/lyric.js create mode 100644 src/utils/music/wy/musicDetail.js create mode 100644 src/utils/music/wy/musicInfo.js create mode 100644 src/utils/music/wy/musicSearch.js create mode 100644 src/utils/music/wy/songList.js create mode 100644 src/utils/music/wy/utils/crypto.js create mode 100644 src/utils/music/xm.js create mode 100644 src/utils/request.js create mode 100644 src/utils/tools.js create mode 100644 src/utils/utils.js create mode 100644 src/utils/version.js create mode 100644 track-player.json create mode 100644 yarn.lock diff --git a/.buckconfig b/.buckconfig new file mode 100644 index 0000000..934256c --- /dev/null +++ b/.buckconfig @@ -0,0 +1,6 @@ + +[android] + target = Google Inc.:Google APIs:23 + +[maven_repositories] + central = https://repo1.maven.org/maven2 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ab3ba88 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +# Windows files +[*.bat] +end_of_line = crlf diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..4a9b57e --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + extends: [ + 'standard', + 'plugin:react-hooks/recommended', + ], + plugins: ['html', 'react'], + parser: 'babel-eslint', + rules: { + 'no-new': 'off', + camelcase: 'off', + 'no-return-assign': 'off', + 'space-before-function-paren': ['error', 'never'], + 'no-var': 'error', + 'no-fallthrough': 'off', + 'prefer-promise-reject-errors': 'off', + eqeqeq: 'off', + 'no-multiple-empty-lines': [1, { max: 2 }], + 'comma-dangle': [2, 'always-multiline'], + 'react/jsx-uses-react': 'error', + 'react/jsx-uses-vars': 'error', + 'prefer-const': 'off', + }, + settings: { + 'html/html-extensions': ['.jsx'], + }, +} diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..315f274 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,66 @@ +[ignore] +; We fork some components by platform +.*/*[.]android.js + +; Ignore "BUCK" generated dirs +/\.buckd/ + +; Ignore polyfills +node_modules/react-native/Libraries/polyfills/.* + +; Flow doesn't support platforms +.*/Libraries/Utilities/LoadingView.js + +[untyped] +.*/node_modules/@react-native-community/cli/.*/.* + +[include] + +[libs] +node_modules/react-native/interface.js +node_modules/react-native/flow/ + +[options] +emoji=true + +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable + +exact_by_default=true + +module.file_ext=.js +module.file_ext=.json +module.file_ext=.ios.js + +munge_underscores=true + +module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' +module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState + +[lints] +sketchy-null-number=warn +sketchy-null-mixed=warn +sketchy-number=warn +untyped-type-import=warn +nonstrict-import=warn +deprecated-type=warn +unsafe-getters-setters=warn +unnecessary-invariant=warn +signature-verification-failure=warn + +[strict] +deprecated-type +nonstrict-import +sketchy-null +unclear-type +unsafe-getters-setters +untyped-import +untyped-type-import + +[version] +^0.137.0 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..59b845b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Windows files should use crlf line endings +# https://help.github.com/articles/dealing-with-line-endings/ +*.bat text eol=crlf \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/----.md b/.github/ISSUE_TEMPLATE/----.md new file mode 100644 index 0000000..848bd9a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/----.md @@ -0,0 +1,25 @@ +--- +name: 功能请求(请先查看常见问题及搜索issue列表中有无你要提的问题) +about: 为这个项目提出一个想法 +title: 例如:添加xxx功能、优化xxx功能 +labels: '' +assignees: '' + +--- + +**解决方案检查** + +- [ ] 我已阅读常见问题() +- [ ] 我已搜索issue列表() + +**描述您想要的解决方案** + + + +**描述您考虑过的替代方案** + + + +**其他内容** + + diff --git a/.github/ISSUE_TEMPLATE/--bug.md b/.github/ISSUE_TEMPLATE/--bug.md new file mode 100644 index 0000000..f0a8160 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/--bug.md @@ -0,0 +1,42 @@ +--- +name: 报告Bug(请先查看常见问题及搜索issue列表中有无你要提的问题) +about: 创建报告以帮助我们改进 +title: 例如:音乐无法播放 +labels: '' +assignees: '' + +--- + +**解决方案检查** + +- [ ] 我已阅读常见问题() +- [ ] 我已搜索issue列表() + +**描述错误** + + + +**重现** +重现行为的步骤: +1.转到“ ...” +2.点击“ ....” +3.向下滚动到“ ....” +4.看到错误 + + +**预期行为** + + + +**截图** + + + +**环境:** +  -操作系统及版本:[例如:Windows 10 64位 18362.156] +  -软件安装包及版本:[例如:1.0.0 安装版] + + +**其他内容** + + diff --git a/.github/workflows/beta-pack.yml b/.github/workflows/beta-pack.yml new file mode 100644 index 0000000..bb59571 --- /dev/null +++ b/.github/workflows/beta-pack.yml @@ -0,0 +1,80 @@ +name: Build Beta + +on: + push: + branches: + - beta + +jobs: + Android: + name: Android + runs-on: ubuntu-latest + steps: + - name: Check out git repository + uses: actions/checkout@v2 + + - name: Install Node.js + uses: actions/setup-node@v2 + with: + node-version: '12.x' + + - name: Cache Gradle Wrapper + uses: actions/cache@v2 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + + - name: Cache Gradle Dependencies + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-caches-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle-caches- + + - name: Cache Node Dependencies + uses: actions/cache@v2 + with: + path: node_modules + key: ${{ runner.os }}-node-caches-${{ hashFiles('**/yarn-lock.json') }} + restore-keys: | + ${{ runner.os }}-node-caches- + + - name: Install dependencies + run: yarn install + + - name: Build Packages + run: | + cd android + echo ${{ secrets.KEYSTORE_STORE_FILE_BASE64 }} | base64 --decode > app/${{ secrets.KEYSTORE_STORE_FILE }} + ./gradlew assembleRelease -PMYAPP_UPLOAD_STORE_FILE='${{ secrets.KEYSTORE_STORE_FILE }}' -PMYAPP_UPLOAD_KEY_ALIAS='${{ secrets.KEYSTORE_KEY_ALIAS }}' -PMYAPP_UPLOAD_STORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}' -PMYAPP_UPLOAD_KEY_PASSWORD='${{ secrets.KEYSTORE_KEY_PASSWORD }}' + + - name: Upload Artifact arm64-v8a + uses: actions/upload-artifact@v2 + with: + name: app-arm64-v8a-release + path: android/app/build/outputs/apk/release/app-arm64-v8a-release.apk + + - name: Upload Artifact armeabi-v7a + uses: actions/upload-artifact@v2 + with: + name: app-armeabi-v7a-release + path: android/app/build/outputs/apk/release/app-armeabi-v7a-release.apk + + - name: Upload Artifact universal + uses: actions/upload-artifact@v2 + with: + name: app-universal-release + path: android/app/build/outputs/apk/release/app-universal-release.apk + + - name: Upload Artifact x86_64 + uses: actions/upload-artifact@v2 + with: + name: app-x86_64-release + path: android/app/build/outputs/apk/release/app-x86_64-release.apk + + - name: Upload Artifact x86 + uses: actions/upload-artifact@v2 + with: + name: app-x86-release + path: android/app/build/outputs/apk/release/app-x86-release.apk diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..089c300 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,109 @@ +name: Build + +on: + push: + branches: + - master + +jobs: + Android: + name: Android + runs-on: ubuntu-latest + steps: + - name: Check out git repository + uses: actions/checkout@v2 + + - name: Install Node.js + uses: actions/setup-node@v2 + with: + node-version: '12.x' + + - name: Cache Gradle Wrapper + uses: actions/cache@v2 + with: + path: ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + + - name: Cache Gradle Dependencies + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-caches-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle-caches- + + - name: Cache Node Dependencies + uses: actions/cache@v2 + with: + path: node_modules + key: ${{ runner.os }}-node-caches-${{ hashFiles('**/yarn-lock.json') }} + restore-keys: | + ${{ runner.os }}-node-caches- + + - name: Install dependencies + run: yarn install + + - name: Build Packages + run: | + cd android + echo ${{ secrets.KEYSTORE_STORE_FILE_BASE64 }} | base64 --decode > app/${{ secrets.KEYSTORE_STORE_FILE }} + ./gradlew assembleRelease -PMYAPP_UPLOAD_STORE_FILE='${{ secrets.KEYSTORE_STORE_FILE }}' -PMYAPP_UPLOAD_KEY_ALIAS='${{ secrets.KEYSTORE_KEY_ALIAS }}' -PMYAPP_UPLOAD_STORE_PASSWORD='${{ secrets.KEYSTORE_PASSWORD }}' -PMYAPP_UPLOAD_KEY_PASSWORD='${{ secrets.KEYSTORE_KEY_PASSWORD }}' + + # Push tag to GitHub if package.json version's tag is not tagged + - name: Get package version + run: node -p -e '`PACKAGE_VERSION=${require("./package.json").version}`' >> $GITHUB_ENV + + - name: Create git tag + uses: pkgdeps/git-tag-action@v2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + github_repo: ${{ github.repository }} + version: ${{ env.PACKAGE_VERSION }} + git_commit_sha: ${{ github.sha }} + git_tag_prefix: "v" + + - name: Release + uses: softprops/action-gh-release@v1 + with: + body_path: ./publish/changeLog.md + prerelease: false + draft: false + tag_name: v${{ env.PACKAGE_VERSION }} + files: | + android/app/build/outputs/apk/release/app-arm64-v8a-release.apk + android/app/build/outputs/apk/release/app-armeabi-v7a-release.apk + android/app/build/outputs/apk/release/app-x86_64-release.apk + android/app/build/outputs/apk/release/app-x86-release.apk + android/app/build/outputs/apk/release/app-universal-release.apk + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Artifact arm64-v8a + uses: actions/upload-artifact@v2 + with: + name: app-arm64-v8a-release + path: android/app/build/outputs/apk/release/app-arm64-v8a-release.apk + + - name: Upload Artifact armeabi-v7a + uses: actions/upload-artifact@v2 + with: + name: app-armeabi-v7a-release + path: android/app/build/outputs/apk/release/app-armeabi-v7a-release.apk + + - name: Upload Artifact universal + uses: actions/upload-artifact@v2 + with: + name: app-universal-release + path: android/app/build/outputs/apk/release/app-universal-release.apk + + - name: Upload Artifact x86_64 + uses: actions/upload-artifact@v2 + with: + name: app-x86_64-release + path: android/app/build/outputs/apk/release/app-x86_64-release.apk + + - name: Upload Artifact x86 + uses: actions/upload-artifact@v2 + with: + name: app-x86-release + path: android/app/build/outputs/apk/release/app-x86-release.apk diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dfb453b --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +keystore.properties +*.iml + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +*.keystore +!debug.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +*/fastlane/report.xml +*/fastlane/Preview.html +*/fastlane/screenshots + +# Bundle artifact +*.jsbundle + +# CocoaPods +/ios/Pods/ diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..84196d9 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + bracketSpacing: false, + jsxBracketSameLine: true, + singleQuote: true, + trailingComma: 'all', + arrowParens: 'avoid', +}; diff --git a/.vscode/javascript.code-snippets b/.vscode/javascript.code-snippets new file mode 100644 index 0000000..1abd323 --- /dev/null +++ b/.vscode/javascript.code-snippets @@ -0,0 +1,52 @@ +{ + // Place your LxMusicMobile 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } + "Import translation": { + "scope": "javascript,typescript", + "prefix": "imtl", + "body": [ + "import { useTranslation } from '@/plugins/i18n'", + "$1const { t } = useTranslation()" + ], + "description": "Translation Language" + }, + "Import store hook": { + "scope": "javascript,typescript", + "prefix": "imsh", + "body": [ + "import { useGetter, useDispatch } from '@/store'" + ], + "description": "Import store hook" + }, + "Import toast": { + "scope": "javascript,typescript", + "prefix": "imts", + "body": [ + "import { toast } from '@/utils/tools'", + "$1toast(t(''), 'long')" + ], + "description": "Import toast" + }, + "Use getter theme": { + "scope": "javascript,typescript", + "prefix": "ugt", + "body": [ + "const theme = useGetter('common', 'theme')" + ], + "description": "Use getter theme" + }, +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5a26fc0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "path-intellisense.mappings": { + // "@config": "${workspaceFolder}/src/config", + // "@store": "${workspaceFolder}/src/store", + // "@components": "${workspaceFolder}/src/components", + // "@navigation": "${workspaceFolder}/src/navigation", + // "@screens": "${workspaceFolder}/src/screens", + // "@theme": "${workspaceFolder}/src/theme", + "@/*": "${workspaceFolder}/src/*" + } +} diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..41864c6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# lx-music-desktop change log + +All notable changes to this project will be documented in this file. + +Project versioning adheres to [Semantic Versioning](http://semver.org/). +Commit convention is based on [Conventional Commits](http://conventionalcommits.org). +Change log format is based on [Keep a Changelog](http://keepachangelog.com/). + +## [0.1.1] - 2020-05-15 + +- v0.1.1版本发布 🎊 🎉 diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 0000000..5d6f1ae --- /dev/null +++ b/FAQ.md @@ -0,0 +1,66 @@ +# lx-music-mobile 常见问题 + +在阅读本常见问题后,仍然无法解决你的问题,请提交issue或者加企鹅群`830125506`反馈(无事勿加,入群先看群公告),反馈时请**注明**已阅读常见问题! + +## 歌曲无法试听与下载 + +### 所有歌曲都提示 `请求异常😮,可以多试几次,若还是不行就换一首吧。。。` + +尝试更换网络,如切换到移动网络,若移动网络还是不行则尝试开关下手机的飞行模式后再试,
+若使用家庭网络的话,可尝试将光猫断电5分钟左右再通电联网后播放。 + +### 其他情况 + +尝试在在浏览器打开这个地址`http://ts.tempmusic.tk`,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器,对于此类情况请尝试切换其他网络。 + +### 通用解决方法 + +尝试按以下顺序解决: + +1. 尝试更新到最新版本 +2. 尝试切换其他歌曲(或直接搜索该歌曲),若全部歌曲都无法试听与下载则进行下一步 +3. 尝试到 设置-音乐来源 切换到其他接口 +4. 尝试切换网络,比如用手机开热点(所有歌曲都提示请求异常时可通过此方法解决,或等一两天后再试) +5. 若还不行请到这个链接查看详情: +6. 若没有在第5条链接中的第一条评论中看到接口无法使用的说明,则应该是你网络无法访问接口服务器的问题,如果接口有问题我会在那里说明。 + +想要知道是不是自己网络的问题可以看看`http://ts.tempmusic.tk`能不能在浏览器打开,浏览器显示404是正常的,如果不是404那就证明所在网络无法访问接口服务器。 +若网页无法打开或打来不是404,则应该是DNS的问题,可以尝试以下办法: + +1. 将DNS改成自动获取试试 +2. 手动把DNS改一下,不要用360的DNS,可以把DNS改成`114.114.114.114`、`8.8.8.8` + +## 列表多选 + +长按列表将会进入多选模式。 + +- 例子一:想要选中1-5项,进入多选模式后,取消所有选中的内容,切换到区间,点击第一项,再点击第五项即可完成选择; +- 例子二:想要选中1项与第3项,进入多选模式后,点击第一项,再点击第三项即可完成选择; +- 例子三:想要选中当前列表的全部内容,进入多选模式后,点击全选即可完成选择(注:由于**在线列表**使用分页加载,全选只会选择目前已加载的内容,若要完整选择整个在线列表的内容则需要往下滑动将列表加载完毕再进行全选)。 + +注:选完后可用鼠标右击弹出右键菜单操作已选的内容 + +## 播放整个歌单或排行榜 + +播放在线列表内的歌曲需要将它们都添加到我的列表才能播放,你可以全选列表内的歌曲然后添加到现有列表或者新创建的列表,然后去播放该列表内的歌曲。 + + + + + +## 杀毒软件提示有病毒或恶意行为 + +本人只能保证我写的代码不包含任何**恶意代码**、**收集用户信息**的行为,并且软件代码已开源,请自行查阅,软件安装包也是由CI拉取源代码构建,构建日志:[GitHub Actions](https://github.com/lyswhut/lx-music-mobile/actions)
+尽管如此,但这不意味着软件是100%安全的,由于软件使用了第三方依赖,当这些依赖存在恶意行为时([供应链攻击](https://docs.microsoft.com/zh-cn/windows/security/threat-protection/intelligence/supply-chain-malware)),软件也将会受到牵连,所以我只能尽量选择使用较多人用、信任度较高的依赖。
+当然,以上说明建立的前提是在你所用的安装包是从**本项目主页上写的链接**下载的,或者有相关能力者还可以下载源代码自己构建安装包。 + +最后,若出现杀毒软件报毒、存在恶意行为,请自行判断选择是否继续使用本软件! diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..afc5415 --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +

lx-music logo

+ +

+ Release version + Build status + Build status + React native version + + Dev branch version + +

+ + +

洛雪音乐助手移动版

+ +### 说明 + +一个基于 React native 开发的音乐软件。 + +所用技术栈: + +- React native + +支持的平台: + +- Android + +注:不计划支持IOS + +软件变化请查看:[更新日志](https://github.com/lyswhut/lx-music-mobile/blob/master/CHANGELOG.md)
+软件下载请转到:[发布页面](https://github.com/lyswhut/lx-music-mobile/releases)
+或者到网盘下载(网盘内有MAC、windows版):`https://www.lanzous.com/b0bf2cfa/` 密码:`glqw`(若链接无法打开请百度:蓝奏云链接打不开)
+使用常见问题请转至:[常见问题](https://github.com/lyswhut/lx-music-mobile/blob/master/FAQ.md) + + + + +### 项目协议 + +本项目基于 [Apache License 2.0](https://github.com/lyswhut/lx-music-mobile/blob/master/LICENSE) 许可证发行,以下协议是对于 Apache License 2.0 的补充,如有冲突,以以下协议为准。 + +词语约定:本协议中的“本项目”指洛雪音乐桌面版项目;“使用者”指签署本协议的使用者;“官方音乐平台”指对本项目内置的包括酷我、酷狗、咪咕等音乐源的官方平台统称;“版权数据”指包括但不限于图像、音频、名字等在内的他人拥有所属版权的数据。 + +1. 本项目的数据来源原理是从各官方音乐平台的公开服务器中拉取数据,经过对数据简单地筛选与合并后进行展示,因此本项目不对数据的准确性负责。 +2. 使用本项目的过程中可能会产生版权数据,对于这些版权数据,本项目不拥有它们的所有权,为了避免造成侵权,使用者务必在**24小时**内清除使用本项目的过程中所产生的版权数据。 +3. 本项目内的官方音乐平台别名为本项目内对官方音乐平台的一个称呼,不包含恶意,如果官方音乐平台觉得不妥,可联系本项目更改或移除。 +4. 本项目内使用的部分包括但不限于字体、图片等资源来源于互联网,如果出现侵权可联系本项目移除。 +5. 由于使用本项目产生的包括由于本协议或由于使用或无法使用本项目而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。 +6. 本项目完全免费,且开源发布于 GitHub 面向全世界人用作对技术的学习交流,本项目不对项目内的技术可能存在违反当地法律法规的行为作保证,**禁止在违反当地法律法规的情况下使用本项目**,对于使用者在明知或不知当地法律法规不允许的情况下使用本项目所造成的任何违法违规行为由使用者承担,本项目不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。 + +若你使用了本项目,将代表你接受以上协议。 + +音乐平台不易,请尊重版权,支持正版。
+若对此有疑问请 mail to: lyswhut+qq.com (请将`+`替换成`@`) diff --git a/android/app/BUCK b/android/app/BUCK new file mode 100644 index 0000000..dcfbdb2 --- /dev/null +++ b/android/app/BUCK @@ -0,0 +1,55 @@ +# To learn about Buck see [Docs](https://buckbuild.com/). +# To run your application with Buck: +# - install Buck +# - `npm start` - to start the packager +# - `cd android` +# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` +# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck +# - `buck install -r android/app` - compile, install and run application +# + +load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") + +lib_deps = [] + +create_aar_targets(glob(["libs/*.aar"])) + +create_jar_targets(glob(["libs/*.jar"])) + +android_library( + name = "all-libs", + exported_deps = lib_deps, +) + +android_library( + name = "app-code", + srcs = glob([ + "src/main/java/**/*.java", + ]), + deps = [ + ":all-libs", + ":build_config", + ":res", + ], +) + +android_build_config( + name = "build_config", + package = "cn.toside.music.mobile", +) + +android_resource( + name = "res", + package = "cn.toside.music.mobile", + res = "src/main/res", +) + +android_binary( + name = "app", + keystore = "//android/keystores:debug", + manifest = "src/main/AndroidManifest.xml", + package_type = "debug", + deps = [ + ":app-code", + ], +) diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..cc3ed1e --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,268 @@ +apply plugin: "com.android.application" + +import com.android.build.OutputFile +import groovy.json.JsonSlurper + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "../../node_modules/react-native/react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation. If none specified and + * // "index.android.js" exists, it will be used. Otherwise "index.js" is + * // default. Can be overridden with ENTRY_FILE environment variable. + * entryFile: "index.android.js", + * + * // https://reactnative.dev/docs/performance#enable-the-ram-format + * bundleCommand: "ram-bundle", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property can be in the following formats + * // 'bundleIn${productFlavor}${buildType}' + * // 'bundleIn${buildType}' + * // bundleInFreeDebug: true, + * // bundleInPaidRelease: true, + * // bundleInBeta: true, + * + * // whether to disable dev mode in custom build variants (by default only disabled in release) + * // for example: to disable dev mode in the staging build type (if configured) + * devDisabledInStaging: true, + * // The configuration property can be in the following formats + * // 'devDisabledIn${productFlavor}${buildType}' + * // 'devDisabledIn${buildType}' + * + * // the root of your project, i.e. where "package.json" lives + * root: "../../", + * + * // where to put the JS bundle asset in debug mode + * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", + * + * // where to put the JS bundle asset in release mode + * jsBundleDirRelease: "$buildDir/intermediates/assets/release", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in debug mode + * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in release mode + * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", + * + * // by default the gradle tasks are skipped if none of the JS files or assets change; this means + * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to + * // date; if you have any other folders that you want to ignore for performance reasons (gradle + * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ + * // for example, you might want to remove it from here. + * inputExcludes: ["android/**", "ios/**"], + * + * // override which node gets called and with what additional arguments + * nodeExecutableAndArgs: ["node"], + * + * // supply additional arguments to the packager + * extraPackagerArgs: [] + * ] + */ + +project.ext.react = [ + enableHermes: true, // clean and rebuild if changing +] + +apply from: "../../node_modules/react-native/react.gradle" + +/** + * Set this to true to create two separate APKs instead of one: + * - An APK that only works on ARM devices + * - An APK that only works on x86 devices + * The advantage is the size of the APK is reduced by about 4MB. + * Upload all the APKs to the Play Store and people will download + * the correct one based on the CPU architecture of their device. + */ +def enableSeparateBuildPerCPUArchitecture = true + +/** + * Run Proguard to shrink the Java bytecode in release builds. + */ +def enableProguardInReleaseBuilds = true + +/** + * The preferred build flavor of JavaScriptCore. + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +/** + * Whether to enable the Hermes VM. + * + * This should be set on project.ext.react and mirrored here. If it is not set + * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode + * and the benefits of using Hermes will therefore be sharply reduced. + */ +def enableHermes = project.ext.react.get("enableHermes", false); + + +// Get version number +def getNpmPackageJson() { + def inputFile = new File("../package.json") + def packageJson = new JsonSlurper().parseText(inputFile.text) + return packageJson +} +def npmPackageJson = getNpmPackageJson() +def verCode = npmPackageJson["versionCode"] +def verName = npmPackageJson["version"] + + +android { + ndkVersion rootProject.ext.ndkVersion + + compileSdkVersion rootProject.ext.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + dexOptions { + javaMaxHeapSize "3g" + } + + defaultConfig { + applicationId "cn.toside.music.mobile" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode verCode + versionName verName + multiDexEnabled true + } + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk true // If true, also generate a universal APK + include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" + } + } + signingConfigs { + release { + if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) { + storeFile file(MYAPP_UPLOAD_STORE_FILE) + storePassword MYAPP_UPLOAD_STORE_PASSWORD + keyAlias MYAPP_UPLOAD_KEY_ALIAS + keyPassword MYAPP_UPLOAD_KEY_PASSWORD + } else { + def keystorePropertiesFile = rootProject.file("keystore.properties") + def keystoreProperties = new Properties() + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + + storeFile file(keystoreProperties['storeFile']) + storePassword keystoreProperties['storePassword'] + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + } + } + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + + signingConfig signingConfigs.release + } + } + + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // https://developer.android.com/studio/build/configure-apk-splits.html + // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. + def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + defaultConfig.versionCode * 1000 + versionCodes.get(abi) + } + + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + //noinspection GradleDynamicVersion + implementation "com.facebook.react:react-native:+" // From node_modules + + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + + implementation 'com.android.support:multidex:1.0.3' + + implementation 'commons-io:commons-io:2.8.0' + + implementation 'org.apache.commons:commons-compress:1.20' + + debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { + exclude group:'com.facebook.fbjni' + } + + debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { + exclude group:'com.facebook.flipper' + exclude group:'com.squareup.okhttp3', module:'okhttp' + } + + debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { + exclude group:'com.facebook.flipper' + } + + if (enableHermes) { + def hermesPath = "../../node_modules/hermes-engine/android/"; + debugImplementation files(hermesPath + "hermes-debug.aar") + releaseImplementation files(hermesPath + "hermes-release.aar") + } else { + implementation jscFlavor + } +} + +// Run this once to be able to run the application with BUCK +// puts all compile dependencies into folder libs for BUCK to use +task copyDownloadableDepsToLibs(type: Copy) { + from configurations.compile + into 'libs' +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) + +apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" + diff --git a/android/app/build_defs.bzl b/android/app/build_defs.bzl new file mode 100644 index 0000000..fff270f --- /dev/null +++ b/android/app/build_defs.bzl @@ -0,0 +1,19 @@ +"""Helper definitions to glob .aar and .jar targets""" + +def create_aar_targets(aarfiles): + for aarfile in aarfiles: + name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] + lib_deps.append(":" + name) + android_prebuilt_aar( + name = name, + aar = aarfile, + ) + +def create_jar_targets(jarfiles): + for jarfile in jarfiles: + name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] + lib_deps.append(":" + name) + prebuilt_jar( + name = name, + binary_jar = jarfile, + ) diff --git a/android/app/debug.keystore b/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..364e105ed39fbfd62001429a68140672b06ec0de GIT binary patch literal 2257 zcmchYXEfYt8;7T1^dLH$VOTZ%2NOdOH5j5LYLtZ0q7x-V8_6gU5)#7dkq{HTmsfNq zB3ZqcAxeY^G10@?efK?Q&)M(qInVv!xjx+IKEL}p*K@LYvIzo#AZG>st5|P)KF1_Z;y){W{<7K{nl!CPuE z_^(!C(Ol0n8 zK13*rzAtW>(wULKPRYLd7G18F8#1P`V*9`(Poj26eOXYyBVZPno~Cvvhx7vPjAuZo zF?VD!zB~QG(!zbw#qsxT8%BSpqMZ4f70ZPn-3y$L8{EVbbN9$H`B&Z1quk9tgp5FM zuxp3pJ0b8u|3+#5bkJ4SRnCF2l7#DyLYXYY8*?OuAwK4E6J{0N=O3QNVzQ$L#FKkR zi-c@&!nDvezOV$i$Lr}iF$XEcwnybQ6WZrMKuw8gCL^U#D;q3t&HpTbqyD%vG=TeDlzCT~MXUPC|Leb-Uk+ z=vnMd(|>ld?Fh>V8poP;q;;nc@en$|rnP0ytzD&fFkCeUE^kG9Kx4wUh!!rpjwKDP zyw_e|a^x_w3E zP}}@$g>*LLJ4i0`Gx)qltL}@;mDv}D*xR^oeWcWdPkW@Uu)B^X&4W1$p6}ze!zudJ zyiLg@uggoMIArBr*27EZV7djDg@W1MaL+rcZ-lrANJQ%%>u8)ZMWU@R2qtnmG(acP z0d_^!t>}5W zpT`*2NR+0+SpTHb+6Js4b;%LJB;B_-ChhnU5py}iJtku*hm5F0!iql8Hrpcy1aYbT z1*dKC5ua6pMX@@iONI?Hpr%h;&YaXp9n!ND7-=a%BD7v&g zOO41M6EbE24mJ#S$Ui0-brR5ML%@|ndz^)YLMMV1atna{Fw<;TF@>d&F|!Z>8eg>>hkFrV)W+uv=`^F9^e zzzM2*oOjT9%gLoub%(R57p-`TXFe#oh1_{&N-YN z<}artH|m=d8TQuKSWE)Z%puU|g|^^NFwC#N=@dPhasyYjoy(fdEVfKR@cXKHZV-`06HsP`|Ftx;8(YD$fFXumLWbGnu$GMqRncXYY9mwz9$ap zQtfZB^_BeNYITh^hA7+(XNFox5WMeG_LtJ%*Q}$8VKDI_p8^pqX)}NMb`0e|wgF7D zuQACY_Ua<1ri{;Jwt@_1sW9zzdgnyh_O#8y+C;LcZq6=4e^cs6KvmK@$vVpKFGbQ= z$)Eux5C|Fx;Gtmv9^#Y-g@7Rt7*eLp5n!gJmn7&B_L$G?NCN`AP>cXQEz}%F%K;vUs{+l4Q{}eWW;ATe2 zqvXzxoIDy(u;F2q1JH7Sf;{jy_j})F+cKlIOmNfjBGHoG^CN zM|Ho&&X|L-36f}Q-obEACz`sI%2f&k>z5c$2TyTSj~vmO)BW~+N^kt`Jt@R|s!){H ze1_eCrlNaPkJQhL$WG&iRvF*YG=gXd1IyYQ9ew|iYn7r~g!wOnw;@n42>enAxBv*A zEmV*N#sxdicyNM=A4|yaOC5MByts}s_Hpfj|y<6G=o=!3S@eIFKDdpR7|FY>L&Wat&oW&cm&X~ z5Bt>Fcq(fgnvlvLSYg&o6>&fY`ODg4`V^lWWD=%oJ#Kbad2u~! zLECFS*??>|vDsNR&pH=Ze0Eo`sC_G`OjoEKVHY|wmwlX&(XBE<@sx3Hd^gtd-fNwUHsylg06p`U2y_={u}Bc + + + + + + + + diff --git a/android/app/src/debug/java/com/lxmusicmobile/ReactNativeFlipper.java b/android/app/src/debug/java/com/lxmusicmobile/ReactNativeFlipper.java new file mode 100644 index 0000000..62b64ce --- /dev/null +++ b/android/app/src/debug/java/com/lxmusicmobile/ReactNativeFlipper.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package cn.toside.music.mobile; + +import android.content.Context; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.android.utils.FlipperUtils; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; +import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; +import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; +import com.facebook.flipper.plugins.inspector.DescriptorMapping; +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; +import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; +import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; +import com.facebook.flipper.plugins.react.ReactFlipperPlugin; +import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.modules.network.NetworkingModule; +import okhttp3.OkHttpClient; + +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + if (FlipperUtils.shouldEnableFlipper(context)) { + final FlipperClient client = AndroidFlipperClient.getInstance(context); + + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + client.addPlugin(new ReactFlipperPlugin()); + client.addPlugin(new DatabasesFlipperPlugin(context)); + client.addPlugin(new SharedPreferencesFlipperPlugin(context)); + client.addPlugin(CrashReporterPlugin.getInstance()); + + NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); + NetworkingModule.setCustomClientBuilder( + new NetworkingModule.CustomClientBuilder() { + @Override + public void apply(OkHttpClient.Builder builder) { + builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); + } + }); + client.addPlugin(networkFlipperPlugin); + client.start(); + + // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized + // Hence we run if after all native modules have been initialized + ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); + if (reactContext == null) { + reactInstanceManager.addReactInstanceEventListener( + new ReactInstanceManager.ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(ReactContext reactContext) { + reactInstanceManager.removeReactInstanceEventListener(this); + reactContext.runOnNativeModulesQueueThread( + new Runnable() { + @Override + public void run() { + client.addPlugin(new FrescoFlipperPlugin()); + } + }); + } + }); + } else { + client.addPlugin(new FrescoFlipperPlugin()); + } + } + } +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e5688cc --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/assets/fonts/AntDesign.ttf b/android/app/src/main/assets/fonts/AntDesign.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2abf03542c17e6f7a7806a226c3be732b51c5a40 GIT binary patch literal 70344 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®9K?4Tre1; zBfh-v+x_Bn?Mb!eK419`vZn3mQES%G&Ff&(QFh>bx~09vyF-frs2p50rzaMRJqUw} zI-K`p-{n=NnYXvQsc(En|9<2t&TerOmFJ>RX>%}uR~z8^NjfC?f05CU)d+SM&b6B`(KWz$7Fxx$8Ph{CbRt; z{Oc}92a;iRpd8MDT* zi6)T+#_T71x~3ctE7R>6W6qzFzpGyD@ARuz+qo6gop0e=K+CQCbeI2H49cr9YOmE9 zku-_8ih9b`SM#6qby%vcZpRZg$;#KOw^${cJ$f!!_D6fgfZq$|O5(^z;*gH!?4`aY z{Qs)OgV?dMwvp&5rc6sKO`Mii@|TjrPvOEOl4ZR#7N8&H6A(UIeJ1(rf?L{KaEsSU zdr2>?-v0}l^>P<}rG150rRLc*pKQQ*>CoJjEi!1E)E%mlzUks()HqSS!WotO)4fq~@*cb4o z!dAKZn}~}1G#EF;pAJ=2gr3Gub94Fjx4qRdw{7iOo4YdYeS3R3d~W)9qw;HLB_yYq z$T$WRrYQD=1(u?V$nTWz1Ph~4hrj$6At|bnl31DHWZCjjnbCBg5!!y4*&x3vTL1>L zrIs7-Ga1W1vdAYJ%0h>zj9b(>B<(AE*DR$ZxA{jV^FPd1X|sesD|SskGP`lX{BGIo zFQ{;{XcE2NPsx`ejw4K~n9=ee_T<9n9@IY&)Z!*Rm|HNP`aM}s1|EK`=jC&)wc*0u z6*WGq2VrE^3v4cv*=pze%B>63g0+KN)ek8=e7VISy&Q@}np?c;Kh=LZZI@VKBQuoS z_*LBKZE>r6ZBBL9B!rh)dAS+atRrM(AFI;vDv^=FD0SWmiX+_ihs7~ZRrk@D4IV@Fn;Z)HTh~mmW4Kl(Nw=tbQU1{;FOsaFY6a z#m=;nnvG%p6AGs13rV6vY}7Z3%vNjv-^jaR1M0+T@M*NdIGxC+VS(}@E;|i*1+7O|FeLWyurS|DG@N{eo&%Xugc0DAlzZ9@q|M8g5q-h$`rczJEGA!5jd*Cm+S5;{Y4VvY7034W zO(*8kfyZhFk0W8vHC>X$b4Q&i%bP)KG?@)?_Y&kKvb@1_ks>=McuGlgW37tjb^@<4 z`?DQcU9`{?bci1Er-=9|yAbB#nK6>%V$$QW+ViY-huyhg{gDo9;WDe!X_d~iI;6=~ zsJ3Dj`7Dow=Pxt=}x|9 zDH(=uu;H&#leMs-4!rNHkag-IJsg2m=No7>GWjs1weMf#B>S9fQh4h^# zyD&x|dKX?EM4M{jr&090I3$AxI5vV{;R(`s8qCXCJW6je;c7j4KpRGQgI}H%OE*N5 zTsm{8tF9WqBss6saxuY3kYMM4)F9Id>J#FLT zRd$Q|vBef@?C$S|^cO7mhht67U@RT;@P#(ZCmCCL5SJQ5{Fay}SexskqN)>Z@q~27 zvc6nx$P=qt-1I#vtg@m#^S!3Ue5Kdx6>rzdy11eR1!tPu1sa9FS!_1T_o})ZgTbH_ z=!!q=wz*rY!fsE@qdsr3T|A>Z=m~~^P!)!wM(1|RPh&ncK@S&n4sD!8^lml{fd_4b z#>W|75VVV$9}@`e9n|R^CQ>mt1$>j5RGVN2>0DEG!2dC%eD3c~_Ai#C#r^m-sQaRG z>X&Siq)kiOmPGzWXP0pNR@K)J)YljGb@e*;#!|6Q(^=eu1HF()R{baG;kIK)y9ZnruD` z(b=47mN2#@lQ~NZ#e$H*psGuOpcz9C!zWK(zqWn}%>c>+-(4s6F;jiGk8U^n#gh_Z z14tCdz|~$X!GIw_V!}uZLS&Z^EI^_iMj>8|-Lz<4tvRcLE_tnLwz_;fgydJ$*1NSLrwtMim;$(s3lqTic;_Ie=azL}OwWZp8qa%DegU+xo3bX*JOisUo1j0F zc&@tzfG7Oc&2$wk1xNV99hwUqqZF$Sv~w~RJz#C1aC_&1Z5Yw?8n7GUqW#1oX-9h% zemcaeq1Mivh}%KL?G3?!T1O&PSKi<<#v%cm)#mVaM1r|+Jn7(OTQE}XvODU#!*wp7 zRWeRa&R?_s%{4QQ4}{$Fe9QV9jyrBe-4VTxsNXD^GRcalNtUe6kSAo3{E<*T8SM;7 z@h-pHVwS8XM_dZp%cL@=EA6tFtZsY25;vQqchY^5E!h&C-V9$~(B_N>Dknz+jpYGE zaT=|`NX%%c@nl@Sj4RUnSRT>B{#h>?aKa!na#nh#TRfIET&8dk=FU%UeYx&jt>5o^-U^2NyboUI9^W5B6`WVJ4b1Kj|Ghd(qRy%`@1+~m zXPWzZFX`<&E{yjz|2?&0&2pVb?1GJ_3z>N+I)ibc!=wJ0Y8r0Z%F!TdQjO7*qc{uj zjy7%BX>4^ejM&jcpvxk^?An5n`L0qXZf-M1@h6|1a>yAtof@P{BCvWfO5#Rkr zkL@Y-W3$cXjYi=zGji+8{xYN6YH}vMf%067$pXi}(?}*Y^;^fTT)Ma`T{EzF(TZiH zT^ePZEEye5Hirqq0le#1uJrpQQ@KCFtxm_24pW7H|9k!lZgzj@;r^!ODSsy5YFM7C z51Y-faR>dbtK7c7nQE&08q(4|RkgWT0zne;UkqleY;bsz6@AT(C$~GxG3Xw+Y^u&% zAVci|y&1M4^29+k&8QiV$W(-Y&XWDK9z<4Lc4?Mx*UX1*&6K$RQAv|1HB+Kfw;qux zQTj6llpVKHTY-3v&H8WK5P|Df>Aw+Yn1l?#cn9bnge8+%Ho>H&**Ei^_O#|=>&T|^ ziJ%b?w^~qC&XbV8w8`LesND{q;be)YDx}TuysK~Uy6JWN#RdG@MTOmWl+Qs-MACD6 z;eP%U#2CBFX;iaVqwy(`+=kL{T}O`R7>rz8BKX*)0%2iN2y zk^GuL^(plp&X-@a7&P6!*i#vd$AeCI@U#qa2i}wK1iq7DJ6Vb>NGBtL=>kMAU54x} zw;*=u2gqRaFwGo)s)PRL@E==0%v~DLz6O3=!5O+PuF-wkxsH^vct2gG`|%6SEalad zF_3=EtQI51%%8>iw0=y=8Z7~X$*m(u_v`10XqBEX-cRRArY_zuZ|GlfOAi0;Ufbm}1Zhe2QKf7+bdQE?S_x4Z~=T#xGiCwdPU_iQa z_*^0pyQZeUf5Ye#>gdO^0|Wfy_3PJV+v(MtmlF!Pf%f)w>)LDj*Y#&}z~OEbpX<*p zAGoC-$tH?LQptVSpxnDhpUMuXo3(R^gnm;^zqqO71of#F`y<~e{RVTRO3U!sLw3zf zibMxQc4@&hP=$!DijG2Dft@p7Du^y6ULyOuP@IL zIcxL2R$e$KQC~l`zCIxx@tS0is;~@dMCT$$QHs3BUS6@JI^(zsz{#9(GlQ}&#vw0mo z<*|QzyqZiaZ-YTYz5T@sKIPZgQ2RsI2W@&rdKdHmXiXPwk~%0Z57J93so*Ya0BVLotk=zB{q}Bgt(i@sR7(yxj3-rxkxwOiXv{yge zD|!{>J9s1mQ~rYE^Gl{@BECSfw>8Y;;g+g_`Hg&M+flR9{8lbyBlX$lBeIPZDPyR) zCs|hJjrGiHnBNyq&0N+xv)JyU+yUYUhb}owW8SYtp>$}P3+4owk9~)M(yy&C>kL0E zQ`5<0a0!ksu^k#sm(4c)bFvD3K7$0HORRVbNd?515x7$%&0*jU`GXuOn7(mX0ibeK zV)l~ab?Dao^~E+|OXbh-#r!j@uyGu+eR~9|e(Q{b=wq0d^z{nLFLyYY8#BN+pCgSD zd-;w&cnHWBRh$)?b_oZCwgNW^?vNf;#o?+SMqT$mZ^J4|PcVZtx#non>vGgr_+xE- zwX-IB9u7R#lg zzGP*0vN9Qm#ZvY+hEqLlVSim{`@t53(@$?ztr`CxYRi7KEC@Rp>pTv>CIHIAYe!)8bXl*_i`pS6aii%CiS%W}Ej_ z&RI04J09;A8)S@{(v3l*IMRQK@na#cv<}6yYcJ++ERK{YH z<{UX^lGtc6q`=*c94Eb$eUnlIkvqCig1s1m?y$j1sLfwc6|5MfYLa$Mla1751ZV|g zlEi9DknNsRdziJHU6bn1t*NS7lj~2_v>wylJ224Oy}U*GX0Z<4gH#puAv9Un97(i6 z;tQ%j^T?%h=1y7~3@)8Cch0gSJ60bNz`rBb=(Ob-=|$vD7V(fp{%=GpP<^VXaxxs5 zF^PC-6-Wq{=fj9M+&&VkgDIt_hu>oJ#{J!k)~fs09y!TR@!R5<8}ws!^57cI*9^`f zD-8c5?;#sZ&pKnOaZ+?vZChLItmvf1lyUU&{l!P-46eca6>%7Za|+pY2PxAknfND0 zmIPW_Cqhde1l}Nn!n#pvR)g_hm~rH%4^@#tLn6YPr!D

9po(mC;xgZJxI5gC)~i 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

R0AMv>n9kBSrZWQv zj8gze2D43>%1lq=EoEYKXnJNcW0)Apj%Q300}~mniO~t`cy@Yp@8}R8Su?eG2E#oz zY#1FM%pQ@b);e`ybSzV&eM06J7y%kZ ze0N}M2;9eXc2XW1p(e}wMyE$+1|2yr1@mz~0B`3wNBcx}Wl4Gh8cbcvLHEh*B$Sh*B@x=+zqSq9$vZnV2gBzYHA3 z3K=-6gGafR<8>4Jv@cE!@8tzE;i`;&Z(^DkEHmT# z$Fqld*>pHN$y<~*4rATWe{-%-lT{962dRO|^Z;-;eq|7Cm_mgqaH&|()5hTeJQ|qF zC^U>%Hl~s6%;dhYfvG8Rf99yPcWhuE7W>ic%(Mc;K{Hd_vbk59+CMrjO=q)XB4&{l zy{5&zZxZteeVd%5`eto9(*wtRk=GFq42+ATQ-`E|qkE_2(P6wYY&igwIRq?&b!-Lt z#45{-0en-^BoL&$d0=m5`lx((U<~~*9M0kkG#2!A;L-8@a{pv@V&tfi7BXOv&J`LA zW25^s4FJv*FYrr(6~6>PX2u57$|R;Xz=M$*15ncPzy#1`TH&XftZ`s`crrUWj2l|P zJ}@?Vcwl@V{jbTUEqRx~&`0%knYPWBQOh`yJ)D`$?%iveo*Wp?92l6~FYN`IFww|! zoNSoN&WsNmXq}Hphk@p#siWgVSbzIQ$7LL85GDbXf#Ece_0-hBzD(Kx%(*`!_H0;b zMr%QZCNnizQ?7`|Lj&V!nnaliqB59z*g^~pO;4GovSTy+mV`C6Um}7F>t&6k5IU~W@Ue-PX$_dL*#X8G-8XInmzOjr9qJ1n2en@-h*gG(U36b5ezocLsCNM$FT5Vzj97L$l_}of% z&^($sP;($Vp4~S&aDcGi*uY@!HZ2zdy|8hkVQT-;iHvP}AUima)qfz@Ms3|IG>>Nn zGxA|Vh11G3mN`~{;c#YjFe~--uU(USTdQy75A+`C7g}#EOVOdtm_BH{3^*K}88;jo z86BBX1~VgI5;Ml($X^j< literal 0 HcmV?d00001 diff --git a/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..522dc3105c81c753c96ba7b0b0024c42301dee6f GIT binary patch literal 899432 zcmeF41(2R+nq9BdYDo?9Yi4Fcm)vsbF58UU)o%*c zM`i!GTMgZE!!5Rd@AdR9xopz^ify*ueutkoKK$+UF8xRPZMIo>_I~&LeGhB-`|rR1 z=s%#6fB&BmpEDs{V)pY-T&KWd@#n2tL%IF#J@7Djl_uFFAjfZmoKTh^zU#<2d>6d~3 zmQsF9I*AwTw-MPQ|8@SD(Q-ijQFeBa{ty1M>_!W1ka_vz_}gEPsrh4>pKbs6BXNKI z0sOD=_uv0(`~Fw&>)Y4&>-m539q9WW_I+>uPrf(*FP-^k|BnB&Ki~gLf3EwUweRm| zecyrqJKur6zmNUj`E~F6zW4pQ_k9Qc!eV_Wi1AX6t|Jiq-@4t8Yz90Xy??>NS-}j^MJJ9zX==%=*>wX9R z8UJ_ZKjSm?{Wb8f``19o@<9r(Zd9pJand#2y_fIY29E1!0(s35h2L0~Ig-RVGCneU zYK|gtj*8c}sOD%A=jiz8R^ z;+z(rmb~V466f^z^yD>XkT_?=XC$vVlf*eQJ~MgEStQO`@ma}h&L(lrj?YeBa}J4f zPJB-CnsZ5}2j=bjb66Xr|3gk6c z6n>iFv9HP?_h*TmN(uep}Qxi-EwdChes z&UNv1$!iXkIM>71Bd@u>#JK^!0eQ_0CC-iTjmT?mEOBmvZ$e&kQ;Bmkd^7Tzn@gNq z;9HQ_+*0D)3g3#n=GGGDHuyH=HMf;Gx5Kw1uerU%xdXlfdCeUq&Ykd`$ZPH_aqfce zLSA!MiE}rc-z6Mcc9%H!!1o}pxu?Xr7rqyH&AlbgeeiwAYwjy??uYM3UUPqm^8ow+ z@|p)qoCo0tk=Hy};yeUDguLdV66ay~VdOOrmpG5Wk07skq{Mj?eiV7lqb1H`@MFkp z9xHJkhaX2?^LUB#1pEZ@nkPz}C*dcN*F0I`JOw|6yymGA=V|z9n6}zlFT!trF*L_-*7hZY6Yu+ny-iO~u zUh{s5^8x$;@|q7yoDbm-k=J}!;(P>uguLdX66a(1W8^g-mpGrmpCGUKq{R6Y{uFu5 zrzOs3@Mp+tJ}YrPhd)PN^LdH$1^fl_nlDP6FX1nd*L+#xdZdCjjS&TsH<$ZLKpaejw?M_%)LiSq~i z2lARfN}NC8Katn`S>pT!|AoBfuM+2P_;2Jje;59B5X?U$&Oh-#*;Df`iSuu~{v8TT zUiXW7?Qi}1Nu2%h{^T_~B+dc&0P>oh66ZjCAbHI}66auiFnP@`iL)E;Ca>8earWZ9 zLO`e01`fV@RB1;$xE6982OH8y}mz<~S1PxcIo_HOG@U$H&JfuQ`FlIUznFdCiF= z&WZ7f$!ks`aZZX)N?vm^iF0y%a`Ku}NSssRQc66d`5yyP|KlQ`$c=O?eZfW)~Vz94zcg(S{}@rB82E+TO*iZ4oDb1{i?aeQ&| znoCHWOX5qC*IY{CTpC}Ryyh|z=d$>+k=NW^ z;@kt@gS_UR66ap{UgS0RmN@sp_aU#juf(|@z8`tb{Uy!=@B_$e9w>1hgdap+^I(bd z5d0AGnuki9hvA2j*F0R}JOV$0yylS-=TZ1k{1ozDxHP4nf&%w_j zuX(P-c^-ZqdCl`B&I|Ah$ZK9GabAR9L|*e^iSrWt67rgtN}QMBmyy@JT;jX}zkwuf%yDejjCC(S{7szYAC~>}ozeHa1Wr_0@{1x(=uS%S+;jfX`d|l#v1Al|O=9?1dTlib# zHQ$yv-@)G@ulcUT`5yirdCm7F&JXYp$ZLKmaejn}7AMhW@YyK#4{)GQTUh`*( z^B4RV@|wR&oWJ3}k=OiP;`{^ugS_US66as|U*t9amelMYiL)Qh{}6!IzrV!Ufp?JC z93XLa;+^C*2TGiS@ImA?2TPn?co%uiZi%x8?;)?*D{&6N`T0Mz{=-O|4d>_o(E1N6 zaSn&`^M7dlhnF}c&Ux^8$ZO6k zan6U&M_zM&iE{yb0rHv)3je}E=0XzZ!uZ1Mskw;6xhTFUdCkQn&c*S?$!jhlaW083 zNnUd)iF0XuY4V!ONSw>!%aYezPU2i1U!J_?3KHjv_=@B;SCTka##bhNoa^H2lGhw6aju82M_zM%iE{&d1M-?1 zN}L;*ng>dp2jK^i*F0F_JOn?4yyl@2=VAC^ zovCrX?r;U|&T zJXzvA1wVzn=BX0rY4~a6HBXl~&%n$d8Nd86@C?Y&8sEO zYw&BxYhEjHUWZ>tUh{g1^9K9|@|rhFoHyY&k=MLg;=BdFg}mmi66bCBZR9m?mpJdh z?;x*vr^I;|eiwPoyCu$h@O#K>-Yaq5hu=qD^L~l*0sH~-nh#2x58)4y*L+ywd<1`l zyyl}4=VSO|ulc6L`4;{bdCj*a&Uf&4$ZNhU zalVJYM_%)NiSq;e1M-?5N}M0zACcGmSmOKy|Af5erxNF9_-EubKbJVaz`r1``K849 z75)`@&95cSZ}4x(Ykn(neusZYUh{j2^9TF~@|r(NoIl||k=OiL;`{~wg}mmk66bID zZ{#(9mpK2x{~)jVr^NXe{ug=8za=$0B60S^`|*$Y)a);DcHnG))-gch?8JHhht@Gr z;v9tY{tvBVu*BJg^ZpO5qg&$a!Fm6O*3m0*4#9chZ8=lvgA$EXtLXgKfx&^kt!ILE+w|A*Ewro=fG z&ig;Kj>QaagK+NM_zM$iE{#c0`i&@N}Lnny#GV%m{{VR1n2!9TF0ak z=VUnV|Ij)nmpG@udH;vjF{Q*g70&xVw2rAI&S`Mo|DknED{)ST^ZpO5V|s~m2AubQ zXdN?3oHOCP|3mATS>l`p=lvgA$E*_PY&h@#&^l(9IOo85|A*Ewr^GoI&ig;Kj=3ey zd2rtUp>@nFan6U&M_zM&iE{yb0rHv)N}LPf3z64cSmIm+Uxd8oq7vs~_+sQW7neAf zz?UGexunFo6uuOB&7~#IW$t^ zg}mmf66b38YUDLnmpIqJ*C4OCro_1xz7~1SwI$AV@O8**t}Ag4#fOsDTuSZ?cak`F#&;&Kxr@ZPE50jv&D|u<-SOSYYwjU& z?uqY7UUM&rb8mca@|ycdocrSYlGof%;@ltKpS4<@g9i2TD3 z#SbN~>@W$RTgTxNvmq@VRvyFEKj- z=l$R8MEpd&vXdlyZXG8}%ud01|2I1oKNYX+Gzp(u$LSKYGjQJj&CbNn#49^X!spg; zw#4il{2caFcCLiat>Zk2+4=bS?5XSm37=cXg%Y!i@Qc_}*~Jn*w~k9BW|!iZvZu1k zBz$fimrKm9zV?-v7<6#jnLHyH3LA)^WYW>;|0of3q9$ z8}Z6+lJL28+$=G>1?T{k3%yt3OQd~O}LOU&-TdH*-N6TcI$>@EqPTgTlJvwQG+ z*i+fP5-b-XSydjseF-|S8NO}w(VBz$fiZ%fSH!QWv|W$#M( z+&bQqn7xm`&z{OYknp*6d?+#d2>*yZm3=JXbL;p-V)iNiDSImWOv2~Z@wvq83!L|V zvoG;4@yfoE@VRw-EiwBB=l$R8Tl`zRvhO5(ZXMrC%znUm|2O*){}He3CkdZh$IlY8 zUvS?4&3?sy#Vh+w!spiUyTt4docDjTKk+~D%Knn@xpn+4scb+bl?~`8G3$@_=O6R0 ztV6=*Hei6ntP}5KPh|rod~O2 z#H`_sJ(UeB;d2`>oWyK+e0cU$HiCrDZNP{Uvyt$T*i+fa5 z+y;y;F&hKt{oia%d`!Huu_SzM1ICt^jf3<4Z#FJIE?(Jq5@mbkZ*=!O%w*j+D z%;vy(|2LZxpA)ZaF7cmD8Zb9LH+ikkBXNCRd|vWepHJfY{P_IjwZ4GF^#$<-$!mQf ziR%mF3zOISA`;gZ#TO;7^~EHvFODxxUh7LpTwfAjlDyWJlDNJ!zBGBQFC%e%S$tXY zT3=4$`ttblN70GLTC5h`R<13Tb`YICFSH)K)ul3a=uCI=-PG0M4NL*hN zUz5Dn*OIutHoi7_t*;|-eO-KA@>(A%aeX~}J@Q&#U*h@(_y**)zM;hRjqr`gYkgyh z>zm-4kk|UA64y7wHzTk0%_XjHfp0-x>sv}(-wNM~yw)M$;`#~r3FNhY zqQv!+@RP`E{bY&jr{JfM*ZQdv*H6PwBd_(-C9a==pFv*hXG&Z@3qOmz*3Xu>ehz*P zd99x-as52}Jn~vUU*h@&_yy#(exbzmi|~ucYyD!0>zCk{kk|U964x)oFC(w@%O$Q~ zfnPyh>sLx#zY4#Kyw+jh;`$5t3*@!_qQv!=@R!JI{bh;kui&qc*ZQjx z*I&b5Bd_(>C9c1Lzd>H>Z%SN$3xA8e*58)6{to^Qd9A-Ias55~J@Q(AU*h@)_y^>* z{-MP6kMNJkYyD%1>!0ACkk|UB64yV&KO?X8&n2#Zfqy|>>t9M-{|f(#yw<;#xc&|P z4SB79D{=ih{5$em|6bzy5BLw{wf>{T^`G#c$ZP#)iR-`MzmV7ZuM*dP!+#^M_1`6~ z|AGHOUh98KT>lIIi@etVmee}0??qT^o&6-W-q~N`dI#Q-xIO?MfY*AbgtgW=P{La4 z93*jlFg}?5wcaKE|95nD$yz2o4#|GRfwd|bTtjwf;N`1ttbwRZvu`&#FO68BDoPsE}#EqN!&X*J~?}8?-UaEPKi%RUVEpKu&;GaEphKOIPd@LYn{_d+&djU z9eM4YUc$cCIfKN#GvYI{r}oYyaqrCd%;dFq776=W=d2R<&W6v%p4vOR#JzLiy#Kp* zPJB+h_Rb}7@7(y@uA*E&~}xOXLdCHBgY z*14v{y=&oXv8VQ~EphKUI6wb)@4EQ9c~>pW26-h=Ri z*i(BCmbmv2{1Ecmd#Hqct@AL6dk@DCXHV@tLgL;d@gvD=?@iF?n+&t^~UJxAi+bMbS@Ywvjy_O;IQCGNcdzkofp_da;Z3JLpK=amxoUWN1i&%V}qwZy&G;Mb7X z-fJc7Yn|6g+h~G$FdvB7kuXWxmaqlhoE$peiw@Tc58-5#k?Y&*X zzSen%#JzXoce1DU-X(GG-T2+)wf7zg`&#F{68GMR-^ZTXd%wiJ58w}w*WL#u>}#D5 zN!CyKZe)d$0hE40_XjoeXa9J3Hw^-Qxf++jX%wv+WU;e zz0czO{NKIL;m_f<_j!qXU%+|)XJ6}lQNq5~`I5xFFXJz>r}n-gaqp`*KmT{{Yxrw; z?R{P1-Z$_!$ZPML685#uw7%dF}m4!oJq|v&6l>;Jp8{uXX+^aqn;V zZ{)T2cM1Di=O5xfhu`@p&d>in_ZQClKWAF!-;z2vFp@equ%D#P4eT%BOdHrCsdEDd zNIchx^FI(gHxMWE+#q}qUgri&JlBPHk=MCy31`~C9tmgKz+Q>xhTy#abEXX(M&h}K zH}X0+ti*G};lq*Fx#1X(gVU4(I)!Gi~7X63@+m&p=-1W|VktCVVFHIybY#bF<*Hkk`3cC7zoN=l!2E zZQ$$@&&`4J{?C~GaOdGhg#Bq$JfKE6JAo!da-xef6R z$?M!k63=anZ%kh2Hj#L4Q+!kMI=7j`bDQIvlh?T|B%a$6-;%t}Z6)#C*7(-sb#5Dp z=eEVSC9iYaNj$ebzCC%J+d<;F9q}E>>)cKf&+UxwOkU@9k$7%bd{^>1x0}RsyW_n7 zbEXa4L*ltT@jc1w++GsT?TznEUg!3acy3>OU-CM)pTu+fxdSAgI}ksRyv`jY z@!Y}q!Q^%B5Q*mw#SbN~bB9ShcQ}4Hd7V2#;<+R7BgyOBQ4-G`jUP>3=Z=wh?pXX- z@;Y~%#B;~v$CKB&6C|EH5kHZ<&YdLj+{yUK8iRVtmPbIH&r%60_I(|BNojXI~ zxij%I$?M!%63?BDpG{up&XIWTT>M<}I(MGLbLZpdlh?TmB%ZqvzmUAnT_o|`#rVbK zb?y?0=Pt!BC9iXrNj!HsemQxayF%i*EAcDI>)cfm&s~jQOX?iPvXZpCjUuXDFaJa;>OJ9(YEL*ltR@jJ=u z++7mS-HqQ(Ugz$Sc z#UCZFbB{?p_c;DId7XPg;<+dBC&}yFQxeZTjXzCZ=bn*x?pgd<@;djN#B9iRWI$UnQ?|uSq=jI{rF&oqI##xi|4Q$?M!(63@Mj zzfE4}-jR6jUHo10I`^K$bMNEtlh?TqB%b>a|B$@SeI)VR$N0zOb?y_1=RU)clo&wY)5Ol)eDA&rO6+L|*46mUwOwd=m0HH>t#Pli`z**SX0ho|^)ng1pX6 zDe>G?_*CR|Zfc3=ropEnuXEE%JU1Oa9eJIbUgEhK@EOSK+>8>>&4kZHUgu_(cy1Pa z7Vs4#U-9w0$+l>&MhhN+*0^b z5){}T{eSCfL zI=6wua~t9tCjIJrwUPMGdJWnb-`c+dEK{z#QS!{cOA)$ z@7opMmAvlTP2zpK%RRY-nT!# zKY87EfW-R_#1AB|`wo(L-@*973_Z=hgzGLxY$?Lx3B;I#Cemr^IcY?(GPQ*_nulr7tc;CtR$>eq4DH88H z6+e}{?mJE5eW&B6lh=J`NWAY%{7mw??<|S;osFMOUiY0N@xF8MbII$z^CaGPK7KxV z-FJb+`!2*UB(M7}l6c?6_{HRP-z5_7yA;2ayzaY9;(eFnmy_3hS4h0?O8iRly6-B9 z_g#%&OA%#@4FSh zmAvk|P2zpGYMQ+MAh@$UQZ`^f9=`z7A} z0R8}Z-Tk1%yC1?IBCoq2mT+$y^oYc}AH^SKPu=~P#JeBIA1AN7pOAR>llYV5b@x*e z?|vG8n!N6QM#8;q(6bWneh%m7|J>UKJumU@7jS<5&%JHXixTgC3Fn{x;odgrWr=sc zg15ZF8(fg-Tj_~ zd)uJ*CEoo3{sDXH?hhs2{Sp2VdENc7#JfMiKOwKXKb3g*XZUC2b@%5I?rnp;@UUv^8@$QB<^16Fi3HP?a!%4h*czk&F)ZHUUyn94^MDn_OB#C#AjE_uS zcaI|R?oshk$?NXXB;4Buk1p}N0u_fL;4n7Wf-94_vyT`-F zBd@#1mvCh75&-aRuu zGkM)Ti^RKU#b+h2yJwSl_w4xW+TgL-n|me`@eUu zjIWH>-K$8vdsTc@^16F9iFdD#uTEZfuOad7HSsmc>+ZEA+}j4PE%EMk@O9Wzcdsk) z?xFZl^16FHiFdD$uTNfgZy@pR4RPN8y?Y~kBfRe3SmNEA;G2-w-J43hdoz49^16F- ziFa>-^UwcqZyUU&gnQfItt8&PHNG`_>h5hM-n}ipEqUF&oy5Dh$G0c1yLXUy_l`L4 z|K7b5z7t+|?=11|UGQDV>+W48-n|>X8+qNmyTrTq!1o}pyZ4lEZyUUq#Jl&#_hwJs zy^qAZ_r>=mue4-F>peyHCMSA+Nhnm3a4Q_-W*I_vsSvJ_A34yzV|zl6uawBy_aFXG`ok z2S11X)pM@Ip7ZeY$gAgki9HwK7m!!ag%W!%!Y?APo{J^+T!LRhUOkse?70lTjJ$d- zm)LU!eg%2;Tq&{VDx81*hmJP*YKcA9;QaGHbhN?OO6<7~zmB|mu9w(z1AYT}_1q}2 z=O+9n^6I%+V$Uu3E#%d6tHhq$@Y~3%=XQxbci?xBSI?aid+x&TBCnpiCHCBd-$PzK z_e$)!59j@#jyCvyi9HYCy#LeD20tjV=OO$d^6Gh5V$UP^BjnZdsKlPf@W;rj=W&TW zPvB3GSI?6Yd!E9dBCnpOCH6dnKa=!-miZ4tUmN_K#LnmO=Q&%QFG%cs5r2`qI$x65 z`7-`8d3C-bvGY~@Rr2b5O=9QkIPd>;Kap4G&k{R- z!G9sI&R->V{)YcXUY);7=xc-jkl6Vr{wI5?^Dl{=f8&3X)5+_2k?QQ~C!w!(^_Ns< zSBHeY)-^yg*aQp|5ofl2m8cU>Lgsj=VaDm)JQ1J_31ljwqq8b&Vvkb7XvE_EhI65<5r5MD``dZic5<4frCm^rR2_<$; zgil0XofAv!oCKeQygDb9*f|+K8F_V1E}^e=O(C&!N_@L9;Kb5@C+v*ELmSLf^!JLkaX zAg|6jC3en*^Zrj?>zZ3aU+bDjV&}a0yzHsY`6PDEkIzqDoeN0pTo7N7ygC<>*tsyi zFnM(@BC&H(d{Of1Tuee=>snl5=Mwl5?5WNrC3Y@_FGXIROH1rr249A}I+vB$xg5^> zKYguhd5N7X;46?<=ZX^gTGvVvJ6Fb6W>0mlBC&H-d{y%5Tuox<>iFv9)wzbm&NcBh z$*XfMiJfcXYm-;!IuiO?*SZorhvK~d)7QGzli0aF&ig-ot!o2`og3o3|I^pHHj>!6 zF}^W*b#5ZDb5nd%^6K17LSO6JTw>=I_!jJ`&MhT&ZiR0}UY%P@?A!+5hP*nrmDsr* zz8!gWZZENO2Yd(e>fBL6U+daQV&~5I&g`kqT_kqyitkEZox4fw+#TPYygK)g*tsXZ zCwX=5C9!jFocDh__rdqUt8-t8o%`YYkyq#b5<3sT4`G0sD!@Ob(qA?!|}t}Q=Lah>^u@blDs;PlGu4Pel&S?9wV{ySe*BN`dZg<5<8E_ zdH=Wb1pEZNI!~0?c@lmSd3ByFvGWxC6!PjkRbuC9_-W+TdAh{TGw?IWtMg0=eXZ*( ziJfQTXS1g|&ym=9E`Ba~b)F}&^L+e#^6I=mV&{eUh2+(Fk;Kl6aen@9=Oy?hcy(SX zvGX$gGV=H_!Z>Ud8Ne8tMIGHtMh7!o!8*J|I^pHu9eW&x~`Mhc|CqTd#dvW ziJdp%HxK8Zg`UY$=#?0g!3n!Gxnk^DT*;Z{u&1 zSLZttJKx3MC9lr+BzC@!zfWGBA4u%{5dV<8IzN)o*SbEI*!cOYHmx|AxFezm?F}y1tXx`91zUd#dvXiJd>7H7ycJ}s`GD2b#_NWU+eBC zsm|{H68c(qhom~Y2T15^-JO!^>>eno&h9}H`das3Np*I2N$l*#5j%VE9=tkxC3X(M zhmcq2FcLc(-pH$SSc#p(;k^IbIXpf*UY#RI=xg00O6Y6dBT4KW8Rz|ThJ?P>J*LFYvGB3jQ=MZ=>>LLlhrBw+mDo8R&ig-ot$Tcl zofF`^|I^pHCzRMZ5zhO+ofG2|HuXQgdv2!7OA@)?~!V)_d!51N~&P645E`~2gUY(0e>|6q0g1kDHl-Rixz7%@_EhI`5<8d2mnW~z6(n}9h_6UqohwP~Tp8#6pT5?;ip0)Uao+#! zTn%3hug=vacCLZ1L0+9}O6*(Sb&xs$}sopIj(?c4?51+UIsC3fzH z??zsoyG!ic1K)$ZI`@>=xfi|{d3EkBv2!1s_ka3Y_r4PPTK9euJNL);XHRt=AhGj6 z{6O;RJV;{a!T7=C)p>}-&O`A-$*c1)iJgbzhm%+55fb`Z_mL7ikHU{)PjwzGvGW-G z81m{oR$}LI_;KXbdA!8V6L8-D>1*95O6)ud=l$Q#lkt=B>O4ha=c)Lq}LNBcZQ#pDVHRJp4TNROk5;J1@X5Ag|5~C3aqf zUqoJ=7fbBC1iys5Ixm&jc^Q5gd39bcp|5pcA+hsH{7Uvz=T#Crug0$?ug+^Ec3z8L zOJ1GVN$k8H=l!3))_sG-&Kq&w|Lwd9zX`9-nU=waEh=LikAx=ePK`ikneU+ex$ zV&~uZ-|V5YCz9&y=_jGD_4JoiXHSQOzSc89Qk^}W68c)tKuLA>43bo5&tM6Ct*1+3 zXE)CKznwiep`E>WFJ7HPBz6vi4?|v^O=9P;_^{;FIh@4K;c?#o?HmCg0k6&xCG@qP zktFoBo{=SXj)ITE{^}f6V&`c1Xyny7y2Q>g@G;1%b4&?+t!FHWonzx;v!^=8k=Qvd zJ}!B6jwi8me0+TJ>YPAg=Y;r#8hje^>YP?WU+bApV(0Yu^z5n586H+(np>fc>r{~kE+|Mu^R?}=CcUJ|-n&)yRI_rdpJPxbFBv41~&Kl19| zUt<3O_yOeAf1t$vgYbjMtN&mL-L2;kiT#J-hq9;o50lW{dJdP^e*}I6d#e9PiTy|6 zN0C?m(GvTQ!H*%Y{$nNfABXe)Z~yW5@p$#0AhG{M{6zBVKS@G&>p59s|0(z>?5X}! zCH9|&pGIE&r%UWV13!bj`p=Zm-FnWF*nc+8`#;^S=NyUs=i=v*SO0kux?9ir68kT} zFJMpgUnsHvBK#uq>c3cG|0Vb(c2%||E>6~Y6tN&gJ-L2<7iT(HEy#LePdLEG2 z{~*r$zx@y458>7Su*CjH@JGn2|51tkkKvDzSO4P@`=7v{Ag}%>C3Lr*rzG}2jX%wv z>VHN;ck6jpV*hjabL^@9=Oy;PfWJUq{Vz)Fe+hqyy!v03*#8Rt3VHRvDxtgeye6^# zb)5Hq``^Idz^ngFiT!WkZ;@C3+YX#`iT$79pOIJp=MwwBz`r1`{x2o=e}#WVUj1K7?EeP;hP?W} zmDv9s{vCPse=o8B2mA-}>im5~M|7bYx|8%$B(Ixhef%E=Pck3NfV*gn9Smf0| zwuJ81JC4Nuaq)54Q~l#f>>nQ=pS=1fkkH+FCzRMf5k3)ns()gM{gdFl|I^)iCzaSg z8P5B^{gdO9zzqr|IGNz?5X})B=*mW&q`kXvq|iq9iN@N`sa|)-FoMg*gqFO7kjFIZi)T# z;Pa4I|GW~qTkm`l`{&2!XHWGnAhCZzd_nT+Ur1vA!uZ1E)xU^@?$*1g#Qw$b#n@B* zi%aZZ0$+l>`j?c@-Flaj*uONsG<&Ll8HxSN;>(g(|8f%hm&cbUul^Mzbhq9WCHAj` zuf(3}Us+=RD)=ho)xWBQ?$*1S#QxRs)!9@1Ye?*06JL|O`qz@!zc$YMzy0gr>)_SD zuEhSKI6wcVyY;Rov44Ghee&wxKtgxx-B4oxM)*eTss4>6_HTl3LSFrwO6YFAn@Q~7 z9N(Nh)xU+r{w?t>$*X@WiTzvSTa#D+HWIp9@3s>Ax5Kw%PxWsvv401A2lDFQQ9^g? z-AQ8q&iKykss3Fg_V0@CN?!fDN$lSp-<`br_mI%tdiRvrzZbq2d#ZnLiT(TFy#L$3 zFTO8c{rgGm-yi4a|8%$B10?nzi1YJ*x?Ar-68jIv4<@hvLnL&!-a{q!ABG>sp6Wkb zLU-#uLSp}s_>t_X{-Y%JAB`VPUj4^N>^~Mimc06plh}Ve&ilXpC*UXG)qkSI{*&;N z$gBTk3Ei#t6p8((;-|8w`cISCe>#3TdG((mvHwi`O!DeKOaAfSFK6St|NGxB=iuky z^<3vle6I8G^T_MD&X@RH7vQ}A`&<{|7vl9?7fF1si}8!e>$xtG_*|Fbmy*|WT_*9l zF2{NQ=b2jX6%wAQ^w5fp_SAFT zAo00w#QFI@&(wNvlK5OV@&vh@(&;NO*)_b4C=ei%~{hw!Qy$?uyt_N}6|9Pg?`;dfZ zYP}Cje6C0EN7z%(^{B+>dJKPzyq@cEiO=-}{sehF*OL;Ssr5c3@wuMHpJq=z*E15I z>skC+@_Mf4BtF;k`19oTTrWs?rq=tS#OHbm=l!2&YP~N@e6Ck;-v4=~*88f&=Xwo) zjl7=gbqUYZdf$-vTyNrUvZtQwEs4+dHvTqwJ=Z%DpX*)xUGjRa_ar=1>wRD1bA5pG z{?9YD-VY@{*GKqA%1OMI?R@K4C=xjvQfOs)4biO=;p{yBTFQ|tX+;&c6g^Zw5>wcZ~kKG#n;@Bcp6&-l-H zJ=ZT1pX*orSMqwU-y}ZQ@A&WJ^;~~Qe6Bz7KgsL4{*v%at@m$9J=c&(c&0X_pQN5^ zNPh{>)P{6Oc&0XFfTW&lNT-BnYC{G}>bZstlJHDz$Y4o5*N`p=&(wx=OX|6X^hoNt zhV)8&t|2($a}9$JgV%F4iO)4GJ}h}X*KiV_Yj}Kk@_McjBtF-OIPd>H*GTwCcs&mOL(R>WDJSVH6}hLd+NEylK5O><71Q8bB!bMxyHqL z|L2+7kntouQyVhA#OIm-pMX8}ToX!su8DBo|9Pf1WMYZWH3`o9zt1%(J}F+$HJQZc znjD{;yq;?ciO)49&ig;l)P_tY@wukPrzWrGnnuDiwIS0=e6Hzm-v4=~He`B<&ou+i z`#;arhRi78nc9$FQyVgi#OIn7=l!2&YC~p|_*}E&y#Mn|ZO9xFpKDHh zPV#!Lxg$0bwYpBHMS`S~3yq;@) ziO;pce_`tU!|NK`EWFM+JD;M-&X0p4D55QjpeTx>2#O#miXte2peTZ%2#TO6f}kjh zA_#&a2#O#Gf}kjhA}ETvpY_+wHTRr#)_(T8@5lAcbUX8nA=lD}*HK3HI-1P;zrBtj zA43kW$wu}%mV7LIcpYbCuj9$b(}!1`5l(602}brhk$fUE;dPRcz3R#J^x<`~k-bhK z^Zt)hT6n4vPHEv3BYT}jK8>01I^D=#XOMaS$0;qGYGki7$!F4s*I7n5rG;l3*{gxv zz)X0ZV`Q&$$-MvLlop<6WUodt@Bj8XpUnF|PHEu@dtF54{U4{a z@M0r-T|(yl-(F4RCUSUPYGkj=$d}QF*X2g`nogchA6{1&;gl9$X=Jaf$X78FUd=}K zx|+=UKTc`kHAeQjmdyJx}GmJ^6ZO!s`Yjd(9-zqz|tfjqG(3`6l}C zy4eV)w6MjkcEF(!x89>@|zb`#(-; z;ax`dx|@7AeR$ntWUtxe+4SLcuMtjZ;eAH-x}SVMGvPJI$X*YSAD|Df2aW9Y5cwhc z@S1CcQ(E}2k-Z)vKf+9SJ!)jHHgX$%cs*uhugA%c(}&j+MmVK~?MC)`lFa)*PHEv& zM)rD|{4{-dbr{*}8S*pq;q|N$PHEwDM)sOVp2tjhJ#S>M7sxNrhu4cn_Ua^e(udbe zMmVK~FB{qG74j?0gjbi5ywP18eL((zKD>I3?DZk}L;CRg$Oxyj z@M9x;^^yCS39nC#?DZ-6Q~L1w%*bB-u2)M%!Jo3M)vxZ{40HU4H(($H}Y@v;q|)_PHEvEM)q1lUcyXx{b^*czsP^lhu7am z_F76_N*`YT7~zx_{%d5f|H%I_gIAG^!mB7_gi~6SH43kyoKbicB}O=@|!$j6S@E z8`*0Fc?5lUt!so+TC|>#z1AnM&rEoYG_uzQc0r?hB0BYTY{k7Xvjwl}iZ4rG4+$0;q^(a2uo$m8h4YbPU|(xRP>?6nJd z7iPk%%E(^3l6R#KuicF7wL5ut`tTZWgi~6yhmpPZB=5;gc+GvT$rk-ZKeA3z^o6O8P2Ao)Q0@H)r{r?lu`BYRCGPh=*% z4l%OVq2xp9!|O03drcxwq7Sdbjc`hfjxe&n$p39nisdmTkSiaxxKHnP_-(yxH5%FLd@}FR4zG)h>~%5uV*2p9#K>Mv zNZe*`3$XC#Z*Of;0x{7=ieRwq+;gl9#ZDg-&$k#9v zUe_AgYX*4+eRy4GWUuSVy#L$l2J#K$@S164uN%oX(udbgM)tayd^3G`wHVp!7V<6h z;dQGKPHE9?M)qnYw=xr6w;S2(4l=+0wfb6^x-wf2&c5@0V8`oNPdu+@OsF|UUSKF>BH+`Bb?HrM~v+C zDEU!l!mG{5UXPIs|7@ z^x@TGWUu$g@6m_X`$jmWMIRX1tC!r%On7~0WUr6NAJK=`$3{4%MSVv0`h@%mGvW2A zk-a`6e?}i({YLisocuX`czt1HuP@2G|J!Q;c>y`RzB01c*W|D1!|NL(do3g{qz|ue zjc`hfzB97d_vG)H39m&)_WFVR1ATb?Xk@RS$Uo7C*J2}_(xRV@?DY%z7iPliS0j53 zkO%0)>o+5N{Z9U!KD_=g!YM6UVq~vB$$v5vUVju>Vk^x?JC$X@@D|Dg}Be~oZT zi~chTuT(}jrD?_}ywa=@PHCDm3a>OV3a_-l2&XjtpHXBDP;k-gR>uS*|Z>lxW= zee(MB;Wg3-r!?Kb$X*+gH)JNfHZrnTCApG5yf!w%DNQ#qve%~MO_>R=QAYOKjJz3r zcx`TEuPw-1(1+J(BYSO0-jY7NwlcygO}93(*BJ5`X2NS5BYSO2-j+VRwll&hO~)G9 zYkTtc%!JntM)ul~yd!;hjWe>>PUM~F!)s?Fd+kErg+9EhjBrZRU5)Iu8+kWo!fSUU zdyOZLrytAb9!5B&>7GXR+KapwGvQTjWUsx+d((&4K1TN1m%J~1c-0u$Yd`XS^x?I? z5l(4(fRVi>kS8z`UI!Z4>mc$$^x<`|5l(43(a2thkPl%dybd+8*J0$t=)-H0k-ZKl zA5I@$M;O`bNb-^N;Z7*%#~9gbGI=t6cpYnmQ<@%UWUu4N$1@XN zbw>6&fqVjec%5iuuan3p(T7*Pk-bhP^ZswIQ^==~!|PNddrcuvp%1UqjO=wf`E>g5 zI>QL3G@WW>uQSPKG80~B8QJS>^4av^)nH_=bI9k=hu67AIHl=%M)qnXH!>4m=NsAU z0`dj);dP;ry{3_Q|F_pgn0@|lxhrX51 z2aIq^(+7?0^$__XX2NT(k-Z)!KTIE9j~LnOQSzho;nikjugA!b(TCULMmVME6GrxG zC$}>bUQZg?>nZY6^x^fi5l(5^VPvmo$j>knUe6lY>pAjs^x-wn$X?HrpQjJ67mV!n zBKbx7@aixuUCz5O4HYj?DabNb!NhAzLCA&AiqH$ zUT+%N>n-wI^x@TQWUsf$Z_|g@J4QIA>AObu>LK?q6JGBb+3S7s`}E=Ufe}t=+G}L5 z56K@g6J8$~+3RES$MoUVXJoHW$e+-M*QZAI`i#u`zrFg&{p9fa+{j*EkiVc0uP=@4 zwSdg~zrDU9e?<O@A=5*N@~M znF+6-jO?|TyqG?`em24>O@A@6*RSMXnF+4}BYXWu{*6AoemAn$ALKvi!)u9=z5XQs zNgrN+8R3+se;e6rDS0U~;q{M^z5XTtOCMhU8R5ihs!@0qXN+)4i?c@IRh%=zDJ@Qn z!mGHz2&c68e@5X|yo^zJ6%R7PDJ@>sD7=c7Gr}n?Ufw9YiU%9ntB_nM*{g_LL=Lai z$X>-{hV4~CE+L0ksgb?P$Yu25l{d223gi{&!)rw&d#yy~{oh_g$V15CwXzXTY4IvX zIHkp_8riFyT+V!Wt!9K%TD-cEz1ASF!Ay7!HL};5&53gN}a7v4-jO?{5c~@q_Yd0f%?M~jEKD@>o*=rB-9`xb0rx8wR@m@yuswP)6 z6JC28*=ry2KJ?+WuaUiK$TjrgwVx4AY4QF>_Bw!k05jn=!N^_*k`JU0uY-*2bujs0 z`tX`)gi~64h>^VxB_GO6cpYYBuSw)d^x<{5k-d%}A3+~pM;hUj7S|ft>nQS3%!Jp` zM)o>}d<=bfO*XREvE*av!|OOBoYLasjqFuNu45*=PB609iR2UM!|Nm?d)1Tc>BH+} zBb?IWQ;h6&D*04q!fT3=y-p*aMju|M8`~${rT>9`j&j_cqxY5X7=abK8CcG{%ve$*=3+cmanvuOOBJ=)luZzhS zlf&y0BYQQGoA_r<{J`g>M);-0ml@gda`NTe8;;YBmivp(D~#-WC7Jhs`(8!9iX6Vp zM)tj$d^OKn%I7skc&EkJ8rgjYc?S1}`*lWmr^VMB+5HCc4a|i5Oe4GBNap?D?l+Nd zB8U6UMs{x@^Zsx5TgbPN!~Iqxywl>_jO^Y@Ze=FiZ#T009ppRc!~ISpywl=YMs~l8 z%=^FH?^_@3n?Bs{HNrbBzR$?+_ml5uCfw&3;hh#gU}X0P$qzCU?hhH^ zofgkEvirm2hnWfYM~v+LDEU$PaBnlhJ1u_92=BD`aU;7wL4JbyaBnxV`;+7+>BIdg zBfQh%r;Y61LGEBC+@CSRJ1u_J$nMXPdH=WjJn}qpxIb@X_ZP@7(1-hrMt1KcchZOZ zOGb8onfx++xW8g#_bzf5eYn4BWcSy|uhED5>qdB|#q*8q{sx)%f4jd)ev=&TZyDj8 z7Iz!j{cZBw%!K;r_mn-9I3IKp*bCMt1*@{2_g~e`I9$ zkIB6M+r5w6M-KN-jPOp2KQ*%ZXJp?0?cPu3{U7hN_;Vw>e?k6&KHR@Fvikxu@BetG z#a|iO{cG~q^x^)Ek=+-P7t)9Ow?=mVj{F^cxPNbicUrv2$nHOoe_$rue>B27E&j;} z@3eTak==hL|IB>2|6*kKU&+7Hhx>q$-G3whMj!6K8`=F2@*ni!zQoAxf0F;C5BI-} z?EW|TZ~AawYJ_)M{Ev~{|0VPOZ}q# zjKaO-e@1wxCCeCvd&wXpywj3pjl#WTIU~H&lI4xUy=1UaxR(?f;hmNg8R4Clq(*ix zCiDJp_YyLt-Al=(dTN&AX zYx36g;XcO5?%R-g|HnHm+1AMJ+mW}U5BIS~cHf@7J$<+vittz{prK~03*9kAWxtV_XCaaPD>6lvirg0 zgP95UiAHumgnS5nxF2d{_ru7C(TDpaBfB3?KAb+>k1(?Pk>n%k!@btX?njZ2q7V0@ zjqH95nfHIZ(~`+Xc0ZQP`@h|fBOgZ&_v4N1UPtErAMdo}1S7kjNIsE1+)pyHdp)_H zKHN_>vim9IQ|QC}R3p1jAy1(X_tT8*emePd`fxwP$nI0gQ|ZI~Oe4J0lCzBLem41R zX2QL}$nNKm&!G?ZbB*kN9{D`_aBnoS`}t(v|M5;sE-$<6fP zezlR^uOVMUAMV#0*?k6i27S0+XJq&5$=B0|`wd2RpGlrcAMQ6A+5ILm@BencnS3)j z+*^$7ehc{)`f$J1$nLk1Z=()F>BD`Nk=^ei-$ftpcN^LL z9`Zf(;Xd2Q?)Q@Kr4RS}jPOoN?l-dg9P%7y!uBIdkBfEE#yXnLIZ6mwCLw<)o z+}|~_dk?vXKHT3kvitkw_vyp^10%cll6&dH{X-+We?KHNVx!aFVLGqU?9P+!q+x{VVcU^x^)sk=?%`e?uSc3ytjl zE%{seaR1K8?%$L7{on43$cxC~{)3U-e#fJ zA0Q9Vhx>0vcK@CHJAJtSVPy9u_J1za6QMi{bV}y5FI>;#8OP4jm zJ1t$#DBMezHwyRC!A5werG-Y}URq>?cUqbn*}a%tEZMz;%=^FHOUVq_y^LH&4)?r~ z-B%#5Kp*Za8rgj%@=EmKKE%lGE0cNuxBDvORmkDKs*&Bx$>sFnzM7HUS0}GdAMR@y z;hmNaHNrbBUDF8fv~(>aywlRPjqF}QuHc+-U&qMq!^p$v!+p4s-A9l|(1-iFMtG;C z>lxX7ee(Lug!@P%yKg||_kX<8(hZI5z7d(<|LtB$t|W*1#zuDEguDrTxNmBNcUn5i z$nKkwH)AH;H#f5T7UV7H!+o@o-M1w3{%`lK$Xk)aeQP7Tk0Fnt5BF`1?7l5|Tl#R{ z&Is?cbgYrxwgzB_q$X2N~Ek=^$o^ZP&EY3ZIucHfJ<7k#)_8{wUn?rmiEeaQPT6Yl#O*}aBb zLm%$@8R4Cl?r&uG1IPz36Ydj??0z8mK>Bb$$O!MW^k5^qPb5!dCfpA(viqUrL+Qi) zFeAH9BJ=yd-47=pP7e1YjO>0S`AGV3uQjs!QRJiO!~JL@ywlQSjO;#{JeiqrKi0_Z z$B}vexBKzrf;hmPAY-IOS$fqz9?xz~reF}LB zeYl@yWcSm_r_+b~8Af=grBjXUekS=$X2Sg}BfQhnvyJTDKyF|r+|Mzx`?=(E>BIdz zBfB?}8|lOSd?UQm(hH32ej)inX2N}%k=-vMUqm177aQ6A5;E`qc5fm#k;DB`BfDQl zzKlNHFE_$FEuC&;_bbR(Fca=q8rl6SGQa=hot8Em+5Kwr)%4+hjS=2y>9t07pFy6% zOt@cXWcTaI*VBjl4MupUr8AA}ek1utX2Sg@BfH;B=KbI9E#ww*xZh%A_gl%g(uezP zMs{x{x6+6E?M8OLgUs*$cE6K+Cpp|_8QJ|V@?G@dez%d`?;-R4Z}-{c+2nA)*U0Yo zk?*4q_xp|TPD|$)+5G|X1I&c`gGP3Li2M+JxX(4R`@`gi>BIdIBfQhnM~&>>Ms8y! z+#fTt`{U%t>BIdABfQhnb|bq#Nq&-|F?Swxq}?;&luVLS@N^=;r^VF z-RF_#(TDrNdl$Kj9PY0g+5I*0 zYxLp%x)I)K>3k!*zd?S3nQ(v8$nI~E-=YuqZX>(DO@5m`+}|<6J1u?J$nHJl9%jP* zJtMonPkx_1+&?hFJ1y-svipbR519$~kBsd8G5KTqaPKq1J1zah$nKw#KV>G|KQpp> zKe?Yi+&?$6`xj(>|F`>>i_p+=}xR>RO@J`DTqi`=PFv2@6`=3#`mn~xy?q!3F@J`E?H468#<&5x7 z%a%6^_p-r8;a*l~gm+q2WEAdYsgd1_$-MvDy@Xss4);<+S;l8qw-B%&={%`kH$*YpXz1+y|tC3fu5BJrL?7jwh4f=2&YJ_)M zwx*HY*CMaQOt`OYgm+q2VPyAp$m=i@?!%1iKAb$9KHNtb*?nE|y7b|`o)O+@+4@Fy zA4wj`Ot^1gWcLlp8`6jSMn-n8B=i1n_l?OLlf!)zBfD=(-jqJvM;YOrmThKa_sz+h zGZXGx7}D*5q&>V`TSj$lK6|`?f}Q-;TT;eYlS`!aFV7 z-pKAdkau7v+;=px`#3WH{vW&VMBa%U?mHXVeHZdB^xgWxE^M zeLQ(QGvU66k=^$s?@1r-dl}iinp{mE?t2^IotEumWcPi^`!W;mHAZ-+W&0V~eSh-) z%!K;^Ms}Y-ov_alw$UQ4c}5BH;t@J`E)HnRIM=YxrpGrQJnQ)(CWcSm^r_qP|=|*^` zWoH=KeJXh>GvR)wk=@TCpG6<;XB*+2mNgjJ{T%W+%!K>7Ms`1sd>(zcHyYXfeDeA9 z;eLS;-f7u|Ms}Y@p2keLUu0zWi^&($hx;W)c&BAeMs~lHd?_>GewmToFDGA4AMVqQ z@J`FFFtYoV%( z-(h6;JITEN+kF;!7CGGSGP3*KhBXD0S|!pM8HliTTIk0*`TAuW5#$a_3Zewvxsqr-?D(z0iayvMU--v7PFbL8j9 zvBx|k@9{kOdHUGn1tahABANGpc1X)Qjl9Q8WZwV1$IIlG$+5>PM&6@~%=D_$9`BOh zrH?&&jJ(Ht&&YdxLjHuA z*yB?pc1X)UGx8q&WZwV1$LHkF$+5>5M&9E~GVlNFkd`el@*ZE2dH-jJwCrmm@9_

z{9wcmY1xlP-s2}S@BiK-{`+k) zIrjM3h#k_hUyQuRujF5ui9H64yvJ|k-{@nH-;KP-ALKviV~-_9?2wlIY2-crBLBrq z?D4me_gG3^N*{atW8^*lCG-C8J^myAM`jORg#)oen$H-;9{H?M?2*qIu|t|qjAD;` zfe|~T`TrTk9{FXA*dfgiGKxL&%NoTV`Q?n*A{02teV?*+W z%)}lW8F`ONawUE2v9Xc&*o3?ZeeAKRk@pxy9z`E}Y-Z#=HYaaRAA4+J#13hGw2}AN zlDs7|vBy?M-eYSr@Bi$O=EoR$k8Q}?(8nIz8nHu~-_FQ;j3tj{Cid9g$b0NS=KY@? z()^A_-eVkj9DVGulacq>nauD1?2zVnG4dW&no3alDcD zs3Y_K?>$Z+pFoa1PBii!Cy`I0k3H&*yvNDplj&oRQ;fXFsbt>&y~h;t6mslwnvwT7 zoqRfd>~V&X_n1oN{huAu{Fz4H<1F%7^s&d;M&6@=+&~|DoMXfeY5rUz?{OaaJZ55# zMkDWWKKXq5*y92t?{OjdLi*Tanh`ss`HPIa$HnA}nTb6vG4dWw#~#-hd5>$!*V4xxGmN~) zb>!>lV~^{N*dfi|VB|e!l4mj#d)#Q`J#Hf3L?3(HY~(#!$h`lvLz=(E$a~yMzLh@q zxXp+i(tN9t_qd&WJ2SDz9Y)^cPBQQR?2zVX8F`Pp$am4l9(Nmgk9)}X(8nILjo2a0 z-)rPO?jzsFOzd&Lk@uKG=KY@?()b-Lq^_XE_p6}?D4P>JEZwXjJ(IA zD~7hcy4bk@xt3`~fquN3W6h_>lY|eeCg(k@xtR{4ss( z(PzXCY5o%<@9`=5Q)Xh1&y2iBKe?Yi_W0b0J^ufHOp`MFPw;FWCPKTE8wLEUE=hp@ zX;Hwn0{&I|ze?cyGGnDdBVm!WEPq-o+sWS<*T6jfKVXf9F8-nn_gDZm*ka{r2RrInUSL%6;& z*H&I4twLUvYpb?P<<-(^L!{L!VX?Hvcxh+_^hj%tgC@XntwF%|wPpb4t&d4dyA#E@Mrb!zPhWK10ZN%qBJyPXZ7?3ue3hmM+LxA%)>613)tWB3n zn-xR7wE1M{mA04we2!*zbS=yU=C-T?p1mb|ZZ#67LZ`Gfb6a!o*6q@mJaE<+oVUSi z8$7mQep}|ZC2!j;ZAadYbHKI$C=P8jjM)P(oTb63gECaf30?5 zZWqqlWwBJn%&wfb>jdbLcEe+L?%#cZG=4nryggc_J#pESv-YZmxl(lnG(n%VcNMft zHFWz;l@8$k1IY(Y2kt+J^ABo8OdYP&#^nbj%o_n=Gh<9_iR(sD@@3kdCW?S<><4fXnfn zQXRRjT{>YD;Cx~QFne1efOPIOSRkFp^~O%= zeC|J=^DbzSE*uNYOskeI8U?eYi}}2m*-L6*p47Bhx|Hrx&be$1G{HjY^6|iV(|P9f zInouyFcW&ED+j}9;8|C;0o_$YfHSYc?<&r0=6W+{Hup$Z<8k#2;M{AfV6Jp+IW$T$ zf_C7Z>ndOZG(aoNgMR7yYT)yRTEJ;0pELWU8|iQ4`%QS?#O%$Zq?USEAl-u7traj^ zx@{!P1^QN=-^%lD&jU_(Fmng@+|e!FITbi(Ryi~Q^LI^x0qJgL?qT+xM(CGjH$aHbRKj5$MrogQHBfyvM%J;=<1TzinYhiYJvG`AYK_V5U3l^$XK zk*P2sJvs?+X`3NEhTCJ)rN zp?{WppX1(noHwsYdVUl%!b0hVk$~e1?b3^t&?$8$!17 z>Fse)2Q3nR!0R2(dxzO~$3wT&!?pJ+U_g4m8sQB21Bd#=_F{AK5Lfxt6+}wIiFu7!0uo2`Q;dx0(@UE0>}&I zOJ8y3*Tq2oh8-5xz<~7K4C(vvut-|Oy^C6)Q~Dtf-19?^^doLR)8y4rKtd+TM<@w62G6ZUYz4(DEvnuDV+Nw->9%_JH$_JELjWbqj2J-66tj_!z6)*#O zlo^_b8sPjjheAEH0K2a>8F<#(oUu0NtxZ?K^DCIIn6At^bwD=^k70ev4Cmb8+%ueK z3}39w2(FLdI`1@@bvbw48PKWBdZU16@WWPSeePX<4h$$WlKGKs%4{$mxNpPh%52o6 zOywA8Rc2%6d5_8P4wKnrnlhVCf~Crg;>^vsZ}V!1&pu_gz+sCe%8Z_`%$60(Y!%E> zX6sQfpv)M~-G;mkp4-k;X1j^Xj2#KJ%52a1+fM=R-GTddoC@8_j2jCb%Iwsp4DTTs z-a|6G^eR(@M-|t19jDB0%Yv*$Bxtw<%vyD8bk$cat06s6M zhlR>qSO-g#;k_j@jptlc49&1enTt8+;x=V2!Q&F1fF;4TxBlf`(+)< zTs~2m>4RY^bSZO10=3Yi%$4|Exj>n#8i0GQ;`&wboim#AFdjIwneSJRgXzHaYk2N8 z>~sy!y>=vU_OAIIE%5z@#mdaYX(spHSOLw-+{CkPYK2A0 z+{_s_b5BbX^eS@;&$?wAaQ>~F!@Er8);?u!m-YUjuY1bN?uq4(v6D z`8i9Kd4T6XI2h<3|R&3l=N$8`poQ`@Kz>Kk)p6?|*Rbk`Yh~bAfaJtcE$t{52Swp;MW^dCt!i0 z`21g|vdfHxc4Y^Rf*xg;t$=CDF30`LO;L9Fk-+uAd=BP%;biDiwn)$n3zSW(l`YOg z9rP+&!fXjXCG(Xn9R;$ZG^I`bN?DVduT8bICJO{W!L1|nhnaXl>qmzwMf~uM?)RVgT=~L za83nhR`e^oP9<<{onB>!(GQym^uxyj_YZG{E?A`Oi22H{%bx3XE4x0=S-)A?k$jG% z-)JOot+G?ujmN_bSgPzMoU_R^WjCz`K1U5zb~EnTjBA^7{}%jp*`i0;(d96p?3T=I z*{|$YQt~F>ub97U26foUu*4vfGY>c3^(HJh10>b;^z%1o7Df-O6r{+YUou zma;qYoE@uy=ZwR19QW=t3OIXbuI=2W>@I>XWvjTaY6dJ-cGm_NP?mR-?C#9%-mL8S z!N4>2;CXv+<{q5CCwb3F%I-B3xOXq^t>&J+E1*N!eZ~U)KK;t>I{|u?t*L}but3@U zc;Zq$j{rU=a{k1bz%vdR3w$2h zqwJ(&n4|3B3CvUWh&)V&*~%U{1f~HFwN=2}(Sl}WkC_0AmE~O|JGoEUV|o6uO+Y@b z7TDpqc37zF@!WI#2;h6&VBqtFaj-zy6DPw`Wlv(hehlDnauu{FdrBpADSImCojO<9 zDdf}0r;$&`^Ym(%4gJcVF$6l5o!YDHnF%z(fU;*zQub_~d3J-c4R|zg?>ThmlFw~b z_Pj=zr)(qlH1fR>mkS0#9n4qu!eU_NLT09sr_oQNzeq3&_p0$s}T zZj!xZ0&s5==QT}L_EJ7Cqra?O*~=%x5@n}PhegU>F&M@IJ6y@NE4!7wito*MHBW+m zWv>y`La(ydR>2GyP<95pT{je3l)b)5S>83WGjW|cU)dXbl)Y)OvN!iB+ro2hX;t=C z&cBWM+ql*`Q`y^Vl)YmtEKv5&iOS9@SN1OMzYD*+>w*5BYT*9a%+BWfy_|F3B;fx0 z29&*@d+r|%^!N8G%Wodp2gU)m}?KW1NS{L5f&@^=mcm{wrwOV zQT8#O`xxguK2zBz%Apo`e)|Yu?#T*hfL3LnB0t6a(+SL0wxbF-$S?W}}ZuvpobxbJ12@iH?nGy6)PvR%w| z@r+mJDf=2{zBU;+@AV1F&L0Fkcm7;u-+ zF#B!;^efv_1xu8DpXa{cqwEKq`vHCLB1m6rYXBP5A;8e zf?j2Rsenf4QubHQ`E{wX13YJdvj({S8*{&L{kJ}4e<%OWy}y(H;LJbzm0eN=^OXHF z54FHOyeDM;TB7XVJ<2W}3mwY-!x&PGz{W3Mm4VnZU(5Kw8V_`b*eYsK4uH5o;%TELD8_fNM z1IiUKQ?x`m{^{7cbiQ)MP%;`gqqGw0U=A=-HdVR2pd9E{sDgIo_&p=HB4@5N0cI&T zqypNMTbbvr+yq=(Wt?)W4g#*1b4EF5moHFmHO^UWk#eioLbq~jum`_ktJYm<02b zTeli!1M};V*P8`Plv|(K^*MVa-N-KGHsEsu<~A&b_*|^qM)k^73OK8hnT;m{_is`K zoxnMp;9^;s?Pn>s!%$#;#~SERZrljKZ`>RhP;MvYcH*p^ z<|(&x1u(bs6yTm+nqZM~Rh(VbtlX}7<#rzoA9#u5DWI}&PVD|b{q^eA`qAmHp{_&jDhELLvv9OaI!0W$9yx#LGG zS2q+|fU`~*1I(VlGfo@=#cvw$sIb^dfq#7)8{L9MV)e276bQPg=h01 zm64>c<{w-^SLdw8aDkMJzs zJ#vrME7vwnxySN=(_{0Ld%POjm3v|=%vG+vT)8J3VUcoAO#wcio($c}buiP>tlTq0 zpjWwPae8jHa`Ohkbmg8O0dtglVJI}g0_9#Dr(EZFSfboZQ=wnEm-+rO_r6jEoyv9b zy{kvLS0@7ZyjBOezs}731g0zZ24}u8Te&xR{+nETYo>DDjmo`U4m|7aKIPsazcU%y zlzW%6-|bSahpwjv<|y}GG1S6R<=$@voIaSKTrbb>tsH$gotR_^zqut2##a9YB5-X(H>HY@j6C2-&06Jd#R zOQ!>$|I7g9|Ls@qzdj}ERg#&cBs(5DmEJOK@IdP`ClC@RKpxC}gZV6EuCP%_5!Z_1lY7&tN{WX-i;|LZXaf4uaezzNWF>jd z$xng~B`Ywy!W5VdJaa{^uO#5wkZM?Nm8{48 z>rDrqxjvsGYk~VV7zJ~bY{)$u*27XI8%=-?C6z;=Rmmnppc(MlbfS{YM=KfKqGU_X z+>*Q{K3g%nRkxC@ncbS%F?^1h0zFE$X@mhK+x98hj=UWXW6PmV$@YBm=X$ck1SLBL zT;tF3WTz_N`c9EKcjsal1)RC_beIR6xyxvn2;?g6uj){;>kwde*Qu~n$!@huc4uby z1xm(Gf?g$iaQ+_cO7>)CuMsd`N%c5rQnGgf(|~#YY)|$bucT%q%vG{q1vEg9lKlq( z*YUkA#`PbB-7aoO5Ii@V&Mc7AZMu3M^G}^fV>M42Bs>CUf89 z*-DPZpFiJ|)HP8U%blsS)~>)bq)22g%9vm7LP8I+hW&+HgNj_^VaK_m@qk(%G29%t`{5j)+bIzRroPQqI z8riY2Q_1-P`tzB+ph?MveCKzAWZG!p+-aOOZHbbLT9jNo7;2$M$t9e5$wDPfGn8DK zhp8}I$z>y;OUdP&d3nE*=|f=>ELC#FOeI&2f;yP5ZKSs$7ElOr`-c0%%Cj$50G!D3a(?TUT4~8n>oR+b`+%46>+^ywG zZmWS-SgPc9=I$5-^)Lr|l-yYiqo6~{tnq-yT}{CEyA~_Cn`?JZhFQ?1$-R8u%d_rnfj%YoRl))#a~3LjU<&a0U@degc?jo+CPTZDxp|F;9)~n>P3YZIYkB^2qN}k}XCmMk3?L7ZUuJfBi@>IW)r$@q6 z7*Nu|XUBXc&x}&?tbqCFc=mG>fPUU!r~~rzcs}0@?MhzY{1@tBsgf6`E9vCEml~D4 zO#kvMC9jNtP9i` za_^gSmAu90TOCT?;qx8Nd3PMlQSv_d1J3!NO-XMara-@v4<`cWeblVv<1tG51_S4P zG8%CIbO=m^J|&+uD(UBp{%$3o*DCpfbH2dg%SlQW2qr)aF#FYjlCSHPd@~Jtlq}?| zZ#nDR8A`qz32jQg=Xu}r-0yK)G#bc1aP5aBN`9QHYxb|xW z%u+H?4&3)!0!=WW0BlMR04ba z)1~C!p)eCT}? z2nA(JRFJQSxhmk#{(=>_cLh5B+%H&>vsan~d=9CFZWXM|b5?Fw!739}uw8EK$MQIIZ2Mf{G3mtiwIS1_9TG zEmFa79EWr6h;cAm1?%R4Ze6aeHxwG6O9ktXfEt*gf{{4#J3zsP%_`Wa8aSK3|1aS0 z{|h!|ev^?Z*ff}@f>Gr#9R^geSv}yhIcM|t`vqGtyTvS6sDjah0f#L+Rj}1qpxc^j zV>o9_zY4ZtcH2s*gLYV|0{*_gV7m#xwe9G(V{Rp?%R#)yG?~o73@9~>Y+yk<11kr^r~PFuJ5rx1$%P-o*gRKi*xpBgl-j7kAoR1 z*qd|q=9znQ_C9>_`$0hsb2aTM*lz^zto=tpuL=&Bs)7S~&VgOPxd&B19W(>o!NpMd zf2_R?U{hE5KmME~_cckIH1AEDrcK(kN#C0`1qx(aVGJ0QjdaYhtwS~$MaLX$Y_ctL zY_hF$Y*Iu;*G)EoGR4Uh6=$Y6(V?PJh7Pq(R2-Lj!c9p4 zbeG_|9KECZt?+=8_4LHuQX0Mg$YBw@J|SVlsB7YXk@L&E!Zl5iW+ z+y+`JJAu6<+>Us+Zy@3Qi2MEl67J{*KxY-gS0T-6$akj&SOuIU;jR_HC<$wjhc$SA zcM?GQyHAmD&s-ow!Uw?b1N%u>i@ZRG5bliwTS&OC89?~`8%annBH;n>cmU5IM7j?i zCE-C_9|Zjehe%l01Dqw{p{>Ai5+3dYz~@5*;C?;QKVkz$NqBT6aEOG*WMCn%lZ1hK z0P!D3{KuD(@Znk#o`Ad?Aor6_0P;K)2ab^N5eu-NgpEO94+(=vGkB1MO$dX&Abj*V z37h+XQ4&7Z1K{1q!vJLX_yCXrAnPZZ0nq=%X5at`TR>+^7qF9rPp$wU`6_7abpo4#vm|_NA#jj{mzx2|@-o7{ zz7jY>LS`wjpM+O}z!nm|LBJy55DDK*0tnlOcl(fT-%%32wHN^XR}t@3(0Fx}gl~5P zkaIue-Jb@|lJK2Xz%dfOy9PK;!fSH@&^*us>?7fOpz}REe?JKvB;f}L{{g}eBK+VU z5`HKHYXQ*s5#sy^?|vKv!1KolgPlM)gm@!(H?oa{!-#(v<#PBW39lpUb-X*`1y%rv z|C600{B#X)hJ-gj_l;8|9L4o0;{ObBeunU$Zz16qPGEq9QKW^PK=|c;65d3-U#%zM zSQiPuCIDf-0sr5eCgHaSNI1S2I7Gtlnt@#;z%C%Xb(Dk?OMxRKoW%9yK@xtCG`|O5 z*ad_?fFJf8gi}FaFA0AFzds@TPl*3##QQU3{tM(fZ34jiZ5xmw;jfEG_*Q@5BGGV~MB_RVO%`B1iGmF{NTN6w z7$Q+3;3SDM;>$ZpRD!?}5>?PqaWx~{yoW@K3D{4fbpwe-odDt%oh7k&Apm-|THp|g zcF?u&BC#Y6>?YCC4IC%Yxfs|+BIbV)^S|hJ0_#cifS+d-02#bJ0C@Uv#oAvi?E=8Z z4;p2Vvuq8C28yVN(v0*oEs< zVA=-Y5Q)>ffdeEa5tc;UOX`9BBwo4#*hS)HT>$8J#{tlpf%r3!ZsuANFP}@|tXcri zSKxVe8aPejob@EmwE=rbyb|=T1mAg!0lb?(Kw=NVdUgWfx4;XmA@M52ziKIfG*_7q11~cWor`I>@&eJg?tH;td4!0LMtY5$SIP zy}lrcH{tyf8Q4JLyPJXCBrXM=n@s@1Zdps>d+Gu3S$2xVTUP+v0MJ>E_x%=NCy6VT zlK5WGc^}6BiMQ1P>quOQ>q^9X|11*kC<6|XxM~?NO5$o6mw@y;Fq<#ZSL-nE&; zHO&BITyvbnyFvSI@V^IiFvp6RW5o~Px;6=b_r3K1=-!7km}ABJ*OQoDNa6!F5HQ==gZIyDAo1BwV2H#|sJxb#K4J3Xi3?Th?5%%4U0K#8`d{2e*>=Lnp8T0FNIb?vHkn_~T{(G!FqIcs~LeM$VFWcpZtaTLAEV9ej=~ zB=IMB{z(sTio~CS&KovhF|duqqh0`Mj^f?V5cg;MN&GqD{(J*~`(G>qj*&PDIe!Vf z83YcHc0(?)JfSmx+|DFKI z@cW}A{sD6Q0lfYg237%xe+qn09U<{gabO4lzdz3+@h?bodM<#lx54A>Wx!?<|7rn1 z_iqCvo>@xb-$Co|$4LA~CxEbjjFR}zB(RgjvtD2$iT_8y3Lryb7I{8r0nU;{tAJA^ zvAMu*k_`30Ns^4X8rK3xNHWa=j*}!T2KJF8ZYD{J19&GRy}X|!r4~SZwnt^pB6(h_xK$0EL_Cq9u0C7B^;aNnIx0@uN1%NE2h*!D|KwAHL0N1h};225eYXCe4wvtq_n4}>1 z1$UEFISV*RQWe5OpoMu<3L`G&QK=eqtG57nUo${b1hPc-l2p5aq`EGWqCsFENioP9 z1K;{2aEPP^8R!ELui+R;O?cn5lcZ+EZyqA41$0~1k<>~6 zN`QU>=@SP@>O`DLNHYm(C$A)FikGCWBmf#+qa;lQ{i#Ptnud7OodD7#=K_d-Ng1$* zq)S2X(gP%2c8a8Kr0)iu8HhUr@n&oQ&X6>71+br_%kgfO1pvJ(Y`|`kX73|uZV-T+ zS9Sup&cpLOgwJ0^QV-Jf93yD~;$F3eq^nK9Hj)ta_)VrCaYrx|g z@LRMNI7-sB2)`EL?;-#+v5u9lgG`IN0o-4|7}yAml7u-`x?v|tHzt9-B=sRpANcm2 zCFv%FFF8cg(pr*kt_OCLbPMuv3*>kY;x97+0|4UQ3YxbbA!+$i;5bSBbAf{-tw8t+ z@O&?LzZbOL*9Dv;>9(~btqcPhl5Xz=5bt)-f4>(PCFu^t!#=ij$61nAZ3Rw|w0a@1 z1;G0|A;+DN;ZE?nD^1cGJg?bF(%ox;y(Hb!L(&KEel4!|4v}qBv1BT4HCSVht!eIz}K@JDx(^cd(q2AYqZA!z{D$3f@u0g^t9@DC&I z6LSINZ^J_107*}-An7UO;VIDn$THw0NgFdH4dVUaHj*}3fW0JrG!Co*kY+Pv#QIeF zSUmumA3H?S#|KFI#0p>|fH`0Qa9t0xN-oBt6{+oFZvx zH%ZT!fTaM!pA7<_`7F|Z8uy<@_@~za$4T0{5P&>e!RI;T^Et$Sz7yC((q|wy)~wR@ zdSE|EJC>0&>;xd!&SqeMq!&Qz1;qWV3D`i==ip8BH$=V-vYl^LG#s7lD>_1-`)&>=YHJpNBDlE`3~g#4&r}j z7XTiZi>2@GB0M`Sv0KEI21wfkbBmVbSlJo-^Xa?4ibP(?j?k4GnK>$2{c#5PS zEd@aT$DsG)Edb;>v?K*K2M|X%OR~5K*iEv8 zFlhidNwT~WI88F)Oh@y;d#XGktt zOtNDo$2Os z^+O~#tO5>@+*k$-0B1>VLRb^7&Fe{SL3j(&w}O7_UXt5@_%4#$Edb(m0ErdADUv&J zKPd?uA$jsb;3UaY)&NM;+}i~lC;6H+BrkFTTS&gP zndEm_fJMMI0PnBs20-UJ+%Mio^7X4ozCi{+_r^{D>H7ANe3K18nkC@B+c9Q(TI50}`gNp!!uiHZMLpER^$qz%Ghw<)1 zpuOG#93=S>q&7#JY=X}o*-ILSk}f2J7#-)C`s7JNR9I9uZY=sbt8=QaRmNq!#X^gOPg z!Sgm70Djx{k-QypY+pw*)}r!`jU*3ulf2UcfaeRi|Evt`BKdQ;{~YAowUgw}ZzlOg z@ObeM$zP}k@VpyocBcXGcnLhdxRB&8A?!;?_a)HXV*(Iw&q0#EjCWtb^H;q9!oGTj z|NIcUA&tN&fCKl3xo0dr3Y3d>^uWAMt*$kmQ3lU=PVZ zTu(CQJNd`R!;gnZJ_MR0^&}rg+{0@~ejWT?-%s+9RV4qU3^+jYPm%vO;=neNkFEeR zB>xQYezuR~pD!c%7l`+ZgCvh4{pcZ*f7uLdCHc*6;26oj+C}m)6974mAs*&4`PZQP z8(e>LoaEmk-SH&JzawBR$!|fPxAu{I0_jfT-S3-$qa^~K%75kNd8M00FS?nl6)GpvHq0bM!dgvll(W(``cpR z2+3!X0P=h049S0ANb)~clKjsB0MBP}|9|zsL6Wmbm)%eDIb6>jB!#+wZKSXPQVjK^ z7zwBawvb}N)s!Jc@B({C5!a9+$-pdND=9MK%bS6-q$qvBAyU*H;1nt5rKDImklu>) z)(yZJQi?#M7;$Yu06grt+Ci%%4jd!Jf%s0yrp0C?Zt3>+c_wpk?sc@wzrgsh!Iq)fu|q>ZFZMw-dX z0Hm9;m6Wb+q)c5z$~4F~Z6_(y5jK64lq6^+R{-F3i49l7WO3HP$zyVSg zuK*DL`Y^B-I7P}0h;swt+_)GxO-kPeAVbPcCIIhlf?PKpCuK%KPh+Nde<&e);Iygxf^ls zK2FL#D@pkPWca{dQr05Q+M}f0dw`Vt7L$T`Q%TPy6ZAt{f7$D^A`d8{5l+<`bLkAu$RyMZI5e0T+r zA>|41d}1Fd8^CWvAFvTPO3IVq@g(Ryxdy=VQ=s$I22wtPI3GDl%0|#01kFL*Z$g}p zg3d>Azj-bx9}5FpN%=V9ejL0$ag3BL1EhQsJU+RNluz{lr%8Dl{D+YC8Kik;A8?8k ztSgmg5$DrM0O_{k-ByG@w~mzOA@deP|T@Rcgsa;N1@(??LeSVJ!eUKRiOpkD39b`Eehxl`vETs{n+JbORenIgGHw zcz-xU%IjUgHd2lt-A_R0rwf5&q`U#y-xww3D8i3!AmwK^U<+`Tl%FH*&vyZ*NWr>M z`2}eH;t(m=*HlJ_Ncm+wDQ~6$#QoJW0CFC~^%$OijlBG(49JjzHKX#|lcZp7Ro?hTQ`0h?%C#fDAuz^%B zuHHSQ`s#u8z)4a|7Xe2|_0J-;3^dCQky?&)<&Z0YumIu&kuC^1DiKzN`zr7cIRT^# zBW^fDYBgl2M%o(OM|P1~yNcAhg#cv29I3{_zyVV05mvvS)P@zLHhO{Gq&DHc*#r!b z+R_Y+lG?fj*bAH_wGG!e(#Lm_+Ky}c9#T7cfJ3Av)&N5Q?mN2x(3@l<;zpt}I_F940J5bvrrK!((-LF?)jz!6dxCV`!#rVu{`J}JcQg&e(mNxcSXuGtKL z_9F1Qb`gN|SX-*s^^v-G4RD0i>yMFo<1AA9mXUfB?w51{L%?ZL-;J=PWxy6vZ|)@Z zmN=>Jv5>lq;}EI0ZY6d3DpLFBlDfhPoF?_X;PJklq}~P^E5YY>lriQ#_5JHfy~7KD z{vDuu#|BbYfzGM{Qdi@;8uF|@OX{6?z7urr!t-5w0Nk%>2KJMBH)OecEpUX?d*Z+< zU@w4lAHeemHUkGpT}uGc-wWRNqFnDy0~u291E2el{=QSB-Vd7hBhLN%NKKakNc(^n zSO{zcj*|MpdSHmu2l4(v$o$|QQrCgzx|P6bQXc}{hd}G$rNAhuAHsD#c&y(`>LZ~4 z$WBrp1&v3M?lGhv0G)wV0Ny_y1l9pZNd0g(06I^sC3OSR!=9@?xrNlH@ctv#>a$@0 zVV^!p>ejuaJ_kOSAJyj9H zhCjr>A7S4MGK@fm_mY`BR0#>7K$`J0NN(UK3;Ox0Y8{mIpk3zlYhhO8^1cKbJV2B>|sr z6A-}tiV~kM?DIw3ie+%nqV(z)H(OCY@0xi?K5gc7Paxo#K69EUz=JAEn&OQhaJes_ z{ggDun*zR&5C76Bs}fbL+E0q$`-(s0@tQGt{C~^gf0Yw<aMms-EEa<2=;hQ zsIp2-d!51Z#`2)kdyX>I9o6`Ej(jC7ikdIU9xm~voVFrGl9VEw)0Oe__tlemcrFfS ztLN(#_5h@CP&wybU1_gu2YJ^RcE)(5rb-gaSzCm+Ox{A-VD>PJjv;q>IM5XcXZoCF zWwm8xF&2&KQs~^WzjhZ{EJbeHE&OdQ$}gAiQIx4bMd&S5?U5o06nKbNOPeQ>FJShK zz+ZYHIehh=_+EzJk>;1 zk--@-v`#a$#~aZKBHgY+fx5aQdU^Sy^SgqJA&1$sk*(U zroB3ui-1dX@{&opay|ETc8+DBK{+Tub*N#> zO3X?uUrS@_sf7Gm>Ev466y`~^>1|xf*OUkSw9q45Y&g5a?(^AuQ>k8D_j;?Unyacd zpQA$Uu|c2x9R6R>sTA5C*?ldQh|pYl%yGUy@H*1_-3gRU5&kFJe%@9jkvDR%i_}DF z_{88TH20*ITh<#ajn!md8cyqj#^Bie@u?t}#r$~jK2Q!&1EEn=yDHmxF8F_KT0y%a zXm~}207Hg7Xd2+h`D*`F@%g}w7x5aFLQgY@N>NE^MfB20nOT@!TGtR%N~%2-^;bAO zEX53hWG(jiJ3V|7Kxlm`8dc0{vDqravQ%nOU-ML#D8Yuh()wOogD)DDRkcVhl9g{- z%eu>~Xgnwn%w1@uhuQnIaXmxu=+#T@dVglhB(?mFT%JUm@fn zq!p&boBWu3F;7mw3eWEInTR<`9r*Xs#C%4L?(+6}q$w4;F2M%R5o$`Z6njd; zlPbNcDXEVTGwe>5G#F*G!#h<~91cZAUpkeHCGl@!Rq>G;!^%~*dT%spDYBH9i#})c zUsh&Bw_45&d1AAlrIs~L#xxkNXcCtOY7eKwWyx51qqNzd{iko4 z3I$5rr)DGTjgMnaKEi=`Y1@kj; zOxJG)RkPjYPbU2?yIHN1Ww+$N^6{A`uUv#+8Dzh+T zjN|3ec#Y3zVK~MlDPgL_WQn5I$EB>ELw!&>(-3IDzs5jgV_@6>l^dPf@FpJxc|@6? z`yTtbHV%3yOpVATuT{6%_;F))K$V35h-won3EsWjbriJeLM8E$-~;j8z~)eZ}F{aG6(i88Bu-xpvoh zS*gD^G@%?SFD&!?m@IiBi6&OeJW{R{^wBw}m%@wjqNZsc@3f}kil*?E1w&?Y4FK;O?Z<)-0*e7gS#OW)N^|dy+yaExm1ghKY z<(jLvHy0DpQAK>b()#-_IjIgKa~I9vJ%g)=9(M)9gr1u>Is|>{&MT1G+e$tJdnB~g zh$CN>ZTTCP3j5tQizFCWnlV8%3$i17oKGnho7+FD)KhGcL<2iVgXv^4os8+j(}q&6 z`BXFPk`$SX%&HQLsa9)AktiEeCP76|k))h|7mcE^$C7LlPoybL_|^MYL0{9fPgc;% z;*AC)DnK8=P#Fb1n9&%ejO$!b+#BaF=07F68q5aIYh+w=%cgVh5os9mLlMrEX$ET4 zx3Ef_N|&HSVW4nyV8Uwkbkub4k}YBqX5kJu*9)MfRYgR%$O{_nKAxx%YZ4ts47}w` zUs$4}pqvwJQYevIZ&uYz#ggxFZ%egUWN|Bgm(T66#H*#!rb?qJz=N&UiNPl5?=h}C zNAItnUO$|~AKDLl(P3??mVC|mggJVi5=%TRb9%;rw>2ylSzVk>_MopM9gC$w3V*}H zu@nfVN_@O6@&3-o@L`PMRnQ18CGv1V+c1!ajIGc_cpsN?Qweg*2lWmQMtM=fO?$j1 zf}+vdSrMY5oN6MC>_mw#?JIG)-43@Pm?3?M&nyUddd27V_=^>#q`1lB&+hPhnu<#l zrP%Lr`yf*+R^nraMc<-$RZT@BUz;>m)KtY6`NU0CR|P}XvbL6{hWPhPC5 z-_3gZdkVDX-{Z%##$n!PT$qycv`=7dW#F_ul@Uil$!!nWEA3d?>zZzwQ96@FWucBz zES*9{`CMt{@|B!}`Wj_)j-oz0gG$Tk^09#1IX*@ftZ{Tp2j-EBa(*^mJiy5U)x=mA9Ui2>Vh}hQt$RJ@v|qE_?Niqx);o-t(~!;yN>l@Sh}{Y z?OF_Gz3Hyf)*lD23gRDn${0BWXi+&iu$=J#?$fFHB z5>`AH6UUmD1bS<(JdE%!c47vLVtmB^<2sTM0BP(X?a_yqHhnOc+FX1dMe`PM0}Bm? z`Vd5ab&>B{7V%!|TZZ*}~w~ke4!~-RZ}{HGm5S`QCaR_tU6FX$?3!x z#6B>)eD>_XobrbAqfN{aZf8tSL)Qp7LXykVmVjlHXDWL0(8`rVD~Hp= zF&4wk${`enuCMd5FraNHuwW50RvI0Z3Cx5Nz~}_Z;+gEr13W{6*?yMHp2+m}VsheT ziFFK8Jjm)Wl5yJ;T6`qLl}^k#+%(aG*_1c=1ZEg+4TS})wIjhkSZt}WvS4SlZBmQB z&TQ*wknC1TyiO{2`YZe%M^NoHO`1BrIWe=`AAf&sxv@JOX$%FU;V{@?`~=U#EQa1@ z(^ls#u!?BYxISOE!Oq1^!mz(;^Y;|2XZQlE9Clm2yqXFtPJ0N$HMc+5Q5sRr?YF{bRFHs^Ut-5CdOCTxp_Cy zF&#>1q|t!vV@?i5pmgL72;4r1`L}|(rARy0+gkBJH|c2iV6ukv5vVa*@pZTpHByz9 zG{E>oF4jzE9c-Z}n?;jk^43;Vd%eMOdzr1Gm@(C^+I=R`lu(&c8*K8rN{j8HQ81|n zNxG%R>37&Ht|9~5Sk=_n(6u6JG?^M#bY6X>C>Dv$MrO2>6#GRJNE=Oz*{>E%iY%xi z#v*U5ve_b=j7EdGNHiD8C3cf28q`Kli6|G@e74FZHmhtgs^Tpcv$fLUDe@Jo&ae53 ztkD{yU?>e#8nH(xnhc83V3hntc78Q*(}gxJy}^#KEvQqcrpKdBg$TFxCa@~SI?0Gj zTO?G$G}}&$c{&mWJ6yp4#=cf*YpAe?k4*Km=SEFUQPX?+KJRx1i!JumCc}^$tCnDJ zlYW7nw4%WletnuhdmW1ggTcO`rZT5&y3;7s>gyZ*H`m^{ok@mtF6;>;P}BKEOafYf zkbkK5@FhH7!0W%f7gVD0<@YK=?JTWZIvUz<%zjb7Wu3_wRN6FvhQ?wUZFp^mjsoQ; z)Bc!#Gn(p$%3jI=RjoIsjjl;vc39`49dbR&11neVgg_kS6g(58&Z%456kd9$QJq*OsmYW!cM{FiwlwE}tfy)(hx%%}L+dMs( zVY?!m#u%+|Fx(|mDHn{1NQ3A|#Le|HTl@7O%@(4|-^fdrX~P5x5*?T;rdTCo+T?cL zsn9*3(Th?$x^Me5bgT1AIY$0!k29Gpb$P4Jm8o!Ncd~m@C{<~$M(a-|9o}kx&g?l@ z?RQp6zSzrxq6SJTlgWxit;bWFs7NL&O9HAQyd3jMl}>+kR5yY0`AHjZS}<3*wAD4A zmfBi$lUm^x{jrf@X$?a=q%L9=fK&UsByB1 z?J!MlyjLw&3;+738bx%FX->y9g8{cweb;t$EGo_E|C`vesChfI4L*bCCrXSNy2*Ds zi%47&USgU>v_{Z1%Bif9CH10sM87=IP|_0Y4z`pulvT25W%h5HehFJ1=@q2^zPrKR zVzaf_8(h=FZg+V4ub_3{UrL|PPO&ed{Z&GrfQ6dx*zwVp?}xRwVck)|nwVG>DQ1ug zU1AD0%P=D#B$1!#PejdDhY~7r#)AIK47Hbpt_odJYgnr|tmdlH$)!QHRQ2TRFY2() zQKptOmDXJ5UDZ^2yWM_!Y18Y<9INBI7E6bs+&ZRR{f@l=x!PztADhu~s%mt*W=I>T zF+_JHreS*WV8aeeB(6ZVAexKcxIL0+#7lRPfsfhj3A?$(QB-TQsG_;VTH>(aUlFqx zHTi92j-s$)D=M-1ZAE4mD>B;^k(mc9A)CSCt+E>=G3YbfnB8bF$*ja&S{AOYiB@>a z%~Fv8L#(8F6{|m3j#WGs>OnRc>zr_zo!K3B-t_Y8g$FSDc+tCO(oLA}^r=ms)DpR6 z4mas0#waG(ZE~}=8mRO7q8CeJcUz(+fmYJqf($1@%pMXYt+GT6s4cJ#Gl`dgPXIk|-Ap4T=14TxeeBEk3XV@fC0rSlwl@&Qhn% zQ(em5waHLkh24 z=rMEoZe(>%oy1y3*PT!u(4ahS7xX7K(h|yMLoKxd7IZs`i|xMJw(?R|UUPq_r6p9+ zY%+=N3Tvp?9SSx}BKFL=R-4nQZJ@5t2yyDfx++QC;My86IExHbjfVI%1J+bnhPXY` zQ6@$#tWZ4YssV;&OM}x|U9Iu#i8;;ktV8}D2^8B5x@)DcN zb#<}FW(f}FZzkGyc*@Eto}mRUFWzi{c2*0*Uq-s8m0TF;}q*4x0yR~N?&QiVjOON@NzjgIS@n3K6 z;T(4Kg4Ou70EQ1orK{3|9bt3@t`%eFImy!5w2Sp-cibt6X;FZ^!ks-aBAS9hleUFq zD6}0TUk^Btx*A)`+}k45j(uUw3_G%iqgaVx3mJE**kR3Ha(*4B>JRKk z>?zb3>Wf?MBOs(*u;k-U9#orli7;1xFtBi8AlM(QSh%nPm$6SH7Yocq$&CdVJGnN8 zshbxYDt|EWW_09nmI%E0_=r}<`k0Z6=YWxn7jawvxM=#C?(6J+O+V0fJMF zRYfS0OB%5!c-5dd*ifMF%1yER0)4SfS7!N7AAjy+xe)DbRtw5zwAZ|8^Fn9aHQgAc zY}X6sMD)(U_U(Z?S^qg&&F@xg(ZKH-2H9&Ge_Bp71`A8w*9y!wRw*9Sf}y=9lqkv+jT4*YxN<_f99K?Q zlT0ilG{OlbgqAwKd~)rw8V10EF)*U<@#$Mk7a=>oJnxEOZyCB9Yce#COeov5JT{cuf**3k#{6 z2X4N3W`F-R_uZG~uUnxi-*-(#MME%%_sLj=)#zhBW5lJI z8$8_1F%9byI3!`Wq+Rl~Yo-TAsT8zHe?@WClrQj~koL^bf_syA(GsmF3t|hmx}v-S zmwYJarR$a44_n3#GWW5ef|H{iBVWM4S)nUpM;4O+j00obf;@UdZtbYf`$eA6Hxi@a zDV3T*v~pG8$uRcZb+@3jZe%={vyrB_anfpKRjE3$E?KQ@jn=i--4S?_l`d$^Z`5aW z6DGHd!+g$V#`ua-c|}`4Ibo+c?=6>W<(iQhTObiw>v9$$tQm?}4SP)A#>k$)E`oKC zyGASt%)3s39o6Y8jh3k5RFm1~W&PZlt3H_Bp>HF&Q`gC=Y?1KK_JYN$nDa7Z*cB)@ zzN1F^B2KDwwL>R|A-=so6?o*4K#HYCMn;Bv`F(G6Fc!n12`)ayBm6Lwdr@vYf=gGy z)7=OgG)(v?akzPnWHT=79d}q=n#J#`z}zbXSK{B?z+9Ggyzqh}=WG5KEmVJ(qp$hb z=RJ(j_dSVFVN%Da#9eJQ|1K$CkBm_2ym{okC7Nmj@k_LtQ1rtEERCmBD!+~G57cUv zn?Wyz3s>Imnt`8`P*Q1y+e(7mO3QCQ~ky9CoMSP;xQk?0%?= z@%E3PW|yA=>ED4H3RJVpyWlvec|-BjH2U_b0M&&Ly6q`!+_>G?(@(kG+!xI4&Thhf z6!Oe5AS53p~Yx_*!OIQ0Um2W zZ3F1S2N>rue4s-h77Tk@-*Cc<6ozXU`S9OGA3`8kv&C#Ogy2#wmD@b-3vP|@(-w+~ zvE3GoTTXsu}-D0n}*aJ+nc2}9Lvcl$fIoygJdtl{7 zo(e>7vAokmB!bs^zhaxvuN-{rtZqZg;|olVN~{svTrr$Vf~_0I{TAe0WNBCSunT`I ziXVQYBxtkQ9cDZB+|p6*P8Q|Pe@*Z*_qxk9TbaJ+T7_A*4SR2w(R?&}?Au6fQ1jY6 zB77yaeS2+V0p+T1Mtg85L*Hd;;~V`6kC=cB6E=2K1-8DLSVt4XwhHF44%8t#lD*D< zo8%2X{=zJy(eINQ%VD+dZZ;^Yt=QO9>993sU-yMVt)bA@eIdgf<)$ZtpT9NK!n}rn z(nT% ziMB_p*(5#aWPIDzqg$jf=5s;#wv8@Aq%DCBO8$p_hb4C^nSIUT5;_goSH-?8ngYx;aTFG;H0~Qa_!for=R@D7G}54x8op~Y%` zS@XxV*}?t{4yjI{%GY~u!MB_DAE+f4>p@1orO{UCN8h&C?d#w&Jh3lf%V+4$T)XAt zpTOzC`whL{crp1-B>R)^52eGrFLIhAn-1?_I9xlvf9iQYsnJtlJuV&T3+R+k{-?<^hzeUJn0>+`Kd{B6sFu z{pNol_elSQ=JjvnMh#xHWY{~%&0H7h3+LtL-hhR={I6-lYi?pQ88cpLUX)nOb0mxmj=61KLgxuPkB;MAy{ zBX)(jA_%{rhgqv;3wnmwI zLhI4%h4kd+>Z|LT z{l#ikZI#+EuL)M4rg;radn_&+E^8@|TT+tOVpSiNeRikQUXzTP7+0cj^gCI@Lww55 z%3I2o=gZ_3$WjhZyLRpLMLUc#?Rjt0oUP2o*Ct{J1_jMMAr9C1h$I$#Qqulv^J>L{ z#gN@+QC6F){n-;>M~cPN+_9p^w1Zm-tX5aG-%)%ZVo}`OQwC@MA_s~c{^}&RYKh{) zjunrJU&%SDp}zP!>MhMSh`x(cA^$?I3;DkTE0E3g3!dj*CCdXEyI^o9Ew3Sj+x*GQa=(w39lEW}AVUZGU9fsR| zzRiwkezBU~q@CZ!5K$N=;1>ypZ1fR^vpcaVO&Fh=rYy&A%w#k52Lye!KrY5#3R978*B21m_*3|KeG@%v+%Vk*_UJXrSM0-Ok?3F z>4E#MuX-|gR9D^%=i|F?Dew|3*$?_ka7;)acZX5tT#KyIbSiD6^^9S{Jv%jXRE||D z!_Q`RHNkDTu?x!I7jcB%mwJq!>0G_KWsbRs8wrcdb6QrzXE)`u+jTy=9onq5RqT`N zvk^Bk7`e}o&ZJGV*1{hx$KI$r^4COIzvitxSmFcAZ%eS(n$@mG-&9|TxkOa)2~(J@ zqF9QdAg%M;(owg|4YRGm(>C9V;?4G#_*9rIc^k>~8(vr3kCgA&^OC(teL3I~=W4^( zSK!H2GD9=bQ8qtaKZ7Qmr1wA}@oLFd4Q!i*|Y3+z<`5^0>Ae`Rr z_@0<9+rN?v70C6dP-3DSsq~B)_;*px!?8&%(aG94|0DK3@ZsmM2!2x7{op+jUc4@T zS_$rT3C;ByyD#Mo)~ELPw^}=zVr`YBwb9AVRVIJ9!CP9M2wZU|yP>foR#Vz2GpQjQ zZGXDX7;@KFlbl}^g{&$r+k$9V;{@i9@@V<{Z18Pgos`m`;UQhXc2Uh3JdDJdA$ zavLnR(o!4iwfVLu;mZ|Ef`R4>23zQ7FeiY3-FOv2?G<*+xiti~EABXm zV;DG*i*Gq392bpR_=HM7KXV_8RpibEmzA~bzP7tguq!rozPV&pO>^sg75vGW1umnwhd{o^LL8nq&Qsg<7*GE{O7RH&O=OyzDT~<0lQ< zAUq5mcK8oPDwt&Npa1HvP{(Z;e}`kYT{Gos-!xXFwd->z=QKu@66kUK)R$&`${i7% z%3y**#bUA6=FpUwHV>Y;Vs3=$cp@5&Srq6Sv6Mw|C6oP%B^9$Gz~V}>BDz9ZXx5!3<(p*cFu!wqS1onkC;en$F->3X3S;wo0H0C3LS@-aELTJH~!^ z5K93=HGJD^syz7_4rC)ZnuypEVnH=9PK~NoLvvV2)CfxDB)ff5r6SaHh~Z|&tZH`baNDOHm~tbE24TTw%)D^grxD=v<>N*ju7Q)a;8 zKk0hA-Lr~+f}_;Y5@@z4hO_#NBtkO#@~?;Vr={l}~1gHeT7NSC$U>4Vg^qH3lTbS=%)CE z8$Pxx+^ulG!f@k(uL=z2SkB;}80_aYkPV+{;r`h?lot#}T6|i_qS_47)UQ|^LXqXh z?N+h4%z7OYl!i;@R#h}8g27-4xIZE_*OV98jn=Z7SftEqvKN)r`l=1#&T2yqyVq> z=HBeOGduhSpri1Qnao^0W5((M{xg$1Sou7xzHCN~ew#g1HiKnyuMvm497Stpl(Bk` zFWZ}Y$R6_eG(AQ4kKpHLYq4VjYZq@dx^Dt@k@Kzy7oNnBw3BP_PH*C)1&@aT(5)H4 znYlx@T4nyzV3m9MJ$`bI1G*zYiZPQ|g2QvH+Mj}2?8o{ow?*BntH(b-e?Y^x*Ju-G%g<-=i_uGH-^S~Rk%UkK#=7Hep(m+)`SVY)>D!CwGpd<#W{$94~M)m8;AxyKcKHt;wv zr^PLSO|`7MHWawz?*7;cE%4dvS^~;~I!zbJuzOf0S619+#XZU|Qu^G|E zsKUn}VzJ(6^oiOYUM2TDi%MD(Sn}*Wi}i09VzA?Stlmbg7_l9&+whSVwF?uewiA!> z72jBhxb!tw0tfB6iHJ>Jytq&;uG(6RzS!l(AC_EYix=O`IU$?RE?7{vr*6Sduq%Cz zdf~mpPcWZ*o4v*!LwV``yxb}>jV{+_*Co_XtLR>On4X}`^bGBwFVJ547JZ*yhgA8+ zZegRXaFg@0iPsdyk3vYngi;78q$=DLUY)ABPC1u-sU z%3@e*`QewLU*63JIM{12Z{twsEJ3p@n9yr6>J6AANtUE;eGJUGhK#@L*3%W~36xxN z-9GVgJ^63-CqZZQDLpW|PbYeX{+Rpj+j!c{tow!Za&i47eY(@j7xln%`2V$W>1OMp zb95ueOZrnvACECC^U=Fkw?U~onLG8s*?RKqCjC07rysc((bam2K0S*0Vzhbxhy4Mq zCIemed|T7cy3V16vRSNVD@)OF#eP@#nozR)!06G-`+f|g&1CvlID{Obal zLIUQ>)z7%gjk$`^FWH~M_@duFuh-4oT;1xIa(*_4&ypz9Ts`F?r1bLb)r%=t_H*=- z?9~fxHNImynkzp&_8eWIOX;=wc5Fm1R;1<}`t-WOn&9I7S1-%8^bmcRK1xHhonE4s z`T8l>{tE`F!cC#C6+(o3pH*H@aYBj>T%r&}CERQ-2{ zHfjl~?M6LeuFvJ>6W-?nuxNJTYfH1~YWV8hOz)$+C{2%`&s|W}6Tc;L{u3UB_Hn*h zyxWSeegkIWBSPbM&rZkTCtG^^SjOv%}T&?JdZ`1?3^uQ_l zWk&8vuQ08Ot=8dON6XdC`9nY~J$`+XtKgI#F|A)vJ6zb{xWJ_Tlp8E_m7lA*+`6Cp z#bQp^zo^C6qA<|l2=jDk+pwoX+u~MD{>9f}m`H6le5y-si?_*R9|rLufwq#8HhfNi z8I5e*6CYv=IuKTT_`CuCW-Y!v!VjkDd)RFZ7Fc|vs=dR-uNQc`f`-1<#if{q>&p~NhAt)dtJX4r!llC{Pe-277rA#IhOa*5LVFoS9;_D4ygHpr6 zW*29{%js?Kxk)>zOWe%BkM8sQ=!etuC)C^RHAc+_0RtRNu`E+nHzyk16q8JXyVE-- z>YCy2isBO=_R^|4{|px%>#A7F91I4t-!_R%wFZky+)OgDgf)BI?6AIFRHEki>-w%q zTi@fPuT(vu6x013IH8s=Jmi4&4+n!IV-JPr+U6$M2|yLAKYW2W;oL^Y3FG{bj>|`EV*IsnO(9xwo({F&jgDVP6|rck{Fwn{{F*yZjwz+%mr`9 z^EuMj`#e89EtXr=_K-c{K;N|IvV|QWv>a^t;uJ>z;r_f#e6t*?Hgjc9G%@>mlJL01 z;$@6XsHLwQ~Ot_?hyrwdhv~Cy3c#8h<w*QCx>n(17Myna1x3{Grp)LYsUA_6ddS ztJo-qMF)0eoIiwJo_$3WTd|Oj_PBZu_ps%-ZN(~Gd-^ZSp%QuJD@82dxLZC-yFDa8 zN!2|1aBoEZc?;p?l`j*%y42z$%!qq7h`edpLsn4=TICFD8Hb~fRt(4_Z$jEHkMsX= z_AX$Ko#mNe{kk39??*=}RjH&>Nve{%s=6*J^`*L7ZuiCQ_NCicWw%Z2w!t=(5@Hg3 z0h~dQ3>O0dVpkCY2IEP9l(Gv?62lXQN#sm6n+-Ee$WB#u$<8h$4@;h|>@HzKF1w6+ z-}nE|(WR=|hNwzMN9P><*YE%S@BYbGxdIcf$~JmkW>|fGGDhY)g>LX2ADB~R zr=gDKFc~)`AgLoG;tS>ufjpRM`i%mwmA~WVW5--)`d{XK1BtCu--p zYLRMp1K&i0&!NSba84v&cvQBQ!s?$02Bq_d*;clhZ=wp$2j@ay1#lj$>(=~O-*rAy zXA@LI)CtZpg4QL#pY;+AIo7n|1)tvnsCBnRYnxvQd+fHn&LNkZ%8$90&W~J#&F||l zPiPO@#5c#8ZD(Kj$$qijyhqsK+j`dewED{5@L9f9|Ii(49Z3*lpSPqP56}1lxJf|c zx!F;MQyd#?g+=EyK65e6G z!^K`MZ*wHoRW_;xsQ3xtg0RWHvnI|t$IbvOa9sGd#*WWeW6bCHo%i|sT{cDH8wm;k z3XEVIZNv-BYRjwEExGtiKmbPLS*rqE1~^x^31g`G0o#Ou^=QRL7$+r3Ov2XCN{F9U ziwdC3;O>AcoJ%x>OG}|e38|Q^-it#Ast1=)-A}ZZh{IVc$AerP_ka-m*iJtf9UQDLmWX_k1nkyqtLWu6#tA(j5nN|{%6x?K<^LR1{n3I{@tB~m^ z=|YRNRX%lVcrxOdz+1HiweN}(h=+0ryySzRlorUb>kCpEKpnGEy}_?R+H~m)x~XP^ zvQ5tqJnUSc@fm&q<0}3PmKY1Q(gL**2<2pee#U)-BDy6DU&GmKVWpU=`2Cd>j6QrJ zUvk3yw(`g7zNkCgPN&B?GYvP8fPH@69tb(7XB@$xWA1q)n>FZBSXfCX66tE;S2eF! zyCcRgD@F6>v=cvcXe%q4$Ln;SJmo|bJ)3J~1yS<6F2^Y;TmHWIWAU7f1p|t;hDu}{2R}mlgGM0bn3QKA-{~G`#)M&aZmETst&)5f;H$U&0ukZRUkD0L-!&O z@8t3Kn*ht=IohxE9Ot>;2Tl5pL{!^vQ1o!AVnmiZR3u?kwU;&}1q`w!iW(Aj z?H?N`jhUlppa%ovBXkuJal7Aa4V<9lF?H;qwS19ms|s}p!(@F4T2&mORL7Cg-bhVA`Hv%{%S!@2h)~?GhLZWr zd?*u|&*YP#)mdAmVw+u!0JtLNmky~-xBzD6?Dn|~JO+_j1FpehKMso+evvGW z6?3WsXmg?0q^JlPa34dE@RGqjYal4!aS^F5={3BWZAyrh=6A$eTUoX!4Q{9!k)HQ$`R63PK${`zSs7aoR?eiz5I<4b zPD!0NcdAkxwnA1_y)y;|p#0IL(>-2{WFhT_ZOMOBANQgO7`rVDsK=jJEPk%IxZT`U zN(yyMjKzy=QUdnQeorwzw!IV&2IEVnEQB&S)nmPZ)**qH?Sr{6KUM+oyf3Ja*v=b@0Y>J=0K;6z~}{AGkjC& zd5RQd$|^2brF9T@SNJagwvq0QvTSDf;u*jH&|^e0n%8O5g1#E5rWapTDJ)w-UT zkhwMz-D}F3dqTYIsN}*lm`s1HJGMy?1-ucczIW>KxUf-BV@G<$1Gi(0Y#x~?l zu&d2U!vb}{-bi3j2c_bw(gvMTh6T)|5S<>Dnb8y^krjk^j;6G!f-42t9InAfHwx)1 zXaG@3MPTez_xfQis_+o)%R8W7@{Fnp80(b^{WxP=$q;;~gksSX0#upWs1;;FNG&DR zjJV0@5e$m2O-*U3w;6_hQa6l5#)v8J#+Z?DBkF&;kjne!X8lvXxjA1xRS;;H-+Stm z*B?!7<462W;9^A#&S(Pu> z@{LMAu;c@Z<@y+CGq^}%2w+(>d4IDZ`;yieY_*P@jQwVxGu||7oT*%Ea$p7<{#){f z;$0MsJ3+}DX52^kLNl6IPVdnfKG9yCNSA)^T4oXt2Y;Z(S~c}O@fC*pG~$20 zx^^NwUeqfHIWgE?&LwRgk=-JvOW8Dd8>#Rx@rAUzK!irA194(IgDLa2sBki=mjJQ` z=i1$%&V#G8fmf%4B`NbtU_Zd(VN<~1Q*+U3NW87aigo8;dG@MxGn}VUb6PDpsP^iE zM~%r_y5BL|aA5tv_299@w5ATDVCKA@Vgcx)lFnvuyMsH4N z+KK}-_l`&YsSS+SvhvM$8BMP$uasfnR2 zNA}mU+idKw0_B5Wz`=?wiK&5oV{}=gi)wsdw%Jqryg#@p+!_) zdaBZXc%x&rqm4Zt603eJ%r=^VSeUo785Fadv;d!TQCB0avT@sarlbMqX zJFSIB%5N1-`K5&~Fa7RY_sc_Q&q#^^h*lcpMPS@-w}_pd#dtwlI#x+a0>5m)syh{F zMN{Jo=b<-7nB+;QQJGY!kcw>L6-j|BTNt-!H$2{LDQA@(l|xB~2B_SuU}IH!EaoRw ze2R+Fc}nb2!@+u_-EJV2t)vFArKFl?&TO4IgH#25-5kdTYeLF<7`r5*Bm#zxhz78@ zP@9QSvqMjyV~VMwYlT1AzLc(beZVQl%jt6WM~!*^g+@x~pA3n5y5frYS$;V!9$B07 zAN!?-aP)K8Fowjh!Om<9RPSNfeIbGbP`%7Qsz^{wM?Yi)29qHpCS5g|m2h0Z;?b8{_`FOQ8dItuoGMmQR#)MKr|JGXG0Y4Lyo+gMZBejf! z`+N!MvlyS*OW%s#7}CoBha{QXRSaB9Tl{nb*JKMRJ+<}R|xw3G3=s1fwVXt+(AHrOHtVh@e~!uye*YpwNi_Fqd5z|qUOa_ z-nh7a5mFg62J~-tjSq+|CC&(GQE6DQM%${amK@td*QF zCr1i9dIA_wQ%OGnz%#;UOS^KIpB7%1Ou&-(j_&^#Ix~Cc?XOFZJ6;sF7k@fE?%{>y zN7U`sN1Z9-eUtO&Bk!w!bnN1co>=?0pZFiUw1l&{Qg1#ywE*B@M#q97XKC!ZL@gm;PIt-6mA3u|iLJE`^8EZuLB7Xi0k8Ur}k&Sw5E~%J7)^*=meqqhwwB}zw7P(sZ`*@zN5BX0fM_+&Gkl%ZI>dR~QHU2Lm3EP?}XLtp^ zp-RpG>~jhti~Vv2xZu!Yo?+chX+y4e*34c*96xDW`%g+a@gqmrcg+`e9D)b|VRA;~ z$M)5$>q;r1j@#rJTkXD_p)Fwotlf<-nN<%Wfv z9lbNCG=PZ{T^WF{Jm;YXv5Q79oYkVFDA(s%O}@x|U8o`O#K zfq%(N(r&i|k0S0n*a|6Ipu0r>JMYR^SGfISPJ4G7i8+w++vD=Yo({y^@Je-iU2dM^ zvd80cN84AgHkGNYI&ORYes60FM4d;cRj+5O6H6O@k2iqiEErb#;kCXE+##Kdwe))6 z47fNJh_+&=Ck zEBcQ%yNG?pA9vnnNB*BbiXTHu@PLWT!9cuJMY8Qw1xcmye($p`*uO*l&PVc=Uk!E< zvpwA1EPMxiz>ObjydZEuNczl3mKkj;<$Gum#Iix-CE2R4or?=t^V)B7#{Hj(3A^nd znTgRkemhfY@`-P*c7L$gZ(G3Qa6Rkw=aFv*B%;q#eW^>-hJP?o<{rm9lWpJyS~F4_ zC~Z}U7GOzZ4a<^s0%}c;8@=Q3z~GSXl5K_iglg&^srLM}8oRp+cWvH(Zg5CP>OdmU z|Ekug<5@dKa6{kh^v0BU+@e)lz+99;t85=51t~Mac2Yz;u%b%*PGOuBlTh#M1acWr z5`qw>_(Z4LABCH|3Noz_8>_MW}t{o-IMpg}4^e!mOnpLL7 z=X5=hKw|h#Wp@{Xo+kZRA?9C~Vlf_8U5*OZd&S`@A9S(N^yyxUkKOH!-{fnIpc8RZ z^juSpqheMsvFdFeAVorpS_cnjxtHTZj%gEP8k00A=Bv7gO9e~;&?w!7u#(I&)`%Ka zM(u_4qmA$o$Uj1epj&ynbJIMXeOhWxY;#M8GGAl^p48pczlxvxKL41^kyD+8L*uX68 zRv1L|r%$cHg?~I#D<>NDv=l(s>#!G8vOq~csWwC<^*hILIiND9)f`dC>0lg|3f2X) zeVxIoyEm)0!9scG)PwP-yNnHBH4>!pKnpg^R@U?S13)bUO{H7``w{g6GIlB?Msn3t z@`iv0Kuci%p%;^|oj0)prj3gf+zd0@;_$X6`- zAb`PKpx^%)cFZc`$)otD5$$mMHbAc6gUUd9(;;pra`1q-r2G+kIyQNzRQLgIAwpr8z`8G3-jE1u530ZUvA=)w3~L%DFVV({2yiJ$9#9qffVj&Q$7bb=20=v%-8L4> z_(EYLIX>0oTVEALMbI3)w zj>qvz$Rn^QUe-9g+Z;=Sqe;v&Jeu6=1foQOaw<7SqA* z*C6cid#+S|cC#+4D|}bnk}ml}yY7R9gb0OvDqh>9tpq7rcURG@ab`{XIX28t_bh~+^_h5*WU zg8n{} zwlxC0Aq4|WuZIA*jD3q~t%d}|;@j)DF6S=I$A2$z_+F>xvz>{1!nUJ7b?a@_*^iV! z8#ieZyXA5Hsb+V3KHo$#ETzl2F70?VXuHQLr7VC8XP|--f|(n6>~L`~ep1wfXyypQ zMUeqQ85k~cr4o+Y*X)NLo4ak!zUG*J$$e{V_Rjgj!qxdZQ?~}E4Lw>ZW^VOQ>W6Oq z;hG&!P0qhHj%$^}mlyGa+P4lBDp4K3B2NS8*%2S2l)X@cO#|~hF-SPV!i%>()Lkn- z`Rx6L$3OV54nOeB7rOr&p!4tl!{rweuUz`pXXQ`L-;*vKnGyK4+=J97LV~Z+njU}n zT^rghctNb2b#^2lPI;vK1*R@nuQVEKq*CBPu-0e|moK#uY!_%8Hc~X$tVe}x;{Wg| z{gq2!!p`3P)33`luIwQ-NIrpmV-d<)1>`$(*o{xxYP&16c*_IFot>q-m%l4-^xAoWQ0bA{G|^##p?m&HfN19@>%#c`v$%jWna_+{9`c4j zItbex!}C<;De*hsxiayz7;~GMnti0O$dPd`!q258KJ={U~YzSzA`sFx*>qaC=VeF+zx7Rbby=1C-rMA4$ z#D$6Gpo|gC>G#=5UmH~x0tNLus|wl}9z0dp9+y9MuU{UuvCMR^mE-bpLba>UQQU9c!Gm$xz?DuskDg4va&TKKaOR4BXm>76jw~w6PX| z%r-EbB3~rB&Dq7?+V2K=9TQI)yFH<)^_g-@8X4dp&ak~;1y^ilR=b6Qt^!8FcOmnP87i)2pHsy2(Jm{T@Bg} z#Dfot0!#&KAny~P@8<*(Xh`0j@=2;fsxT&GreDze^DsiLVWZM^&G;|gg!hxtuzfk= zTn9{_0b4J*sIn zf3E7E@{Whi_0s~Lc9IUJzgBI+hJzs<&a_&Yht(1JRQM$$kA!E1e?B1U=I^-5=51VR z;sXPZiphaO`oG(>eur$1TIrOHwLW#jpQ*Z9keACg5Nxp9A5_C8DM zDOH5M2gB5&70?zyD+n?Jp-6f>Xcfu@!ZGMWw1J0R&|IBz3qa5+cffvD68d&UPav>M z<-%>1$miC%aMnK;soZt}it#3mpmb~lN;aVK8-zinNiB<0M)U&31j(z+DqoU{PMJ-9 zo`Jt1hVQwXi+?w(rNW7ca3C%7$=}>dB>#fSEPn-5J*@Exvw`qLBAn9FGMD_bRu=hx zlg(zYe%(wWkM=-ZgL$BgbH9%xf$lb}Hx&HPHi!9=!4pUo!oV&;nga3H)EX8WSG3%8PP<}l7OBrG zRvFn^l1aou=+hp`liid7u>1h_&k56RRN6}-m$89lmsZ(5A>Y!0ZJ^y~GM*iu8_&j* z2z5mHo|(b@(|a3L$;4oz2w8q068kF}U{s5yzx>`-4zy3@x&h1E(^b+6fdd{pxIrVT z>wY=jdz&E4_#B-U+za)6)tWRQ$Az{kfc;($QcKctgGyySM^*E_e$&HXTMhjF8s$EV z-VN5N6qvm!xWULb8ch^@gF0LF=6W3gBpA2gfJ(8(%{mER9Nh!^)q^mwfABDa+x(3n z?cp6{ih+Or-nvu^8n{UkkQm3TSFNo$E#J7HIiU!Av}Cv7?gpKvpk=4NxrqQ|6xr+> zYltK1eF!PUjk-QC$4>bDg5x%+$5*d;yOF7VI77bvplTaync9akts7Q~euFM}J8;VQ zNPR@bS|Yupq}Eb`Ee&l4c5qC;+{kI13>mFdJSjEv36&JR23;cby}iJz*vNq;)CDOh zO!UHT0C6a5XHiFvDK8=%Mg76(*z{O5_|Z5HGe>7U0dIJ$I9))9x#-w&FSLyAQGIIu z^!$`Q>W1FY8}#6L&tqx;Oi|nu6r>bg@R^djtJ|H4Ac?$S!udLR{JHVz>G6xae=&}d zL*s?`&&g+|Cp4comUfBU{CrNh(lM`3n{Wvc9~+Cq3k)qpd(?4&4)p_8F<%Af-61xf zlvY166`C+F^MxTvIt@+{0>Prd@oBOEp%!cuhwl`_y6MfQ4a0i+!gAHxb&WwbgwZJMZtRugB! z%T?Oh(_p(jbLKLhIeYoc%-o5!RoJD*D<`J!m>$clUV|>F(P(3-xa4}F9ldJDH0*wk zp(T4F=?$1aNsC)p+0t?~ffzpW1PSWYiAxjpfuZTUxg5zZB#vJnp@izPH$<%BIV6O^ z&w9u!ntlGT(szETTv{}aKLwyq=uIpOU0(-W>EOqtyq|X5UqTOPIYrAYrYovydyTbV z5MzTN2Eq~BIBAjUe5O%smY%WFeNCU4sjP;i(Jqb{K=H*)qtq;(HS>ktb!Hk7jbQ;C zQpeJrC5#}4P0`|%srTAo+8#2p2@e#To3GIdwxI*Q-hv}y zyFHcffg*+k1{9SbPrNY@eHjR@0pF8X1tL%xNUK&i=}Ov*l3FGwMae#f8mUkbDbD;y z^78(d9{tgRJOZ4bwCNZWXV_7ULYoZTcl7UigvWi%6KDPpO98su)^$9<`LXsO%9~=e zlNEbpCU&r!Djb8VYoC;%TplQLPi<{czGdJp>H|$>@@9VW$ir)>KPu2t08<==lO7K5 z8z=((R2Ok)ec-y;mtNT^NjD67$k_*{9Jbun1fZ&c#n`XaUaMuS{~=t}Z$Qhsj|a`Z zF^=lHF~`(u^}BNlN*ZOcDV4?8Xw6(6*leYBI~E_emnBgfC^A7bz6NdI24wqd>LVfb z0iw>wj%1GDzxIHXyp{u=G7$$3P#HsFA;%i6=!h1$RZ8ukzgi+uOs)n9n!xj=#~*+3 z@yA~n7)a6Ll@}jx3|t$66XxKAF=VeaD8Qk%uhx3wS<+Ogzx>QS_dIjYy%Q%-PMkO) zk5<_gT)*d;jCC0|dvMr<9DJU>GNACmuY)GBta><3*o{G-9C*F92W~|xTd8EJ2F0L2 zkFvq9@=RXa>Qm#XZC~9db*dO+*!>KBgM8Z(rbr`R$+sa+b`$dSk-{AH1c*(`P`Qxt zNJ}*Fg74mAv$w|&pN8|4prz^2Yez23mt40j;sU;w;gg}(wk*d<4@I?%VYjuvyzN^v zhkiD5d|#oBi zD3L}(La6P?g=?EF5JafGj7JXp6CkA|yMS!Y#2333|nhLV|Er}8EOdzY(9 zqHqP~T9`1|8lXR@dX}hU5;E9s7DDa1n06>+8R1J3$?Oqk%zQxZo_!U-&HiJ<;y6KCs3VY=XVXW6M1dVk&FU zW-aamlJ?r#`uahzY3-Zu1~xRfZ^i%{l=526t1$|ct1y5Cwu;~l-K=svBjTw;Yu73_ z8gLcirfuRPbQ#WG;E6%!D%nE^dr5{qTref;?;lF_iP9;309%3;rwGf!dMW@yMbGUo-=#wu#_0;j>Tm69+)zza%SD$$5si#gHJNDk8;z@VXN1L=6EFNGs z3REp)G|USbS(SV{;@Ll)OsA81Jz>QEV?J&e@jSkZ*3=_!d1E1wx$lklWfJBGEj)wSbKa=SAkcp{K}laR@tnJwdZs9Lkl61d?J*?D;;3 zG-Rggpv28HN#xc2Iw!_J%h==KUdgR1)h9ptIG&&!BU)=yUq# zGpjkXVB}#Rc^qq%@@7IQ_?`SzE5o+lnE(K4C+UO?#=TeR1sJ zE2Ym~S;YS>S4s?*{@?XU=*z@6~~s3kB%N+&aL2`!}&}a zjygStAS#5-dD-E(YPT>tje;^I_YX3mi1UH_i=cfbLZfkFyggR3!yvQz_N)ghNP(XvIQ!kDFy zxpE~_s7QN>%3^*EC6|l5R=ftpC{u1ExYJRzK$tgq7FsO;)9;BiG{7U<<$hvv3etlf zh=}x@*@V48Qs}y1N(^qUG(ZA_wuSY8I@zni#>1~SABXi|*)$vMosfUM-T|;D*kWwz zIon8gq&^t41>78rDljU5Ya%XlGpx|Xy<^%jNdv~nd+yZSFpeS2ONA#1>^mW3>5oNH zMP0gKc}R66BPPHK+!Ctouj1M4=*no8h!a||{q=1nV44mC^@L?sZOSUBqhz+KnGxir zxN!^g8h1QE7UcDi*7s%g`y1jt{XA?qN48$QJ+0HHsiiHO&Dv1b%fm22kD=_Vv?>PP z$iRDl8*YUpe*YLyfUzcxktickI#c$YaU@@}@1)_l8}6@6cDO^?|Nbh?Zo)Sc!aRvT zd-Y;<-Eh2>_W6LS+L;g6GW)C9kk^M{YJxI>8`e-WXB11@s2xy|oJ8Lf7c;Z>?61!3 z)t0<%&6)Bo=Xk;k4$?rmHYA&mwV@U*)&}bZ#axofqaeIwQbWb$SGcp?gT>-K{pRj= z1JoEyj@wKpWCc-(r0&#OH{G3*ukMSIzf5tYt;byj%W&` z_YEOsQ`z|6u+nWvV(X}C5JtHUre3XftO803_}<^i7p2MW{tB;wq{Iv32zsXnmsT9k z*X%3z8R}2?-e0Lg0|^<>09Yh;0u@!!UP)EH&dCI1N2~?`G(%zg`J&nP}*^iwq0%DQC z)4iwOKHby!*x8RA)Z)BcY@ZqJ>x<+NLSVx=d_4+4&XWBynY=Up8!os9yJ3$3`A5w zq#BUbd!?98u4A$gv78E|qznVN^@_*=)JJtOo<)re->mx=yH#SdW0N8H}9VjPJ z-WY69U3maqAJOCCphwd@!En6UV%xZe6-=4-X1N0_?Mpd=73d$aaqZeQ?ovG5C5^KL z^c1kgVhk1l6^LMIGA@R3s>8H+fQpC=M78I_+B>nc)9ieW&U8|&1XEqDC?!mQZ}`^2 z;01xQD;wKz{XqhUUqXc-^dQ~f$Eqen$VDTIi;*a(?Q@IT;zphJ9-I2tRr-b(`P>w8 zxT;Tg?>Rim@N@X>hO~_#@2JKk%$=M(ouY7QI9mlP1n~#xKqa3xvvfl$qwj7KGPsmC z8;z}N*uSl@ssKFXjt%h$wl+~|!9?8}G`asMT*|oEv}cBG04)@Oqn2LFAOZG@FlgBT zwSSO`To+JAm3hmwNHCq!2+Ev$%!iV9_$ig9O+arVh6DJE`t~;5dk9CDOaVC%2DW|I{jYnj2QVy(G&;qXsz)58qa>#7fOe26Dp;EN|QE5Nu$P9XShuduz@04VmBmKWV`SF+GS zR7AFq8B$MV5kk4j%azvP3bn>e(d3L}&-hz1ih(IxrQ?{@f!ZKamYy3U@M8agfk18l zeI;8iXJL=gH;@G;EW_?AZTuj4G7n@4c_SZsaTr5(cd}@N(tQ&qCQ<(~Xb|Qy8R_d! z$%&QdyN1ufV_xd!xr%!yy$}@gB)@?9T^P76M&LiTeD9m?UAEhihOy#vI{8j`UCyfV z8Cg^xPb;5o_$0>yc)v+q6)pK&lo1JOHk%%B*%AS#y@GdrD78;Q`I?layd)5-E6>B; z{4%Z#b)gMpY}p?z0az~<$tSc0I9_o(sKFDf3aq5T+B1(Y#FlUX#>EvC(~lSNC-Js1 zE@1WvI{-MxS8Gd+!3|`ylXeObTs;34k;~bfBIb8FL=JL}bWL}<;H2eo2A#gFusK}b zKr!HTI(X{y{b{y%vt2-}V6H;)0km%5+ZznUS4M?CHD&ktV{WG#fp$H3P6)fhf6SPyj5@s&NzG+L zZsvfVj2T|LKV;}$uWp3=cCQgj>H*|&wz;(Agx5J*nKVLbqbd876O{ijJ5;#|TU zxPRfE2Ggkp)lT#NV6B1zK zg7-yUGA-47j#4Y=E%FEvB}4V0De#vE>w*?mL68Hnv)Zi&c;45pOcTTa zgiZ4CsxNek#aG!|(BZrY_TIcJpdLc7E6^UY9{OcNz$v4(VWcpLy^*6u2Kf|8aA6Zp zHFnT!v{xSRbJ8!@VF#q>TkKg>)L4vx=^3-fcM`4W7sw{4c2MVIwqw61vx;8YM??8ZU(6XmOOHf(5pKp)_G_D^s9Zl zp!S|y>ZzT+S&&87(hkWDxd9@lU?nKZn#}rZHUZ(3C5re|zy5=pVnrujf9)ojW7@%( zy6ACKD;bbHA?>cYJaf&;6BjQ&QSo`Nk9d8e+`P8lYOP;GbWy*zN0(lcHqzu;V9AJd z+z2Vkm5nWk0djO2dx(zjH?ep8rqBH7yz5=>x*Bjj;BY+P3UsWK^LSx`6hB70>%K?g z4a#*w1>gkZd{Ft_zlBn{+&Z|L-?{M7TR!rUTRuv70RF&S5LY>+zgGktk&Ma?hjcIo z)Uy?^c#vZp;e@m*&&jHb#>U3x=H<(myFc21PsTQa1HcDSH1GMsJ@uWyka#7P@xVnk{t zH#X|q_-?&W7uTGc8#{QN5s@q93Ne}uzymub-q-zs2V~%vDz;>JC!Dka>8zEz?+ojD zSo~|Ou>Nmj3;V%aZ?sgCzdOVTT^<-i^ z2ABNxUQKFUToWI}d^1)T_)tdbK$o!~A!BmEk(}@-#b^+vLFS!jybBQRc`0YWCsW&0 zrWV4X7{c^YuI9^D8f&ykUAxF5BfOO>4#b-%1Onyc^bvez8k`MegwJj?;S?Z2KpuV< zI0}{?uqA>F4JI`hEV#gc-zuT%QVj=bML=C05E%U2KW?-AW%O&&3y1P2^yG=`$v5b? z>M)tS3ERjUPL|H6WARh@Ll>eyh;GAex;URnug3KAN9jX-^!!A+lAf3^RzN7>CG*3B zD_N?7S}QF8DS%KxbYwWD>P65hKu#b_NWLxUt!mh9TUh~yJrxW4y;@^5>brUs^qAWh zeYpayL!x|fegWZ8?B%if?9FAw)JaB@LGr-;x?s^4LoXBTD%^aeLu{2jMlTt^slBbA z3u|ZeisRUHsI}5s87tf0m3V_^DuJxqm6%bPS%shF24eW)3sw&cZ-Z7#L!vMVNjJuk za|te4u?dpbL3kA@iRDz5usN5YEkMxiDt4g@4@tSB`MH)%UP!$oxsY5CBQ(3fyqX_n z+Ah%T*u-C(s8c7DLX0h`LGGZ~Sgm^GW{9YX`is*?j!Zv+qTr1F@)J+MA7ppq$fY9{ z@FL~P#yZT4dgH?~DQ|*VDtHR1bz}qv9VkG)Y2_j|##hdjAUXy^OSLX^q|Y(as#28+^$)K$z$!nHk3B9S$LBjlew~if~ufO6v?ItHW-t0 z>zBspMN|8Dz@47hNNm?zt?eO?kPqQo6)_AH&D{M*MM5J`W2Fp4QD=AqF!nGfgxpt} z%9Rhi3R`2+-fX|3g*v_V1M&)Rok#0$-1Z(*C`Qo2VV{+^y=Ig8m8f+jEMc{732U3@h#0pb>h1P` zg}iFqMEdnG!-YnBPUojsbGc|gwXbRQSkAATO%ruCvab8Mr%L?zZb+HO82P3z!GP@= zh%RJ5IEl3Aif6?d8~Q$IBK*JhHRb&?fpO^#Q5|)%TKRGJ&^O|L&;`GN{NIqT6(%5! z(sbx)fQKkcfK?&nh+OcZ5WM0Gh?q?eJ{R$}V(x&e0m%BEebyfLJAW}0^}Q?Mj(wX* zHb3{@-#mB!{pZY2Q6K!qt1OE!|2^?p z&;&tAqcb=I;?As`vXua_E->tHQk5dmMWYI@R=}76f7ZWnhaC&0MZ3%GTKH1&E_cK} zUv)+N{)p>`n$4%(Jm=KhAI07E=(;=N5Z>qi&xy}M4Dm?Cfe`jUHcs&kS0o^UZ^T_W zPO1&y)SNf0Q{)e_B&NOx+3nUA zEGH9Xbu5?H@i%PJFT)5l8m13rowQuJY<^gopL04MCL zEkf`HD%`-y1{qf}kabr<@G!V*^2LW%PjV9hoCIWrZrYu+aPBPxsh~Rp}Kj;laKap?brP0!mN;m53 zYikwY+a|(At(OyP^@?8C8{69rP|6$a_6GJzzSdi0_FJSGfJaydshLS=2+AYau%w-+ zr1&7pkYQGwrc6VT4Ed9YuUO^QyyPqi0}5e`M=A=+57Qi>2!$e5T!U5AHz!3InaUsm zfg2Pb{Cbwb&mxE(Dx$9gx$x4cXaS26U!ZR)HU$KSF<3YB%wRb;mNIV;*glUr;${qa zPG8Wlp#)?sPT^~-%-pM#dSLOZpv~dFZpI57uEmU9yWKOeQS?i{E(myT*oU52^1y1% zUj4$W)Nb~1UDe)egxWg?+kn0EhOOvT-fNC_&>#cr?DB88QpoFiBE5uMhAq#Pru$9h@-Jg#g zedy;OI(qb>W2b7DFV*T#B$K1rtUj9buN|7TtU`C@kMFE%KRuor1!HaDkB+zrH8Ywe ztki+8ha{&47)#j2Sez=hN?`qK*GJrefEz|wfkq>6L1MzP(6_cK0rw8?Tx?uxTyzIE zDCxj1qVN>``c#Z!x#RV8Aw7+klF@RH1JW~9)NRCRkWo{ub=Jp2O7~vC{)xc`Pcw*4 zmwJo82Z_*6UKJJ>ui^zeRf0(V@nUVz0}W9 zjE_mkFdP9lHNH!DW3qeiz29LKL+g%~6nC_FZ0`_s`GOooy;`8cTJ&PaEb|}d1Cb(j z7*tEr5NiJ0BfFBfBTcXPLx>gjoj@fnEe;r-1OMhnX9y@v*f8O$BG+R?@(LDb+f%*u zPAvA({H^(6B9r0D%)OfO3Oi$L)SzdQo_2WyyE93PMys)*S30fMhB^LC3ERqFWA7Zm z8rq^Tm-Nz)ajurljvUj$BjUyl48J)GX5yz_ED)}?{q2x#VBHWo$Tr;Q6A}(iB@U23 zn&$ulRCc3(z#zs5xT9{u;IP~nHnNDy0!f+*X!mNLof}tz$|WrBZ5pbTb<+n3njgB@ zBPk%EnjY^Ai}iA{l8dIl)X7%hES3dZAI(*aO1AT*batg)%?{9IW@N^y8Ego}>@_rk zWsGrZZtkY}#4~!IAWPMsNzC6gH+RbD45ARUi+d4$UE5fd@Q%yP*%08~&=UsqdI-A$ z_8H1rNT`e&21r@$Al4qD@j;jiHw${^Z*1ssTc@*lPtD^Gzq4SZ8pUXw65~{K%3DrD z;o`mN%Iup@pMJ*f4Hzxt13T8dJ!o^rKRG(ORtinb!h3EUzH??j*_JU_D2%{rMdEbG z7NpzHaRKo$G>ZuaEY@z+A^^RaXsZ(oyeP_}kyPoRHYvQJMk6$Kt>*B(H=6o7ly1ck zB$#Z`IoOSpr<40#%fwpqBR3ISA!H8T90JQEfW&gChWtS=8wTi|IZ+=<){r+JxqJ1>LT@{1sm~>-2cWQ`zL9vC%7!+?z_O;7 zp#-N#Xm(%7<@5T-Q$?>U=(RgFJLCz7)BaUNvh@|UHBpyx%A|6*7m&W5^ugfk%Qvv%4_ynby)S-?XO6j?fD;W>EeDRc# zO-@AOHoMy&PZi>EU(pi^`MhC&(5Km4Wo)2|w`75Z0`VGmKQsDvX10K{kF_Z`J z2(;U=L7OJ=uN+1Y=CCcgw?|Wlk0-xSJ~Qon6nXrH4V!KcL?B8+#!;m7@x<1ux#PDx z4_~OnVvp)DPupXM3J?d))#IZ_N3t?YqlN{@co-N4VW;slGG;9M``E z%zYgDLy7pMRxAOwfO-LI(g>;KDwY-jR}g1Gg@qdsuu{E+JPKT2xTfIpqy$H;==z(a z!|U<{rpG7C`K%UpdVLE&m-O2`?%Z7`ef~h`4X1JikxV_8z58-H3Ip>gDaj=00N(a5j6oX+TECOdQLiaUP3R4LAsl7ZxSJT(@N z`rS~IxijgD*=lA?AeL;V zssPvm572v4zVz&+&&k8*F8$f1`K!M@kHh@cIkWuU?-1M@yHo@)&y)J+E8<6C{DU8SNwq=w7 z%M4nA$QL9a()bgSFsRu2{UU&QuyUNE z7p1gP8Xih|Gix-Emc9?N{j|ZQBZN_tc1FM_;^jn^yI7NliO;m#SE72uYRazTtuXeB ziq1sBC&OvT1L7U*HY@A30C_WMTD0c#wh?n2G053xYai#FQ~IIs7qzq*q>wU=SAoBj z73)x5YX%$vA!JiI$i+zEc;H)s<3(k>_-_=FKOr?5((`T(oNV6$^Wsb{H}kAAO;pED zpQRQpGfXC3Z zk;sN4h&V2LHm4_A^QF>!dl*aqnjS@nc!YkB(vU@s@wc(AQjlZLf`$VwizN(520%~N zuz3<6%P3E^q7&p$Pac7s7hGwIPO1%cAv<7F1i*XAG*%Nx>`baDlkEddrc;l=&*av`$<@sp^-ZJCk`uzM&ETBGq z`$lc2FDly(86*a~A1cJI7!M_|DX9j-M8DT|Fek6#h5B{{^IuT#oY>mygW7HNCkHu% zqM&HZOjU1@27Huxe@FZ|;N&zStv)dF=8>Nt`GBOgG;VJ$80DHLc~FW$wZ{$ZaGy z8*{iFE@;;L<9Cny-5N|ng5hX%G--1>15vC;yUPZ{)O<0N2 zQ(b75usbLGnT&tJDRn3&E%jr;eosoKS?~jKnGByNJ@a1$_McVY`)0KQDr56K6f}Qh z(66Ycv+B1$qemwEp^$$fq7UFsdQnZ2LLGv7Qg>LH;J$%+;9tk)QqTkg10YiC=3c=6 zhzl|vmn)Wx{jQ!YB?(rA#9~^QtKapp6`Syka`V z4OnQDd_nl4?0Xc)3;7ok2uVRg9Xc*3`CE0w;9!nE7^i^-*+$lwib?;lJQwye8G)me zKOwDlZd`DCYaK~W_7uL`uB>m~p!`iiUvb#?Q3ptmam!9sly{-;1KwA%Gs+z)@1zAI zx&fR&B<*za+OT|6jO@UsOz49m350lMzpnqC_$JB=fs%kum7ZGCB2wBz+QCr5e@)!C z9tiwV>U`>AAn;d#{NLZ^&j&8PS-kDdfjlnbY95!n|MfP%|F$<fKueF~>_ z#kgTS*naBtDDTP3c~P1?irAz~1G%$u!^5+I!N)&@cI6}DoIXCTcfX2bi>ktU2mhj; z(Yt@f8{)7I@KLq%(WtMjZ9dlh)AS>ce6n(8wczN$^X`5YSjC6|v+M z>rRgk20r740}>Q$lw|P1$MQ__0ldYBtIJ>v7eIhn&jNU4p*6a(A%P!Uz{P2xf4d82 z18!$3eTQ>4yyS9wLy@H0DWZ3|G^EASLh*^IRMZ1^aAemRosga&vziuiyM4&9=ke;1 z)V$m04f=u_#5{q2I=l8Kc8A-kMLpPMp7%tN)DNy6!BgPd+<{(%x)=;k_T@zUq_Eo{_u6Ri5#j@NPOxM&sv_4H`K|Ie1fW8XA4Ec?j%y|6H z*4S9<(>#C;kjdBD{XECQcjf%~D}19qMaNU_#+(Xy$}?k>TOvIR;0%BT0~~2HwG2rd z>*ST1Fr=6Xp~%nx8ItTrXA0>DbGAZS({jkfv@pJY*jr1DweDOvbW6JX-ml_{`{ZI0 z7Y@zL#l*X+dj3ji&TZn5|5-c- zTgnJAEsX6DP!YJ5X6Hn@B|ANZ#S3$pUw=4T`i;!&)o8UCo4N0gjq0Z}e>|J{jZ*gE zU(d|tW5sH8=Du#XYJ3`#r{+@a2Pjp>#Df!+iq)tup`WGN%JTCwzcurYMW{1xp2=i> z|B*k)WM*!5RdDgGi!OQX4<7k_c}?my1#s#vaOwtij$|C9Xd38LhR0e2++raEGNA@M z3DFa$4}94CT}vw~l|nL^j(Xgy-o@p+=8irro(I=ey?<5PI5}TB zZ$Qii+|GzyNO{9_&s$9Wf`4f9ptgXxprK?S*Z&4}GG+A!A9mM(ej)^I8| zRvtJ$d*`^rU4#rdW)q&32cLLgUlT+WoPS-^apuIFMQTpO zfz`j+nZR__aY1W~(4Dt;|p zs9#IeH#axS>}nv;{fZ2FnE-VnU~SZD71AwG3>;a!Ro@^;-Si*}+d8AGac|rfe*ry< z0}}i?T7s}8aD!xWI)I${!QBlaMD?Qz@1yJlxfuP@Eamdl6A)Avo|DC&35%)H|F#bQ3N zTRi@w37z&pw*DebSt-ewn$0%2a+7 zFz>)@P>3~L{C8Z3#*LyknJc6}n3x#fThDH~V8rcHOT}yj%UZ#QsxJTvk@7)Ieor_U zLDU4sEr2jnRAfX#Znw<}1f#9Wle9B4MTR3=2)bB#;t6vvw8n&Ee!!@JoM3X&;fDWt zM>)U_k4sxBVJ%x1wa-wWOw9+`Ic^I41g+9tYj0%KQW8p z#JKg_&oX5$(*3hR?2nBAAiGQpOA^;`vKgElJzdbZbUJ#J{d=l{(~u7SPP%z8X}6kx z#z=of;zuBlefS3{##Ck|Q3rC|!r)89c1AfQi;7%pvVM#l>|;pAw}#dPJ(KpV36Nb% z_yZQHx&-EF05xou!5t$5k*7YiB-Wd#WGbb-l_+8W#$;x?Ju6Pe%or#VB>zTpa4f(A ztTlzcompZ-I>Qo&(0gIE;LzAiZ6Qlcca};QJOKP1GheDNBTQjpuRfW)Nn% zwAzZXl5mmD!%rs3_Z==3p?VvJxHo(9G2I&qjb?+Rxh&Emr@YZXGUoLo<%83SM6Hpe z7!`rhu}sh(xZg8vOZt5ucl&*s*X_L>jq$N%|Ab3FNV0B8X9d3Dn%52C-R=v0NJ?7Qp z^OKk3MpUam`PH*N&$!3;mjk%EU}Nyi;b z5lGLM>hJ>lZyTG!@M;uR^G!buDbB>_#jIC*K=VSyv$YiqbRZuU zH_N<16lo%&VQUmZlLdCd`+TOZII8LGUwn5f>oegBGAM zT#!0@1VK>ZOC)3jKh4*+^|8eh93UTp38*yvMAV@XUd6_S7j`x^9@{d%g0c&ofQ(_9 zQF>xEB@jhD5z4O_l9LV}s=^4EqmsH9K{mHB@sac;*2Quwshv?)zU@K)*_3!B-F@rW zC7g-^4q$&}6Oml_Ou<=R<8LUXqKxCZ_$}ZDEZc&fkRtC|72-;GOXomUg@C_AFamc+ z@lKaLpoy{;u)E&b`2sAaDsJyDyr4zB-l+D1TJvUEG0?Ch1*@=uvS2`9RBNz_3`AXP zns~Hd;-g!QawCaC*EH{2-lGbA&pUqliOOf?9!q-gyW;z3r;oN1ur`87hjvDwD|@ZZ z57Z=%udZfRPh@aBv3iB|Ropi5PA5XHhzdfhIN#~Ot>ee}!0PI^4(N_t+g6=2{^wAw zH}2grq^yvoqTn;oytx`~@o2x|$A0tf%H4yNFW#Wn3U7Br9W5bzN{d_Om0^@7@R<-b ziq~Q=6bpqhAc+FS9tH!}+-!by&$QLll)G<<6g{+ZM9u3bymlOI}P!tflQQ9Gu znT$l_it%Aeo}ogQc2zVZgb|P>sfNy$Pnc>g{Fs{NRq;)3qF85gohhSj-DGrCr-7jwRCwzmte3vR=Pa6HZ6qh_Iy! zkwmgsD~=XM%je6pcOZurwsE%zhxB`v4_}^FxAa&jYd9Q;qx6sn2Qvuxi5W+?YY!Q*>E(&)1pXmxca&3Z8{cS7<0N@ z&csY0WD`!0CTxc^J(4&!F)rdZDjy`kl#;KM_pELm@-+1{}^n+D#bdp8D7DM|}a<$vN_~z=?-ThmSI2 zMk!(F5>nCr>fyZ7*@Fy)?c)lFnhATtz-`LvG#7e`!NG3`mH|){JF%Tjb3p*2WDA^shXxtSFyL_Hxz#9k!(nio2 zEe3)PyImhc#0Kb2!n!jqd=uUf0%oO?RC2={)aOaS9Yxq6175yw6;`6cNR`4_S1v1( z=zmU!Wo>jaJti=Oh-MB=IyCSh!v!D=9yuP3!yW)C9^aJVa=F}2SIi-tVNcL8I_ghr zdcg0{pz%dnUQfgWaq`^dMfWj|qvH7)8(?0_HzD6IahbaEitNm*z+!-hk~$;ABvhaZ zJO$Gz#dV93@bcZ59&bD_7Ixzm9t*?~M9h1nn6JbzIsusaP2?tXi#fRLx_?T!;OlkA z^mxP*aoQ8Hn_~&PGvbLFdCxgvN1#}L!k0`QOBudH0k7TGQ36A@8T%0qZRm$Q_(Wi1 zYCAN@ zmY&{pKV9yWA&fz2bNMPK>NtmdaJ#$#y)o|et^M%;zL;am_NkZ+hO874d9$H;tkcJD zaes1CHuq_?mn48{vzia)5tsuvGy=MNTmUZRLX}t)spmL7vk=o);xX{$F91Hd4P@kSjwY=kN8pxtaL@zS>VmXrf~AyprN*8)Ozz^T_*Dgf&6 z6Y*Fo37rYebRVs6Ao$q$9d|qplCy)Lykexoa!AXl@nQZ-@PRc@bVy8&T5Hh9 zHKD|Kx%;E^dj0l$)4N-9FMlK5ytDI*S0J6T9tZ$qc4sfklk}R?9}P> zOD$!mRafc>2=ZIy?%K6$9mc(j1_oqBiu#4p%c4GO;4oOGrk5%(EKXl)b?RrD{}0Qn z&x=b)NR+l%rPRA}uXL;bH_b0(3Z5GTva%5bqPGP+LF)j1xO36SchY z1Ytz=(Oo5N#CMD+w@#X-Xc>xOAk`*q<0%&1eej2G#+j`CHIHk@4l>F-g6l zX5^4iFW4v##LH`;sfbGo$rx}Dnxg2!SHMTms}218u!PUzpCA##kZF>u%7I*KT8wrT zxy-gafo8qEB@lN#KQc|~ zm!V~*IX;jX!!Cl-z!6AHl6m8>eIpf_fQ@L3L3p50t;?vLAA;i!(mVfrHW5Y+l8InA zk&Og{k!&Ioz}G-TefCiKy0p;{C_V?`10@{Z zY$7zOxkkJHuyh5nK`j`iJr34xY=BSaTvf!jG^JK?HG$wQYh%n%Z_N2y5A2txxN4~a z1oG}@Z>Z5drzgl^p<-hwalgNWVkLYC&eRjorXm0)JgS$6syMr2jW+*rIm)^X3>&mT( z!6F;2tM#jU%2Ked=1fYn4;TroEAkOA*icDT=-50wE*m;5Cv+r5g*1C;bavMu$c8|B z4VxZ>+5R5Q#Bt9bIPR>C7Ja}!s?I%Ct%I1Uu)4i9$rOvMtqehEe|}w@Us$gJHykiZ zu>N2B|5{5;Y$ymn*p-g-#TrM21L+$*S-3XzOWcWrJ?b-B z$`EZd=58hJV1FZm*^zP5u~NsuvWsZvzH1YSUoxvu>}YkaVHv`n1m()C?n&5BXNB&o z*h!dG4%>(p6D1}u*665xagik6U2a(do-1LT)i_k{7Z(>xi%X>?UWpM% z4%Kllyh4g!X?Wu>P#5okS2i|YPkEXSzs+7G`P@XZJu&Sj++KFgErtYy!&%3|UYuG8 zT8s=-B+K%R6?&zzoU0XIQ#ttg&0_6N?bm8Wj_EDD^JNPf@L{CCIk0uGzgH_3YumDN zx|NC@It+RP8tNB`g@lz;4R0j4Uqv-5k{N#l{)Jx7wxOUkD`=C?xN@$g*RvU8H|n!8 zsg>!VMMjFC-wIBzq%xK-T3W2vW+t;qMDC{B^arA`R618^*6NG<*@ebZ>j4jeh`8l> zptaOk$S(MOxQ2KjgM&m!_F*&^3Qx7Rl0HQ?FsHOr;vk1*^L*Uk99ult--hus)8Vaf3fpXh>#Nn)o0CuWyOs6Db8l_6-g<6v zz2eO2&l&FmlZefiF!+i~5K)M!7z88$IA03rIPZof@?87YwoG zd;?~X1+%`Ty^cEh^PFg-r(~Y zzX zr736pUzMdc4cRz`@BbfVAp9h-Hv}9wJT`ou3JRTSyEbNJn@n|Mp=!bsfOycpVtwDdxi7nCO7wQyGop z>rPD*LMy85u9)``TimHg*kna*rPElwNK#npa^P2w30KBzgXCgN6w6M2N2h!e=t^MS zb*J2|CZ>j4+d9wu`1rv8j+Z9$hZfx?D%e)}!eHsHj5VL))$S?GzmQ`v(_?*T^9pA9NH3i}=u&k#AK2W4V}p7*4j>&WXM!pc2y!DPTyqA7%uxVqeqN18wP$( z!GLh5V{n9I2nLPe6%#b$o333e6Hnis=s&)8wY0f)WXvVf-JudX&=+DmY?pCc@~S!| z?23rf!C8ZQ)vp}+8}@JinAGlsXgFHEJ?H!C_bS`Scn>;=$V5ygZBTEdC781TW}T|s zu!n4K)ofWUt7*>8dltvfpY}98PL*U-QJzF{5Mc>@M`Cwm-x9h4D+dk8qA|m@80X@) z2x|60Ip7?7*XnKXg%MzI(avu7b_T6)q&$)A5YW=1Sf@NG6>%TsI_2%Pws(4zr)6U- zPSN2d39Jd+ND$@r-tr@7c6l3!V#LjgZaDPxyY2lPt*pr5=z{vU)*3Q^Fp9(&6lt7( z_u7}QwA)uMw|BAhzTIqIzI^-g}z`P#9j_R#*?w zwRS!V>%%p!+E*|w2f=<(2%JK)uMb~rHrx7)zBu!;1$2uCw2lBI+0a1%)uiM2oOI@g z9&WX_g5VdHC@b-Kr+aez`iRCPUB7Ete|+}CriGR_kT0#x6bq?jBuo%i6wk(> zl`NJD1VJ%o3-jryu@v_kE-Q38*LoVAUf2p`LJ1=nO!}kAL?NAz!=|}iek&BjvWz$Z zjDqUlE5`2|T}EY=IaE9s)-+IXNx%<6b6t6`o6`VJ-oEIl2d zhfFS-pCU@k$8)J<$O@X_b!H`KM*4)I@w<$5Li1RmWGZKDz0s@%@H+ll(BrcVBb_!3 z%jXGx&2X84n)yb7Lk&+l&W2dDfc*J)3m7U;MB0B1=o4e2jNYt8L1e*K% z`%N8!$u39ifK8DVbx2(e1{T+ov2u1%4^600WKv3xAg9R6hRmT!KCve#|!IRnxXBXNtr&~?VcXuUs_wFu1n4CR9Xlp00HnJh&&}p(-h~V8# zO+fdz_cbAnSstW0yPAxN)?bYOe#Cb(H&sdG!%8KkPPOeldgLA>quEB5eP34Xp~I*` zMpF^*%2&az{C`^A!Z7q-nUEc}cK{KfTJq|3J2=T1H>a;Ma>G82ioko&fgkaS5_>-6 zvQC&1Wiv^1eud7n5`=gw>^}fo_x1?)NKF2af4>(Rh}g=1u(uKV*Z|y479?cKdjAK{ z%Wj4Dh!`#ceFQa0Z{WYNBXgwpk=qjk)~ZCe!srV7oCnC_wMPnqKKW{hDX6m6%y;E^ zufm(6W7QEi#injTmKB0F725>an`Fh~iU7aRDn*W~Qt7wo-EOn1yCanl zA7_ArcZ+>6E-9#V71A|QJ+SYL_r)2zp$5%f->9#cVNI(tV(epWiBYM0LBdX`0U0)B z4SuMKUaPyKdZOt#i9_UNM&ru5pOPp`X2G5d>B(ApYqQ&A1fV-MySFyQW3P+L6=!_6 z>A^$g5WAlrHdHyPG%;tO9D~hySkRr#=C&$_6Ddc-;7i7LD6K{vRL}24c!l{uM^G~6 z1Qa4NH@;c;GG0p*4f9Ob?_RH_XMz<^D$IpI_hEB*!Fb%2O+3(gp}ORDrQ?-Q%;5W5 zTMrJu58+1Elh!-InXnJxw8xMxg9z8KVnF+C+~{_1l1#RH(Il~k@T10ojuir`LMLi&}&qOp#R7X-#IrtR=#%@N)n z4X{B9-=)%I=5(dIGFe)B{B>r~Jr#<3&B%1cLX=%ttuwD{jV2^SyXCNAc`0lMlfx zMdh1mzQ%X1|&lrYPb5#!tN;%{?xMkE$Wwxiqp zLH06<_6tv>28_%0pe zjtH@M*>vjwdPg!GV;Kay%Q^uXC76@!iy8uS1%vtNZ+&*R^{qLzP)8L^QiHi7P2;Q>`H}NMv(h=;lhTvp;`_=8%6Y*o%Q`79(6+Fr+ zg;Uz44E^c$wI_>}`f2*a--7RST|Cb6+Gk&2UDqpl4UM2 z*~J}w?+!*AcED<3?5laWOU?J)QdTsQ8}=eA|1t0Kz$yTamGVlqvtn~9 z+NdREk~_C5M)GcFoevkh>@R}UoN#jfa6WO~Q!B=bf-gDLJm(Yn@WHp^+Ocs9%K$;F z->we_f4SS-9qh`6j}c5akq-omwMZyN=*wC$7{Iw0u3i3&4Q)xKKf!$})RaTZ0blG= z=*vy4R@Ek;tzz0L8iPnbKxd70h86U6Xnl8HoF$xSAjD{f0=PIcWO1LnU;y(q<^jHS_jqLaY&Lgx zIr`|qE2J)o8$0pB> zU#qZ;1K+Dsi>Gy(@z0Y#g;y`r#i^fuK+nAL|EhiCHGCn?7~3dB%mao=OXkPrbjA40aiI_#y zF4K+Gvtf{zI86YoWWbv&bf$ACpOYRlWLa^K%SfV#&P|`llYX{%3cK~pw_TJlavFEs zF*bmyd9Vkxk5UPVphSy3);OSSr=JK*l(tmrXuEM}+1o{W30;1$mw6%-VLfG_ zevv4N(po_$J2b z0m*}wToW5{rkj5TODG0D)b}GJCIkfSR6`~sh%2V#5?-rQhlOo75+j$}gW-S9Bubk* zz`#XKdl1bigGi(_?&Q3Fo^n}U`H9uEo|T|#fmjYNg=jGn@O$H?KbU(W7e73zaV`b@ zX58x!M2gYrY#QIUu%{_+(zBq#0APNQrn79TWTxq%`YB+_4yb-oQBPYa-3p)hL}3(PG~fO5_3K|YCZ2g_XyPMQ za}Iy~1>h(E?>56Og$1iI1Mp-Rc%d~VCKE=G8SS$xhK;u8s<{kGs-9*d zz3vGl;|1Src`g*n&9%E7O9jISzuqdZmVt<7Nx zY^;#eOa9rxBmjgC6@zZt_-Ft0(bs&!VBo$H#SOB)2A1|U{D z7CDGDd9<1#P+=CCBZ&lAHe=B+jfu;_Xyh$~OaE8d%b`X#96dh&aARK+V_o8<{!n?@ zT+LpZI~@Ep-A`x8QCFUZ)!1EX^pjcd>&#=1HZ{Tb1B6SRdb%`wB;2Pxo=VQX3x-xX zjIqw@NT6y>u6NK`==eqgtBz(y0+0_0ZsR#$x#VjpV( zvxM+IeL+a=erV~@=GxQk~7D6R}C@>u_k7eLE)Nv8nzL9 zDS}DpJmvQ%(_U|g*g`;Bg@F<GiJMj6}+t-|@n^b1!_yW;qhc zXS3ZZ_DL8pRlC{j{-L&Pii~{Qy?W-{3;h?)ogq$CZcYN}05~Qy`gD=2Z7sEP|fS@Jub|<~x^WgV4KweC-E5 z@KYc7z&~E72N70y3VDwwl}MI5p+F}S@{@UC_B$^Jt%ld|G~Qb*nLaGOJ)s|$pZwGZ z1V;*gu4PeCk^Re#Gaj$NjR2x50@6%cjD&?fREGSot^EALpF-~h#)5-Lbf(>Z@=v}F zN$&+J#>YeJ!O={qfNH~}TQGsd$w3SD>z|F(BcBb2^L{xEX6Je>J66VDMb`8z0o z810fwb&^qRhrV5p*Oz2Gydn2)E0QcZgB~sTz zL8^%dpZgYs1_8GxUQ7ie`I%JE`iE99Y*&$|Cc{Vtzf&p*`%N+*M5*pW)6-ko_q@vr zMskTjC^NP2#`obF7Z6pj(xLpH#+QkG=!05KfFCA0XfY7)EEzR|9;)bv1X{4V0pIWa zo-bfD{{0u<6ArDcum9D*UkMtUfvD&Ae$Nwq@k3v11xkU*cKf9dtw_1RE%PFB-k{iD zqa{Zcr?F!#EsUbthq97NM*N}9bLXEtKlem8?i=E1k$G!teX-viRrv26^U6EuN^ytp>%UZGbF()t9Xp{==;!$pCq`_JE&ky5n?gVI+I-i zT*FSm+QomJ;5zuDtO@sQNurz<9 zP|a6f!4G2sd@5G-#!=`f3C5`jkD2=Lq~lx>mRzOD5gIxxk~L%hK*IX@ z4cx&(olt@I$e-nuWO@JPRXye(D&9al9P4qhO^|G}~Y)AE$8R0E> zLEdPOs*Pz|A85;}_EgYEj97-p4ftR|(F#$EPo>_NWO+%f4&8K4ipH-MTL)i` z=XaX3E#qB7NI@lT4MDt_t$iB~uJeA;Vc4?M7orB#`%E-h#e8BH`gFvGk>;{$kzm8)FD z6ca{SA&QZvhoJ}NjOGTP5}zlNIk=t4pav#RG^u+xyT&fp<*s_Bt8NoGdAB#fj4!>( z-T}P{WQq;F7g$viAp-GVn-wNo6>Ti;1EORj`8WWnRk?DeOAkK^{j%~csvx^ zaj!p&X_a8%~0XrY}=W`BGC^YpziCc;YjyU@n|p%tW%$`PrD)YrHKRbb0u51+$aQ z`rK=}v1&M*4o{~}zJ9Jw7j0TW*NNTIUtg;dJi$Y+;H9F%5{Nhjq(r;4xP>+%5c%ud zwp^{bELSz+k0CeVY`$!yro*$I*i6)n<&yqdC`Z(RSMR{{uU&HmT_=*ktefN6tFH6q zP|$56xC(~Svsv9gHHUA5Uyx{oLXWi&4{J#fdpmM%1g22~crgZo0=~(;?2ZNA7)k|R z7dK}IsBqDDW%R9}$K(A{uC!3bGQ`-zS5!<9!@l~*Jdv=EK-Hd) zrL0E2yztckgr_@HMc5q3XKS!G`@>A3uMmJqaSGv7SB~$4JW*=Ic zoLqZoHn`TPw^m-Wrz{1V-F|WH;YS``D_+U9=D+2epTZ;9-lN2JC~9-H_%$bwU@S=p zAx^ZC8{LpB=}PcCQn8HoPL@btN0(Oqp)bKrS5MC-Jzo4=;@>`X8}hWLre% zhByFyqnKC&0F2KBY8{-idWtmYb&Iv*Poo2P`uMFveYZuHK3=Wedf^tAq*zU-h#z$k z+yoCQG@@OqKv!GB5DEm~N`GWu`_W)j>F}b#(_*339E=6F>LTP}Oz6>Dg3+F~^TzPz zP$)4)dkyS<+1^IFJ5I&qV-RH*c*<^863Et?K_GmBE*$CUyOhuP{rY==0gC*o;RHYJ zsk&$GKc?yXj%#nbfA5h^x9Wx4_Souq6TTB~e8`x?eF4MB)G2EN23pbDYP7M`Nl&-7 zCuha&ok7enifOS=m%QGylY0jn-M_MyrZW9}VvAcm(US1yuvh)e)ROgAs(&K?*ZoVf zUs8WEtJn_(HY#ox7#@j(l|73rLBo*bdIW@U4ew+t3n9V>Z}$%UClgYUUiD#!gs zV`gCzQO^i|WnJI3qLZxSj>rQ=P$ISpI%LwJ%;iyIHI|>rNAi9@A2a#b>X`FA;R+7+ zBF18>G?|-`6dp6V$x>?3=D}s%WT=Ev9#ba=|k4k#RVxlZNhrlw1k=42)_*{qbNr{?lT;t(KAjsQfr z^N#Ud;Ci>fgfKcu3A^M_A6h3T8wxK`n{wf-v4`(MXO`4-e)2#N0H^D6qg1k{%zR*a zhFIHJfp(1@*G%O`GZ>HiLh(SR8p%Zhs0=;1&K#lnS&3sZ7NN2hWRw_ukk(<3Az%YM zMn*B4?^XlzU^48rn)yN)@tj~(Ox?$`A)b8pcT(YCBonOWi^`D*rmZ^pj|h!35|cJ1 zbiJ%MZ8MOhek@j$g^HpNlujGsAozK2#QXW6eYg=e-{kSU$qWyi6PuP2dkh^n?jEI( z7M3)2N6Q+B7{n=NSl*?lKJ(O5pV2S`LeO+59z5(^SybGj&K3s>g%l(&uC^dk=@9g` zU#UD3y8`Apj%9ooBva}%v-9WYOY7-U;bMb5Z|!wtx$6`be~o80Hb7LFW~am}_mz_x8F(hTk0wb{(GJgFF|py?!Uw zkbMxxMHo57BMDo_Ti83cn;o_o_zm&Cz+B8=$C2Rd2m5$(5di^@DW`5+d5}X)7+LLg z2gcjo>TfAyVZ5ApOym`>{3rI`Thu&*rPbw$XD8kPv?`1u)6v!=pUrr+KQPq{gebS8TF`GBs8Ft1KCU|Hx*4L0hR1jEP2pR z#-_66bT+v>y_H#;qisi`TD|{GYj>6Iz-B@ ztDQz6wPS6IsvifDX~wDqyV|3Yd27t6(b=zTD)5!fA2QdK06y}CEmIv(g0&Z zJ`o8JvICp#9zu-)E_Qu^KICIN-4?!CKwVe&4}5n^!IDtOkTYuUC19rfgH%Lh;WWXR z04rRs*RqqjN-{flKC3D?$;psM?16!*f`sil05%w8l&a$eboheKFTY z0%=@3_&2r%K~tFz7#mN#cJ`5>5kXgM2-4mEHT!O7-3`cFFJ47XG2-W26}ICxDQ9UJ z1Z6(4ZTlA5dqj|^l=R77sr+Ij=O2j6ci-p_v|P}bz#16gbZgVmz&U$upRxC;avU82 zjx?%r87e1(jwu;=aB(uW^@iM-u>s{eF29uI%IKb&Ks z=RDGnPPUVsChO3le5hYszkCC-t2e$9UdA#yJx04xls(77Yl?j}A}kf31vaK()sFB` z{q9ot$yX+}*4v_?k=apPW$Ve#lizA|cPo{>Bf>Ce58Hr`m3b3$FvmC#)SaDfkh4{p z$!Tp!#%L1Lhc*icsE<2De9>)`eD5D*S5&!QNqNhl-=naJ-p)v97uV&rHe?j`q`iFX zs}fb2v`Ev$(?TJt)-iX^ziq=dXxIA&oV+tY}$9rMnJPgL4e<4>P$_ee}j2m-p44^BJ39Hi7 zrbY;CE*ZV=?Sh9M{AOD6sjhq`HQuaLIBtB{)WWTY5lt^t5PsFlAX@w=hJ*XkVwh8vd8&@yikR4osn0y-Py_V6sa)oY>gO&mT^|5bsg&NbIh|@;v`k9#< zeK13J>xq1S*J;Z*tiL*>-yg{D4c=P5zi;f3(@Xp1NZ$53FuAI%B8Uxy)gSV|hS`CH ztC|hR)TBXto=%ayk!6(wj2G>!y*Nq7cz%P)$ z&sUn6x=hk+a7p7)P7PRQ0>ps6+-_js`6=|$DetITuB#1;CsGg3;vEB_> zo`eyfJ`?xAd?dIVAHQjOxjA!s1bZSYO$qGPj%aU?48HEow5`Z9^y1w9L~vvx?AZs5Cqn28rFXjU&3lk?N9)kMP zxQ;5JMwOkg^6t^Qv=TJetJxuirW<#}1LQM5H+^!Nmp)8Y78fhOBp-<&fo@~5H-qS$ zWQux;8Qa6B)sLF?5BOC@evye)Mky90mLD&@_85Cj_u`L_S0F~8Vvi`k{o*)F3`a%% z9_-z|z2DjvNPz&}77#%vX4|XR6t)5MjVwJyQbd5KX;3?McWa987aLJ{%yY;A&blxQ zvet-&Rkz?N4VEh=$`M?jGmDR=VxC~uIQWm|aw$CMZ{io0x_2{ zQCLdUlgZb=_r33}WV4n0xrff>IVq(QwRT}S@%l6Geed+sPgnB%Ri1v@86UB)+X5cN zyN~K>LUS<2#7>2Nat3;M1_ry^>QihSi1c7=XAX8UT|72Oq8q-WQt8HG2e-9z-;bdt zB13rM_=69x-r4QrX&B3RUJxBtMrE~o!IOz8Rg;Qrfkx>@FnEPVj@Ds_{?~zBX%!7p zNjAMDY!A{*q)33h>W=;8FFN)5dOhGf_-%}=>%8UEIWxBF>$Up2@ms#YTR6-%*5#}r z*M18VXN_NO!w;UH_@;?IqXH!y`QLfvYFsWu)1#it#T%w3?@w@ z;wM{dDisN0rR;JeKXUo3a4b_Qr!i$nd5uT_0V4OYc{jOdx{YK$Q-1FF>|fT}>4Z@) z#v+L`7td6)1;neSQCd4k(0aco6iZHe5ok20{-QMhzonv8Vyae1nrJ%_WD#P) z$!%gqq23m>Pt36fo^hNCTCWsFR-X6YTD1brx?beQ)8XC96Q=v~tkiMKW!+sUv zlaDkQzKdWZjr@>PL*jd&o)b9NJeByd`b4ja4oqu4S=S@$9Hhv?o`}ma+~o7&hniaV z(tIfV#$Ib%laL!VeC96VL|20Z8^h^BWgi2#3SSFADt1=z3KflP3`e(wX+C=UmW zf9iFg39OXoPMnz2t0pWL;e)!z4qZ03t5b+ZCTCAvKVhe%-kF``O1C>zm20xpiU^0* z`T^?+A85z;e3ceT%kS9?622IHRe`QjN1NFf{e-hVb@{SBN8LQyMJQVaS&z=W>tVO& zb+5YQdiQ^@KJ+75;Rwah=$`fcol>XcyzWuyu5*uvsM>~E*-OP5NaCgdv(*N;VTn|< zYCR*D8nQ6PUa#9dmPi(sXOlDNf~)2aXy79BMfaGQnq3y{A5fM|ym=^aQ2@()Z7{Mr zLb#6LBhjzLx`aJUBIi-{p)5Ie#+=hGxq+x%Jpc;{yDGanJdEi6;9-PbLGM5??45xe zFs`*P493hWNh;2rO+;~9eA-_&M=}OLN(KZQ$S!LNenDB3G^XJVe(!3j-!EM?miDg6 z$u&K0Jli)OrBB%UNNgqKFW8{;h1BamE6;UXpH@dH76})+O)a}H+4mgjwG*>)No>Hq z9Tm*#Z#oc2J?;#<{;Ffq+PKpqP#SMS>F{ZP*&4}5q|IW(B=lk*dq8b%+JwiHY)e>v zYdd76b=w$s>vtQn&SXr8ZBO}xMY#_wkNo2wmN-NmIN&z($zC9+c=(ps3)6fTV+GNw5l2V8p;d;@ zj6biSs<(-QTc(@tp-t}^n854UEMQ2a%lnL^{lB>-Q#$+`JGYGq^eu(!9Xqc&vM;ee znu)s1w9Fe62-E-y;w-*exOZiQl3ee!#oWkS=aN_)cVq=NhL2>|B)tWTe#J!K22fyobKjQH`!Z*YCq`LixlXQ$<7~%_)P&Jl-p2z;Hj}4SF8Iqt5#hxlF#xyb=yyvRp3nkua6o zFd=w{=$T}2fibY{3B*s$c#oL~-VxgRPB3A<(RdhDx=`JI|93ORdViJQdc?j~@KY8M z%8?>^ckW!BKU7Tb_SScg7bNt$=DE({M|eqecqp1RSHi9V7&zZFHWPrj*R?hcu(=qC zrQpOMti!^XkWmFcidKXEPNRjS)7hc6v%Q%lF!ycFF@dIB4n!|+F{Wx3Jx8OUlAKnCw|7muQHC{fP1!^>k^~|YnvgS zINJ7f>(H1UY_|se{yw-KTytb_8C$qK8E1RA3B6%s2(TM};JFPrl(tZT9paBvaq>C~ zhl$;@qUa@A1I`xgTKH~{f-_oxCvOSPC^x?D_tkQjE*Vdq%g*}3nQ**z%vhS63O^98 z_$nsvaFeUeaK%#p;TEpZsf?N4I_~iqPn>)7y3fV$q>b2bAY#zktk2A{Xii52ZqNsjNKkxO|r=ykf+uI4$8hO-xUenW^H= zXz4-!&Cy1FYBrD{hWNAo>0EI-6wLcWLLRp+LqT!SNuN4a?)_ri;ZF-yaT` z?m#4-DrPg`V9?{m!6=%TDmKGGzsGW$u>kUTk)YCf!+3}tFa^K7!aQFD*Nw|>P^^hW zr6XZC#iwGu?tHJ?4g|ky1JK;*?^tacoSUixQtbOlwD|q%n z!~mzqFVh{tw|@lOejFL#9KCrQ@X&NfOX+Kr$(o{C*0sb1`^a=kO$AmpwzG*2ts@U8 z3PvM+ycyfaXJB8AA1PF;g&*;oZCcckkS3o`$vdKG>d?eQgh8ecUKdU$6_7Q5|)~1HqASyTPr7w5(GniLM1TdNy4~@IyXkaSowNo6flZ)sVEhDFp#mjM z2pM)QB?HJJn*+?~&KfSiRg78WN@HCd7XZ0&;oxqm*(_DUftG(ZU5Vwg@#nL#(vns2 zR14`p9}^rJFE>v&&3LLXoleKHmHO1wQaC-eGbT>dG>+&#eOlKj;lsI zfwhd*)!!}sE@UP#e`Rb$fho#)E?(V66)1Fr7BwTKq+DX(iyfBeMkc_g4XeysNb89o zs}2U$A5))O?<;O^7r*d+`IMnyepSr;UAQF`c^4l+*{9(koZT9uyoPnL`1%Wj#nKfD z*}PsnQ5~H9+ynV?-q?hojPxgK<>t&B z%PE~)te>8JG!j{{-gJIzeJ&O8g;?CBLba4DPDTBl`D#v5q^Y*BQz5qzO}Nk|LIm2| zIkc13qO>GVShuxmbXTkJtNgWacakvzXDdE(pw>_jIMPw2DMH4I7|$I=IUFrjtVzW7 zW54;%2TKng+%9!X7ptpIJ^vY%XOC!>y_GIEctywSg}rcWN~l}6U9@}mYP}^WQ$k6J zGRP?&AFU07?T(iTpi1mM1uJ({?%aTaLBxfkEMy#*B1IrGHu#pbG5wvumHo?vDF4^R zJ|#zst?Naj-za@q#wK0t*9gl{eDkTt6)b69z7K4FL*v|+wn2aLp~qRT4gLGSL0=D* zH{RDjQtLu&M%b5-sml7#E&&9rcu1@EjOkdO6dTWWI?p!Lr;!%l_;&ruY~#+{?Cji~ zhQNX)AIf$?bLZkABN7$a@l=pQg7Q)=Y_|`Jy_$ZgDtgbIDK;Jz}HG!gPGQlSkb{1+z|cRN-F6zV-0#-+2J0kHcNzP z>g}Sknw{L3oSj;^cMBv}RmgZ3k5$^?wY6{?g%#kg+C)1<&LNl>X*Pa;Vu!D34|PTW zBrKXhG@@0*8Nhb$e@&yfu`#tWIk_^0J6hvu1W|GvUL6!0^GYi=-!PjS^Nn@;>!?nl z!^JCeLU1FXj0}mjfiA&{6*300kNu_b z8^*`rdmmr~=%%E}WXC``g(F$iSjU)_H7wE)LT^FSb1h;lxezayl2#+LiaZ1w|M(wE zNW63;lD?AebmpSbRK@TIlJ$1-O7d}nC#slI?o( zYNCC~y5F6onXuQ1Zu^R~UdijwzZ`B{LwD&MUPFgF)R4ed=y9-4s2^AH0-ir{r0FNB z^eG;5Z63LPskA|tG7*2>6*qOvfagyfY5$2CU)YMZGM_kd{ZgrFS?N<#^<0cj@TX}e zp;4mP+)Dh(yRaJzKsYB0#D>lc1=f_&7@}4#j$=8aGCviWw9cF%lMI9DmMH2(#W3isqj$?@l)=AZ3eOtG z32!_V!c90qyn?lL-w&3K$0Vi{@{H4`^Cq^{v9*e6c*3EC-!fh43$16)2g$tbi(zc* zG9vC^$RBWpf(Xsh8F%pI^T*>^D;k-Mth$WVaC9{tU41ZQ2170!_}tcoVk~xY9(!&g zP?1YXtxs_8u8RL5b1^|mO}&F*9fMNxJPqrW$axu@OCk~8nx%{S?C^V(9xL?n7*Uz;7#%FgPLIb z%{rl#g^j_GL3suXA-K1_y|txeQUmtX!JwJ%bvL?O7~p8-3`=E0lBwvmqHStbxppo? zBoIPTit)0u{YlJbqT5sOwq0agRp1mX#@0GNi*m=-w4CTl#Y#o*;cK>TOOlUTvYU=y zKpy$Rxt4OkXq|gOTsN8uWSVmqj4l_H>&9`O>EX_yM~4#|PDGa$(iXvoBq_EfjArF9 zh9P?g2n&?OE^18NZ4%SOA{K)ibim?^j?K&)?3hG`6Jm(4k`mQvQ|^l(Okm_sjGr<- zrT8utE1D3@2syRJFb#uXA=rXLung-nA1QBsbhGr#+e&g$`poOqsqv}Le6+Or(T|p1 zzghms>p3fZMxEMy6W<3N>v|$7c7(_vU=FqG%aV)OI`l;>FUiM>^Gc7QNjFOI+db$h zOe|Y{J#hU#H)5qmrjP!!>&Q61V!UjZU1hg=wbBtrr91boV^7k{+^3@8%Qs&Zd<+Eq zJo||q6IR*XXC-%OTWLKH#f1H8ty`NmwVe~m&Yna@Lo71)K zm2Ryi*RP`)vuQ?w11&cI8=*rzQim{P1E|2Mc&Oj(CmO4q&z)b`QFPjBLy`uE;#0~a z7XN`mWdg&=dzLw5m{^f_mz`4j=6jT{t~X^@Q;kPHBX%jETxh;d8(|ZMDMS|0q@NZ$ zL3D|tSW(?%FFbka(n%f+&&n7Fm$*kjJ@m0wsyioql zx%1bL&#%l>i$gC9877U7^;(z6a$;vRE;l`7_cjb<0xmx4T*$_F_u3cpI@W&EPWv~r z91g?@3&SfO2ru6Y7ucqGU(;3+?_8eA6f)U(EEI~xvz*SbUyQ9`k@twTu(LxBT`tGm zPn0BDdnSo>4@NacOEG1Y3<&W`t;SeQCvx-Wf4Du>a%b>cm`-NTESF|R19#XtW&8B& zme<{RJ&cXj$0Nnd&RP+_g9Ll4c%)hq)^<2c*^V3b0@GOGa)ipmdhLzRezADoqh~8q z%sx`w&6MNUW^p?ypGaSby-jY%;sg(rSu0FWUn&}f@?z|<3&)t`T>3mVcWNy5ln=jH z!XsJ{o=Z7vIsRE}5JNkcBxZ%ot_(v~sCtpPk{o6NTZdF^G9_-EsmWLhy9Z5Fd{SZS z*>bpcW%EicT%I+yXHGr5SjBKRo1H4nR~H{XHPh1u5(oRaMmF2XrK+K1Oh7J{45^rQ zv`O2VCgD661;X$KF!)buDoYa}YI~O^iA>g(VBh18v0FK~g9T9qT1q@w3OWq=AK6j& z-~w^@Cs#uSMY55p9PHE!@?^19sKZKg*)IEAB4^=La8fDbfE>s zZ$Zek8Vehg$I`B*wQXzG_=SU)LJ35#Z|C#ipU>+*;|#~M-9+eDSSa|aqo3mT9R!V)8C*xM{!{d7sB7ySDJ9QBn z$p|Z(JCP<~TesVIOFB-FYXAEiFDBgeoIjMx+G6h9Vt!yopDfn?G{5*~DNHv*{=7Av z((_M;ywWM-4~-0zl5ksVVx6O;)Nq5Ml&ZHyks^o#gfH9{njwOeGPNjCV8kRZl)S|W zN*ejL$=Px#iW6xxS~uo9v!!Ap63#`8no&K|$d#(q(mPMrPFGIOp80w%%wGpuFF1!!Yz%z zt)ftlKi#=~n>{MAlzQ&P=Tb|FNB@I;9r9(*rl}YY4I5f>t8D>*4W%Vg`=D0X3pFQi zkp;A z6fY{88Rx&NlF`76sv|Ck7@W(r$`8@x>d!y8@nuaY03h+RawBR?2A}D8EQ>-Fw~L-se|1?24V)F!ix0q?hs>psY1iK z{7(8~TU?}N)DD-SjMHxk=b#JP@9nmPmAGG75m}Wrl+)h!FgUsn3Nma~|K--rS0;YY z?RVEao|pb&R5mu(>o2+8b?*G2aA@O|Fj96uJ?vcCTkdeVTcoAGf%&l0((N0#-5o8) zrd9NKQO@BJb5C3G>G5HUAMC*`9U45c4KX=m^oWKB232fU1nv~<9UevG6B{bK(*CG@ zdjfD6g&yjrz|7cuvc7FJyEdJ5LgI_t1W75yxI@INj&GzhmqF2;k=_UB)Njzmcqz&Y zNLW&N_Z+TJiWK{_EuHpU7Yv+?=&mrmQBJ4W;1PxJ7S zEcUT^*3hkUGMqcyc2ZK&KA6`b%v`vzd;Yu($~b)M{puELB_un7&HCHwNGKJHb%XWh zTB_s{nJgMm?XK`M)2C;fv!|z<@lr$Fy6|Z&_8|ZY#Dy8uy7T6P51RAc8Z283q3H<6 z$lenciAxPj&~^4VC1ryav5;8}>%yJ^-JG1vQ{s>8OMs&qND)DE6pma;027JMYyM ze^-zg&mSVtbKtBR4>dBhf&Gv;Znu#AXq(kJ)sE_24H4HCaSX>wVAKY=U~JRzv4-?8 zvcUyLH{*J%wO?MHoLnu>o}Du7I{&s8Q7Ge2Wqlf54$ z04ggI#{YC$Btx6C)SwQlv+19XWim~zBzN?W(v}DmPZ2J0WoQk`w1phN7D8~Ltm6C` z=2|cuFxNPt&99ye0CL1KdR*t znu64SGH=SMo1`P-+Pm>SxJ4T(`@&(5FACT?93OnQdDPj9wv6`Z5Y*N*CEcIn70ACo zW4nF(_Ny?lcj&l`ySA5hD@ijWYYUl`rYR%iu61E;x?}66fIcM{+(FWa)gw+g+eDT` z4?a>XbD4grm# zAb)rS>>(6sBV)FQjg`obwZ4)~(8k!(6X1nnHSS((#H+H+@W3866+J1O)H|)doQRh& z`@>K)E1R_v8lyfHajxFK=!CY95zh#QaVYyxx-y~2hbOoSqhiMl%^}aWwL8;$w426z zwCus~9SqXpzx}t(WY9QEJ6_g)662p=ODgtC0iVDKuq<}fIa^8%zlUkFU?Rp2y_iB- zkO1hSR9oN^kS1k^;_`QGyy;r=C&gc++BO#rk*dvo$t)%$A6cSkKJfKSr2?D0j|m|6 z7H5iXOUdNk8B23L9jnyk_CiI&tKiKYuy|Bx$|UJs)+|SEISoIGP+`A$e(u&S#jqdj z3~tSxH$Lw@_GqiGq%uprKlps>QBbbn5M7qYRVQWNRT?$vgm@d`xj?iejr7D}qC-TW zszPqX?3o$Ly56dJUh-_EPX2M=2Ru@x#$@?So||MUj(_CyFXSt~)0>+5{y&iV?e!*W z;D@N)FZ&K+aAEV-J84|6&<<;^e+>7l?ePH&3TY75?zNTME4BVg4dVgQ`{G)Z$cr3% zlIuq6t=8#!{j~MgEiz3>DxKmMRumb`GPFQDOWvujgYTscF-2`nu>&0+_FZ*d)z*=w zHPVgsEIAgXX-u|wKg-H=kiHs@azwYF_63^PKau^3^XE6}g>=PwB=fA($d(?PQdTrT zsv*+ahhBRk_gkLxpQo|e#G|Qey1D0@HvSZ!KO~6cA#H%#^?Tg*0Ba>EF)>NOi9ne} z3!c^yT{kuyos`hh8Xx~d_6sCM>=ek$*~nO_+U;h)`H}R8Kb-!EI%Ga<^gng2cI~m+ zW1q5*V>ml1Sd!H~zGbZ8Bdbl1!D(1FAtM;qQ1+V-q|cm5KVTn@=qC3rR%=yW7wzM) zu09kRB%281Apk%ktGFE8wNvykx{zfQ>2=383}fP^T2sMy!;p=x+iO|&9w}RTa=7#( z{Yp!ixUm`pYdNLerwSbrZnVdSRkTRPMVZ1X@NVd+-#S{j(d$J75wOk=?^kGB-yKv2 zB{#Q^cqu#c*=Ih5Cmk!Bv|babEKci}R(nSO--aa0LG?B}vf2xHc7xy8v1ZZ;*OYXn zJ(T8>VN?D3;;Nu((Ixi(ZO~AKG#%$By?+bsp)n94JVt#(xG5w<_L<_qZUz={M0+s$ z#eu0?Q+r?0i1ofrNC6uzb(_Ze(T4xB+cE5ffU*6&^cy(FTw<(d*~$n^REp?rBkZV^micN&#|V zv-uj@FdV;^p$EK-pBsT5HfS$LKkRwsym3Zo#$JSwp zou|gGu9YxaAtTIyWaxE_y|UU7bOyzOa>c{7bLRAyMvJklqb=yfq{{R2aEw!U1$l!0 zkLW$I%@h6$?oV4An+@^^DnOQ?^P=q^Wu;N}NSjOf&{8S;fz`&609l?-T_T;l0 zBt^-lmRR7OJEf)2>c#w0T7|#sj#jXW4anZh_zQlID!mjI^+$1P7U&j21I)^qBGdo@ zxr&-fy|snbc$lFZh4n(A^Pyg^-ERM8Ay>>5!+t_~8C%1>0J3Vof8`3VHxp7jTg+YG zx^d;o4YAvjCIJ$4yqjopuupe+!pB&WVNu5UHY z9=Vk$8QVspc<{5ugez7pK2&DZ}Q_ ziCe7cl28=nAk{mU*byj&zsx2^J(@NaS`nf~rZ(MxaMMZ!$Ef6!w-C16BD9*4Ej~Z~ z&B+@h!8Ro1pBQ5jOK0cs_c2&6&>m%bCfu~bRLmICZat;gAxKCYCV8B;K)BgQ0A^=e zB)<#xw1{!U;#@cp#SqFWJ7y+BGL506d2D9~${lGQJj3WIg-`wzdGjYHE=;_esfI?E z5WFev6#`Ku(gjQ`gwe;*j&E3);W5H@EQ`2eRWTvr0;*F{&L2nIjej0~C5TMKluiYN zloCYAMtK4T;_AzYW)WP|S5b=keLwE=`+f5fzt^A1yIm=7I=0|){T=(|o^u;Un3#cW zG7_pMf7~}S(@4fHh5XrkDTJ|+C+&%)m+SKh+*dNzd@k)VJSl9I>c%I%&v;|LFZp8L zEZ|niei3K>d8%8SjUR$ASUN^!OtoAE^$# z`ABkdHK-y}n%Qs+%cV&%0M`4i&@L|V{zLmz8%>yqs9HAq4VZMG8z0`>HXh2uyXHD=Ak8Y-0#yUjbRkH9?*XfCND@V2Jc167!9iZX$hP zxOAI9w*9^X57K{Wld?R&SBnVuVGsIPLzIL|HAD%n`g#=PLX((iMA8mrm)Nq=^P$-Dh2=A zI6!iy*YL|_Uqg~MKKL>LP)F-E2UN$Um_t$DmeUB3FjJ3KQIP-HZR8TzCQAH0N>MG3= zK6FSMNCf|u;-_pF()@yqt0qS7HIpO6oTjge6cCz-<-T|C(64&})(Wx|NpK(J42(k) z>Ag<3OXW2X^z@CiY9FFV5d;F^wB;~@h7{D47ze15SHsalpFzPNrIeCNRA3z<$Rs({ zVM6R+kD7MJ)~iJCk@&M@?Uj{p{WSwBE0hqD_a4XoZnL?2pV1q~sk%4U_~fZ#q%%Q9CQiH}b1qG}KJ99mi? z)93gv;94MCw-BO2=>1oNZyZ5Y1J&l2 zk5?iI7ywY|eaH}77NlX_X}f~)*+-VFeZDBwfDyCs$@9~*Y+~i<<4upeeuNsV@%`KE z8NPJ4i;R_Tiuy#s%4Y6^Xl;cW);{_|6FWq}G{#aQ34Qz!GU!DjLOo31kR@A)9>wxV1&=0SBL6tSYGEXq z6U7%+jFU5=~ZOA=2rlCnG_x&u3z5SJ|!PN6Lh;nQ38azJXXf-4n~9iNZk8`{?WN}7QanfPk0g$fAE*J zjlid;R!@tY;ptT|L*hkU-8mwY+Fz;}BCez*C4E9mn~nx3bh_L#<_ z2me{fA&uz8h!zFop)LmCI@U57uXvo^ zamm;-yrRDZKZ18bGZc7Y-V={`JcW-SC{M8Po8d&L-@V!@pP3c^=$aWuQK@;O zU!h;S@Lj89+4-1gIq(M>3geN*i@3*rBYY=%f`+oTa=?};t4|Lvs<;XwM_1P^B~n+X zjkJPFrqB_utNFaUEcFuw3H7gslL65*X9%jsU*h1e{65Q5e4uD15^l>M_gn5sqvPkm zH4mvqOOy8H;%}6(RZ&kQk`{OEFS)G88a?zt(Mmc6*(H!n-c>Yqli^n;e3`J=!4%>Z zg;#^&B)q$a`imC21-Av*xhM4nuC}OJUD=`~9$pFam^o=*%()Hc_9T~yxh_u>Pw+g=l&AViNTGDLjx{pZ(T+d2RKt5=`;o~N!|Yb~~~ zE}!VETs^+Hxcbz?*RGy_YSpHXZWAwa8n1#gXg8jq%#xdg-oT=YHR@vRbXLx~3FIva z!AYc5CIsP<8$GJH{$RV4$`IrS)hf!a+BzH8r@u7Gr6AI_bi94D4R6KwqjxXx- z=Sr1WwmFl3G24pzqSjNV1Cr-^@P+fiY$!IB4*QLjK*IOIUkIdwM%fC+b77u}g#Vop z!6~7fi^QiInfP=ui3+J1rdF`5MPKPHm zF~7%cLdOnq>lRe4#ENIL9ur1L@B&d23Q4O><0m92yls;K2ckqn`TdQ4-w7bUr$jX1 z`LVJk7Y6f$6&W@p6#qXXZqGh4X0f+LLt$8Pt?+Nl(4#(D>m<`)^z8pf*_(hjl9qSk z`gGrS>9DNBmL=IL+wvu=yY22)yRYeEdb(#uo|&GjhcLjjX1KcvOc*o-0^yv6*o5JE zHY_ZVwF4v}kc4oEe@Hek4c}E3PuacN}Tmwr}y?x&4nUTMuca;gNUxbf`fJy^pw-Dr5V+x~qDySUNJ{ zKpryP6^s-vX(o-m4*S;AiVH=!;z}Le4!nvC7f1y3Nl+2vI z`*bEb#Nq6g>lS^vDZ??IDI*#lu)y9ADv*_LSrR~-==}&J4c;=O4gm&0)G~~^Yrc|5 z0%C+9ab+fGhO2p_NQbaY$>XooB$%vL@q6Hcfl73u7`Sc)fQyUSQKx2_Nn)U4Mq76E`?UhYCXg^=sIMeTo_YF)Rm zE}IG~qXQA1DkN=min1jODVxNh?C|MM)LH6_sM|x-k9iko5V?r@-Ylf72P-VMGO16&-&#*X~ykXf^s9sQhKQvrMLw-Shs@_zyzRq-&e zF&U<7tiFsb1sVww1r!Lmn>u(N@J3jS!5v|EgIUYgYS}lUNC?XP_h1~c`>F&X&Hd^a zK{InJ5h1+Ju+F^DDs#|E8ok}gb7 zh;kfqOv9@h&71XxgeBzd{XHULwh|d%xc7b8$lkDT%*@wKOg0aR((uUx` zpoI+}4+uaV3=Z@JAhYrJUpc*c`UviR9e2;-Y3w#UA<_H(6R6IdirE#i}8!EVT_*&TmlwfCm#Q%6{s&P}pnCQhYJCQp5X&wuZ2 z&lqikc4t4ExtXLlG}uZ`4EUs~1IcLeOdmi8%#h4oO+Xh7v~sopesBeb5JY=Fr*;M) z`F4d%ewp;$TL{F$(O?Pi(1m-u3XI%RcrLYVsdHWF%@<4KA092WbJKE;(?6|)k)tp> zG1|->kZm0pmkqpa&^0+=S!ECz2s5*kYQTDkEds53t7~0QV%kcoYnf6Z97Yy{NJ*o* z2F^QhQ|~fh;i+=HmW;;JS}ryO)wAp$w9z)&h`zjwmcy1uNUK3-!J#w45jGON3$|UZ zx;UN0x+5D%$wkS`R3edbk5$v|u>;-&xL79=emX)4 zpDz*O5zi#NXa>x!>*BNMlOSyQ6jve!JD`g#zo-3&<16Lz%J?0SGZ61><=hI?SIXYA z4NTaN%zZ~SRY%e$Y(EPpJWaxeR6rQ^4ell7b^240)8*1HgQuWJ;K#ocY;%`K!%le3 zU9Jo}aW#!HDqL~_)kOLX(0>I(LFhr`)==D^ODm7M0G}3Lvs)kf+QU|_)9E!2#_s;q z-FJUVw5`RW)#d8_uFJ(Ew^JN&x*Ok4rM{gKM)~PO@4~#dAS4yMZXkA-Apt61J3xKl z+pYp)F1(AsO4V<;Ap$SShuxj(7vkaHQ>8K6n{{ENSkwh^!sAE{GI!Vtq25|{p*DB~ z>W7C4%boWk2vyV>yXRx(!ChxAghChAxe@KKEq3%RM`N~d|3F8$(fvWWF?bu|+s5Qf zxec0R1Guj-5urB?kUZ-}a)XuYO zC!R#+m|!X6!1VUKw-WhF${pxU~r=fP{Sz=&W>0?0;Uzs34FxC6=0z6p9;mON=LLEtPzx#?Ap6_iy4a#83CvXlRRKi)tNNY^XiF z^2{@({u!(~SOr0$unZ!BlvLlTt&wP&dcI$c6@Agtm@oQEi1S=5BZ9@hMkhh{^|VX8 zFX~F`SP&+oB9@E$5hA&m4#e{@s|dJbVV4&RXmmX0izDxFSc7h=V;kE)>BQS+o7_L< z#QRZqdaf2q%}=}C)AOlNZ7%&!p={7@bz{U@ZJ{w3b3DPI%aa=NMk2o9gd2!fZ`h!} zzmGLn=DK9$R}ez*X~_f*86h0FT*E8e0Vj{5_`J*Ju-jZ#=;(yY?z=a4zm_|HC!*QS zIeVRNod3poQFYm|7~&G7um(7im&ADqu84jMSFp>~+C+ZH!xc?xJsBhr$+5uqiqFf7 zot5*wPoDn=+)>^hA3uXn#+c!6iFGDFyPM9h#YfDUi ze)7$eyR9>C!}*Neu1&rOU$Km)T&1vES&19G37QNP)My}=Y@jtN$OoRNO(x`>|K!cM zubRQT%+qg6Olq=JPvU}|=TgVOthrU_f~ece3T0UABjqS+OAR@Qy7W`SN``8Kzn*Vg zN#seYWc18JA{cGP#FE=NetsP7>T3PN`F{{=`2-@}NtGo4-M&O#iy;bnAcjV+$kslF zs|M+e7poe5huBH#NlX!dXVFoI4m$7g@V71(#=)mE@3?gS(mRIVIkI{lUY+uM1l?a9 zmgh6?_zKP&{rEX?6-SKRZSjaCLMR#Q4*|JY{GqvgXRliY!}u)~hvl~*mm)ZexFXLM zRM6LJD)X>8uDYQA(x-k`29eDOj5b4^n z=&A}}(lPihjx}-(Q1CD$A(l|8xK;ii^5kGlA=SP+d1|WW35<=i>2Ld)mo)sIGdQ$+ z{$lD>vW9e9@^j-QKXV%|7#|CGlpgmw=PAj=vML-hnh1t;ZvYMyhJ85suGlK1pDq90CU_koZx;O}p(YkdJF16duRg1WOogE3h>nO(? zJmpANM=`dkt|w0jK8hkFY3@N}QnAd}{5dF>oplWF!z=GuIXvgYanw1K_tzkSuLPZ; zlsZ!z%4CLW>e5um8C=1V!?l!sK-nzHI7cP=JgNZW>Hz)z!kvQk1#(uV)IvnO1xO8v zTlGg5mmxwBf`CC5cUV zoxY-7EeJ#;8XTCl)NSU7-7H+yuAJ_W{+R8tiB&Z#BXSZOj6qI2=8c5NwWlpWI>G~}v((N;HI8Sj<3^p;vmqJq=|5sh(^ZP^A5{Wa zlDG7C-m(nu#3(=+9M`YI$K3)NlY|!f5Hd{OhEl+`aWgOdQlGrhZy1B+MhZy0z63fT zT{xIzZI2(n2q|(moOQTr7%+vj8X9Ua{bd3!zM7tB4LbP$S9L`?Wc4}a=y8UV>Lzk* zJp$6KBUJUDb95% zznJ_VeLf*;NZX~7y=m(~fK03-@|N=y;V8C27-&lkh2pKYw|Vm_9@3;_VDfk5yjr^C zdl-PEa9+chN@Ec zR2|CL9f??7!#Be!{@lZ$NRWC*hli56!}lJ}C5Ns$3%T@=!xv9Ew8(}xqB&A=pJOPU zD+tSA)Pc4L#Ow~M#~Y4TL-nI7vgpxzs2UA>J;*x-Yw4g!-3<9BqHMM3gg^9oA*`_& zGmnJ=zziTZ8BXww(xv<}{5hXN-$5hZ4~#7XXCw4@5-cJ3wo%u`52TN*%ta#U52RO) zVBZM)ot=wk({m@&fB1oPBrNmt)ZTRQO#0+pTJl`aLk4C%XiA}^gM@w1 zI#`FA`&vSO#po-#5*G+Qjl)UOHO4(&2j2&yh>SbHA%j?Rd4?Ro5r&lXu7A_$EA$QB z{!QFR`OrW06tKVHuwMOUjjpuD_@-P5$plYl#z7cU_^)lPwVRilm;bG29hWNnN7g6&4~9SaM77PBye+wD?+$^|TdyMNJ9Caw|EFSxL6J=k z^pF+uy)yVF%N$xtwIf+2d`&wvbJ1c@CK1&KDrSsITryxqL}GQP>nnx)fO6pML5Cx4 zx23{?pcg^25x222SDDPD-EOOJ+H7&ZuaF;^99te8o-2fg9U&*Yg?GgJ>d_~XvRbX4bP~xg!?D7?lLw1I?|c#*o`rI^svC8SqmX#O zgUMKvQroK>XLmG=FObe>NB1zjqk6naW}o(s5~8}JjC`RaKU}|5+-1@bsR1>0_eyg= zT88z@l>y%_HK#E4y^$8bv2=Uii^sa%u@`rg4Qf*vvwmu7oZ(Bxr~2brcQbsMhR_ImAX$Ih-V3U4Z?w!g!ZB*a{ooOn+!f+xtJ4}7 z3h35L-Ah|Ly(`s3aveAODr+gAOnWrJR5@_Z zF4h?nF+drsFa*iI&d?5TBexu@P*Z(B4k1CH6j4LZ%8-#1Znm8}Hm z*gA4xN`FU5{RYY)RJx9Vg2;HmMqyN0epm2bE@|(=O0C=u8L5LLnyMYTAtDSvqOu*$ z9XyyjxSU(YtA_|rN^=;IpVe6piKA-czd-JXkkmX|VoXI2^1?K2FjQ8!8kC(3y9rv8 zvqFbt1vG`LAN5uVxpzKSTACc490@wz$M1Zl*BVNB&%|QU)WW3SKE;#Jl$CVUvHl8dNIR}*KQW`a{=*-$B&=qMrcw~qTM0{Xm8WF4j0Su(Wm8EU;|!&KDY+T z`~rmH1%kU9G{X$;jy{Bs2mO3~QjdbUZ$9G3kBcSiDuJZ8h>ayxMCj?QTgAshZ>aGG zpdPqmFtX%B=Ie(=1mSU1RPT3OsxHF67FvD1HIeLX{|!c`K|el+vC26swc*U7P~tqr zTQd42^`%m-+`FDH=f2KRsJ~Lqm2-H-njj%k)=~6142{h+FppeGckAz6^F;F@d79M* zt3;zn&|jsPv-aT|2-2m3Ynw5)_0u)Ss(WgA%Dw8So!0k!1Xs?$E_;H?RL751hsVZ- z5yz>wv2%P)t%@kBG3OX3kJRqQxN*?6b_UFlKtAl|^JP>o+y^wtSesS5S(21U_z#{B zNw-&DGT~Txwmq)cVDJ*ok)UyFYiXa`-kd9{ztug%yUVEM}i>;?S-AOBnB{~U)_#=a>cESQmEc+8}$NmYyidVzPV8FKlh8h`D!9-)r z2ZK46X;f80Ren=!8bBtg^Ka>{RksdUi5>#p&Q*1{@WxRH+as+I+`D&l^;Fp)79qCW zbyj!AXa_tWV@Cm3sW1p2vK7jFIfcl;1cIvIk$iSUTJlDQk=RNynd2{qcfr|wPr3>8f)~u4bPz0D(EItM8sb3Y4nJb(KE4BkKFvh;7x#q zZ|dSI3UF+xSX?@GAeu{_)~5-ho7PXC0bm1_m1RKf$ZM%NBr{`BOTs54@vh7>Y(YaR z&&eEY%1Kds`-R@MW*d<`;97-n0s4ivzV*q=-R@=9i}aYZXcKw@aLh5o=1hXf;A8AH za#kaCeFH>cLwmBUGxJRONv$d1>d$V`pGU5s&hylaefN{zXLCAQ0QhEu0Wffik5X6|KcZyN+5~>CABxW;7%HNYOybia zTc|0a{nW+=5UbD&BW!O8p$XfRh+w_Qqu>$JQ4z4iAFf1QC9!+NQJQX^fmLS6% zq$8Y-sfMC5yKg^}Dm0uBty1ob#8m)5t0T>x+``+rK0yw zMC^+uyk;;hIEpZ4YS! z9FS4uqSWgrIu~=x)#cp94s@4(k66Q#Jb`WlXB!QiZghdB^7uL2&AsbZ=3pfX{ zlo+8j7Rb`cVIw|UKu7~b&;uV>NR5o7@bSXv%;*JtM5k}@G~plvr;V%lBXATfH1$WM zr2$FLl@IBD=pK)-4m(B%sF$Q-3sezjIbrZdQ-SK@P?{;we)R8TJ4$l}_9VcFIMV_H zsQj6*TtVl`&p6S8Py=^tZnml$O!tE+Mpt`@2Ehaq@Px$)ZYcFbu7jrSdKWUqS7e!Y z+frEO)0Vp|4_F>0&BYi)5m5-L)KJphC1)v#612&$aEyJ0rN>*=6`9#ps2NR~Xh5D!6tp61$_Vz zX`Rc)wyHMTN?(N&9nQgP4u4y^ei=waeXX^@pU}k*90Xan#fOjgvOMorR}(F$-TgjPww(E{wU1S?AT6rxNv>J>UeNsPQwH``3o1MY3l z8Ano%MyM-@UBbL+Fn%}2JgfjPdAdsc9@9#Gk0?zM#1EBU%WtoY?+aRAZVk$iu*0cj zGBqqCzux5JIGw{Viq#HDeq_wpgxd9fHEs8MQqGheStY>Sd;NBN@c8X%kx=KH@&b9v znc~-CbKm$dlziqBlgE-~F>W}i^U0I>-ZnNk6x#03nV`+%vIf0DyVq$Aem`h+dhPgR zb$M*Tx;p7om-N0K=1Cur-*zn5#(Mn~xjrRfX`(%yb4faQVXP^(K$`5abj!KMfqH|C zU)S|Beowd%CZ$I}#I=H6z-wbb0{C$AjK^On$l%F4Pk$=dNXsIgXWJql6)(;$`;q1t!BNhZ}m38&q7C|n}PHBk@1CQX25HJ z7*z#0IFsg4hB%53;2ryLSx9->E@stb4Aez+p0*o?Z=(m1p}#AO59E>=#ljw|P9KzP zZ9JM|Q1r23BZ}J~uxv!!lS>^cnyl@NLwBF7NswD{s20hk5ihZropw#_gm?Sp9i3n6 z9Llf!PFQ}0=He=U82%dfVa9R1GgjoDJ!v;Z1NezTQicEvn=dNE&an?@Pt459fZ}hAi>}B3Ngc|dM30o zn6SURa!f7-CS=Co)7xlw;^IwPoQX36HAe0lP;YQ{`+V=aA{R9hk54i=?k!_gV zFhihW-YGxFdl?>Vw8N8DV!19#a)~~IrP~F{DdEHTPBLXsh;cDCB4t{kvH-PnAqKw6 z+zUkL(Wypb>L^g6#W`mzCx>G$=A7ez%VolqNnGOw^c~yjXejWT>+8Q62tiLX zR}6>d$EMY2oF1DGg^P2m_+e=!Rn6WvZ)iKJ^Y>+|sg)AG=<8A5Ds6^o&fI?VMVPG{ z2+W^!mLLQ&)$Tmz4zNKAGYyeDdT9Pcd^&z&zW0wOmu8ZgjZAW8>7)^5@w%nZ_W9a{ ztt0L9>wML8y6Ssfx(%+N-}l5=XCVi?knZf3kn25~8^BFuTE^_`3uxOf8T?)$<)q~dXbVO|i2^yI(`p!q8jQ5yr4&6iNUTG02Vm2<{u{i2Vi(9V zs5eKI03X9BkdZV5rRMWZ#*%`@2IERx*xG7>bKU}rX}(}=M_2*4bL*{U01SzQ``qdEc@o(K$Q~oj)Yw~gOx7V=4Gr=oxz8ZntTew^t?S1iv zN1El7&nv-g%lH9UisVRLY_InIZRdf)w(EiBZ=p0&&x3wXvLfh;3bcEY_285L`_3(l zLsr@-xvKh3*})Mu3`L=4s0j5BI!CG_&JP;9tyoGnSqjQKQ%+u$^M&z2EtnmOACmb; z$PD!l5J(8|8#y+I^yTjm=8>_$}!p;sCXx=8g+PvI1`iGF&7y zMNJ8Rx)8sgd+zbvx#tkIJ*^$n53MvwlAB-4J@-WJjyvEHT}+SrUVHiS8cL$>Eyv0u zpj}bZiYq}xBZ_TE!ipptll(*6Sr_Y!M%KHG?I+$)`5XFc{4a;oEiOfa-=jheo7Ou| z{4T(-c$vCc`X5o3L_Lp%c9{Nu1QJdEpWZeg^YYy++~Q9(O*53#ISgJUHU>Yf!N?>7 z$f*9Mej1XMkt;?~VkEs(`hMu~yF1!{w2OlcFYz9f_h+Phin*jbUX?$RmA(dSDt3Tk z_CXe;NMmwbgP&l`uM1ycX)2|ky63c>o?2SNBI|Xh)2T#T&0j3G5Ag{5|D=glYHF#V zQ}e9zSC=6gLUW0)+mbXeW_2LZgf*Ibf>bz8wt(e+6Z$eQWk6V;Ff6IafJ5^a;(BQ-zQ|lvr$SHR* zzXJL>4>Q^Px5|ghc%3=J^ck;T$z8pgTd4s4tCtU-JzQpn+LhcDoZB{eYB~1Xqz5qW z8-CYVKxj8%UJJ|~3?*5_*Z29~rTasZ!IcSv{hf{;Ul;ogZu+);r5S^nK2A%#!ltc4 z=Sx`y1E9`6EduKbbyZ^)97dh!zy=?IF;YxAU9;$Dq_{AoP0{kjeT(5h{fyOmrVc}> zckzZ3&nsGc53dMB>b|(Y4i74K{frRugg@?6Ctj!2Kro)~=%uLZ8}yjG843XnOAR=r z8Aw~ugm3PN?ED3(dH``pW(n}7gJP0gv`L-Jb?j+I4r|ao7_AH?JK(OcARDkO=#HWD z2P_votk2)KP(GO{#20fjM7y|;O;_(sWtuJP-OR3h-#mO97qUYIEjg6FvpRju z_UBeQdag;twNO(AJu(mnP}u;>4ekz^lb|oMRFRVr>f~yx37`^Su-vkUq_YYa6U3TH zEq?+z{U9pEi=1G4^3TI&4 z*9mGs|0b9su%sXa*WLnZnqIiNtB`<}z_PTfq!?SkfHD>UeHeHT6-)sW7^p>Q#KD*X zoTDx0ED{31NFyDUL~FI(UM((3`%Mx4v4}qaCt3Wd@%k04rC!uq-ZPN|`9?PP3$GrJ zf_bta|N1@kefKXxoomo2U_g02$=%K`Fz2DY7n=FQZ?CPb6D-ZsCUMj za=0~*i2A*=9-kZDng4qjNo=I>FV9Zb+FPrjpv#sfu(h1!Q38LA66=rS`QIzJB;?2VEzSptfxCmD6fCzY=a^2>7 z(i;%}!@kchF1kIb}6xWSHkzryXJf^cRGTBNHF5{jXAVHGoU%fhU57#LotD1Ya=rYFCKa8g1FBH z|J86JGde!AdchwE_%E!UZH%V__AN!SIi7duXV@}=IgOb{F$C%~@Cx8IBP1|T6VQDF zBN47T7OXz`43!LWAu3c!Cdh5GC<5^0^A`J_J%aQrDBn=_{%B2wy zDr|{l9f6&Y#iCJ0YAM$|P$rK&GJWviG+-Fx$9}O?%cd4|xUff}xtv3{i^oh546q9(0?qIt$$j8Ve)Su55q3ZAfO3^x8HWM$>RX6R20S&Kr2P1A2)F zJ%XSBZxm5s@CMEXK&**mO=#3xiX;F}XlqTpEYC{3xK_%iUgyZ>BaXR8Wc{JXJUD$N zi&~x4ox}Oadr-?%_R1qGs_s--q9yLab9d^@)t7Z!kiAZdErWP8jl!6hhnebM1NuZ>o z;twHKRjX&f1Fu99$z&oDjYf;Xa2Qu=S6c8@RCFzxZj%m6KFwI0QQAfkDJ$!ZBzQj; z89;2P7=l`M8;o5?)41gu0mReM?J9i;ps67V2lAWMWm}`Z9}zDC4-zM@1LLu>om8Z+ z7w*Q%#Hl5Z-V)1X%EQCM_uqbIa%%b18&4m2WdFhO6BDoI*>dJPQ8XbQbKqDHW(R)xh<2~idK82W$l$SSknwFlfePeRroip8cdK#Ag@ zwoN~NWj8MAx&gv(>*#6Da~-WM4ISxwNezZCyde3ZHiB%z^B`(|&EE9Dcp93md( za!KqH3)tuL3z*&)d+YnkxkN5sPZ(dC7bWW@d@1Ei;^6)h+Eby44v{h$)_EKI3J#DY zM=EX~h%B*F{w`l5{E{HXM+hOJhb_2uh7e*kGUtv zBT^2F8pXUI2_! zEqg0js#D=XF}wn$C$ykS8sN;MG$0dN_pW7Uhjpk>n&qKgA=;al5Lu(6gO9?OYeQx5 z7dw3VAkCrHwT@8=-4?;Ra7S@L0%9vjZ5ILqF{KSAf1?7+Rc2Lho$(SI;E_1U>1k_vzpV}Ody*H2I9XVYGnBXGt)685C$ za#PcFV5y$mR6Kt$`#KcsH)W@*FLId7_WU*d>%F3nXthC4= z*%EXsWg2`T$#YT{0bFS;{#q`ZbxgD-&&_Ozjg6UeldTCyHk-?qr>oQD$H+u^J$K&e zc~cIQTG!_9J?PPo>3De#-aD`9(;o8K_HqRSN6~9#XOl>+y)ztx1tMw^ zs(M102B-8VigU+3lPhz-0npK|C8;_$wzM=h*SQAGBi4D0#%D${~*pJtMM2Fe=v7g(#Z}q~3)jRnUj_EH8L~{er&y@sYItkhWv?bhklcFJP^izk= zz05{L2W~85KxP(Q$q(0$ISY=HuUZLSc++*u+lA$MPsa0hk4Ff#e{$!0-_WJyBaa^v z7ZSqqcBlfA9$c95^scM@znEW}{K}srcM`LATckI)3lD36ghO5ctcXJlkSPDJ7tX+b zzIwXw8(!h7`J?)JReaF@8->%*!Ru!VzaAR#*ZkA^nvA1Lo*r^Z8LKlV0w@am-{imv zzmW4patwg3AW{%)sv92oZ)Kj(lo;c(ltI9;=hF;2*bI1{$JtT_$PFLQno?t8hmTdc-!WOZYD+j-(bZ3a#-v#U@bLwxIt{;=9zr8X z2LMIGst4l<@2hyx&!8Wq_8Rr&Kdo+kQyUWQC22=>VeEZoHM?>syLzY~g@eMk4%q8; z+kUw%W&yxxWjhn}WkycAg^35V&9UO)Z1!+*tjTAoH5(~XF&~1oJCrc1z!L%Pfq4PI z%HlM_FXhA{()4a4U0!dsv(f4Ob_^kCN_cNoJ994v4^W+m$i7Y zwOp{0jS|MEx~ceYq29kveQq?@+yBmuOQBx-iBu#xH-q!~KL=Gwj3K!gECpdJDV;$54oR?Bp<86#i8Ii(L7R#Y z!8o66ygKNN7qd=n^iS7QV|Iv{&gJoS$IBAgRCYMM2%qh^SHzOGtbHu`z6%9$n^#_( zb@u)-m-_lQEAyRu!cMn++7XIm98RlkB>q$~+eAZhjrg9FAKj=uaA7gSg=>_E#htFK z6zeG2yiqc`vlB>wl6@pV`EYEy-`@J;r&IaSY-V31=Rl$2!{wpJ&xqUo5_66G=(2~G zAHO3W2-ZY8HsbUS$DhoUU_#|w-2z5zQ??N>Dp1@&@qyKZ1xX&VA|#Pz&3)(6+FEz+ z-bDlv?H+wB`lUCl)K)tO9zPolo_+j42V;eGBCprMNErjyfIFcRu^JoF8E6WrFa)E6 z0*oI7MH^VXSxAd`z+SK6+H$9}T+>>u_;^|mcqB82O)-9dy|sUTtA2l6xW-O&9HY|` z^amZ5;aBa1_Jw&-(y|oekj(d3jENejD6n_^95HT``;ysB-6&F&c>)Bhrl6 zx50fYq5B1#VgX{HQA=151QeEE9)pHcLIKT0Hm-pkPDqepg5UD5*Hu^YSp6Ia0K!SU zH1W_<0WM{*K|R$@obp*<^y$aF0;DFoll3D~n*LgJI^!Nxuo%H=C=d80{n-iHPD10D zkf;F|%>iTw&>Qax-uTI=vkMmS+OKP}4Ug6b@?v&}w2?Prr{|=lq_RFgqE3 z1Be{afT;Wy(3|)kE@D6pb@)9uxE87@wv+U+#md>mxLJ~=-!aOA3}`6mz}v9vqbnq_ zWW9FYZBlXhV%f}NoKb&VzU1G{FQbJVQAUy~Xii z{Bcy>WWZn^?qHY9_>L9KM%IGf3(8ZUgBX>VOW06cIqb1yvZY7M96xZP$3VbX#~a)> zoU>pIZ$gDog`xoQ66Ns*7yfI2OaL4yNRONNtEPJ&lo#?){0HDEpkT*!D3`!n@vRPc zYfK5mC)AO>r^x_}-R>HPx`B0M3>sxC9h|#TQr=|)mvb1LylE5P^O-|gGu}2FP_X11 zF3)7JdK=u{;`p^t4d74C!>ZWa2>`Nbfb4J!9GXFkU`N_gqnu#a4OtiPhjLuEQ5R*i zy0Hdyc|?hbJ{c?(p5Ce^5V5Si^I#xN0T;zBp_7qx_G!pG4a^yZg}D{Al@!cGrm?4O zds>Me6)1v4$FOy7AjRuD&9n}$jDFL}CSn5(&}T$(kceuuivTr~7h}^x+kkAScH#K! zVx4#zHSs_LvIK0_Da-9L!nj;9D#(Wm&VTQ^Vbo*^Of=^fBygi9I)YLcD-LD#*C9Bl z8bK9j)F!;tP1`g20a>6mfW;EBPD^?ivu}7z)#)#m(^YXFYgg+mtG-9YmX^}#0~wvn zKb9X=Jya~LXJFw+&6d-;8U~%!>Q-2DqUVX%W&NldrR>ZeB5gj+=){x-IfhYYmJ%U9 zT@_>anib<5t$-70^lMasz?u~mnZFE#XP~o;LGvBmUWMM_9T~0n%dEj4=^x{+r2A}> z!{QA*KGylF$6x!VriH_5SQ~@7s@uz+-b@D44th@Y*`&=onNjjY2enI2b9je7zte?= zPNEClx*FTXotpJ$V}EQb%0h~B;}~y(YQPM;cbrSlMvV2nbLfShL-myeWx6UiJm>aC zu3^6RK5TnmZXaIqYff38F~1ZIQk2u2XSV};-tWVHO=X_~c5RH%uINHIW? z6#|=;NH&EeCB04d6^|F+ArCi2CiPc1XV4=O0bT#zrN!z*<5E4B+(Vf{se_30g<-i_ zJUS#h^ajGTrZ*=~d%dS8o7U9+^aMyT`M>AIHzBLJ8Iin1wHp;A2%JGQ3R&Wiz<4ym zf4NL(2QVv87Qnh7Rj^ykGi0<>vE^; z&UvRbHdB7dyMO^{{wiwbt(Cc0(i?r^-3=+F}YH)3S2AZ z2G5F4D*E$Q>w0W~?n-LE5c_}_TNoRAEPSuW@3}Wh%WlT$xhH}vBKNvnLt|s}B~>;< zzQN2EgF=lV&WO!jg3OLQJw;3`8!(m<1dk_<*#2eLz} zF-_kEvr9l-ThMaa z2~hQJ8^n?kQCX9LGx)qW@Ih*XswZ!L_`?F?J)Sf81oh0`_GK`9%63F~&;@x+dFMg3 z9>e+tRIHY%+ISR>w@N2$1@UiJ_;}N0??>r4;5bk<^BN=-*Fv1w$hPxne zxk_yZ9exM!2tXucJyEw!tWQcFL`Dz7qFlBl;yNbl)Lx6_+|kLalcy(p|2rrAlV5v9 z?iC-AXYfIty7~&7Gj$*z7MJ9`=wGM-kpgPZooGG({FyU&i%WIAewv#z=x>Z6JpaF; z?oo;I;JO4J1>R!7j)3uQ%#Xl6RVj-0EAh9qJXI|ex|fc3mwMex_;6fwF5$1aJT=kj zHoMsIcJiJb)QRI5(UR$}3a6YA(fMkp^VRDXI2BnC(Hvq9-X>O(?e81pKv8Z(dO}7- z<*p1vKI+rZ1st?CkWu<_;?9Ge}EP@s&lucGxg?<{(*9xq1sK5(}$ZHy!jOVXGd?0_6AxD zGE99wwp(MY;YZcBdHeL{686(>X7(TEz)HL!G@r(3~0Y@i22f-8J z9}5Koc!|zP+8xZ!?oa8fNBTz(PtGh=!!Cbp%I3o*H1cDqtT#~DpGZ{vZUkX= zM*MMFTMDasYX59D=uRK$ANBsFoSzFIFoZJ^blKr>XZLxuTqruK1){EyBkGH~9e%gf z;r9g6ZZtjDF;%~L$W_EF184@Vo>7f{#fZD1Oi6Q}S&e?hV0XSrtB{dPIuU||j7Md0 z+UhC`QAx$TA=Jz5^o_=2^TR$*S}P3C`aNLdaMD|dc$~q?LiOI8HO^--ai2}a#M#IE+*T_M~#;0pO;xo{v8bpy%lKtOAM456(({>jYfU*D|3{H29x>CC>U zKhi(o*igD3;x&k0VAPvAXa-MGYC)z3Wl&F&y{8Ncb~mP&{j8AdFF9bS3J|r2t1(1W zUIPa{9uFBU3f)NdP+oeP4Sq}>*0XgD98p-Y6)81qgA;prmHwtR9^$NCY`$f zJ(mNOgS+(~X3j_El<+{m0&oy$P=iw)VeM{mB(^)Z-G*m(jpVMv*{!q<)FMkK`O!u6>}W1XP0-JNl)A?s%|dm}jbt#xRm)go0ULTiaU8 z^wz{Hjq(*#;hvOb%9%yH>#%69HPG6dxDpSJ$AFv10WVo> z)M0N#ad7ec+&u0!k3hQ2Cnf*q86<<0)|HII@U#f6E;UU>u}paWrGf9&~LZd96q-L zb|AmqYY+Qkdej%OdF`OUUI$$ztbrinn-#rbuUiObAQg5EdqQI&&#)_;3_7iDZzyK7 zPsQDKAzU$Jx3qg~Ru?ER((BnEusaaJKb4=%IzkSV#3t-kggXP-684Zc>cSnP@e!L% zJnV8iB1u%h4t%9A6!!T=B#??CoM`|iI8h>baL2*!xllT6nn&mXlr37JVBh+#AqOB z#Yz-#dVOvyeqkR;;8_u`JD71qVu8^;yyWv@3%mre z&BU|Fq=$Wb!M&7yzARLz+>F||E9=6h|O;$Dp>?PcuMH>~*aABZ8-$RZMp!~**rp|~ICYtBW-;b0`zf&@olE;SKK40%enU_6kDrDq(A z){%(UlR;*~5;h)hWW>7Ym`TS{fq2kX@(d+H6H@o6Wc)DXjx4Z3I`sbg5jWrjDz)QM zja3b+7EVYK#C=%IJ6(+%f^ju!&PyeC2$ub! z(i@uxGW$-vCOWj}7=;2$OGFF*+FY(2ox9SErQ?n1)Zh3D`-6K!b7{FiG+}cmGS2ad z+ZTg(&YoO}YVoDHx#9fe#L1@X#DU1l$!f`&EyZS%S;d0^W8IWAA6^o~f9}C|EIQ;l z<&ePDOJT3gs5NU?pgQR<=wNKqy}wVulUNGSPzrne&0eSJr;jotFQ{!3-qJkQshI1+ zBT&WxQF=+rRvv@vwv14r3#U9dLt_o97;ng_(xsr;Tix0Ml)eS;0N6~bu$kb+HQ@T+ ziZ6%{fucEZrGIH9-`Z*c@!x{C1>h$qWFzxjux@b=W{c@Iw5!^Q>^x}9~M8lzpbSV%Cg}p(WE%;G3B9xEI zld}heb?LzaBgIo=@BP&>$dD`U6T$o;U07!;`56SDwSFcZ3C4uSVe>|Y&Z$N=`H!yT z*SS(+?S{JwWOCXcB)={?NT<`;thRL;KS5ToqT&xS$}lu=G1#bc5*10yoCY5a$$0}# z>jF*{F!8?l!bYEJ8i|FhlxpFb*s>%U-I7UD%e9SXkK`m%*o=nfdrF-D}0 ziZt(p7#F>Mc1m0OL!gATgr#>jM@6KQ|@sd#4B%?^2 zoE!D|MswbXEt&*1OvP=Hfsf`D5nDXP)ST4*{2#UZS+x^urA&Op6;1?3#zLX7kw7Bs z8i`Ac)(E)x&{!d;MT|4JE}{hsV*kQ0H5!BV9YFI)pmJD13|KF!KIrId)XT_3B^qpon128Lpii+B zkZG(m6>Zvx^X;$+6L!%>SP3X`AO*7-RC?16-aOmYao91Kgy-e!w} z`+h?v?+@YeYnf6Qh|Jk+HJ^*!g}wc~jzj=oRNJbcWXFGIIPXbE{@)*!GO1WD4|OI0 zpJA#?-|G({huGig-%-UyyO9?lkKO^jVsD^U-~CQ`rKL*qNj&5OropfXBW*l0^<~XENg-8iqzQ zl5_v$H;_PA8y@lj=UP0J;B$8>6|`L? zDAeX{MH}>t;`cv!F8BCzz5h5lIWhUf_!Cp9pZwY<@5nvzT=nYJ%L0Lao2;T5AH+@4 zuVL1*f;(X@GldkUz2r+J@dcA>oRh3-5WKH>O^(U;%#ba}_x055*^>*d5OQiSpKI*{ zbBJWi0jK`DIhP+C+|pZS9rm2f>p1f&O1qAqy31jEba%jrKg+rtVXG?~v_=u=z#a+M zkYUr735KmOs8}PRyfxT#SZ&io!if;_nR%;E)Qrd*#%@ptt$a3;7G{ZsEJMpxYy{rP zu2O`?hu8?@{YJ&qLib6R{&+I^I2_;>3wIYp9v_m|D5zyf7(Cx zYoQN>q7PldxgX#yyr))A`^WIbt8xC!Lvk$qmH2D)p$B{)Fl7jBP?YYW%+YL2W%#QA z+|fvam6&4=6&cM&@v{w){3UpceZl{REiyd!*!?es&v`SUr4LL`=K$IU4tr`^BTE3< zBoHnCIuM}AH~>G0{?m2;UL@W7?I~PoT+DGr-6Sz#n^GH511Guyebn8UQ--F75%Fns zf>fbv6|6}lu%NHz{O>O>qBWLDgn?qTB4odCIDHOx z?B{0^0qdqUket~+lJeT2A-6hR{!nr#MCD#ncLxFy823Ti0Jwa{h*D$mxPm_LRUTdU z(v{rlw&@XHFzAcuiEuiA(;hFrM-DTfJz%TWX~D*AA^~0b7n)v%9Az z>Eear$8%3+x1LQt+xuLl!gf}+0mez8BAhCI{KJSM{{{S)T5GG|=D^Xd!tJNk9Q+N( z3p|-BjT!`7dWF5E_}ULHFMsg0#q;Oa9}T?w-GN8fc|B!rC0lst*A7fCy&y1HRlpoG z*1EWO@nY)yV-pjPonL|H{mzVRE-t?GxciYyp5yf|zu_LIU^XE`O?O9nrqYTt1fs&d(A1udt?c_say9@J^vkx3}udcceJ}^)q)Mu(E;Z&r9HIhw?)FMr*0 zY*fn>)3$}$O06~`PJ3&M7Z-Y8bo!Xh!xbzRgTc^;7=R67*&_TUOf`dbBK2a11WO4l zIuNrECg3c9H5qavI3obvMSrFW?Z92GrfaHzXgY`7k8~b!A6hL;;mlok-1F2^pL*)4 zr0cE&IPsNXYbbZc4TCFWYK zu7e#~fYjMs$ryId@KqhX8^lb6}{|rGmN)-sT_;7WgF5gLN~2YVQ{g)x2lt z5Gx`Ex1VwvU_kxn`D2&C(q^Jn!w}`w%1TCHgGeh4Qk;SpE)unenF1 zbLFB;4kVVTRv0)US4xejGOvPBL{L3oxYP{pXPu{pml1XPo`q1q6gwzG8&OdK{81RQ z1RJ?|jb58#SxEs#(6^se;VkIxOq~QIfd7aeuQg$-!N;8tsl9CkO~oJ78ycd$Dmh1O zwN`hntq#|l)InerC|_pA(M?Ny0$NWx+_C&L8TLQKur_1BB<5xOW$EWq0Y0PME+~J* zH@Dko)X`mcmFFh&1z{=VC+Esr?QP}T)-ex6GZ>$LF0U7SzJi{A4mb#7-1N``WwbQt zB!?sTeTttHK*{=tKp3fF##eBjfkvr0G!E5fG1D0i+pR$;{ldeYOwsPOO{AM?-5GO+ z@zz^o>E>`H?f?(zbi^x}m2`15b--?4PGaaN8bdljynqEBmmEQ0r8$N~w*}9O7B&ck z02B-ipiKZ7OuE!jzd?*~4m~Km5f`L^s8|vlgGIN)U$3vjYAVM*>{i#r8^NJ5nkTY9 z(?A81K$SDK%=4O3S1ZLbEpbqIU@3ywA+6aoWKreZA3l05RVjpH{uzI)0I?t1MW_?8 zE67vfLM2suPcrjZ!r^^G>ZPyDY3kBnSBz^@bHm=IQM-ywbLTMV);3+IGGLXQtwhiBF^Avdnj5C=x6o#Ih)F{(4YsGj#4uBwj1;yDgLaD3ZWrl5^&X%}%pZi`0fDR)Ukk z2bPM5lK)e0Vmm)@R*lPlLp|Hj4OTe+u?)#4%W9P?C5go9KNi3&I=#ah1T_>GwMDVn zsYT z=?ctc#QEB!Ggz>ZzN`jBb~`~MyHORB z4}2l+z8R86hrqms@tREaLYY8ZhH~YeE*6Zx zBUc-CkHk~UF^knv;wk7S@xIM#&>>R|sC+vJV8BJV0HYTmP3a2J`=IohppQfc-@`*< zi+&V>-W1A>g1~Y`uNha?#FYbKa)Xa43QBq;gVb|aAG6IMHtmfa zv8z@P$&@7rXySD~O>J1ScL6GFVusD?shBJ~Ropbu#*GG|2uPbM@qatd&tsn5h$Lp^ z@HTsmF}GRkoA%xY9cYB6)Na(h!O~!$tswD97X&^RWByNMKL%l2V7^NXA)=Y6XFw1y zR1#rSsG|haMC&qXHCw_ghxkJcNufQ+RsF|LPd+`lDPRt{^S;Vk*d{>DAQbjTaRC%F zcF&WzfDLjVzUP=ik@$x(#bSVSmTQK}vBH=vW_grv3JM|lC&1wc%fJPd?ZLU#F!nqL z+BgrKH;d8R;1;QnI;#jmj6aMsxTbI;DFNeML_`y@VcA0X!^qquE^U(^Hk+oNh&;YI zK7OqJL6PLp2Vcusq~=n)+P;olTQqm&kljh&5WJ?ShLjHE} z*|0x=z>?=5csh+cjJZS4r3${O8}sl-JbUd&KASj3a||HrkU85Lm3|v2w-v2ldp!GV zm`~;xvZdvp&Q#F zmbeerC-`~bU#=$*k16NaunxrbtWx4by|0VKSFWxiY8h4Z)CQL@Gt^*4Aow~9|_+}%+rgRLfS55gdm|6Wmd7ALv^l0SbJaLIMVx>Ug_UerYp=Jlw* z>&MBWqH)({E-+?LAA{VaB7=cvQeNLMqxYQ)5UqlVNzH}arIaAxY#7ZjC;Cp&q6rpC z#wZ+J>V22;4zi@YuJ;FtK&KN(h&go7AA?bZ6ts|?a(%=##f0X#1`HPhr^yWxols2L zihTOh5%ea&(wj>5xjZ&JJa$>ka@o=jVmgw zhwudgmjlJXnv6^BKdQao?|+T<1~Uh00}a;>1l9r(m>~kG#QUMQeU0{0s=pN<9RbgZ z?ty-9Pbav@yTZ{>iIL)KyZWNrUGMh3rMl^BvOgjL)gPb0Hyf&>P`90RRy{}MJ^m5T z;*_Lja^RVxfpx!nCXgiQSnR&s)!b&Tl^c9^U{pREMt@v!SMEx#nOo%=$oZn`nuK}{;L`yKLiY?-l_Y-_DP8~kj}yoU@l#{thz~Uw;M z!bt#=;P-3}ww(uS1*HQQB8a#e#bm`{te2Qda{aWa_*3(TY-qP@;Va>*SGf@n^xjSl zw)jbGe{be|ZTfu8hMjf#T-U7LP__8O_5-$v|6bkhn!EUO!1Z*7 z?Ge{cJHyf5cYR+DfdV#@fccddAKZqEgkgL46Y*2JO|J z=e3ZW3+%hZLZe+i54nOf81cEFuApHM_FmX6lSD5d?1lA4+mg66JDwUYG5G69I$gf^ zw2siiT`UGPvKqs;l{u7#vrYV9(ug-qClI_0(=WRO^9s*o?m7=J6^P{oM6jxw3ECVm z#cy{zmoFpV(ZDk_!Icrhz@9s+{-)m5M_yS&Iy0bAz>*``aO;UDZoj<@WooDMy!I2V18Oq>i0CmO60CJm|Lt?X_-jauDHTaTzXk-f64P zXTVfJf^H?a-X^L`&px}f)xIVW8VNNY>OHHATJM|s55KAIW7LJKF!-_Dmif7CKyhDRo{1TTAw;tg^u=X_b2Y-(CS3e97j^4iebE7JL#UB zWO53qW?yvi9GFlz7o*Fbj%gqb%#AGO^NUE}-ut!O?-g>M zTqzJNWtY+^S2FAMW)t7cFBU5Kk0l;jc0zksOP%a}cX<)HSPtKIIGSH`K9>JX>g3Co79U-5d?i(5+ftA9ym*zAKM{4dBn=N) zC{Ja$*)nL80?~;krowPMvG3TvMEn7dzv|!I;B48@R*sC1A6eOgN)FmNDa(CZVmFj7 zMMd1mp^d03w_u_v!3cYJa|4NM!?2|!pM;DFtQoMl17)xtveL}kF9b5K;qQ33r8|GX zqww)rs0}SBS~B4*F6^I9IHMk@!>d5X$cPWILs08uMIf?zH5se6w8W|^cXVN2E#Vri z?@I>0W|Up&^pqZm9QJ%fw{jJiT5W{qj%#3m8!~>ASOe4EMNrNowsiDunkV_LK)NF= zLI1kjjj{D2;K)45cl#M(RgK>*L%)=fmND3pfTjUG;7SSPydn}r6GP<>{Rt42Ypa{! z2;Y_TXm5+AZATCTwELCAzm<9rPocqt!CU?BPI`jQ7XkY2cCY(``kMZ#2aP^OOEa%n zN=gd!X=yCbqeCg^$&vuWjJU^0kBI%2>v-ccu+0J6Y9xd(J9wCToyv4-=R!+0iJ0C%QQQ0f9GhcIRh zSv&?4a{<{dtuXTyQ$!J)H+$%rvD|WQta~XwJUl);+`aL^Pb7lKZ=DFggx`-38+vG# zL-`~?N5$ZIn7HzdroTn?7ZBZ*zFq*x-dOjv@KxV||EqiJJx0G|3^>rH4rmj!Rj{iv z2qjRn?RK+;Jhj`GFK?UvX4F?O9}W25TjzR5Ogkt^aso8v1yVWBL~H4bsg;%4NaO{w z(L5Q8buJ<{=`faq!KFjOSCa5udKCCZTX9N~eb*3HdkPTKFD^Psa|DU!u0dpj~%0%;O z3n{cOq0o}rQYk4@k-Ji<+Dlz)ckNZ(%3j?rm)(m~b}w$Xjd!`R+ithbVo#RA%$Ua5 z24`a6ftSHBIL!dVV8aaWBa`_s56qk8z3F6VKVTla>iz${A!TNDwQZR1ml9cPv)bMV$xrC2ZFvt%mDnV z4n`u;q8V_1#23PFI9+bd$MMjDPJ2AeSdim^dI@ff2LdtzM%3>O8R?qO?{WvjA#W@j z^XZ9H*c^4jf;kkxF4_NE3YUNX5b7 zU@JEe63U2Y6G{jwr!-*$1|Yr$R@q^B+0JH%RTS4)XBa`8ush@bi=EEdFLlnIEk>k4 zT$8khbi@rxTN+_z*BL~}K?*P+ODaP+J#LiTP_anqigBZX%n-0axN%Rd0SlGM2}Au( zO$n>G7&(CqgqY?lm~3QAe88W5X4|Od!iOxm-8hsVt%>n;^ciC* zkMT<;V3>kH0W@ZQOj>GJDp^-JS2e6dYKt*Za~*eqG>Y*+10jPlO&w?rps_<61=(#y%q56Sadr~?+`7{A{`uGZOB*M5%WEon&M~I`1(u~$Z$!JR(X@^Ba5que zp}#40A^NLjE7zf*7)Fn+t>WN>Gw^I(J7(3vaXwN z(BGbZ-}D%8AaGeY;gcZmwROE1q>th)+l=JqHRRm3A>23h;4-qm;qFlQUVbk)0eUaX z(XRRi-gk@9LBV+RGP?H`(ML|4c;x1b*KdrRIDx_5-TpLY^mn-GZr{Nz?yw;t3({q` z`;pi;g3|(?lfl|lePD$f*!FJK4=h#bw!!P(Th)lz+T4Ue>83{yOb+CC>AAvOx1Y(; zk*9EdVj^Hjuzz7zAxIRzHj0$Q**+xA46wd1uFtMv1dQ??gav85{8XL+V1<;Xs7Zr) z@K<`)SMwP&n~5OU%oow4v1~Yi;z9@*ORASZI2()Vz%+Y2kxbUij?d#QokyDW%UR}B$$HJ+qSdB*y9=i}lnDgkOQ4R-F z;e1vPhxKeeoC=1^#^R_y=8j%Cb}$-8z?)kjvJUZpuDZ*iJ6v+pERD7!o^-f8hA?8J zOe~es6N!90FjfwyJ(2ck35HBbKOjSN;rE7w2}=cFCz8^Yq=|~bHb{*D@ktRD+84?a zX$!7MTIQOH;@D%cm5N}^>1{dP{peaUkzA@1~({dgrupTEa z-0q&3-RKx`Q&!<9=M0deXs9G$d8f%o(Q@La7%xJOvcR4UQBnZm!*>Ts9Wq(1>Kt^D zp~Hk>4|^y^F4UHQmzt|zu3Hi^^@}hdBg6ZVF1(30x=O4LFjJN_Kuz^Gl&j}Db>-`7 ze@NG^qg}+j)3?Z(&J_9J_QRSw`iCxt+xpdmpXk^g4Y z1Sp)w2#~ZN6UG{UPKl)-<99)_<$QTBwRXgIfh{gFGx8Fb8O2TrpfDR5+mXn`zMOa8 zM7kbyr>s&eRcqUXv#V}QVD@;KJ#DWQv z7`owm@j`z?Itkm@{_kP^qCXt=U(~~2kz4s*tiqExJgNUHi09S+lBa!exUu^Nn<_0t zl~#@ZBmAOj-u$DTPv(1_XXo3)z20Cfwt)A8?uWclz(yKkvqQJ0M9|5hk{kP)1k6K2 z#BX!gHO20Ws_~^A5fracavEZ5TddmjPhwhRof{-VbjC|an2wKsqW`OK`F0USzrCBE zDr_6pGR#%9JV@^jD2`+vVFW)acF|-MH&(YBtA_ug7am<34R%X2ap^MkI6IH|6w0Vuw2o@n|v`9e=tj;|_M@8`4(L zG0+Qxrk8`XH^1y*(2ppe254)Et?O>Bq@%}xDZlAa0C0W`B6knS*>+oWQ9>x1#<7{b zPXcA4k;(e{^)Ay&?HV_>WuE@Q@4Yoxa}wDh$LzbdYQ4Hx?E$0mJ+w^b{aU|{1}eJ5 z+!bC}DGZ7A88RH)cSzwYFqq4UW2YdKiO8Cwr)Yb;{_1VDC-Uw7CZKB27<%}(nu@Y- zG@CZl`PMQ@sW9&t|0TUw{E%%hK;g)Hzz;sJ4Cw(Iq&alp;fBJ%aavqz z@49WfeI3x2-u32A!-94LySwk-S+)@2V)>hAcl%V;8oD9=Z_xv1XpD@MKy%@`U`i+^ ziL%=zUHUu*Q4knU2EN0h18JO&NKTmbhMtWBBAm1|qIYn*WcFKZVh zUP!sP`v8G3XqraS^9pT?prBGLvb%YSsFBY@4SRX}5~vix})ViuHfTp8}w(aADpPo!?$!Qv(l6ay(MIw+(se2%YkgGb?$P~~i*~qxh z%EH^V(2Ius-PQNG1FIaO=hNxsYNR+-Fj6_V%Y@#$*VXR!*Ps~7VrOIl94oe=i#9NW z-mTjJcs&fKgPS8$I=CwQL#QKhi&k9dudTa)3L%nhJqqRhrgnU2(;p^g1kxnDb}KS1 zm`ww|jIp4NlzA40yuYR~xDMuU+`y9$LbpS%D3;pYm64lkYjD{ z=lXws?%Z>mzj?UX{IBer;#uE9-zb@*Xjco4QBZdD1V$>TohAeVY%wKkAbNbURh}kN z$o@%cH0RG2vXhl1=f2mD1(HaiP%rp{UY~C^H{bUA+vhGF*Iy8t?r%c7DwOu&x29_+{=mX(_!dwk9rBe>| zj$i?)x6E|YQBY#$vsvwQl-G?ih)DPI!`?V;KpIWC*=D>&Byv$ z9b?V`yG6Swwce^-gMz>Vfrss)r1no}*XG`at?q8u=AdC{7Un40_DyjLK11Lc;smj9 zE+VW4@+h#|a)=te`%gV@eJPqgB@n4?@1494$oVBDXMFA%l>W@JUh7t$8EhOMhGg0-%14039*jz%DRuVNpK9R(9M!+c#8#%nS zwSiSbZ0^MB-Gx}=pY$2JJB|c2Q%F{oMyeJk!oHmqhn3G;j*2rM%{jy2j2R2<$LHgS zlhns!q3C;{<|bf8HZ~v?f{bkJ3iQME=iTm@;rGN4T~PG9qES!I8lAXa%UL;3H0tsf zwX^Y}UQA8;$NZBi?A`7*VjjN{b3YMI;(FoX7;k`baiU_6%yf$YG=Qb|P9octpbRqe)Fmjpm8|NpE zH6kaL2XlQ`=hz-&hIh~@g<6Xg{vjm;T2uU|6gpOG=o)AtW3~~Cqv4rKnZG8kC^qd%2 zEMB#R|BHxQEMT>z9T*?WElxqDDN3aL5>CRFs5TrfTL`;NS{)?Z?sbedUXjf&xm<^g z&|8H#Za_mc>PhGUI0Nr+5)LJoS9?Ys-$TJV6s=q31=^?@fsiBWc^HvD6i#07JLSMaas==5xe`(Lk2rl=s^I&C%c1E`-x(kC zN+EHSK)$0=30Fk}kRHGZgBQ|Z31|N$y_9r$FP?K(T;f>V>-2dY7m%)cFb}Wexih!T z2z}8YyBYu?8%$!eDe7I+!|Flvkn{b$;p3E5)@fYY3C4tK0c@gNu{a6< zCRZ*3mD)y|Hqf>|l&y`1kU6Lw2#r>;2U!(?@ym4t0IW@UlEL_BHW5sEref*akkK$c zIvPiby4%3@uxa#Hv#7z_Hd~_a230d&8Rdx%!uZsLpa?t&q$Q(D4!IQph~YIie{B3*k|G^{BGTH@0^NnT!GZl#XL~!h&VCg z{mYmOK%VZhd&=@2usOs1NANPZHd-k*t;FjNOXje6_;ql1Tdvq0Q>dSZKkG~kQR@3o zOTX=@188QaHZwu5?o6$>Lu1y#$;aT~C*M*}05fgp8H0G*&z~PEbJ7AQ0w!QnK7ZJx zPG zD7b)>LY}fmmJ|iWq=lRkJwg+0)0BGM$#M?-L_FyAT-44iCzDr>&zGkFh_&>KE-Hv2 zO}h|V7|)p(ow1K%en{5{G&0vk9VdyY^8E2D$>j1G?V`tv>ttiji)L(xD){1a*$drXZO?ON*Ofv3s#+B7jV$?9HF@{Je zokUHT;d<(E{cN-idqCA3?=gG}w^I%NGo%%0gbq}8ZG9P(=gRNpa**5+lw^_S= z_ALETT(1@%J=hkpYfZ#6bxewOR}Q2s&kRY$(MOhz z?`{CKjKBJ_QGfA8u_i-)lClQRV2%#reg@SoK&7Fl;QJgq&>cK`71-tM}56kI}k^VffqVM6Xnc&2$@gklbROfjFZ@lasyG-r3?T z{2LH^T6Y|qTt#UJRD~jIwry9W$qG$~jIM)L4H~3Is$}2aI$BTkp1Rh1s#H(dci!Zv z;pf^@z1O@MS$e>n4Z*e%$t0DBefxU{Q{=5?cBE!H4;LWo{nsa0+Zh?z)Uec=@gfW~TwiiF(u+ z?bROA1FmAMr+%bXtKnX_2W>UPE|cGt>~+hPxQo~gc^xi}e0l8G9_H5D?%jf;;V3RI zudiy>xiMRiU!5KS7{h^wkOk{DJNec}@;$pqLuWbP`fz@4m4`vR(g@}oYuXPY2ADMo zQW0pJ3_(@i69xfu1uzm#!#`|+YyJ&#KyD^L|ExYnnFEbr-FUDsKST9UWN+F+9Krh5 zde7FiHpFeXn?&F$AmIQ)2!{r$;4r3L#9zW2QZKLctX;YzL(S&`}Bx-Y3Qgxo{FoDbL^v`D3^ zYoY)v*b}V790B@|kc%yftnFvcVC|x879vz|bp+yfo?coydlvsq*;3W?vrL~MpAYjK zFxHd0tF$!_uC`d!ZhFty3*GP6h1~Ai7d?c+=z)OVL!^w{%J;VXrt-F^+=~FOF?Wl= z>-xsVX1h-q4fC6+fArVMiGwx`u#J@eur3mJ^aqD`!In! z?;*d_>GoHj} zJr&-b^Ac3B)O^{9A%h6@#{Q~&8eMGrZ}d~aDudTewg+u% z51O;N-tVcF?ev5Baa1;F*&60AL8IhvM_?58{DVNCCt&u2xZ0iZQ_;2Z8c6OXe<}2{ z9UPO50alo=DCNN)Cavmkb&O?0y-+Tcec5S~93_q~$ChiAufuWfbiv5+kklU^7CA(J zn_DR2!)LW~J+x0fD?+Dvy-i$!LA~l(t1ok2_1F|;uNd@k*teZ=!ToruntxxDF~+ns zj6l2CLuDE_y)WJLUKnjYRc6Qdh)j{exBYL}2NCOr`hY|FffH}NZ_}Ya6z?EqhOHS& z0Nfz35!PTTfDMh-G|0-WB^<&VvFW^P`EVsujwfBYgfUq+7Em7pNzs-Z&SE4|yyuu0 zJNkwaX*tKjhhx(OSHFO+V?(;?ko@E{v?(d%*m zTk4wk`Sef_SX;dibUDkgxWMY-4VX?q+HSg(ebxSd^!OqPmp1D0_bgM6^X26Dm% zbfmZTAMxp77&(1`(4reTvmM?*Ru5wS^7*JdoH`^U#_i(y0KZ}$fpH0DK*Z^)0U$E~ zqjA!jEI-jqpeD&I+z=kc$Q}FhrArs``ND<&l6`xH3|)+b1A2C&S}3HK;`!LDw>=9r z;l{{A?ax44&%@k`vkUd?JJQkhSX$Rd#l=Ly@5QO{ZhOXh9F;fPQV-nSz8Pp$OaFux zqR6S;M9R3gZYBV_yPIj9NS|OkFV)}vnam1|xpCJ4AAe(>) zva&goOL8dr>KTK=ig**rTv=WXGaWW-IMk2AG#vJ%0>=U=N8rvv_JwRA@x)!hl&jzh z1;yKgA?&1rQO)fx{AR(8gevQiM7E^_W*xYr3 zHaFvlfDH_}orN`X=+I34M6GthpG&23{cm+Z!{0F#y7;<_p(%ao!hIK({HqWlQx3E-dNj=K>lqyC_8p#Y32g(X+rbvyzaunt(-e7YAf?h*p+LvsF8Tp<3+B^EQEGlXeR^Tx zbUGhkn%=;ltCzewcrY(I?H>q?@e_IIR7zaux6*mmpbpB7yiEEa!@OUIS|DbXa4-}KhAUa!pN_rAK4PP2lZq*&JSX!@ z3?w077Y35m}*H@%LibJDhUXBmrCF4ZuaCGpn z)jx*^x*oj81B=ov#-R;sKwAz%ueS}u3d}L>T^)uEsm|`w5CiRYch_W0A~As1F&Acl z^4K@hhR5_0Dm^|R`8-gqQa_XiEUZ~&cjMGxd*CD?v4e9|rl75PG$f+MZdGd_S8y2+ zy#`#T!`CGQ_ax0~tHI~W7Y(Z%$-QbP>p+XL#_Y0sN!Cx+aNOY1Sf8BGkIv08VuSmNw{nE!ee( zZqdpjTtj6EvPR};_>g-$`7@9{KX0rVdBm;CmyMl_9Oa2qskgs9b?TCO8QcSrq2M)R zT>DVW;Rb|-*0!V5B{#g!Q9v7nwbIPL{`L9hiY2dGo+{^^JGXP@%bQF5e5os2G+J;D zZ|E#w0uS!Ve#v{b2KO{oTm%JM=5Qc?0W5=luHh{=|2el*yyd-+pTS-2jBpSc85hZ4 zdgH_hE}V#rCQ=FfjYbk<2Mrv_*T*Jv`BW;On;fg>krGbQ%6}9;E%_jG>LPX%si`Sj zwh#s5Ks1atec@4_wWxJ5FX z`PZ;{*=w?gwo*ruxvwel^OtKuMyWxjWfI?^L=KaelE}q~uG_6gE|oSoeX^I#`XiBK zB+^wc;vIp&us7)8(yM02e+Xywcuq2MRlN*&0@r4U7V(NbQe;RFx7|oL3X%=G8%1lF z^0{Fvh}hrTv@i2`7Q!*A*QHC5WX#tEmgfGP*sGaRi)3pVvH*P&^3o zH=Yj%&TimKNfM4EXqnOwEHDECQPeyFeJ5{CAnX4~%bv3I{=ljv2|5jdAQGTk5}l(A z8i46341DCIHGZV()W;VV#tD8$N|Jz|(bG)8nYJYSy*i6023HGOr?S zI3iE0flrza{ykbVXnuKtDGGLVz%@N-@l0;sETrDm-^NvXirlCz^XId3<6@zVsCz^p zHL74-e!aJwHF3QvfBV1>Ma#a@1_!>j-2<-Lk69rR1-ttQFw|h44reYPFKXsWoevG# z)hj*}*>uU_clECF1Rf3?R8OijEw@7u0Kcaix#xl5Js#A~Q|l-%m8I~I9a~0#TnW1; z`?dsc)h*}Hcj^+SKOPhe?T8I8-(p(bx(6tYif7t|`SDVu+5L{qMmJVEt1E-&@SnwR zNC0Q#g1dITvTuZ*oJIom;l2POxOX3|%@qPQ^OD9b82gW)-<~mfT6?K=%N^ zEpY%?8OH>VMVYS+JbQU5q6!P4`$nNMLm~a(gY-7=oa@$h$+xV3s%MnQ&ZHuozMo3?gJ|6tiF%2wBXcTHf&b9HWkK)aT4P!Vmg<&MCfe zOgY03s!w8Ge(uBCvk71nA+f%QH@$Z`nh9^z=k~Jx(uO1AeZ=Q=g?*3U5_t0&yuntz z8GbT3SbZ#!0bq&C6=F!EBB|w6&F^wWqApK7Aj!GZ!?_k$;W=(gdMc;HUa~G}$9Gzi zilu{5G5;=fEyX$smtKTCUz`74NsT`MPVi%Ht$>GD2>4Mw0J*gB>;vBM81jMz8J#&= zn=Kyz0X@Bd17vU*Lr_sn5)_KGl9b|;)?I;66qwYs!I=OZWsy2Q>CTp%2a6*Q{&VRm ztJE?pB*Z^X8!mN7On@E}6AjsrQ%Y9*_+I-gx!>{GvImt;#sW@Gli;j3;_`WKaqPQN z+~vTSCl>USXT3g5j@h8Y7Y#daag4N0)xrEF&|!MwGtkz@K_{pcNK_s~G&K!|bv|k) zlS#K&+YbxKtY~<)riNGotp<~g7?I3G#?PYsHp6GLjr3yr*?SWicctRaBt*K3?LGJ4 z{l^;VMrL=ot(~%I^$wp8HHfCN@4uXxj{WiF%uM9}(4y0sU&e8^dB-

w*PK%@U|u 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

M*)e_XTX!Db|G|4PhT5;}P?Wgk?Yga6kuB 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 F{{TjDuT%g4 literal 0 HcmV?d00001 diff --git a/android/app/src/main/assets/fonts/icomoon.ttf b/android/app/src/main/assets/fonts/icomoon.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8faca2a2f3bd5a8e683236e3eda3d0a0ee8c34bf GIT binary patch literal 4356 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 P0Z2!yw!i(uEXV%`NQxAS literal 0 HcmV?d00001 diff --git a/android/app/src/main/java/com/lxmusicmobile/MainActivity.java b/android/app/src/main/java/com/lxmusicmobile/MainActivity.java new file mode 100644 index 0000000..c94173d --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/MainActivity.java @@ -0,0 +1,14 @@ +package cn.toside.music.mobile; + +import android.os.Bundle; // here +import com.reactnativenavigation.NavigationActivity; + +import org.devio.rn.splashscreen.SplashScreen; // here + +public class MainActivity extends NavigationActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + SplashScreen.show(this, R.style.SplashScreenTheme); // here + super.onCreate(savedInstanceState); + } +} diff --git a/android/app/src/main/java/com/lxmusicmobile/MainApplication.java b/android/app/src/main/java/com/lxmusicmobile/MainApplication.java new file mode 100644 index 0000000..99ed766 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/MainApplication.java @@ -0,0 +1,86 @@ +package cn.toside.music.mobile; + +import android.content.Context; +import com.facebook.react.PackageList; +import com.lxmusicmobile.cache.CachePackage; +import com.lxmusicmobile.gzip.GzipPackage; +import com.lxmusicmobile.utils.UtilsPackage; +import com.reactnativenavigation.NavigationApplication; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.ReactNativeHost; +import com.reactnativenavigation.react.NavigationReactNativeHost; +import com.facebook.react.ReactPackage; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +public class MainApplication extends NavigationApplication { + + private final ReactNativeHost mReactNativeHost = + new NavigationReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + packages.add(new GzipPackage()); + packages.add(new CachePackage()); + packages.add(new UtilsPackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + + initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } + + /** + * Loads Flipper in React Native templates. Call this in the onCreate method with something like + * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + * + * @param context + * @param reactInstanceManager + */ + private static void initializeFlipper( + Context context, ReactInstanceManager reactInstanceManager) { + if (BuildConfig.DEBUG) { + try { + /* + We use reflection here to pick up the class that initializes Flipper, + since Flipper library is not available in release mode + */ + Class aClass = Class.forName("cn.toside.music.mobile.ReactNativeFlipper"); + aClass + .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) + .invoke(null, context, reactInstanceManager); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } +} diff --git a/android/app/src/main/java/com/lxmusicmobile/cache/CacheClearAsyncTask.java b/android/app/src/main/java/com/lxmusicmobile/cache/CacheClearAsyncTask.java new file mode 100644 index 0000000..1f8699d --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/cache/CacheClearAsyncTask.java @@ -0,0 +1,33 @@ +package com.lxmusicmobile.cache; + +import android.os.AsyncTask; + +import com.facebook.react.bridge.Promise; + +// https://github.com/midas-gufei/react-native-clear-app-cache/tree/master/android/src/main/java/com/learnta/clear +public class CacheClearAsyncTask extends AsyncTask { + public CacheModule cacheModule = null; + public Promise promise; + public CacheClearAsyncTask(CacheModule clearCacheModule, Promise promise) { + super(); + this.cacheModule = clearCacheModule; + this.promise = promise; + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + } + + @Override + protected void onPostExecute(String s) { + super.onPostExecute(s); + promise.resolve(null); + } + + @Override + protected String doInBackground(Integer... params) { + cacheModule.clearCache(); + return null; + } +} diff --git a/android/app/src/main/java/com/lxmusicmobile/cache/CacheModule.java b/android/app/src/main/java/com/lxmusicmobile/cache/CacheModule.java new file mode 100644 index 0000000..875c039 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/cache/CacheModule.java @@ -0,0 +1,74 @@ +package com.lxmusicmobile.cache; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +import java.io.File; + +import static com.lxmusicmobile.cache.Utils.clearCacheFolder; +import static com.lxmusicmobile.cache.Utils.getDirSize; +import static com.lxmusicmobile.cache.Utils.isMethodsCompat; + +// https://github.com/midas-gufei/react-native-clear-app-cache/tree/master/android/src/main/java/com/learnta/clear +public class CacheModule extends ReactContextBaseJavaModule { + private final CacheModule cacheModule; + + CacheModule(ReactApplicationContext reactContext) { + super(reactContext); + this.cacheModule = this; + } + + @Override + public String getName() { + return "CacheModule"; + } + + + @ReactMethod + public void getAppCacheSize(Promise promise) { + // 计算缓存大小 + long fileSize = 0; + // File filesDir = getReactApplicationContext().getFilesDir();// /data/data/package_name/files + File cacheDir = getReactApplicationContext().getCacheDir();// /data/data/package_name/cache + // fileSize += getDirSize(filesDir); + fileSize += getDirSize(cacheDir); + // 2.2版本才有将应用缓存转移到sd卡的功能 + if (isMethodsCompat(android.os.Build.VERSION_CODES.FROYO)) { + File externalCacheDir = Utils.getExternalCacheDir(getReactApplicationContext());//"/Android/data//cache/" + fileSize += getDirSize(externalCacheDir); + } + + promise.resolve(String.valueOf(fileSize)); + } + + //清除缓存 + @ReactMethod + public void clearAppCache(Promise promise) { + CacheClearAsyncTask asyncTask = new CacheClearAsyncTask(cacheModule, promise); + asyncTask.execute(10); + } + + /** + * 清除app缓存 + */ + public void clearCache() { + + getReactApplicationContext().deleteDatabase("webview.db"); + getReactApplicationContext().deleteDatabase("webview.db-shm"); + getReactApplicationContext().deleteDatabase("webview.db-wal"); + getReactApplicationContext().deleteDatabase("webviewCache.db"); + getReactApplicationContext().deleteDatabase("webviewCache.db-shm"); + getReactApplicationContext().deleteDatabase("webviewCache.db-wal"); + //清除数据缓存 + // clearCacheFolder(getReactApplicationContext().getFilesDir(), System.currentTimeMillis()); + clearCacheFolder(getReactApplicationContext().getCacheDir(), System.currentTimeMillis()); + //2.2版本才有将应用缓存转移到sd卡的功能 + if (isMethodsCompat(android.os.Build.VERSION_CODES.FROYO)) { + clearCacheFolder(Utils.getExternalCacheDir(getReactApplicationContext()), System.currentTimeMillis()); + } + + } + +} diff --git a/android/app/src/main/java/com/lxmusicmobile/cache/CachePackage.java b/android/app/src/main/java/com/lxmusicmobile/cache/CachePackage.java new file mode 100644 index 0000000..d717db2 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/cache/CachePackage.java @@ -0,0 +1,24 @@ +package com.lxmusicmobile.cache; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class CachePackage implements ReactPackage { + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new CacheModule(reactContext)); + } + +} diff --git a/android/app/src/main/java/com/lxmusicmobile/cache/Utils.java b/android/app/src/main/java/com/lxmusicmobile/cache/Utils.java new file mode 100644 index 0000000..d981ac1 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/cache/Utils.java @@ -0,0 +1,80 @@ +package com.lxmusicmobile.cache; + +import android.content.Context; + +import java.io.File; + +// https://github.com/midas-gufei/react-native-clear-app-cache/tree/master/android/src/main/java/com/learnta/clear +public class Utils { + /** + * 获取目录文件大小 + * + * @param dir + * @return + */ + static public long getDirSize(File dir) { + if (dir == null) { + return 0; + } + if (!dir.isDirectory()) { + return 0; + } + long dirSize = 0; + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isFile()) { + dirSize += file.length(); + } else if (file.isDirectory()) { + dirSize += file.length(); + dirSize += getDirSize(file); // 递归调用继续统计 + } + } + return dirSize; + } + + /** + * 判断当前版本是否兼容目标版本的方法 + * + * @param VersionCode + * @return + */ + static public boolean isMethodsCompat(int VersionCode) { + int currentVersion = android.os.Build.VERSION.SDK_INT; + return currentVersion >= VersionCode; + } + + static public File getExternalCacheDir(Context context) { + + // return context.getExternalCacheDir(); API level 8 + + // e.g. "/Android/data//cache/" + + return context.getExternalCacheDir(); + } + + /** + * 清除缓存目录 + * 目录 + * 当前系统时间 + */ + static public int clearCacheFolder(File dir, long curTime) { + int deletedFiles = 0; + if (dir != null && dir.isDirectory()) { + try { + for (File child : dir.listFiles()) { + if (child.isDirectory()) { + deletedFiles += clearCacheFolder(child, curTime); + } + if (child.lastModified() < curTime) { + if (child.delete()) { + deletedFiles++; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + return deletedFiles; + } +} diff --git a/android/app/src/main/java/com/lxmusicmobile/gzip/GzipModule.java b/android/app/src/main/java/com/lxmusicmobile/gzip/GzipModule.java new file mode 100644 index 0000000..9060e10 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/gzip/GzipModule.java @@ -0,0 +1,103 @@ +package com.lxmusicmobile.gzip; + +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.WritableMap; + +import org.apache.commons.compress.compressors.CompressorException; +import org.apache.commons.compress.compressors.CompressorInputStream; +import org.apache.commons.compress.compressors.CompressorStreamFactory; +import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; +import org.apache.commons.compress.utils.IOUtils; +import org.apache.commons.io.FileUtils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import static org.apache.commons.compress.compressors.CompressorStreamFactory.GZIP; + +// https://github.com/FWC1994/react-native-gzip/blob/main/android/src/main/java/com/reactlibrary/GzipModule.java +public class GzipModule extends ReactContextBaseJavaModule { + private final ReactApplicationContext reactContext; + + GzipModule(ReactApplicationContext reactContext) { + super(reactContext); + this.reactContext = reactContext; + } + + @Override + public String getName() { + return "GzipModule"; + } + + @ReactMethod + public void unGzip(String source, String target, Boolean force, Promise promise) { + File sourceFile = new File(source); + File targetFile = new File(target); + if(!Utils.checkDir(sourceFile, targetFile, force)){ + promise.reject("-2", "error"); + return; + } + + FileInputStream fileInputStream; + + try{ + fileInputStream = FileUtils.openInputStream(sourceFile); + final CompressorInputStream compressorInputStream = new CompressorStreamFactory() + .createCompressorInputStream(GZIP, fileInputStream); + + final FileOutputStream outputStream = FileUtils.openOutputStream(targetFile); + IOUtils.copy(compressorInputStream, outputStream); + outputStream.close(); + + WritableMap map = Arguments.createMap(); + map.putString("path", targetFile.getAbsolutePath()); + promise.resolve(map); + } catch (IOException | CompressorException e) { + e.printStackTrace(); + promise.reject("-2", "unGzip error"); + } + } + + @ReactMethod + public void gzip(String source, String target, Boolean force, Promise promise) { + File sourceFile = new File(source); + File targetFile = new File(target); + if(!Utils.checkFile(sourceFile, targetFile, force)){ + promise.reject("-2", "error"); + return; + } + + FileInputStream fileInputStream; + FileOutputStream fileOutputStream; + + try{ + fileInputStream = FileUtils.openInputStream(sourceFile); + fileOutputStream = FileUtils.openOutputStream(targetFile); + + BufferedOutputStream out = new BufferedOutputStream(fileOutputStream); + GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(out); + final byte[] buffer = new byte[2048]; + int n = 0; + while (-1 != (n = fileInputStream.read(buffer))) { + gzOut.write(buffer, 0, n); + } + gzOut.close(); + fileInputStream.close(); + + WritableMap map = Arguments.createMap(); + map.putString("path", targetFile.getAbsolutePath()); + promise.resolve(map); + } catch (IOException e) { + e.printStackTrace(); + promise.reject("-2", "gzip error"); + } + } +} + diff --git a/android/app/src/main/java/com/lxmusicmobile/gzip/GzipPackage.java b/android/app/src/main/java/com/lxmusicmobile/gzip/GzipPackage.java new file mode 100644 index 0000000..41631d4 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/gzip/GzipPackage.java @@ -0,0 +1,24 @@ +package com.lxmusicmobile.gzip; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class GzipPackage implements ReactPackage { + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new GzipModule(reactContext)); + } + +} diff --git a/android/app/src/main/java/com/lxmusicmobile/gzip/Utils.java b/android/app/src/main/java/com/lxmusicmobile/gzip/Utils.java new file mode 100644 index 0000000..b727e3d --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/gzip/Utils.java @@ -0,0 +1,50 @@ +package com.lxmusicmobile.gzip; + +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.IOException; + +// https://github.com/FWC1994/react-native-gzip/blob/main/android/src/main/java/com/reactlibrary/GzipModule.java +public class Utils { + static public Boolean checkDir(File sourceFile, File targetFile, Boolean force) { + if (!sourceFile.exists()) { + return false; + } + + if (targetFile.exists()) { + if (!force) { + return false; + } + + try { + if (targetFile.isDirectory()) { + FileUtils.deleteDirectory(targetFile); + } else { + targetFile.delete(); + } + targetFile.mkdirs(); + } catch (IOException ex) { + return false; + } + } + return true; + } + + static public Boolean checkFile(File sourceFile, File targetFile, Boolean force) { + if (!sourceFile.exists()) { + return false; + } + + if (targetFile.exists()) { + if (!force) { + return false; + } + + if (targetFile.isFile()) { + targetFile.delete(); + } + } + return true; + } +} diff --git a/android/app/src/main/java/com/lxmusicmobile/utils/UtilsModule.java b/android/app/src/main/java/com/lxmusicmobile/utils/UtilsModule.java new file mode 100644 index 0000000..739bd22 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/utils/UtilsModule.java @@ -0,0 +1,100 @@ +package com.lxmusicmobile.utils; + +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.util.Log; + +import androidx.core.content.FileProvider; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.WritableArray; +import com.facebook.react.bridge.WritableNativeArray; + +import java.io.File; + +public class UtilsModule extends ReactContextBaseJavaModule { + private final ReactApplicationContext reactContext; + + UtilsModule(ReactApplicationContext reactContext) { + super(reactContext); + this.reactContext = reactContext; + } + + @Override + public String getName() { + return "UtilsModule"; + } + + @ReactMethod + public void exitApp() { + // https://github.com/wumke/react-native-exit-app/blob/master/android/src/main/java/com/github/wumke/RNExitApp/RNExitAppModule.java + android.os.Process.killProcess(android.os.Process.myPid()); + } + + @ReactMethod + public void getSupportedAbis(Promise promise) { + // https://github.com/react-native-device-info/react-native-device-info/blob/ff8f672cb08fa39a887567d6e23e2f08778e8340/android/src/main/java/com/learnium/RNDeviceInfo/RNDeviceModule.java#L877 + WritableArray array = new WritableNativeArray(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + for (String abi : Build.SUPPORTED_ABIS) { + array.pushString(abi); + } + } else { + array.pushString(Build.CPU_ABI); + } + promise.resolve(array); + } + + @ReactMethod + public void installApk(String filePath, String fileProviderAuthority, Promise promise) { + // https://github.com/mikehardy/react-native-update-apk/blob/master/android/src/main/java/net/mikehardy/rnupdateapk/RNUpdateAPK.java + File file = new File(filePath); + if (!file.exists()) { + Log.e("Utils", "installApk: file doe snot exist '" + filePath + "'"); + // FIXME this should take a promise and fail it + promise.reject("Utils", "installApk: file doe snot exist '" + filePath + "'"); + return; + } + + if (Build.VERSION.SDK_INT >= 24) { + // API24 and up has a package installer that can handle FileProvider content:// URIs + Uri contentUri; + try { + contentUri = FileProvider.getUriForFile(getReactApplicationContext(), fileProviderAuthority, file); + } catch (Exception e) { + // FIXME should be a Promise.reject really + Log.e("Utils", "installApk exception with authority name '" + fileProviderAuthority + "'", e); + promise.reject("Utils", "installApk exception with authority name '" + fileProviderAuthority + "'"); + return; + // throw e; + } + Intent installApp = new Intent(Intent.ACTION_INSTALL_PACKAGE); + installApp.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + installApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + installApp.setData(contentUri); + installApp.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, reactContext.getApplicationInfo().packageName); + reactContext.startActivity(installApp); + promise.resolve(null); + } else { + // Old APIs do not handle content:// URIs, so use an old file:// style + String cmd = "chmod 777 " + file; + try { + Runtime.getRuntime().exec(cmd); + } catch (Exception e) { + // e.printStackTrace(); + Log.e("Utils", "installApk exception : " + e.getMessage(), e); + promise.reject("Utils", e.getMessage()); + } + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setDataAndType(Uri.parse("file://" + file), "application/vnd.android.package-archive"); + reactContext.startActivity(intent); + promise.resolve(null); + } + } +} + diff --git a/android/app/src/main/java/com/lxmusicmobile/utils/UtilsPackage.java b/android/app/src/main/java/com/lxmusicmobile/utils/UtilsPackage.java new file mode 100644 index 0000000..3241ad2 --- /dev/null +++ b/android/app/src/main/java/com/lxmusicmobile/utils/UtilsPackage.java @@ -0,0 +1,24 @@ +package com.lxmusicmobile.utils; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; +import com.lxmusicmobile.gzip.GzipModule; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class UtilsPackage implements ReactPackage { + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new UtilsModule(reactContext)); + } +} diff --git a/android/app/src/main/res/drawable-hdpi/launch_screen.png b/android/app/src/main/res/drawable-hdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..063dc0a23118c4b03904eb559c2eb8263e4d69a0 GIT binary patch literal 23184 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
vZqVS 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 z�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 UU$6+&Twt(^=C)=G6VK#-02^$%cmMzZ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-land-mdpi/launch_screen.png b/android/app/src/main/res/drawable-land-mdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0c031b2982969e043771281adf4b8844648efef GIT binary patch literal 13902 zcmds8WkXv{uqIGiq)6K06pB+^iWMycXp!RXRwTGP6nBbyaSJZN-KDs@y9AeDH}Adw z;(o}7lbt!UJ1b}QnP)=fe@bFu5Mv-AAz}Ua4pKxy0<0r`*l4d2|0tyPm?9y4Liz#v zrtF%2vhv1NYtD=NOc))vXIq!DxRpk_u7zsY*_i)t)fV*#JavXzcBw&jvDR&|U`u-H z*VT_WZoSl6>r1Z%*{z;(PSR-lRS!^|v6V)+^gEt!zDVD2*DiI>JCc%;sY5(i&z>*V zH;`Fb%1PU9(=Ubhl&Rl^k^#}tfIuLgG%g^0eTSBklA&BGkFA0a2vkr&Wprx|4G9U0 z2FQRw#>lVPfWR1Z!VVA!M5~YV9tceF{r}ZK$J!)#EgLmZlPkF+-yr8s8*E}}A?iUs zlkn3Vg7IC_$)BmjI^N_|LPK+f9!sUozTFrEN>q&bPTdEh?(o6)*bl`X_Q~{;xQTGt zacUEibmI7v)R<k7%a+D{^Fm!A94wynWfK(S65F)@;m6klV@YDQ@GtDuQ3S7?Y#KT;h^0Ic4FJV{a#hY7xr^FW;4vN%Nv7PPAFTA_}@ zNW{Pe;t`_EW1k*+NSu-^7!9Qu$`E~PS#1V+l-|^a#r>86)ylusFL@YQ2Vcz8G&4CQ zmSYs+_oR7!tR9@pj{NLEni4{9^H!e`Gf?cpWkooF^E}IBY!YTW?AG>^Z>?RX?k-8H zW23G^0|?Y0Lz#ydRwWC#->BR_&tKN@nb!KNxoaAi*c4l0mX7yDhlbG8yslKi!oeBl z2_j4Ajx)7-AR~r6+AHV>YVYf1J89JgE1?^P4@ur>9#HxKVAiEI% zonWsqVqtaM5WCd}QeO4bMj!U0j0tg+!%C956Qw6h=$FK{z=?RTr&uG!QlUY0)MCZ7 zNtsjKgH)FcqRftb`3tq(m=Q(Y0=l`nw%>^GTt_WB*_)iWo7>IIKSTn7JHK_t@%_&} ze*Bma+#S5#HeOJGeMS43GK4NdDPg7D9T9n7; zJ2;6Q^iV6AF-6Do#WE)2nxt3hU{jbFxImWn!5EWDiQ;}@!E{G1>QQ6~XkpCo&xe|PL>@b!-@2M5wXwgekYpJo$U0!s| zp5|+P?5Cz&(npFbqX==qg2nYqU=ML!r`3Mi4Z;N(zad2_i1jts!ofaCko)+QEx=nV ziTR6?lF4!ZJ&Wk)dBT^N&;fhG z4&}*ljOQz`@GL{&0<$bgwF{{rmM0~7au?g@rl)oC{l{HlUZ4gtO7c)&==b)=lk;XM zW!dDyeoV-57(m9vgaJ4gR@>%zn8fjwtJBAmk^>7NI=L#Jgb>XfhzXr~#PJQ0=|n21 z4!q85x4qb_1~;_a=+IJv^^ue`#7wSke+tvA@jbmN$qOwiLYzjF7iVYQ_j{*rjP2dS zlKex$`~Wgvj9{)wo*UC+G=$M-vA7dCMo8}uNYi*3^#lfSX>)q}k!U&gqp;ZnLd_=F zeM1#R(0uZbyhCOBUEM;=6xe)2Cq-PY=9fX*#6q-Y&s zRzp8*(unGfTS`b#7UGdlgz-+<_)k(;2u2V>+FzZL4>_{{+wFMDVRegvYiaE^9#K)TbY#S&Ee>8*Z_TSN1U zILr7q5M~z=ZEEo9er3xS=k%ngkljecP~~oMPB!wXa@-JO9C_d8rva1&UG^f;YWmVi z;GACoCt48p@z)!xa%1(`@qr^KD9L63i9*`#d5|zG1#o9%P+G!05<7ER#T^Qh`61AF zV@C~)3qAOJLZ#(db3!CcQzFQ$`jv*V8t|HJq`JFCqWq$C&{ZKP)Zv=|_s5utyMP-z z(;gjP8#kKbQaZvB(h|J)<%*xJI5CH8i2#PMRt}B}qFrbmrJV&EoCoE(NFS z&zn&J|E{5+Y(^}gQ3eKvT1gWV_@W?QpOTW&A{BnP`5KCk2~=BtrC4zNYC5@v^dwd- zM^F>IFj~ohkCGg6fmn=wqP$xQDk=#AOvr@aBKo(tjXC}-rE}TmI@B!hFEO<$=n{6+?&A*3%*-sJjEhD| z3$mv)>FU1YwyYg^$V5rNcczAI z;%H`y8E;3v)^E%=kfPrX_FUzqhrAu2OI*>uy1X-3i>v0DW=@(ZjV*iLsh(WYymIi} z+TdJ-Hb4yG8W?p7(#6=>eFxvkFYlbY_MA9_%QkFzOHr#zx+r)aMyLGlBs-I~LH|xs2vd|#)TUmk~A7x!$m>>684o)Q#c#h(X`V1f?HT~$S2 z+zC`8xPkn0X_fh0m!4PJPa}xaV_pWQcTeuQw1}b<*_oc3#lK3Q!&vORh%_u+_MYEs zVk2jb`je-JVXpny`f1McD^LMlJ}U>4-~`1%*xRA=?=PiC8&1l@QSiuccWl)TBwFcj zxKsh`x)Hb%;e?u`fX3WY3%5_TdSuw-)yo#zqZkfqPU3gor@b$;Lc$!2j6SVTPn*S% zzt`!Z>dI~K$(6wh7~gqmIyTO*o~4h?x6zG?zxO}CMddyo-?Xz1*wwvJ9Y&#gs2v0L zz;RUp=w@yJ(RZtp_U5`3H9jrUy6Au7YpU4!IQa@t7d@{ef-W%h@qURliHZa~{kE;R zV<<66X;xq<(@Cp((D5lJX+6383bWiR82y|Co>HN0jzD-n7Pn_VQG)P||2L~rLQI|I z<0YmN2=Pv{(U=BAvk5Y3aCqe7H8vKT3HvBS^Ky3OvKMg1iY-h-Cx%kvZ6iG;)d)LN zTHIS@sJCh^m?3u;#4Cza@h-M&h%3|gd<-{oF%eh|Y|D4c?5+s98L|=8x#WA&s92ES z89TZqBVS|{-uGd7dhaK>vnN(DKwhgymGf#j>v% zkNKKSgBYW(k_}C>+qL7hTG}k}^X|UVB1f|7dRZy=HB(!|7S#oToVSt$?U)V~UYCny zv(6$o6`OUYcbqbD+wr-_?v8;bh;<<-oLi4>fbS3XHImhU<8Uxuf z&(t@pr5-#Q0P0)TiHQ*6lOQCDy<*27UJ32=fd&l+clE2mJJR4)PE$)fX6x3Q!=RR^ zNTip4gC2WMx*t`blZTKA&6P+Mz{zfR>A5K<;wz6Y&mQT=TpOgoys}X`C3;6f6|I#c z)iis+etiwB)?0B4ew?}#p6pWlC3@FfAw-|qu>J93!L&W;vT9uFc~V+@qkyq)u&t1mOHwOCEt-^%L9-diWde1~P)-6i~vbk8~ux8Pp$NQaW6!DH6u z>3%ZJB%vOZZhswnjlJE7icq^9LDQ%q z5m(Ry@ya~PhJu?_t(sp|=(Zc7!6RSp6VAX*;`QQ)za0}lUd7h+-gst`LGs>6)!^+Z|qA`C1Wa|9w3+dynVj5CC7twv85Whgi!a5B-aY1)OPME$`NO$jM~ zX1cNb+GZjW?O6a!LFMwV#>%kv=ulpjaely{_=G!3FQtep57ELO1E|QqqGxcoc}UPe zfltKv4~|V>e2F?a#B5)kZ79<>*crU+1C%{^GSu3YRim=4f`yD08Ynujeo%Xt?@9Tz zzA@Tb#F|1x_%y~8m0 zz=g((96sTP!A?n2uSi@_!->~>x3~avptnjBcHjW6Hq-y~$hsYG%tj-(sn3`R_}iw;8{~ zx246}8Q@oWGk@`?ST-`6eF_5S%az(=gqyE)YQhR|?Jcwkn16bfe`XraXbW0D||1b<3Jv;qw>7v!i z30ydpNSZs^^Xqu95>pit`m0?Ft2Ghdn$c9bB@fIK~`JK z(LDsmip(4(Z2E5~lyPVYzS(H0tJA?WiO}0a&aR(#keyjxhBK+mz7cC390M8`HyJ76 zkrm(9^mWmbZe4;`b$neu)$EFpoM2v4x7YOE!XIItP0&_U`l3m-tl@u#pDt6PEqM^W z7c8YI>+`R;DNQJ((`7t-T)!rBKqed(I;8kF4)I#s|LNAh3$D%77r0AwQZviM`57@N zJ_6niC?|ttvpc7c8ItZhtM?%v-Lk?vIX6pQNGpB>{Jn{a)=` zsCGu(mS;iBY+@?9zd+o^^@O*OX_H6uyGV5=`c6;nSr-kF;!X?%2$>C-rhh|oD=tbC z^a5`1cdYI|T5B8(3aK^`j!!<_rbZ9XxvcS*fC;t=Wmh$=v4J zsStO}SFhNdmAa<$h6NdSvd;i1OkL_{_s=GZ*^we?C`OgZ&R4l!&A&#<#1&@Re!stv zA6rgL&fzxd@LYqD&vP-}U48Q$J{)$?#lxKXyV`P!!S|l*XIouWK6d0^&6Ac1hQ6b$ z{D?F0@TUqE@A_HMK9~`M%GV-yZfoMR$^D~^ut?NXcBY6JZ126$b%m2EZ!@`72fqoE zrtwo-sO#$}C{3m31dnk?(@a>^Qp-{$z5@mRJ9d_;&^b1vzqJW$zQxotwPt&l8BL8*{xB}!}#`3v)x zr%_3FO{c4WKFAhH^ny?xme_OYXVmsf8;F>%n?Fk-?h-@I_jHAG7$g=aFWf( zpsOsv@u1Yb?o)Ru=Uit{3#WD~eeXd1JF(1SJcyplJnv1j>0{n8G2fp@|LCpl=HJ3i z-V-}zv-!^}btScPB5HhHC|h0da`Pu_@%dWHoXo4T>-l4yzanZ*Z0WDx(pI31MDb>J|l*V}Kv^ z(7-}R6kinX0{-+W#z8zZ1GT@x*(9W|Q*X-n2#gI_H)Z-q@kX7Drou{x^@)jG#9~u6 zOGetT4@#|NoPR?^;#0=Sq5^BrdK{kRVCCB|Lz6;Jt$g0Z#Sfd3Ph(??9`owVrBTsm zGd9!;MYy9q4Hk0@VvL$=#J#f8U-zq7gOo4Br2#0(QelhZ5m5mvYYd8^` z^aIoA??kqy>^WsFR!t;UyO}`=yx)@)X{j7P z4PhUiwb|p@SuT68e$>Tz&MuOzE{T3gIdGYM@4QY~ME}Lw1_NoP)^P&PQ_#)jZ#yHe zdX_NA>H<6{LbB_QncHeSn9Z87&HkdzEtm~iTA1ar=XY+6_pf7biJf|~rqyee%@pTU z(fmfjU91W&8B;~2X4{(VwYsxNCldR`{p@&l-{S300ad*HihG+YT(HtLW5W}NU+`I) z-7DfbeeV}Ho;>Ye@5+8DvmfrKFm<3AW++9CxZYLn_!st@QF7Sw>3emTTNKf>RifMzO+Mcz3-Q2+Dp8mRLjU95u9b` z%fdBfS$=lL&7x|hcFYE^CM&b^!^^<|8Eq;d_q~l#FG75t`l^`tLi0^j6*(0D1fLte z58*y%-0Vq!6V_FY{@ZD4m#@el zd=Ge5d7@r6?~}1jmNCw&Y3^COq8n>+N;sa!rlP?slW+?oC^$Nm*uPQ=%GPfs>%de0 z9d!lb`ccqvc+`|VTA5;*Kw2>H`!8$S=iNKG-Sp=3U!UGvQu;Mc!B?`bjCSb_8GA_e zQ;4Vv7yffxB}d}q{u$mE-wZtL#x{fS9hL=~%v)NkV-+W!ToNK?ql)bLgA&%2vJ<~N z9K+gJg-*+5>X*J9f;}f}w28Rf!o7&60){5VisoimrNC;l%g^g;R4eeMyH$!tvRM0V z*}r4cl7i z@-1W-l85QK!#W(bl)_FE{M!g1AnJxoGuy0{a^MiVrH!Cs5%n`ksZ9RtuhAKYpp3{} zOcJSm7pI|qn3Hay(^3J%a}>V?E$_BYCuZ(Y2CcJQ?_TR7@-*03fNVxr?^gk6r-nY5 zO!RKdw66Z2>9TTJ-cCtrqRDBWhC_xO>6XCuu!ZW#SIMpGZ$~cKOMp$TNU#XwPUV6q zH{t{EgTc2IFYt)LS>@}_Yyl>-M`I=7>sbSda3$fuy>NaZ4%3}t$8oslTx!V$wjSDO zuDu41&T3}E{)wB_D}#Vj#Sbh7;R2R_GKc#vlY?shaAg6zGIj4~HP*TbExEOj57ZQf zuW6AOK?X_>mfs@r`M77*aA)^ZB{6wtxJ2(Zzp^Mdo%Nm%dl5+)AjJXuWTgSf>KKpS zkU}t5dd~-;!P5-6#l;h+j9Jxxg#ksscq{pbn zS-c6l;d$axwL?)3taDbLYOp;GCyJtfbO(b^XQuK?DPz9t#|z7!5_BixQaXvbFMhghp8F!jS=|s2H!UZ)aFciv_tCChl zXT5akKWJp1y#=TjZ9-(^*Yj1YEJ`uV_*qh}SDEPt@NJ2}_IEq9Yrm|v{CtH!S%BKcZE+CG7n5FH4rO)+E7-wqhKS+v=l zf|7yywJlMnIxMqp<41N^hcaby^^3WdT-Y`6kumVdMwQ5myrd?RB6(wE?TygjS z5MV|p3LRTHWFbhJD~$<9DZz062?DvlU4K_UxWuBir`{P}`Er$ZhZ%0=nRPOh)9OOWAcxQn;wZVTwH`abqI85UUt)&J zq|_LpbDQ^XK}O5$`%&vd`x`4UtX|o|roUs4r61*<%vBzxgy4TfaRrQXEs{h3L7;@0lM6qcfYI1(g=&0NhPg1|^m^P9M%b0)hE`NTXsdj^CpK6xUS|2Q^ENJ&oO#sqIs z?jP~U-$|N0V+P2`W~4o&*fk;*lVm-ASRUj?fP5X@&_@&3(>RWV;?IW>h-NRq}B`Z`7|!;|LpFcvx5m9HN!VL)<54P+zv&3 zzRcI`SaEyBX6=2t-|~|bRkJBJgr4NJEr!m-H#f(-ECEhu5ay7fNb&f_nfVFeGz@~; zdWior8BxL`Dst|#8UOG`FUFtmc&Blm5>vYqeP!|BQ&tqt&Cu$``-1i{nVj?FeCrR}bcu&xYVpaM2w$2{=~T zdq2tlG5StCMPTe}qqvs16t}cq$D*cF04E;foscpSFgPM%rirbQ)vINOWqz{^66rN$ z=M(ztw&hsD%RNbl{^PrNR2s#4YiG>hG)eXmlo#dVO~%}grzK@G2{G}ziaADWmjg>d z3sV!Kj+lew<&}5x@JS>jeDwdg055)z7W*nE(H@^KR0^Jj=eM^T-P(+*?#pmhEcb)3 z`*Su+hE8x^Bi|wN6%ocnFX9t3bV+Of?%QZy1Kz)VonK!5(*nH5(i%oGE*6Y!4wznE zX8J91AMtQ|b2EehjOwoUAu1(#5DNn*+FDx^f)0B7rkdM14qTG@j)f1IsX6b%MtmZT z8O4xb8OMXJLD8y|>ZXsq~ z9G#p6xmVkCtCU2;V6RW`a1tvky#1A~i{sVxJq+I3X7`MyzZ~G`CkKGyRz9>tF=)+?L+(~m;6?Hg@gyE5X`Gg%{U`R{Kof8z+v}#3;Aj0*&#%Nz`E7<{FHr@O(0-9&pYtIF*v&fLa&Spmm@7r`SG zDd>$YXV53H5;<}Ue}DhQu`@5PaBijbQg!xvQ8Iut{OX`qIFmJfNz{)FmYbhXL)7KE zW@U9?3d-|S<;0U5d}HflDbwb7A;kBdq^4tG+)#9Gt<4PX*EIZ8vZG^Vv)=v<{ToA8)kkm! z-hX+{8Q|dJQeUc3)0g@JNGOWMTBphux-Tq$AZW=#UGTq=WM!wRkj4JTw`NlQ`hIJN zCp2zY1|Lrpomnv;Ob7{=<>cf9wM0ZB+4Tk~Zmiit6aqa51Ug8&Xs4LVZrvTu zyXr9vWLH-!@^eQeK|FZW;D;vKB(-LdS8LskM_SGM7kzwGS5uKxQeu=>+KYPQ86Mv?Shz2HZ&YH#~jnx}9QNqvZN2*Ql41BlbOeC&W(OOAUfiBZk(vE8XN?2MFwK8=vSF=SriDjls$7^M7t}w8|!pjtVoud+U^ru*q zUnj7d%$nm05K(R|FdgalujP%CkXd8NZJsVUOwX%g{Dn4N=LhQ9cSr5EWiR1=&*6yF zC4ubbgGKojTA$kE*XR5i%7*x_Vud_`hGu-5ID#17SIV7nLh@&=8yg1a4^QU(Vk*D! zL|^qQ2dY_|mVd=YmWBGN#3(iOevPo@%`S z8P42J@AX+&wK@u-!Ben#>%QU(sg)T!Me*v*q_P%@|0vBdM&{+li>q)FruIMY8l9m! zQUbKB&QLz&df8{2rYtXdSMlyuC9yH5w~^pyQn_9;E7pFB-1a`aZ7V zxM#-Z#x=rx#qv>f#w-6VeDayKZ@uY<=J;KY{+f_m`G$#45hi?QHb{XqPJFVz|GiFV zCYh#7l3cy<1Dlhxv&FY?)k=#4h$z)73Q;}1!BWj6vnt9fd6|TAywZZJ^<6;tuObr6 zfJSd1j-cbyCYP;lqq1fRI4_gTgmiBN)th{;h}Bie=oCY<{Z7lAw6O2;OlSdB$CC!w zF@{5$C@C7uWJ_!O`dSjN>|J#5R;#L_o?b;@NE;@>N;ewY3?8Il^^@n7vb?btA#xdr zR5~(k(-qCcONF)TO@II8IHjaMIM72-aB&aqpG=wMmLv5Hb7>|^z*aF5NSZGxpZ=Or zZKK_2`K>;w)<^zKd1alW!>?PpZT!S@NOM|FCnYp==TPGQ*)_t6%^EMHOf2ld+u+Qa zj+8$d2;RU=e_-i1XcMjs8o-P3r_)?cI3Ba$qYU(pZMK9kyr_C&EK}U~(-#%o;$He` zWg1cv00g5~8O-Alekyt~B}KC-LL${= z(h+k?{g#%N)4BwhQbj{1wZ|Wz0{IxrAXwh_QV;wY%_{jG;W}|=XEv}?TSu}3$ zig9TBw3y;G9X1sgt7@Z{G+2^!>}$HY?KiaG@}+dwgchlD$W|yQ`6|1V>?7mrOj%@O zez2gpnzm3)+1IjytJY!=km8_9zzu1kcc5}+6)(2p#MT^~pU}g2%^s>Lr*RiSqi?vm zjt*feTzuBtip);MHj#yXM^Q%sBuFz>kw+0ZJlfzWRDx(L6kbB&BoDu4W?NcNUf~)p zz-QZpHgEi}i`?^3d+o4?u$%!~lm~*LFr$(liGlSfgp6xcaimlaEd1O6HAKo*@HMaI$^%yD=2tc)7*}P*Wz?uDw2MeXfEu zFp`lr(aH$gXJwvT)G|>G=*0&vQ?=?>`F^wZLi``{!6^*M_W7b;RO%}r0jl6HBzjuR zk>*UAN>{z6Xo@O%A-*&1E-43aRi(P|Engqb(;#Jmy0_~S>&XIyi#ESGDJZF)kV(-n zXDFqiSwX3EmfF~gkw%Bj@toi48M?&qGzb4#e@ElT6LRNeePzOe*S_DTI@5EoJ3k}? zJ+93FfI{)po@fiNmKYc%fEo z9Dei(GT{qAkU*&XW~Z|CTXk zcRj`onk%is6k2iE<@|_7QHBqgs4$5<5}h?FLF)6v%(hi0!z8cjSiqeSr68@$`5>xZ zrpIL7l<$yDo~EMcRS{2A=pEyKC-EV3KkWg0ne4Uc*9ZEOk@pRP7hL4rB znnp>fRpp3DxYeG|@=ngn;rA^WMqq8#u)Er>D#wnEm)LV!>w6$xY(9!Q)R*oZ`_!08 zm7{pDBEC{_8qTq$Pu%( znz2b%*?_64rohi6&tDG@`GZPYr%8SxOdXSh1sL%V2B~_~x6yB5NrOGp=`bqaDw1~% zA6f2eM(Q~O_6E0X2iICRP>$VcDTgb?rzX{6-2RrXAZVlaJL`;}*TiLIW$jI=qia$r z1aQ#SUY>$(hlBb|>i7}3fli$n;0?n{LFTaG!+nSKK^kewB}2n&C=~j3!%cCcx!Ams zc`P$TDhc5fJc=3qmj5KvqWXjc@6v8wz2{^V*XKb^uzw0%K-Z(_{aC^*qG=))dWEfi8HsR{3b$3w; z`Xop`Z-n8ndxj27S|TE;HGI>KtIN-crhQREK34+i4ro3XElVb1%xccDDQ8a)C*<)n z*C+VAB$PQ<2>Ht81^vUu4_ZPL#}LOMavN{yh2YBB3ll{5WYydB)B?}KAQDq!`SbSZ z23&Ft%VO$*Foqyj;6eam!=e5oR;xMKGYqn%h;ZxLA?tdpM_ElZ{HF5oS6RiCR9a2n z)g?QM=-ryT^PqC-;l4e#!GEd=R+=4^gV3I72ln@~;m>oY!Gv93|5N4EiU5?@tzVW5 zHxHQI-u(zVd;6b!1~ctkllI=M->Kv5kCI%0=4`wmHiU*yfwO1GhBSz#n;TFH3u;@eQDw;Qn!cpxIIWh6xi*@5p&b&4SOR5rgcq&?gJTu9 zR-5XTKZPhFj&7J zYaew^J9ckf-QMGGJ<9Lg7`c12k7Eu%`R%*&zwJ96&VYz2eY~!6jNq1TpO}L^V=lA} zp960Z+QP!!^pyX5%TAXwfQi$n6U|V4&mxAW;Y2}RS;nKkd7Dw^c8MVXaoj2Yv?S_a z5Q$%U)XJX$4%~oE_Cy-yxc}Fs_C~`J@+ucQmy zzMXrQG)YB0v{*27Z9_Pph5~H6GN2&$^Vq**++TO^6dJ3YkV=ZV?$ER#OFOD-_)}xU zQrdVw@8d?(@>UO|Jyd@M+U7O~AqH$RJd5b6ga7qbr_EJ)T!{c!R*6RuU z?@eagi@kv_m+`ojK#tf%3JcXR3%N~;MIc#0J5?Z$fq4iMbu z?ns-&;j}q|t7Y7_%(Zh0^Ya;ks|FCrS@9jhlv3QZV#59(?=+t@?E?)XxLXQwmwC~*;7{(&VNhkSOrl!!4CYK!Y8n`we>C(6sz~b;3-0e zcEWR=9yX|>Ktm30mKd$jx{H$R)R)hhaOl;V3JvhQJoCS>e93krmkYG1sThrr76Td6 zbjD)pqXmj`u(QWJ!t)0{H-aDY!$`eTvb(!{DN@ZC- zN`XLo&!vfuNZr%Z@d!fM;MLX9%GiGFv-v(Ax-4QF*Fc<2%UUX)?H9%?OX&f@)?QZ( z2!CppLVa8(!FQ4qt=GjZV>0=HyM{=!@uQq4MzEyRS#dN$wD2 zw_X@-=TUP!*Inxmj*xh!Z3p$0ZQd5>=^L@HOS~4hcHOtJ_z=L%P^1uZ>S%8+Pnq*& zh{_kwF*`>}bItDvK{w8fh9%4yKK;tnRZZ4)EcOUoR(AO7IL)0#W_#|c?LluA$mtjw zVy~!+SSZZA%0CcUKm?90zwb*5)yJiBWp!qa1ACDeYh=;zts%k?%aTWA_0D-VKVJOs z5xDo*bcg`odFp?R;z5wW6a~HxA}|4;>uzY!jI4e|FnpO11bhap9g+?VWWqr4zE4rq zhShY7RIHNCI|JJqDJ+xU+3_dmwOc`TDy#|D<*MgRV`XPM>OB~y2)(bbEB)}|~bb?|=!^ zuPcFF1Y6y%gj&5)yzHM54CcjLVY2vaS9OU(x>`XOcIao8niBsB$hETSkE||cF6{a* ze2A&hTjMEWeNg z2m&3saQqlBqH5ia0D;6o5AW)j`leAPPkgoV@mpZz?*xw4yCu%vn-VOIfnCr&Zgk;V z=k3#u9N|5wwX-K3Z^S3f&h=it7$17{%JT=!4{xxQ|0zvwwfh)qcVWhGto$mm9FD=7 zxh>b>P&NCS4di+%inwDoT0gnEkf!#e{Wwt6~e~)@%c9Be*j1R zKLCp#cmF>h{-4XkU0XKb41sk^2PBFSoQdU^YlfPmp}M@g5L@UHoJ{=W5LQ!vC4 zR8W}BkPow3R5yO#gr7a4B0u{-8YID?pvjrivGiG^DoY8 z+u3`k^S@WQNvqw5>Q=#At^Ndv0CR3Dqmiqn zy)l~D>NmMC*Tpi!7}=s6Y-AEkVLt1Dj%`q0x(qOx6FG3N<$&Kt-j1+n{-`SD;!2ny z%Ee$t|IT#)@cReQ$=P@K^`NptC;I%fmSde;;ZiXa1B*eqK!@~+_@9G&m_l5}&Jh4u z<~-ZE4ke!Q{a=M{JX{Nbh$gf!p)?jr%vAc0T-_ft~O zhrrp{cgm;4Wa*p8P)n|sKC~YO=4J)!RWgkPl=(6Cc;oG2sRL#lzpW=$5qTHMQ372o zPw$1ol3Wd;=$hiN9XEV*j<>B!lI*|Fw1SUd$5!SsMhUwciQ8CQea_KXmVI$7+iFG>HlTX<6R@(v*#i`G^s*flaR#_|w|YxV&D3HV<0jwEF!U+nL} z+yg*Ls7{lw%`qh>R$8nv7 zyeMxW09nUr0NJm4W)7_^)Xj5+>qkxTNU_tT%P1CBW{^6n%Escv17O7mqqDO=0`pd{ zBmRYd^fW)(tF#UGCcmmFhDBTdF8{1!$$}FA;Myl9(s)kt5h9M&yO! z$HL&cbY;havjF(?J&tn^e)sfzjERjU=<;(?i17-Z1bvGH@OZ8qnUY7N!gYzt&_bsV z`_jPvKWJEHh2FIK>E86p(UGd4py90dmyw3MksbQXIo|A?8R{l9902<_`s{0Q0j_%7 zL(+uQLea;bUP%|y?!yH$^X&qF?c+A2vdQrmh4oQ~M*+FLdm@t=a^}~I>kFxQ^NubW z*L$U9O)M1;dd8kCDBrm8Hy|F*bmqAxlZ0%l z@>zk0JC2xp#+(9V>22w;a~82jN})1MG`)nC>DgxsG`^8T*OJw-Kkxs@#mMFavCcyV zu;douDxm(ctNF73=ABlgP5u!~C(gGCz#T^&X!|sSqEO^DK<>uBa|l_qO;2Z4@LFWV zrkD1|Xtqd4OY!s#TK-XiTfY((!sP_10T{b@!L6WPg|bu`haif}Cws}a zf>{vn{|9k}7L)1aO3-?!v)e|4nK^*d3;@ReYwyAR=_uQ|@mr$gss;_l2S(MU9rc7i z<9kOJ_yG=nINk{Qlb+(}+D9^oQ&q&>40h6yUncUcszheM47> zIMEC&*b2l6AxDIh(=Q)qfw01fs9(bG8x#XVlvv;W?gQWdH95tkRJT(ORs9=SCb?I* zWfb_f0oX5)#NUIS0><{z>KI@GerJfS&N%?w=m2ao=aB2 zFl+WWu!jC{XygzLq1Rv+987xxEdSR55JZ;Vg7m-P*$;_fNt6cBJwf{ZwCBk#)+d(# z?z(;TpQ`@M;K88P#RY0uq)F{d0O5H+9B-djRrhSt^54**lkyv2?CaNUfRhcmIqXpm z$~w@{^dF|hq*o%$C+*x;aLvxhpBX1WpwbIk*V%3-rzB@$`nMSa%<0`Es;^5((mx=O z-FYCMlJewgIAn|^Q9KtiOOtNv15(~$SQL>11R@l_G}TalFI83_&$=s1g$ zT!Si#FT}K%0yT#R{L1Ru?FQU{j_a_#$~X`VgmzIHs-Y|Go;~>4&4hHt&x0927C;mh{rFugy5vK_U8p z*96^qSH|4m^0}&|-QEd63Pb~BxoceaA7jq`8g&VfZ#w~;zd$4~YT@OJ?AHqTi&8$5 zIsF4TjwoGVzSV5cfBRJ+E-gJb0!S^80!VE<-BQ6%`@?TrcFANxRTU8C7pzD&6d;?L zBPn+ID6o7KKq%;aihj?jx4=ePfnx`K@z7oCj(5EE1ej3t4=|zo>2ap-sxJJiK41c* z>;cTT^1ofj z+knqL3mi*GQ2_HGo_64?API=nR}Fxr;(6gFsX2BxN^{`qkP6!L|| z+1cT+@e}lj`u1Cez?NoNTT zupb&)mu3a5e}lDt?Qhe?p`n&EJ7D1Se*?*>#$(!P_TqrclH&PqPTftvHo!>DUIq^4 z`z2ui8!Oxl<8h6Az_*?O;vmo`A4&UnwAsbyMmK>;GQj4u#OsFvn|K8)v~L$v z&zI%5$9j|l=lPpOFURJ<^k$k1u+Aiv1Ujy z)0J6=VaG!ML_McP0#8&}ScNi9%@-^R|TU$y>m7R*pKm8^(BaS$G@X_${t2A3l{(VMe z%;gu#TH3H2PZQZ|~R3Y1X6I1Rp>VJJgR{3rRy_WuQo8MP3T->ni+JP@nwe zD==Tz!EpX~<(n!_3{QLITPn}lJ!g!v?$4>+9APOmhy&28$6niDB`h+px0>U;!LK4W z*PgziAgig;V+JL3Yx($%4Zv*kp@gzQ}@>qY2Vg3wuoiOUR zDK)7Oq}&bY@OO+z$8 zrte%tNVY-~VTMV!*sITc;OkARN^;z%SOhfg3F-HbFZ~0Y?*F**xVKjh{~KRMIq~!q zoV`3~q?eIGN9~vuOc#Y(2}5hri0QpGY3Nj&WK}nXp0qOdA;)y>oSSLM=jRhxBmi9c zgh3)@P=$qWR@xX!=T*-111OKpjE|4EYA?u&tC)?9C-9KdiB^zi-rg-@{gMgoV9Tl5 z{d0Qq6+kya4gd|2x}|b0BFsVMLQVDNuUD>x!5)Su{ZlCEZsm@wzF;{YNcg>0XrYWNCYWypf zI52V4E%r$DHTCn63xL�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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-land-xxxhdpi/launch_screen.png b/android/app/src/main/res/drawable-land-xxxhdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..b28cefa7808ad032f0924006ea8986d5755edd17 GIT binary patch literal 64037 zcmeFYg;!K<)Hggd(xP;$fPjS3jiP``C@tOH-5~-Jf`Wi_gEUACIW$OjcX!uN!*|Yj zfA4zUzu|pY%eCh0bH%=P{`S6(As^(W@o^||AP@-tTbb925D1nZ1cEMrjR{aTN17!e z5PHbl*Dsabl6L3Zqm$LV7msug3S7FP$hu;WV5PslW4t2Qqfd_-?G;x#!C5DfWsJVZ z-S*amA@7MKF{``@G4`iP>Trfhx8^XbLk>gDswakfbBdNb-gVc>9<;pIpftHp;)B!}Jief4`o*f`B{%e==Vnc>jKV z$3`Ll_ly2MD%ZbX5|7aJ{{8ZMjotL`7bJwp@4p3!8UA-cKq&t!L!@Q=uh}5Q@V}n& zFHZb#a6ro8|Lx%LRXzYcO+{s=Qb3h5@^Rphz^8=J=(Rj@_JKC1N}`dN%U=aC$G+=U z-g|RHbMq9ILe~b)(z=B^)L-A%s&&ThSC(aa%4v<4a|q4cc#$9l%9dHAQ!=q93Mooc zFKAO(mogZbEt?c}eMUegFTEz`@0u<&J$*t{Uui0-HB>HEys1s6={ernQLF;%KrW!} z0Hn9Ki6t@1@p))RH>c@t#x4TgXWOAS_T|y7pNQtC>kzs60@uz1L7NAg=NQ=Ftfq|n zekd}-`%{@^h6c8~Nn+IoLl<6!2b8@E*c%0|l3HVREPSpd5mjaEn3X}c4_{P1P|}o!Rs%;CWX4OScD75X`hKmGVR3GmTkq z3)3VH1!lp)-Kmzii^4EAPyUV=QL2*(>jtW0^?y0r6v)XumD=T!M`I5ZI?9&adhlP= zJ-Le7=N13f;!ZwKG;__@t|x7a=H-Gsc_BIqxnB;CPW(4t0Ys~t&((JnSXWN*n7#8t z&g6U@OYwf)lgL(i93)Dpzyt@Mz*h^720Bx}UTSn5_DgD3v>S_Bu58c0KYq|MwKG1y z8{a~Me^-N?VW$tEg#;;5uR9wfX%S)Pra{u*vR1;jyyKt#>_1Y@`>R>&_-X<9j5G=sZ_N-}3SURxl%s+(vfcp# zS~4EEyxlP*d{d_SywJF+%u+>b1S(j(w~&-dJU?E}0BB#+f)E@INeF@9Nl1F?S*hKe zgfQdfy>x;)cZ_)_9zRVgL9mzQXF|uI7~sG(eNd8xwy7Q*`(h0vew4H8fDA<$ldzWh z?A-@E28fYxNu2?(9Q>_B=F|vJDP684rqP-C7_6m>Q*GjjbK4Nh>#9{cq$KpV?g8s1 z9VGdP?F*e1Hb2Q=pI+{s|7Nd!7h4VUeXlj)YF@a%Yk6jkL{jR+;JRx|M{`FpE0I+1 zmO1uxu04ogJi1hMs+Cutp2=w%;2Wq-?mNJc%Dd|$9jlV?aVq{ z6RWC&9Zjvx^NLT}RI?5rDPxV#5WJ?)%j3U>N1JW5XnJqYDqPod1IpPlZE33?iL)cm z@tqaqvdk9o`X*A+HQ4smGpKVi+GW>bB38*?T{Y*^1f*QQ;{n5r^%*PQ zw4KA=FOU1PEjI+rEN{c!XNcZCMY8D#vgtA)M;G2m?bFmTVuvZ@acr5fAY9EG*sT5jg#_JetXeKESsAfq4E3g+rqG&TWaO8I0(Zq7Z z3gL`Xg1n26Kv?qu-7G1Tz~`$83hNi~#yTOr7 zp#VZxC*|hmKFU^#?Cfv3PbEL>F)h3T9=fWz05E@T8l(%BY612TtCgo5`XD-Y<$TC9 zL$PGaPD9GGqTTs6uEV;ZxO*a}SS1Ll^Jgpo1B@yKV+IBWk5ZCm=oXTE=1oS1i#I>r zN#VirU6m>-uYy1ZAYt+lOue_pYT{%#fz^h~Ws_=R#^p=SJ9U^Vk_AnMHH*NUf5+0T%Bv zI^qv&62_HYE*Ke@HWMI3qY*tqG_#$IH1iYc+@G^fu0ozrz!uQM`waDG9jB*Gi19m~ zGufMJ0i(<%RM4)T!#C6#ndil;*@b3=tQbJn45kh)<8Z7KLdP{s<@mvx?r4A=q63x$Lh%i7$}$1 zE?9{h*Lpyw<7lll-7tO*`n5zDXc9bA(4Rv?L#gg{11Sibhug-9cx;)KyFG2?;N^Gv}io%aW6NJ#c+92YDdgJPmC(kX2B) z>(#t9^YNYKJ^73u#N^<-zzB>i4%5~0mcw&8C8q%=@K69Y_2x(W!ZXy=J^va}`@3Bm zDm*zbAK7SDii%a82UUYn?=@07(RLU-kg(;x32{>s%QuO*a`}oS?c7S&CzU{Y@p9Tb zI~wAh=nN`;`4~(Wewgd%To7E zN_@qRULy(@BTE{d1AyeY2Ph476i|G6nVFgP#kS14DIPC$IB3h82S3|TR6i1f?dQOo z7Gs8%J~e}bORbUsLwpISMsS65a9SsYrhj6(9|7mLwCznLsfSsX{+BgllO6!ZE#q=~ z($>}{xB#%f7+z%-HlwOdk*eWqIXmea?~N1yBT@j0MXJ{HhsE0;Ba=shkDcEPT){`L zG?!ZoO1|y8+&Mo4_a==7m;8HkDNI(mc_ zq?Fz#0=rrr$St$NR|a0br;HPlpgNl#0a#7_yGD@-nm>m7$=P74j<2PcQC}q(Aq_!} z7ExTtfg$~H_C z3mE4I1$!lfhkxjJrv$yZbPu*>s8c`P&BJTPW-{5Q@sJU=AJ_*nsC+(<`jwN`n~OuR zQpm@!6>Ir1VBP&yE|TcLLTPJ(rhqO#C@Cp@WR2;+n zdXlGA($Tt7XV}>`509zjZ?nZgno|V?=qveU0X2Y|k(a9o6FR7(K~x}mK{P%SfeAo@ z4eThHv6u#fR?Fh!xPoP1ZQ96*#C%a;(`qp457AA)Q5>*#3LFkN0zY59_&7FleI7w@ z{aDpvwH5y|Z6INcogI7|DD>4mb#;PXRRQZm2D7H|2_TS1p_T8vE>2I5G_M;;7wEj7 zzdH-n2F)RD3p{{bY`g^n%;z`{&UxKPE6jAhuJ#5Q9m+xW7O6YB%Z~tDbTozL+Tl2Y zm0=SNu5E@2C;$RE(97bv?<;ttXLT_5@Xr2(v*X)s+!O~mf-)AcX^0&y0jYfZ2H~Bh zmp&XJpp#Hx48G)f!VE5sdgFHWp`OR_iCE44I{bo4oE*q!RiIJ$1uX&51EQ5?(Lf5y zeqs8qvf9^5O?jJF6Rb=mB$3=b>QfB^tAMrxTDS>No)}Sq2UE8PtQYcZFl5;1rv32t zsFBc@KjNX3H8b!I!UmKZ5WhEnTy36+xgKhQ&~qafnYHw4?ll2%;49#&!JV$1wg-0} zB0^=%ccS35XJlZXFt$myl1P`<{TX6$aL&HeuA3ATRp~QOt?I9^))hJq=<3-J^Ob|h zIcUf^>Mr+AAD8IjCTkP!X(01PY$(`%?0Hg0dd1dB7r7t~-xE+IuiQgU5<*V;bS}HN z0Ki!IdRK0ya>=9*_>S}&IFBuj^sL(SG!VY)FKl?R`|&aOO7A16%+k;Du{q0;5nh~# z^U2Ihk|FR_DG?|R9=}dz-ERw1ci-GBEK=>k7j{D+-)2N3W3OiIPt)Pi>7FZ2?$hev zyJ|h;q+i>7r+Niy{QhsnUJ(*5{orB2yt^IFFM?e$E$%?5I0TaMj^XXO;hHJxw+?5 z6d-xy3E%({58{hRS4tuf^!ox=9}t${3xPyX26CHu032K(n5XdEkP1gy42U@Zn+NUn zvh|MAHN}f5|19A-=uV(BNpKfPi^BM?R^Y9zuAN=OKRVh7}x{(hi_Ah@xYxsmkGZ4yH;3!1$I*?nRHxO?^OqPBg7fK3HJhOi^e3f=hV z;#|_TJvzFCf)iW_7l_Fa`j6QfjEJkrR?yg_vvqh)fLDH`NUoM?X%}dG-8O~oYelR_ z!IeUQ3L27zLCu;JIzV%yS}!7OH4D=3A?a^=0gGpr-v0)aVqa_1L4`bd3tBX(Vx))H z$?C{a`w~{>2R16uY9$Pi3VsOy{IB97POeGET6zH4FAFKEjG!<>`|IX9gM-x z_3#E;fVc=>dAtxN-Qjxu0-!@={6Lwr7i*NXFVOjlAhy~fGf2-=7YM*fIZS|bAvIW? zIuV?Bb7X-UQ%E$-1K?&ryRBi|(#yWI2>Ea|6KfD=Njv~$>z8Vu#YG9FyKzAviH@M0 z{Gh*n_jcR~-ONpjdXBDxJM-KJR}sj))L=mvZO((Hix29}46Gd?hgJDN&j2vpYTI4L zL@-YbqJt-1)b`$Mi$3}mt?*_}6+9Ua4{{mKiwGFGF74EPUJ77Up#B9NzR7*&c^N-q zdy^0>19$+sA0}vg5VF-Npi>fk4gjbT!iGm;liX>5HZGK&S|90-hoG$U6yA*?({Gz*ChzeXR$) z@rz*wcMD?*Yq~StggqT&!;E3O&mVBfjJsx?O3{Q6#0pKtJ zAH!<CSQS|&bI-p5NX*eh*y{;RxW9FmE2MW``6U5ILOnH#^+laEb z@k6LSStP;S++)d2XdJg$YorDadMaM zzKIY!Yl6OA`Ww098xd}2dYI>xdm@tf6-jKLb>5zu6!iWJi~}Mh(EETu3V$~Wo`1k2 z>%;?siSDQ8oa5_g6xD`*h$LLB#CSki%rQTDJO!gA+MhIp1Yhymd`ebVg z7ASAK`yj7rOS=gaq1RHnJfQXY{o5aZt6yoLExpCO72K)%-%j5FyS_Oa3eM0fp#*tt zaz{E%5U*mwSKB17Za;tq>5oP-Pyu>goM|vVSgS9JfM=Cxy{`K~^IVsW0z6Vv9T>3v zg7{TaLQ0a|hSLBVfZ&jm18E+3uEb1b27#t>NPy(h9E^7lEsT-McB4Wboku<{cV%B` z0O>bPGsp#V9PTEIfxN|w^cly0G{rEFo7#91ZhP`f4XQMFL;#v!Ig)Rs?&Slhyr`ucK!TVeV?xf^U-&-Qv!Mq_O*{WM9Lu1+ zbGnhn1fjqoGGUroc&;K*c2JoKr7$GVAcl z0K?MOK%bEyhIwDrJRM^T0wq|13>7jh>h65B6bpvG0FuOeF!cHv&2nFTRstscAA+pv zdJ-z=)*1<*G@rDy=m8IDG00UF|0p#@3SofiuXqYdL8kwrQzz7-!K4%*N%SC3w;CQ} zx(uW;Ok8jnHFB8Z`Lo5^Auxm>lL{otsX~C3vyb|@7C=hNMhfZ=Ew$&A9bhs4a4Mv0 znpgPY3mJR?N{!xJJjsg}r}7U2s2FynnMTF7FXZN&Q-D!^ zkQh12JyL%6Iq3QS@U6r#L4RuK((yR{xX36;d6HBBGU?K(5sXhrIna zgiD*ft*5*-2u!C>;HO=Gl_gXHwkWq z{%@=J!rsmg`lE{=X%#8d_ucX+;1ROGTn^C~e$Oq5NeDbYk^c8=>DUQoRxyC|{ipm2 zI)r1?c`mNaT6CuW(w1a(EqTOc}%9*4w9_-y8zX2FF+k^MctxTuu zuIAE1(6^{zZ4N>zeSXmcyL@2Z(?sF|`l$@4Hm%Y=nt~O{1~rbJ4i%lqmUa)`^_^@H z9J1{g;L^aLSSNI9LU*J8DB+EfpX>4V>{n3LkS9QM2tui0swoY_JXZK~_gQRg_vevQ z5xG+3<*zPXT-!_U^PQ0G`sj|qjPqXFut}pUV3vdspg#IfG()tOGuOvw^4lK=3=iF$ zIXWyI-HB3u_pLRi{_g8kcOEx4kQw!F=>k&F(A>T+B_J_~`Qe=dpqvu+X#+V=U087_ z{>E&?ZvNKDSbXZI+~b9Tb+xTu6rq6GA-@GsLhEDk#JpTu-U4gGd!TW@1p`KZtAwX3 zUPVbHTitl$8eKo?;Ze6!(r@|pqi$t{kYar3mPYgVs|S<(zKWm@AW>jF`Rs$PrmNM# z^!JkTzBPS#?nk(rGi!t@)3UnpqjzWd?7^50dWb9}#O(q%iIwrybk&-xe6DLcnnBCV zHsX#)+dtt(T_7vf%pIiP4k{la@eUA%pYbTIby>EfGfa$p=J;;W<26EdNpfw-i>5dn zV95w!ueX)Vq0kB3;uHvZ?19EScnZ!V87IA;D1>=(mOjsRqQE44->X_AwsTPgC$2Mz zIEax)iyCYbm$!o(jes6P`N39GO>3b+Q1|F+Y-p--s3b(uIyuWj zP-Uo>tTMQ{Zn^EU(?oVn*K=A`LnPZj&Vae$2^cR_wKO#~VH_P(&*5{b-5%3IE3qj( z$1xOnvK=YIM_x3~BBex=DuP^JC?=JPgGU8JN?KlWNax<(-oaI;z=N*^V-~P}gttX* z2LE**EJLA@en2+;H?D{<;p8L}e)a5n%H%5usV&Vf}Ra$x+>kRlB!kI~lm z=CCDbGc7TRXbspCJ;H5JTPyg$*~!-aV^T#ZHkF`wv;hB*;*}v#YCZ(S48T(mMb+;o zquP`DvBh*#eT4UxB<@*k%~ut}^$x1Mj0f<2vYno}kVdo>WJec=lWRY_jjOr> z)eDgWnz|4H!YSSnKnIsXGgHh#$pX_=Xibwx!*ZR_1h{maR{TprrIj&mvu)upRu^s!#dnbf8Z$;Am? z9vikNdmUY0c3g-I>~dh5Q)e>GIHZ^gSu78*JD--x{UV$pYO_}(qPsFy<5p|OmBK+C znx~PDA||ZvwL$`B9f+9^U~f%0T`6p{b92ch+<&mOSYs$TuuFC}BXy~&1;u#n4C~cJ zC?oqC);~2rG3_N81ZGKq9SuLs;i;+k61Uqghw&rLrsMB=FjN^7hNgbCqPWe_92L4xSKxT?+5@+D$9tMje(N;j5Jed>ALf`VRkS z6WF!w#{cQ48lvKbR(QO{5Dbi3NJ}zPG%XI>KR6grKr>~iR)1DJsWOBHsALBX+QxiU z64|+N(M|~bvnpEc3Cnq*$xaT+XK)leDS8DIDs5|P3;R=$G0?WS>s)hI>D-=sZ5tkW zrcEWDv_MBV(6IfQOU|$si6bF>pzX@Yx~MoQC@8@C+ZJD?m+mqLcmlo?eLK+^d|lNk z=~&XSa&n!iSaRi%ncg=BHm3k!$q%T7Uf;BHaW`ReSJ|#A_9VX9+j{PZ3Juy(a;i;r zF|Z$DiW8hc>a6R+lU0*%*#nyU`nV0yDkx&8W2!AF;T$j4rrH@V>hVqXwyG(#Irw&0 zx?Kg|J4=nAs)fSyGZ|u%6|wXJNi4GAGfTk+8>>E5#EULvc3Eg5>r8dRN5&|0Kl6kudSA+SqBSMbBnjX5<@3^&Rlz-i zpTepeEV-&KY^xLsfA0npOW~~8n;+C}S|9L*zc%*0oArV3-w?XaG>s!~@~Z9>eX&rG zWn)@WlG*KdAY@%iTBb<&&J=xN? zyW}(WBKE|dhJ?{?nGhwe+?{VtE>?{?KMk0S3(Aj2>qk+~ysZ!E3|V1hV))Wb(9t$Y z)bv76f*$?VtIeWV4R&7QJ4f6Yvn*{9Jwv6@HixEX-`Ph6^cvM*j$G#nLmV6N(({p~145L?H-h{AkZl zBJ5yi_R`g1(9^y;vG%i=5ZPu{heWWGB{y+#h6{;R!6_D?CDy2PZQMA)M-7HkH7QRr8nLPR}7V58N{QS#}#6&;UK5BAS`kZ1uhJAa?a zTGNb{7t~*x(xj@t^H(IOeJl4TpvJ|0fDgZ>uCTL2YtZa`J)UvBvdpuWJTOT>ViX0M_G?i&oK!tpW&}3KJ zh^1gsU)!5bdp$9fk3XN?YC)I)Qfspa(&frFTVum&t6?F zh)q7!*E#MC%kF%4mM z8Fb`x?;j&^k=Q35CrxrT)V|y}MZ0Uokaw-~TXue0TdcC@YZzQl{^^VU885F2&S!Ud zF0AI8K{o6Zg>yc<&100=u>3Zn9)P|8772Kt}YWoQU6`qrMZ-IQdBGY#qdGlc%FujLiV^vgu*fsx&N1hN%oCd@Yz zFjEiJLkoW>8A|DyoxoFzAW^odxSqq+_=X$rZ{r<;s$S7JfUFH)ArUboG&?IxhM`pJ zexVvsQc9H6g=g$As`UMaW#QLoIMY!;=beG)CWcW6-DcM&JvG@!X~=Sw-mSp*fpv;! zxy_6TFM@62uC7&OjM^ceq{p)Fb0bw+uPC?bhrGv;u!UMpxbv@jR$l2Rt}IVx<($rn zN!@h$hKZF9&}7?V(ld^C?tS){Ys&%}aSZF*eIX#QfMfOtH6H5M*h%UR7`Co<5;)q`$=hps zjf|-CW^Q!N9&jyE-cFTpZh91W2k~V>E58BxnujCl1UjVkKfyg;p;u42-}{nl0DD}+ zBtHNV?aF)Gjc6wZ&cN5RQF^V`uILk`YtY6)fMKYa2kH=(Rz z#x;CtBEit+39CGudG#a2iJ-sW=!88NnTEfhfDpAyl|^jd+p&Jsyuf2EwdX1|p?KvH z^?Ml(A5aPt?MNDqdB=ad&A8Pi!+{SQT3`ONfP^KA=J@z{MIsR{E{SHn4h<8 zj(II9@5T4TC2kG7ZqWn=b#TUcwnBm$U)bPMmk|Bh7_t$DDIM()Ay9t>OcVW@k@n@= z%=~uQJ$>v@O+ijmlde*x)%A|mWGLkv`iTRwet5AKfrdFrY`EmelvsEl(!=1pDTn{3 z>*YRoxj4JGf*|D1Zc&8hn3v@$U|366il-25)hq;l_7fdWHb0;U|k;vZ_8za75Qxf7k;u7Cp zRwSYBO)4suCA^Jbvx@0|{!I=0=4NR^rD5OljFA2YgXSW>cw*l9H%cu`zm2*`aXxXzUlDs zFM$Qe-{^+yFu1?|C~%jY;Zsnfv2nRspaP;uM*svwNf4*#loWZFI_(7f-pB&AO3RsE z_H?Mp!Yf-mp25^0`4#%lOw@TU&y1opb!)=Up)_hFsCRuS2P6D(-a)Fd;})>5CA2e{ zZi$oQ7>U1&OEpgRP$0Lz@%OREU@J!b$w8t|umel@6a}AbBvYYO8+zr@t|EC)$j|;%jzfD(>se{9axKmuJ-jBkL3$ z8SiM^nRJcUR$cnKh>wTi_>aBHWoo!1-zB>%PKH_D^Sh)+a_v{Wc-cf78B9$O%tPm9 zC0keOlI=)JGWlYw9U(rlIQg}S4bmbB!TTc}Yn6jzd*A!u_id+o;6M z!qk*w3jRh}axA1hUif9W=F*oAzhZL5ShNfsiM7e6(uL5!_?MB0)MiPAn3<*XF$vHs zuG2TIJjHH(r*^iay$=T0KGG4e{$74{Es0%L{3k`rg<15j*(I;NoLH+&n4CK5^QwA1 zkVY+Nca?7lZW6FuZ!(#Jqc6Pg)}r}uXt8=N-*20>?ivGtExT*O?{aMIr>228LUW`f zinV$yRK*n6QGi$h+i3Yc!SJ^)CE}cww;?G{8`(HC+f|Al0r2d7)z#YJMPB)xjUW3E zq1vgc5H3?Oo7oKBcWNS_Dgg?cS$oaR-d@=}_KJax%%P!=a(oOE>p7gJ3-83YW)wC` zzAkhT(D#%wK!T|3**5+ZQk;&$=-3GSYXVOheF;U&Zcy?nD-`kfzU6C(ccNkS)?44e zXOo;yLu&X7rlm6zw^+WfKjnr|r1i3?n#aZc$bQQOTNxFu*n{`~9`JP8Q_b&Z|8{w@ zm|$V*pRMV+9kQXXVI6A~uap`Kr9O4wwN06m8ur%j$7r+R zS+UF{`LuvtOV-!`u~pBl9iqP(Z!`IXRIkckKju2oc+|`uFlEf zwO0xWq^F5chXK#V^`lz%CGFeoAKAa*QhUobB@M}3&X@fV+$vWP!mE6F z9jY*Fm<=82xM3XjWVpfjIIDUK_k+!0SKpRBeO%Qu{w_PDAaRZlt3?-rjZ4x5@}Y+< zLiMY_9}5%H%*g1;y4;_StloT<7{+*$=68disEvrClGj^aHCI$q{*+u)i`a{u7G`VK z=fKL+)p3H3stQH%ClU-5he^x2(yw~Yx^zazT4CXLq0P}3LzxMnqz>3WWn&603efnC zCmtQjJxX^}jqh3i&ia=VK;wZDWP2CMA4PO;ewW0P8g08OSz1bXSw+N1N;POSghdU| z%oEfw-i$|cVmDAe#)aq!VS|Mh79)j_t~y5vGE>>m{X`T zfBhQJ2gHrolnf?xpT@n+uP9t2TT5-L^BPeuYz~a9ib!4=mYn`6%?Uhnmnzx*6-Njj4W{V}H=Ne|+&VxA7uK z`~oX@OIFuXmQ821I~`SxZ>{c6-ZRUfH52hpZtSl?8=a&%x_2CXrKWPqWW!mpg<8)^ zIs7b+p-R4;DCq+$P5zRs)k6tMm&1*B)obEk)Pe$DD&J8qI4x;Dxe>iI+BeWxO3vIQ zKe>pW@mIpV7u-Y*Id)Yq*`CSqo7}{Nogcc$^36GSTAga>4wdpJS(u{ad!o=Y{inh2 zyDoL3#0ip%dR*iqOpnkp@9QYveSWpWx|5C5mrICvv5hNuvvxl8L*sFyhgBpGr$EY| z5$y{4YYml1PJyhc4Z0d94Gp>vkpZ)~-b%icwEfYZP)4WhOA(EaTye2v1DS6E$IMWQ zo7CR(eb{$P>xubl(em5OXY?xP&{1&o&#PaV!Sjo08Qpy|j${eu7ZQHdH^qJ0L?aig zOHrDeW`<#Q&dkv7uvpG=b1%&d;ghS4uk4qg5Wc zM~(q#nmPd@b<(vzo~E#uqZvM~c0p@;_}^(us~IaMc4DSqI%;mJ|7Eb#+r_yx7J#AP z{*siZ%y*IywAr|kyTSuf!nrw{>zkH^pmV9KDf6T6QXx35Vq->eirLVw-3@_1^<5R6 zZMG^7xE@mHbnN4ve%x@svOYmkA?fNA8eo7BWSag?tqr=$78jVBdUjjhy6`^kMs&C& z@98d!T3?E4Z0ZwImxTtYxXt!w`cht*Fqx=R+p(M}!E?pt>(J=m$H(Zxwzn zkc^y5Is87r)5bf$CmL7qjenhU$Xc^^zZK=EQQU#tWX(OVYrAV$E`eH&U|T@O=Tqs6 z)D0}QcK&A-1g=W&)57|(fG$^>BwQm6Q!W49SpLd{mYG+l8;Q#E;fbFa7)N(Nym4_ZiksfR~B3wRbV3l_iYyk$HCYkA!l zUq9PET5^1|T5mxYPYF2@ylj@>rlG3;U2APGA`{bW$~n05#**2@oNBD4*TLL{-_>bR zb=)NX_gd9_%oiLzNcH`HMJE@&I|o;A6YyPRKEJSNyHupRZ4TXO{oB1vu_OrnOAM|y zRvvT?#|_-TMvHZXL)hFIW7uz4bx^)z&+@QITtO1lsW<}!z1ODgJ&AI`ziSSn9-i(u zdcD}qJ=QWJ7#DoFZlP0bB{f)p2j!!~BN%%8o-fh7{IM!Lbdk&1r1SdK5`lPds|I`P z{bFpd>=n_ajfLdM*u5Y1Gp-u&8rL;;`8K9kc-6z=_esjjlQCK*zIMTr!g-=6%zT{8 zOGdk|(wBLI=A>Zz;;J5XC{?QoA{ckJE!@c{5GDZWf|($vMWsoE?3d&sn_BVj`P1-+ zbq`U+C$5?B!|_+1K$IZ?OakchK#CpKe1mH;)_Xhm!cwK>a|NoJ%PTQ8&IREsk5Sik zJ49E*OmA&iP%}TlAwI5&EmqM(s4{60>Uyb5JoH_;V3cQFBrcYQ)=|*Zj~_t(z3)Mb z71HzJt+mkXx^{vtmFe)Voo;46A@9n9=33MAUxv~jtIKzC5PGRRbqSD7uEfz%Wft`H z&_(st>Dg16an?L`o~H2A!Yp01K}@X1p%z_UN8g&`i{@$kd&2LuP}oADW1GFD-&9*R zgrNiSOo}9>b8Hoz)Z-3j1sKJMTWcu1e)<|$jqxOpVhlibE&5j$kuD5k>ZwsU16}W0 zdkc8c2>dUFF{YQN1|X2=C1!1q550FREG$1`V%`u)TNNp=?OmRxVObMKCj*%iNAD{Y zLGx(u?XAWwn!Wi2wY;S-)?TgKYxpJZpKs!K!+0}hj9#z{O*SBt6LQ5MCW<5*R zg+3#Q6g#~dMqBgVz2c(%(u1T!+WA;bD(ILQ)&7t5ru}V^N4J!{%&|BFcn=oL4h^ow z>Wr5jlUF+S2ts3umO^=PQ;j z7#KQKBp#@3%yWdjjMZ~Q1Ez20 zMpAsEbv^A%-;cz13MUc{uh;NvnwDYMS*|6{8o$~zUSnPScKKe}mln%E!|`Q}_ED!H zywIqLVQl6zyN6{G_wUIcnOpgXM|j~8gXX?e_}{(_)<`f{MxH9f-@E?ws85_Kysy`K z=2D}RKR=Dc$><$yB*aXg0MZfsuTGZbLl&c$)XFQRM0hKdD34aJT=tgY09@!amxL2rWX;Jtgg{KPFc zMy>4Y%nNvWq#|n909dQWM1gE#|BI^XuL>FLShEK=%2kK&_NU}vWvdAvv0pP1pf{z7 z6TrX{)nq(Iy@^Emd&Rdwy^JF4<-+#@_7$ATAfpnt3y1Z9+5RL|jmB9VmbKEBJ>axDQy1 zGsLEx#kNov-BeKM=&I?dc^vH?zR$M*^I;fKGoER!dHM3j`(egY*?||;S%MMz0Lk*2{7VSGL8eae-n;hu=R{J$pP(H2Gf-+jq}9v15}}KKzMdIF8;Rh1v(H z{Q9JRpjnZl>~egwh`8VQ5HC#GJHLI2GuZ##oRTB1eD2d~;`60TDl=nqul2z0ja0KS zj^NtPJNPrv^7S(FRt=lC{e;C9Y7T~yxeH19ZwklVEFY?%u;H85s2mY$USNyg!9K5P z?CYpITpQSE&k}D&r8tNUGGZh;P#M}t-Uig@4ti^j0;jtqRj6E#2?sg~EgN_x%)j}2 z;%&Q0Yb~IOGcl=nTBIIeOG?z5&4A!m;Lx++;<3t0o&`PsG_Dtnofa~!HQipfmbhAp z?DI6#X~k&@SI%m7ejHdO+O{o~nQ;wYR&eyN|3hJl0_ZT0Ggf@Uf`WwKf5--zE>N%L z(k5?2N`o9s;qLJejmyqkah2H@u4my1EGLRl+FNBnp@#exz%|LkG=t^@0GV$GYJBId z6R?_R&p(;3ael)ZH~Eb))+qXf>>I~@)b?Qnpf=0ES~eM_4_&1-UvSQyAUuy{FZL{L z{bpsu(Tth}-Gth}_RKcJy3-Y>;UFHSI(ISgRbchk)Di51OiPS?@Kyg)94VjqtEy9> z`_xa{h-?4G=%lCnQSTB&5a0%r@W4u>va@baws&h14g!0a=5yu?Rnnw>=nwO?J(}rT zxOiuZ5+itGmh)IGpJ;8Tr)zxfqizqs+3N(!o`ZHmn7*;@z`d)X?1s>)yWfp(hEAe? zXf`|h*;ah|P62!1?3;6n!vxaqvI(#UjB5Yb1|jRbBBG0At-`yNtYBa0Y8@oVf#|1_Yqb?I|H4En>)bhC_H+SzJ`X_C;= zShl`!0W9T;Tkc?^kwA{J#Zm(LD8b@oD#TCCx&aqb8GgRwR1#sw79Xhm<;<7y%4wGQ zVqdv_FP8754IM*pe0r%{MB;rlgA)a!;9yRBc&M^gg5?;$_4mgsJxIgvysX>fjJjNOn*q8M7)?1f`ia%2%A!C) zJwz%NqQuUPB2+xiv?BpOcznoY(m~|}=#95HTDn)2MDebkWVUE#Su%2AolpUHTy~w@_r|C7=6P+>~@9$S1=Jd62XHf)%Z2U zUf*U`Z8MV_mXm*m!*3&@gWFn^shMm_!}G}{Tbn@NG5ud_#g7rlbY~uUP-vW#v^2?q zK}w%oYPXhb37lXFy{y^+Yg(L{t=PplnoXecykw^_|Ec<%fMeHB2!F+yJUT@;z=c8fwGdO38N8=DA#Q`7?VhIlp0-PFF}MF^5GsLv9NB;p zPkG#tkC%NH^E2=8m9^sf_K~W$Yl~nOFt^_S%<{5-wW=q5tma)oeXqa{&wPJG3G{1C zbUs&Q22bxAs||Y7)e33N()8;5D#v5je93%RU%BVgi4>MVxCiY6n7rLu5wVwJfLY># zBFSUL{a)Strx3n^!Tx*c^1*q<1V!D9$-=DU?d?nZS%l{(;gJ6_NvzhrUIwlK3{{Ij zM^bNr*>{~%ZPQu)g8B&CV~_n?wJo;;3=b!Sly(89pva9b^cKIt!OC^iLXSX6&!m2Y=rq=*oO%Y42l!-eYUq3W_o*)iw5y4F^Ad-_uOJ(-ZFN zV@p)L?6b}ttFTQW2<{c}R5xE7*mxH-m()2WLuwKmJV#03OIG(TJI#+yDt}N;O4_@x z#Z!A{2zFZ@ULf~8dW4$ErVv|6uz%?g&ofq;S8I(mR6tG5R?D8vqAC;;iDt{VVVx21 zilEIsNN9j76>mcS>?Tub;sIot@V`?h^qC}@VHI_Fr(};#&iShjlB#Yc{n&l~{b%*E z3IRd@TX@jrRYDDwdB6EH0l&5G!K-CT@QOFPs&>h%2;tA7Z=E$hFl4t_pL-Ti%D`XJ zjLYmISI0i|OZ3K=BbiM@&}wdb;mO0r6Z=IjMBW(T!r?WoXVChL%DM`o^<1X2rYF@) zoIX|SmPAN6E}76t4jm^Tv-M*uQ8A{{i%zoBF|Nr+rwHoZttrHWwd7a>$rshRlcf0r zWnU(JPmP}%m?K1#FkcdxgbSu>*) zO3b3DwE%KSpl(;^7dF@#!I*+es2cw;yoTa!ZlhW%{@CCuMVOW|DTf<5B~`kkKh;cS z764LTEF=~&^|+3|4b^dk53^{a=@I;N_dTq*p9XzUzt}RU6`F;Xi@@G`^DG zEs-tz$K1>|oHA#>*6j;`I~gktQ?z~*Fxqr!MXSk|B+tH2%vTMX62aaZS?4t&HkMXQB4`31s~@036Uja< z_sX41VxU&z!=6<4HX4=hluGBlMJWMz72f_^P3+q4}N+aBk7MIb?6B#V(MYxsTOkD-wC7t&!i}wAlb%kMJu>c6*ZF z^Zss+?1XpCA}&HJbz|(+8xL+inj`)wYH1fa<2n#z)NG3m_n}dr`k2fMbz_@{^jSXE z2-(FAb)6tGufrd2S<=(Ls!YVL&Mwm$)7b8f_OY%YEtLCA5|!Q@tn*VjXIs=Uy0sNk zmz(C4SI#`7pS_&$EIHl7Hl}z+52HPzE%_j0Z0{4F=_}}iWzJI%(tV*mhu!$V!vO!%`GPBL?ukf&@!TjfJoOw5^f2s5}#id)uqNIfe zWK_O;3>cF%FVTxHQ=mIOt#RI(%SpYUiun7SMAWpp_6GP^fx$_(dhKF$T&|<47tNYVI)y&8eolRK3Vql&CQND}L9jv$1bdGC-yW(2`a1*qB zDC0EG9sEQpYd3V zwmc>7-*-J}%TC@JMW2uC1Uie7#}@5&^1Q|QlrgMCKI;`}2?PlZ=DlC9@*9d+nr zXR1;&JJg2Kwr98Tg~-u?1~I;G%@u#_VcZ2uuc5iKhC3N%y#(Kj(d zr>Sd{CEI562m6bVN<7!0vgWWB2Dhg``LThL`O3~Co!#NVQlXynwTP<$lzSeYVAe+U zCF`A)XKcp7iezAcoMM^QDLj7SP+pQsn4vyTR>?vu+0l;_)@RQmZb zzkU$Pbo+w~Nam4fi_LwlG7H}HqL{fn0#;WY!Y7h!4ntK+vxC3f;>Z{WRNn7EQUY}5 z_hTjEl&5-BS}j`Uw{Bo3T%yYLQX|%UQMM{x@1_&NTIWVdPKW*##_!on-~1FhYc$sr zqV5l~F)efqjj4F75LBvI+#M4*k4?1KL51k|DY$fA8d%Qv2JQjr|HFrG-=|=Coo%Zu zG0J2=tR2yQ&w18K%Jg!%&-F1xp6Ozs?i&YzOS=|J4})c0V=%0G^}%x$Ig7xJKE!q= z^b48{qgzq+XQ#7EO7mM{lG!cmmoA@1&sJC`wpuh8EgSXE|5WeAML8yKpchyldBYUy z4We4lUw0{Sz309Eip}wHV2#;K9w&j+8{iHf?BWMaop(rJVRT6SW*_9fe|#(+6ZEre z@<3Sfg0#4FSFl@Ucy?V#tEq!K%CkDuLqu!CVy4SdOw*XFli#zAHRZ&&(ndN(CVIw2 z0VXz*Wyxdil`QoO7g8qiuXFXb$E5tn%wCQ^%2D0ur({E>KG~j}Ff|YR<6o2Y=+LDA z`10W~maE81Vc_E%psV^VZ#i1?w(7FZFeMSZ;zFb~Jh$QY6I@)y8bGabAfmnpHIE<( zPCZJ>thZk$UaA_MA+XKORTVGXc65`fdP*?!pxrp^z?HXRnXRJlg&L&0QOdZu#=d9L zTa+2^0qP0fND;HH44jX8SJ?2kp4Jz$0_)0X^Wt3_5 zXdt@?A(Xu-A-iORVYW zR;2!1&$i-MMB0MMt=cLg?b@V3ek6Z0x(5va4!pLy`f7yO!@%Rd=HzZ3`{#>J!A$(k zglHz&qpx8##Jil`TbX*@RKu5DcTwfVfh{2NWSftPXIovL8kl+5`*Y^| zpzn4!^vgPNLF+j(c1>WfA@l9-k%7gb_Y_CRQO$Ob@gQ=bB-t}g^`L4f)7h1naTtI$ zLaOtotiEf-GEvl8G!QY>+=^$kBZWyU!Lts}?*>I3A)He}YM?@}Bm$^?s3izQ{V!|r z$ji%HaDZFb*}WW8x3=q*p(s@th2I_zyc6b+*8p`DSCA6<6SxNC+z}$zmJSAaN9HZj zXH+y6=DSaOQR3Z>Z%m4qsujs0vt3_~zh^hDnzI!b6kaxNKH+*4$DRQlf^fa-r_vY? z(cy6puU(KW`m!m|q49%dFI~`7h$Y&z_vM}!m%a0*<0zTcjKk4k6aKOBI>Y2wiBy~3 zJe4;}=3qCEXOo?(#T?110H_V0-;KOE@jf~Mm` z$wx{8WFO%fQRZUR*J@dHuaSKL4|g`1sz?R-6M#)?NFQm-^t({7YU-`K^@mi`*u?Z< zO06Vn2K!z}(pXbWCbn^(o=to{Obp}31EmrC9Y{ZWh6s5}e6A4M>m`o8S*ZtzAQt|} zTk_z=aBVT1Uo|v`aA(78U!N@sSw0oh(?o#P$E*qA$TF`gc?1#e-u*hR&7FCLS6{Su zbv?DKB-RC=9})QZ-XZyLBz#5R8D>0bsVvH>VnQ!`eGg2#WdQ0S7dSOdEquc+{>{U? zlS%)8?d6|7=9nbSEy7X6V|s9XO5?u0$NmJv96T@mP(UeknV2w@ zQ1{DV(lXh)C<@k+tmfNbv0HhcImkca5%Q5HJ_2YL2;_-_Nk0l{7Y#|whQ)Lj_mVuz zx^Gv%W1o^L6`FEk`xX|`9{+}H!H5+`L} zym-260E7c{UX4+61nqJwg$RAiI8W|@_Y=e=Fz@go<^pds3?Ms%p0f=UDL*sHO_x z?~?4TW|>TDwZ8a5_|V(!oIqDcmvhexjDRaTy&hG(%+%lCQtW<{SCn)a z)V<3|^Z^0i;Ik*|IJ(=@%b5ucf(1#mPceNrr{QcnX(l`0+!k$cOrHyU9B)fds%y0^ z<8A)w83jBs)_=Ari$p5qDpT!Dl z?y)YsRo7C(Y)2j^5g1ksP+EyxX!G02$uodJ-v27h>ye3x905)K{=X?2x|1pP>Y7dX z9W=ds9zO_V76_+IYoNbAo3@d(N8NTGU^6&;r3uj!2QctN1FNYVy-;(VLSxP#C$%D< zH~FgPN5RvH);tKp5|g%IuSxZWK&=?=Fn28nro$4F8{QmSwAxV!w|5N!=sBt$lrO-_N{w#VGh;$YgFYYttj0EW}D#YYeBT`i&J-^GgU{y6Gq z`2wkQ68x;w=QT>(QnVmjh<$@-69Y+?|MwOs08EGx0uO*JXz~6#yNmA9qntAt^Rj3H z?Pczq$~$`HJb2gDugGf38e)RBj|Hx(zR(0EY*v8o^Au0X;mbf z%b@?L)q9|EIPe|$d`^1Aq(6;G8%$AC&aO6B?a;kQY#UkGpC0`Qac9U(#|pCAZ7kmJ zw-n-33>g!RU!E_>&X`z9JjGa4C_D#PzOfuk@N%T0W_mqOMC_Ct`uz;U_)+)HJ?%Y* zf$q^by1k_dK7oQ$e!k)%Axl~;Ner6DhL5LK%~8KCUy_-UJL$-VK!I3%vpowd-9vo5LMAG-cYt>H0iPcej-xE^Sp&xm`E~~W*9x&}0@dGnm zfP*+Ay#FO1{%g)Iz8-U^y4t*JcAK8u;Y~m4KJ4Ste2yl0*Gc=<3C7iz6$2aE*0%ja zV&UUg<9ecMQq^u>b467t8$ywmN$Ac=@6l4Y4wG@8HftD5_49Bm_ebF}7cZDPw);2O zIp#J`)-2ZN>P851O()&)T2hwh?vutDaz&0?9Ad8hkL*bv*gAI)f#!kWL!x74D=BH@s6Ekbci$RZXMoza_b13V zdJg+{oSbr>pRfn${PI@q8GbqGL3h@OdW%BltQSJ8GiO6;lN&msys2%rt4kug z#C9!A&TrvCH8+H>oo`jZ24*(r_fVUe*|`KuM{QbSV7V3{aj(psIDV9l^zIaky5IW+ zqqE%EQ$w4JEB)PGy1T-*D)Fq&LymM>YO6Y!a(L(G+`WFG8I7ta zAk&c$*!v!_I$SZVukLKm`z!bfgq|2YENj^D6Op=6e=c(d_T|z4bD(@$$0K}aw`^`V zOwZ8qhE)nW)abC*MAD@Cvq~ipUS1~Wv^W%f61g)k9kYzPTPC$3CNF=+l^D?Mpkzj4 zyUU@Caj-J8IqAkEcz(p&D_R=QtiS#9hW4l3dCb=kW$;VRWPEi!XmJfdnZ3*Oa(YXQ zd9PmgKzSO*LMMr6K0IvCsg~|1MIkStl-Ye79lDJ_FF-mcFAy&eJ~fva1LckAzbO4U z95CrpR8q8&w!#d970h*6L^?^(9;s)&p~zk6GiP{CzwE~*`#Myl;LS< z^W-^s$K38POj7l7?b>Cu)|OyA96X{GNENXXOm8lxTMHzp-HB(U?;}n1+|w=C;TpC2 zktNV!%pjoftf@I2$e`7D@mE8G--yUO-Hk(!o%7P^EmBzU1aLm7uyYm3tvER~{A8#NfVqD>ErB+@6H22@IX_C^?MnMe zRc@*7sF%?U?0NrrIHAZaJu$(Gm!a5^f2&h=iRL$sX}8~w2bYlH#_hV5=C!IJ>y>wH zqp88|qk()II_gyq2^Ha3Tp&-2FRabp^O?=Q4!}#YS`TZuV@Pt}& zqM(w~?vNk(BzXyi=-svKgg|v7jkcGapvJJ9W|aN02I|+ zR>ZUMZ5Xf~pK1p(OR^1FPYfJ20i_#N@td=C*(6P9$*Udrp~bCCRbL)~ef^9NvoBln zUH5;E&Y-?*{Wybmtad9&UCIT5QSsMi?f6opG~zg~!=vH~T;clpDO|B|8e0IMS+xgv zNevT?YCGqRC|6PT)(6GcH;KS&4qi2ucMF-dWl<&qB_b)MnBdUd7q>$x34qsqB z7)g5BBbQ=DYv~YE^axVLwW?tsx=jUo_ir>aW;u*f``Id$M_2Kq6V}o`l>PcZ{BxW* z+_wh5)8BkL`?({;X{5wOqg8R{YSU;H?yqih55h2)SU5&Km)o25OvH||+md|h+}&Nv^eU1A ztlf}&U%0;GgSmXa)?TeeBd$AyVL%0^?eWWa`}9;t{baFow3!a;AdQ@I4F<|O%Sp3% z8GZJN1~&|P5lWP-($l<2w(0gvw+>jb14-q#QeBhGP>-rrOJq!PrK$?X-#^ zJ=wtR`(s~2TG7BN!Fo=AzZCm>XL?p^GviQ>jB7{S{-*eCkrb>8V-65ff9~_$7rnL) zI{p{e?lrAC4b9G`4LDMXk%MT7CZ+so=zcg9=)F?Et4l2c0vF-V@LEw6u^W2HP;iM2 zI6Qhg@Gz+PCmGYEup<#gt-}w?5jPkem^9nn_nE&@%FVjk!Y>Br+Yy!PzaxXkw|7~$ zDyZ+Bl17X#`Z63M_7FBFv@(5pV~G}}H@{HhqV0sQ`P9Fo_rB~Xjep-UR7?cL>ouu@ zV{Xyo76^!(#`q>by8oCkDxJ@>cjK$kiTS2z+B=t;>x0-r7uT2_6*aX1` zI#8pzYQ@iJEo5|(1=x^rAdQzp#|hr@ihcYYmHlTx#uy?g#1Bz<0C1cu zeeMvRl^;}R-_Sp(> zfHc*QKVfm(wEdC9&Xbe!9~S^uSUhHVwLOIMmn=Kc+{0&ww6%=lHxm8Z-gR_5?JWB& zS9w+xW%cVxsvE^FKx)fMq8t4B(ec3yMH8T2fk=^ony$aRG$I3z_mG*{9~Y-=E%j1J z<&#FOlw_pDYaWR*JFEVY#+9X6qZc<*)VaJRyj#rj<$*R{9fo>O8goqRgYMz_2mqmc z%2iciw&K?{3C;{a@D`shk;j`q(`&dTd`lASWg>5D_p+9Kp%M{Z`w?&C z&I)<{*NBcORBNN-v;O(~bL+ZlX7y+YTWIo5!xPr=6zcJQ|2$UhCO%h=b1713wSO`7 z8o=ZHmnS^;ZvMVUt%7sg}cA@wa6nB87cY``?Y)XUfi^T>CCg$1IT-D9(@(Vvt?dK7M>uu7xSm6 zt(FrgqmC#@vg9$yW?MjstXT9m5d(l8BnCav?Rx6QI|nplJc`y!w|B!Q<#Yfo-TiCX z!Q?53g40>-N_vf^msMJlZeZOH#lz0@h8fKgNY+_($*UE3)n-DXZ)4Q@J6`k)BLc{3 zpOCn6y9p`ljRUku=7kXHJ)OV07SKySa~v{~=eBqWk#BPpJtdQgT#VdrKNw#6(MAKS z##?`_dsZ;2jG8tl)3t$K$_gd{K3{h6X^j0Z!?@SQxdLv&rwjnPsZqokROdlZXSu!e z`=0A7V}UaO(rAh4KNU|ovext`UOq-l+27;ld@@b8ni=VzrzbwT2M7{hrA9C=7`Eb| z0SeATpJc6=CZ<|{JPn0_o2i`?J&G-c)X!#r)oAibt*ss(-UKL*$O&;WNVdEZlm(Nj zy<+!mVKHq&dEPE2EiD-k9ZgeaL#6ul!LGMk766O0CegnD4CrB#qaPt5;p*DxN=yUL ze!A{=+d@-I0I9D2&E?{$NEV-4RsOlDrylJi*Pk_9+bP-pmF}Cp1QUr9T%9GizcEvdtA*e`)E*WcL@VTX}u$ z-Xs!TGW7Pb80%_PP!Ctp>fQ*t#BTYu_fr8)x6mIUGXpMNTH6Wk>$!9NJVcn_i;!{- zofqPR2|qr(!W2;SE(u|_hzKF+HHs&LQ7974C!YObR>qZ4T4U+l1SczEy{J{7Vq?BG zmVjcVjQs<7JGkp;I%eG~RNIN>KAmzfPgzQ34AJBAi%0DXzWgPyQME01{5y`3)66T_{mr_P4oG72}1 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⋙x#%|&vLdgNk{h=MY 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 BK7;@O literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxhdpi/launch_screen.png b/android/app/src/main/res/drawable-xxhdpi/launch_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..7870c9d0e301cabf260557bc8114a4ea1800cd9f GIT binary patch literal 60611 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%0D+zqzexK?As~qer>vCBPy_PJ75!| z$@fMsc}`svp>|5NREj4G^`;_iq_L5{g@yT$-5h>X=o)kZTEh?QB?jFCzS{%1V}~y? zr_c{A+J_7kVt-{2cU2NYF7?61^7tvW#1>f1e*qgyjLh$i}e$3^*&wY9Z@ zch)X#sDF_6q9z2yXr6s~hxbhL!%D|InXCCQz*`?yMR&Avzv~+01u`Z^scCC#S8cM^ z$n?v0H1i!3gCJ%_GbSrU-JS`cnrF+r6XJqS$c=Mioy)=)jfA~k;(;$fTvYg=9k4O3 z|9X4UEqe($x?9_#&}VZyI}U(l7v`>~5ZDw1gL$(699%AiAlrjte0Qd#I3bI-Dfj^V zQzyfm-mZvvIU^YtNT>G&`)AnF5LgvEVA{{&wEzP<^Ao1Tm!+(FH6Q_C^?Nx+cf-%Pbv#tEG4E z;E%w@m&8EB-e(7)Pyijtx*?B6iLhN1!Q%xe#oJ;~;l4o!A>$pOfL}L ztZZN}HB;4hqQ4D&{nh56b#te(iL6(?*4o&c(grLBD!^>@K}YBgJgPg`-|_n}?ZqeH;zdc%IKK`28g~OpL@ZW+wt}93dHw+G(Z+_GskHhAeCBN zzQA@@hc#kBmw|~16GzAUEGE+z+Q~wB`Ind7wd4EShgwQAkA>M>o-@Si4inSQ81?9Z z6ei&-WO3)nZ!;F{+d%VIp$L|l{W(R}0x z2g?9m?)i}=lraMFhJi4^hW8tKZlA|Zm!KM_JU6O94W~W;I0j{Fr6hz%Bu-Ym;8O~!RKh|o z&+{hbrINTes^u6eS4(RK0D2ni={Zl;u@QTaq!|m)E2LqOhsI970niL1;MWX9#AaTc zTlRYjHQC*Mc=Ui`-?v-o0RGb*x>5a;lR#R?YW1j>f^T6cYt;}rPIdG3dX(dA41RI) z9b~2KO?f<@YuXv>(l3+NDFsR|0~k!ugItc#c1x-&UBEL{`()((mA@Nb#qtKcGV=6! zZU3drc_?iNXWXE>YE(g6*^0t>Ad7A=Tl+I?df(4Z-+pLTen~u|B~!`a*^9?@uFiS+ z^~e`0|I)JTZ`q`X7p;%aWAq2lSg`cSrzZ}mne;TO%x23t>$u_uRfja1n@7{QHg`9Y zHj;KFjxH4KKO~X#+TGRDIyK!044Gy@jk|e5y;lp=%E@^<2ajBAChHm zc-83qhtSx%zah(G&&WN{iiQFF!pIvyJc{y_6}^}&i-OV>KjE&Sm&fg~xG?fI$0*A(G>F%itM03FP~F~z zkJ$K>AN}wsV6OO7A59&aBgS?o!;+?}X-{yu4X?V98@Axr3i@U8*O*u=1Qpb)xjMVQ zK&F7>TcLQ3an$T^$Lelps_unE|?i3p^^J z1Uz!yPm1;t+k!L6+~hMqtB%hyDKM_&=NFnPEZ0Br^Kyp4$pwC0hLX!1^f<^S#nsVC ze`r*w8{W z%H0tWlQZ~#T7r|PWRZl&IX(_?99){UJ0!TPX3FCO Hw%?k<&BL1@vgX2~5`I2Cs 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/layout/launch_screen.xml b/android/app/src/main/res/layout/launch_screen.xml new file mode 100644 index 0000000..9a216d8 --- /dev/null +++ b/android/app/src/main/res/layout/launch_screen.xml @@ -0,0 +1,11 @@ + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6b3f2007c83687a9c633cb3bd69537206b51ccf6 GIT binary patch literal 3033 zcmV;~3nui5P)j{000Z1NkllT`5{M5F#XukhLZMVG;I?eL@73u z*N9|9huutHJi`X3m5iM_ljIjUE+-$Ht{z`09OhdC4>27Ui3tl^n8b}38QY~h*24LT zF194P*qZ2KQ~b0l-y+B5YOlOv(^~gdjY7Wq#;t zzQEOPKR2~)XGc@dnvCja!czDzOZp8j&*7@mM1x9HIxuc46?B{TI?hb zPCd_8UjHTgXO6t{$uD3*6SgKg84B}!W8eY)Hny+fcFsxiXrBO)lx(zHNXFuPf9O&E zF}lB@HqKe{3kYRIi;mKK)@whDN;&%HADz?7)_jL9NQm;{+-T-QC}{p(I%sd-Eq^jNJ#2@4rXY^9JA zo!;i7G6TUB&-sUVCOD|3myAfgtpH3+=7i5I6?zPtiHQk){X_y-ck%{;5J^E+2%~@? zI%=z`))uoYuCe>LHr~hem95-gevaX2hHfK$LIEf{_K|opz&1=Q%hCc+ZKYDF|ltaLb_tqBJLkrM1d13{2Bxe0-czsdVm;Ux1DX zQu0=qr_)ODwbTuyghNSIkGt0=A|-8_MS?&?T7YjSfO9I&n+S%&87{KB_^@*^)3SWb z+^g?p;nOYCbeOId!~zxsFf}!G^x8UbSS18=vch}pO|*%W&JC6#j3gJ(j%&rWFIfsD zfQ6bpXG@$9m(0*gP(v@u3Y~^ax6yk{e|@uH~eZ0^(HWqdHPm1HUb zrm`h<_&7 z&aRegz_r*{7^D*TSjJIhRGwNr)tk)FVJ8@`%+?BGLg*P+r7czJQf5<>Rdz?)=yN-m z5+3zf(wdSVuNKG$B?1}fK{+DE=0rQKRuW@zmTD>OjlmXnHC@GIyu?pmdz=@i-oOxs zer}OGQYSr~@n*iu z%KwWOiw8O4q#%C-)ahuJ?DX#uF!TbY1%nIIc)VYE8QzT822lkFs}#M}0> zIn~XmH_fY41ANTA3R@ZshItOlY1(9x&vPX`>2@aTRQFYpS1ITB4nD%uGykG9*2I=% zr}n_hp(^#Q*3o=g&Rf2kQBw%KFvL*#_X;(A)ppD(2FD9`B-%i14GJVd6AO z{)yav{yepJk@$K*Im|W^^dy`0nmss0;ti2kcK++pXX%KgkBi$YLCiZpm4_>bS6RhQ zxZcAf(nSuIZ!sH( zvka5wn8U1J*7d%6D!fZk7x|oDq!?D}-eYGzoRww3wPe}c*3TnT&-2j1XGmC%PES?X zQu(3DOpoG=J4#4A>{;FLh#D2?J*L+;pk9fo7- zt&24$pD=7~Z#ulysaZ+|W5VF&Xqb-`Ci!yzhsalp{C42)WK%A-VJ{M{$B(GKlV)81 zD4`8ia$MVb33pxaNt~EXF{=(6{zSu-(n-<*Fg- zAFOhE%DuH4DISVm;r{%*0509luD+cNmUH+@0Clvvpz2wtlOJ64DYmqAGZxG$d#HOn z$G2H0cD7zjtC^zQ;Owi+E{;Wq;qqX#m-`k4u!~!JZ{V=ffbir3IF|UQ^^A}Cg@%@| zt0KQ4*38YB%XPtGX|<&u92G!{hr$H`1l+Yv31BCKC-DJF(-w(e_$m6^x)}9mb&|7M zG{oYL?(67rIvA-=pP~S4y_xWEw3mDHPf{)yx$Dwf=S^U0es#8_NGWPIzDPXN&3G_- z$~L|n4KYxT@4J1U&>I8e{!GIHsQCbkswp{89c8SL$Mfg7^OBFVyLYEHfokMy(na(|}eDL_K(j-4V^f<2u zL%4Q=W)atQ^yQHAM^5s1BtnZ1$*t^mw(C0mw5TAW+M%K*J3-uZ_|wQhDSe&O+!{%d**Q?nLBS?MsE#YL&6Ev6^HXSO=VD9P?6PHk&;gC+1z8 b836wSr|~NeL{4p*00000NkvXXu0mjfYBbcb literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..1b523998081149a985cef0cdf89045b9ed29964a GIT binary patch literal 5024 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 JPDHLkV1h6>Y;FJm literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..115a4c768a20c9e13185c17043f4c4d12dd4632a GIT binary patch literal 2858 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5b3a85846a429eb7a4ef9784ff53cbc074a5e3 GIT binary patch literal 6814 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 M07*qoM6N<$g32!wPXGV_ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..8e19b410a1b15ff180f3dacac19395fe3046cdec GIT binary patch literal 10676 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 a9sdtN6eHRrdyqB&0000zG<@ufem-oYT zpQ)L?UEO`=p1L&^siGujRuDh>99iWR;j=7Hj4?YvMV-lq9&@L_4j(kgr<#kic3gS9MJ< ztH{8WpQND3p1MGlJh;!B#yqsU6lphhw?rb3MITjEVYN#EtJm;hJ=S2uo5$6`J$Z|w z00#ExU%*pw=U1TBWjEx||DxkC&-?SI;69@-cqsp0$IWcgL71${a=Y)gCA>A!YiuNQ zcEM!I9_C60dl1mv%h-$D%Vu;}{7O%r#(lMjRDgX?bg3NJ1+(h25=Mg#OB?79^Xy>s z`Y5l326GDYN`0C0Fo?>wBhV`Xv!UxFYr_oKKX^8`Tj0Ul3Clu#MdxiIfn7osL_6gn z?IIt}0pwNAz)c_)%npG+-D?itqaqslPig29bSy}JymV1i|0IFoQD)IRF&BZn@aZ`g z{{gqDy`*0^kSnc?=6_syXAP2pBk+=b=h5w`&8! zoPNpwMPA5c(-n(Qu>OB<@T0D!kKI@&WXdI)-W+CpK14JV^+lc?DjbrVKeJdqaA!{d z$G&viVx+aKOT#so@mIiz(?4tvBF612-MDR2d^gTh3DeAriIrHnK6YgP>urbfboPS} ze@-JyxIA?|)8Lb;-GOYK(8P*8APFVSkcd9GKK7XlqQ4Bcu~a zB@PCq6elEQ5mVjw7q3r$*=yrCb)N&5A3N$SpSyooc0*s)x!Yx9QZztF)Q1Yh0PF)N z_KEz3A321sEp2gSY9@7KA`r|a`H<+w(B*Z^YEs-%Q|LN#ne^=i+Mc@CAlyM;%9%9A zn_#U5KeGG4ZFc@8j60n9ZK5gjl4??E*x%nmEYyFLDK4!5#}T7J6G64&3T@TJ%Q`NY z7@IqEakiWwb8q{c5pRzA1y+k%B+Dn7^5$Y!ce*O(&4R9N45!uaq5V-{fr$-&%88t( zwuh3^r}I$fDBretz}~z~q&JvY!1~|Zlpj^(V7qAbUcT?8U^$L-%S;bQ%@RSDOoD-Z zaJXzrX@1xI*jWev%FDCFmxnTQdQa&0ZC?${pJ2$r^c60y->_}Q2NvhnZ6;)7n^|FEst}FgJ6of#WiM(efG*wci$^wpmU?( zl$K|f`{2ho+zkk*bhR5M54tfTx^il55D)BS$UsF(F&E{xh*xH=@~!S90U1Lgjq z1rMWkiN<;)!smxymRCJ~-mvHh_8db9;bQKy^_?N3=ysu?ALBIep`;Hd4hR5CU2KBK&x||682?K!v z+mwxqp7bz1V?6_m4`}yltNK2L{{RvOgtkcv>Xd+irV1Zg?7NrQwUcMJSKqv2{?TCK zw)tEg=VUHm2Ar;h1l>r*;vaUZIYdk%K`lUmA6Vu1n1Lv-Y3wVc10@2CH6Uf0jOBtXih)v9l4QQqgRQn7(e zjaxr#z4F_K_2<8%{Ka+Gh9y@jDWvlLl({hEw{aU;ZNMANr6Myzehvb@kwT<32?G=F_|@c7Cxbe`cg>%f=C4teDX9bv9sroX;jnB-<~NG@j(! zvU{UnuQVWxODb352n+up7sH?HP4}1kD?&=uYeJ0ir`mUKr$AwO)Kbfc_oN+~o_?nY zO;}KT3VVz%uwQDB<>2rIOE9l|&gn$jFZr9W$V|!r?{0P$N+$GEJBt6x78svl&7r7* zYvh+VgEP|7OsOq*q+2onl`Aryoj#4O!O-Y=^zMLbIZKc=yMpb&;H4Yiuk4 zg)j&sFn&s#ZOFYW{=4-KI|!Y7osb>&i!EJV10RdDr}-o2ZZdeJy+e2S9RpR0xHwXB zRQ~z{i?T917guc+8uyvRyPLMWRRNHc)WgGVKAQ5fjLb~ym2ji?LqcMZ^qT7&wWXe! z{EO1u+^pE~nGzuJO{J^<ctaZ$N>yi@d!L`5 z!|D)Y04RzQkp*PqM5*cIF$e>W15*D%6I3afh9tO`a?ao*m##HCZ%gmfjcvL`4+M&$RQlgT&6&YkAomYNQqcp|{#YwN z{*98H7ojo20_BE_h-izPSVsA1_65`T1m~HIkPD@-Do-Nx8AzC zt68rT(g4IA3sB;T@9ro@N-BrBYzgIYns#1-T}jE5q}G!iN5R0~Lo&66uORhf-mYBZqjjPL!|Zmh9OprHyzB5$)$% z<;>4wwWDo&9@S+I3;q zvOc8UcOQ%F59^dH+DIr)ywKnKTuBzVLaW70gWX>+dme6g_3)SY*$*oG>DWxner?;8 zS{kiudq?{=Q&cKkZDkP52Kz;iT*a@w<}yHJQu7=9lJTu7)lvd{iCY5)*uMzp)h=X+ zd`^$0t;!#Q(Cdf_F07GsEMJ{ye)aowT+lR4q4HK1Efud&f1mKYlWD|7@%~w^1vpE{ z!JRsF-8+Lt@)VAJN^T_)3$Qh##cGUjwmLJ7O3xGCdAf{FLJgGZz2@f!>B;Wr*Kknr zUaE7crYDJ3CDZuJ0loksx-bI&$LN)o`NCTcyT%TRCP_a~#>Cv(O*oy?Q(98ijid?wv@A{c0bV>cTF z@6!9%8<5pgk1wiX@7|4nrszvmJJL12QfMH0$1(@iB{16F@d~*lEZWbmkdJ=NxAzHg zwYxj1Rl)6Z#)H8lC}NU$Jk=n%b1)T4gX|U3zisvvX|{rQ4WnoM*jE5aIJk8Y^p%7-E7 zL+JheB{1fwiGA((uWC|TtAL)nzkRyCmdV+AzV!Q{amI{eLmPbD_;TUew3^FTSbMis zI17?5QviR!Fh4Qgu^Gij&KhO6H|O|8&HX>ir9{m10=$v=Q~QXQnS&c0vHh2tE?kT*7)DE`9`5YvfDf+e3CSY z5?>Q< zk^b7^(Swm>u@U>V%bcKj*NMI805UwMv9_oIdfXo#H?8|Ei_iZ|fnyFtSF)y&5plQ-G_~{aaJKZzB`~cD? zlVrt7g)q05>ciY_6s6=aD_s7W^fv2u+sNRXfP|A6ku6rqQ*uYK7|4IkL}HfDh=2UW z7j>E*OceLYk(h9MrBUmi#X=roD>#&1m`RCEJ=2n$;aFU`@Gd+UY7r;-v>K;=*07J5 z9&`B~r7x|ri}v(9t|Tw?`}>;l;h|#a0OL-M&iq3unM&ASk?U_ZmEU6MnC5m%A?C>& zErp?+VrmD6>2XdSoD-xDZ=5g3+zfxNn_~!G7Bjb^L2;!&NpDMw=;kq7uZ|tzt+&ba z30bA73FD8e5hp{_Z-`r?r+fwzxfV5?LmhKi^I}Q@qEyAOR|r${GamEIR&44 zE8%!}-eKXd&bK%duxW5XT(%nZTQQcd!SIsUS5B%#T^>R12h#6CmoWc@l1UZRTYosy zATTe{Ghg=kz;Cau+EO(Qo2H1U_D}4m+Pu{oI%fyoielkB=);MQ;?$j9oFwvAX{EcT z=N*-0^zI~_=b6rry1AotiS!GcxL1|RDU8?xxP(*|iKfuspL)14_{G2Ae$>;+`0dxT zU#m>`d*3m1BC}r#DV2hK5@UH*(Gq4|UNlT$R4}n(&4{0Whf*#^GFOmfL%M4p(*wtk zc@A3>gFfINF3tVjzNSapmvLK_-(j2QC8mz%JVg>YS}q9rP3<~QsvYL0L!K;Y2VWx( z@FP0YRH>D*LOZ1@5gZJ%Wf0wHn65Re2xb!Z5%?ezHV?m<`^Qg|3%fj$;+N1Ccgw>Yifd#SyYFOzQ049y_x4nOGV-53^b=d_STa;3srL^5%C+ z-F}}`wRlIr&9V@!ir;_EJER`Ik8B1k99`cW zyWgXkvXV=>1aDd|@uu)qhk1T;&P!VXeNEl)v0NHS-ewV^L}vB#6plsLg`wNkr0jtj z*|R3Qm}`kFm~@kU5Jo7w75}xtXVG>#JG^P^xuxy37wF+axGh{k6I+jnU(D<{Z{3#>teueSC+`{*U%xO_yshQMZ?>{LemhhF znupVu^O>0ZtefZ}MLOkMon6gy++|MGI2am--`*xd4Ue74!pss%wBA$)`*&Wwc2F&f zJ0wfF@wnj?aeGVW1VwWFFv%4rM;fj;^#Pk5&jc{orq5wzztvzAG;w(I1ZpWoPn;r# zjI`p)khb7=9aPGGS}e|>gr&}@!4OU4|M5Js_{+l?UG{N(b2K(F8i~sDQnRaM(WI?P zr|GA)C9XQ|cZ0K>ETVI*IZl{o7btU-amT|5jAldyb|*tbKpNdt#A$({g%$2EsHgJ) z+I+2)c~nwuTjJkMyEMg;Dbaa2$40@**a1bgs%A3{H5c0Sk$#v*GsawvEG0&%Ki4jO zH77g~&=-JnQOqILVab9nft3 ziedDH_%Bbv>B&;VtYG*NSKc-;P<6kS(u)wAXnNoRt1d376#~8Me%In1a@+^SMp5-` z@;YBf+~T@MD$36xz9@6zQtEsL3#)RObzs3l{#qZE9Mdw@0+8;dU3m1q;7~)ibbw;6uB|AI>fWSs@h)8HnYNcV9ydnWE1WNTas=aqTG+{} z_T#)9bgQz<;nAG^PZG{ajmC?Z`u4AX-n}JXCM*nVq$?y2FG}T~O4-L(3BQoeyhd&6 z`6bg;xhd#HBA0|vxLj5|*e9@fV=$>P4%F_&Ha*5jBV%F(QEap-JG!@qCqctakxbWf zmK!oMDpm1=!K!<=1J!!|?Pgi8J>?7Ef-1S1D&&Vlj z+YU%lJC|G>7>lO(E-S zF1dnVjL<$7f7QWjson`r7>9O{w|G|2fT}LivwHf(@U%O524!7&eClXAS@+}qFcjVC z$>7&-S61TI?Dp~BoDu+HdmV>%sv)49@%NRi9U(qhtgn(TXOB{LM?$OaJn^U^0f%OP z-yGahuF}m%yU*M&^)ARitz#u-Pwuo6`n7c1YosqJO`jL4Sld2}`;1mP!U~}4^{ke< zN#vh(g^z@j^fu3Dd(o);)6k&wmsz}jBF_Kah^b4|hRBi-ZP^j2gHoMxhR--Mas6R< z{QDA^M(eMuHfG=V4^N&x_hPmJQs^HQf9~8C+CP(?EKO*7r(Ai5)TJIh7AR)c`)pG~ z@k-b)aRimL(;vkCa;J~;)euUO-A-R!pq?I%ZNoR(=95)%UR6QTIRV#zI z3^a&&Y+qDx)Qh?9-eMkhpa^PGii*B}{O#*wzh^8yQJNzPl)SZ49w8Q7^^PzYSw!BL zGI{2d2lyH=GHdWRBEqQyJ#^qU(KbwqQXn=#{Nt0+3>Z|@n|OkwhcYCE6nb*TY-|)N z!-i3672jEB?ua^fZfLnyZa|!Nw@p(gv*D~sOhJFL5DXADOq$esk?OGn!6D2M_rZk{ zK2A>qkwCFqBFWL$xNgC3Xs-4c`EOoXGy$}ocj^!rM3-Qkuo3ef8)CFjd90vXo>g4}x!K-F+d>eQ2p4KD*v~X~!!I9LwuP)VXOtlq zOxSHB>;JRnv1%q_QVaK6(B3iisoJ=SDJCHM>VF9Bp0{D$-A?N|h5Q(Kaq4M->?HKq6(aw zI%y*6u;24eD%O~rc>JS>t#3+Pf%e4BU#snB#23$w`3BwU!Ozn;T9+F!OQ*J{GoNpU z&VwH_wk>uZGmUK(2Q$$J%fH4Tvq)J3s&ECx3hcJHSY7~ z*lBK|-KsqIZl`QvW;6drF!Tr6G}}}Mjy987zegD`M7PkjV@OzIk;t!<Bo|qLq4&*PeBtvlBk=ik z3np*vj;yYWdxX)|)4gSE5fpnDAeyn@;-Tw;4lMBygQ>sNIZ!&y|OK6R7`y% z6YQFTXF}Q%Q>SG*y`X}D?2q+#n-iE4XgmCEG(li{4SQ1uA9SiOpqpl~@+K|$$2C;8?ML_`=o&HLM$B{Mu1dLgY8OUF# zp=ewE_&i{L5Ow7+^zmXU!p>{+<*e-rEj+(BIgh0*TXNxua3SVx%n{f7xTXw`vtgp@ zx_H6%Qt!==gwzY&utNg0%TY9an2v4tJhKpE$luELdJ^I4ck)6k@E}8}oJd_;enmw+ zRcWKHj~-U+CX9Q!{n`9EFZ7Tn&xFi|!lUesgrqvMfFjs@URuqr2s~RQ@MA_qZ3em) zo|uH&MPF00YX1u69Bp z_r~W`$$JgVslNE}Uks$uhnw({YKf4-A9z2csNajc3_!%`#3zEzw*C0KmTfR|_zQB)feC zbgms#LA91nQ9*qrdMrX&wX#%R7!aF{w?iKPyt1zq587;C;I0Q?rIHz0fRU>4z@{Pw zzXmHWG1B*l-bKGc^hekrM!)9qu?~jF>`gDBL9N;gnihw8JtFGzX}Tc~ZYTEv$Ge-MxcE9;A0ywtzFe=%IWo2b_IMHTI=|5cX>alq7^$vn^Obu8Z>Brfq zaWl#lwCU=FB%`1(snuwrN9h<5%+)qX>ga7UWk=)^(F(K5X}(3-pHtf$|UFPLQH;F|p8sts-o z)#lSfgX851g(b{xCt8>oG)hnnb8}RSpHst@p$g6TSG!-0&CJZk`nrHHlgAWRY?h4( z&}e1zlp>8y!xsLQl4+nQ)aQAnA2cpC!e+zwm{!p#3M-Bbdpqo5d(m)me<#PV-YGce?%>*)nv`G=wxqL4eo@AXj-OZWq^AKca>3^C-ki- z3!|E4J9Mdo>grh58>u>3oK7vIb=^(VyqNv!*`5a*|5s-~Dcfm-?f*sx)Km85G=!Re z<^1oLKdcA2wX$fWXvcfXemJ7-|7@rpl-A0Pzi3ost)$^}lX$?bT~x6MqEdmcRFTRJ z?{Ev?#op?Y^+^NMs34nC z1}ToY+q8BRHN1eG-8MhIBHZgJIz?9Ls^%k3_IrFo|6_Y;!+>Ywa_U zn)z#>L~q>6=8!P{FV)JUABeYIV|xlHV9W2nS_hsOE`7I-RO!(uDJgYdGV%ZaDwF^2 e8n|FyMe2xIEdfKm=kLWa09h#|$vSbPp#KLY^N%V3 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..4c19a13c239cb67b8a2134ddd5f325db1d2d5bee GIT binary patch literal 15523 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 BIP(Ai literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..041821f --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #000000 + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..b80075c --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + LX Music + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..6764693 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..c6ec423 --- /dev/null +++ b/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/xml/network_security_config.xml b/android/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 0000000..1c70fa5 --- /dev/null +++ b/android/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..459e7e5 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,43 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext { + buildToolsVersion = "29.0.3" + minSdkVersion = 21 + compileSdkVersion = 29 + targetSdkVersion = 29 + ndkVersion = "20.1.5948944" + kotlinVersion = "1.4.21" // Or any version above 1.3.x + RNNKotlinVersion = kotlinVersion + } + repositories { + google() + jcenter() + mavenLocal() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:4.1.0") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + mavenLocal() + maven { + // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm + url("$rootDir/../node_modules/react-native/android") + } + maven { + // Android JSC is installed from npm + url("$rootDir/../node_modules/jsc-android/dist") + } + + google() + jcenter() + maven { url 'https://www.jitpack.io' } + } +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..6ab6009 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,37 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Version of flipper SDK to use with React Native +FLIPPER_VERSION=0.75.1 + + +# org.gradle.daemon=true +# org.gradle.configureondemand=true +org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +AsyncStorage_dedicatedExecutor = true + +AsyncStorage_useNextStorage = true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 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

K7UpUK$>l@ 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 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..14e30f7 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..94c013e --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,7 @@ +rootProject.name = 'LxMusicMobile' +include ':react-native-splash-screen' +project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android') +include ':react-native-vector-icons' +project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) +include ':app' diff --git a/app.json b/app.json new file mode 100644 index 0000000..fe5ed04 --- /dev/null +++ b/app.json @@ -0,0 +1,4 @@ +{ + "name": "Lx Music", + "displayName": "洛雪音乐助手" +} diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..fd2301c --- /dev/null +++ b/babel.config.js @@ -0,0 +1,29 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + [ + 'module-resolver', + { + root: ['.'], + extensions: [ + '.android.js', + '.ios.js', + '.android.jsx', + '.ios.jsx', + '.jsx', + '.js', + '.json', + ], + alias: { + '@': './src', + // '@config': './src/config', + // '@store': './src/store', + // '@components': './src/components', + // '@navigation': './src/navigation', + // '@screens': './src/screens', + // '@theme': './src/theme', + }, + }, + ], + ], +} diff --git a/doc/images/icon.png b/doc/images/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..67a7f8ef6b1e4f7ea51957f2c901865d1c32855e GIT binary patch literal 6856 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 { + if (isInited) return Promise.resolve() + isInited = true + store = getStore() + // console.log('deviceLanguage', deviceLanguage) + return Promise.all([ + store.dispatch(commonAction.initSetting()), + store.dispatch(listAction.initList()), + initLyric(), + registerPlaybackService(), + ]).then(() => { + let lang = store.getState().common.setting.langId + let needSetLang = false + if (!supportedLngs.includes(lang)) { + if (typeof deviceLanguage == 'string' && supportedLngs.includes(deviceLanguage)) { + lang = deviceLanguage + } else { + lang = 'en_us' + } + needSetLang = true + } + console.log(lang) + return initI18n(lang).then(() => { + if (needSetLang) return store.dispatch(commonAction.setLang(lang)) + }) + // .catch(_ => _) + // StatusBar.setHidden(false) + // console.log('init') + }).then(() => { + initMusicTools() + getPlayInfo().then(info => { + if (!info) return + global.restorePlayInfo = info + if (info.listId != LIST_ID_PLAY_TEMP && info.listId != LIST_ID_PLAY_LATER) { + info.list = global.allList[info.listId] + if (info.list) info.list = info.list.list + } + store.dispatch(playerAction.setList({ + list: { + list: info.list, + id: info.listId, + }, + index: info.index, + })) + }) + }) +} + +initNavigation(async() => { + init().then(() => { + navigations.pushHomeScreen() + SplashScreen.hide() + if (!store.getState().common.setting.isAgreePact) { + showPactModal() + } else { + store.dispatch(commonAction.checkVersion()) + } + }) +}) + diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..76ec851 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@/*": ["src/*"], + // "@config": ["src/config"], + // "@store": ["src/store"], + // "@components": ["src/components"], + // "@navigation": ["src/navigation"], + // "@screens": ["src/screens"], + // "@theme": ["src/theme"], + // "@utils": ["src/utils"], + } + }, + "exclude": ["node_modules"] +} diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000..b755f9b --- /dev/null +++ b/metro.config.js @@ -0,0 +1,17 @@ +/** + * Metro configuration for React Native + * https://github.com/facebook/react-native + * + * @format + */ + +module.exports = { + transformer: { + getTransformOptions: async() => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: true, + }, + }), + }, +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5653a2f --- /dev/null +++ b/package.json @@ -0,0 +1,123 @@ +{ + "name": "lx-music-mobile", + "version": "0.1.1", + "versionCode": 2, + "private": true, + "scripts": { + "ar": "react-native run-android", + "ios": "react-native run-ios", + "start": "react-native start", + "sc": "react-native start --reset-cache", + "test": "jest", + "lint": "eslint .", + "rd": "react-devtools", + "pack": "npm run pack:android", + "pack:android": "./gradlew assembleRelease", + "clear": "react-native clean-project", + "publish": "node publish", + "nodeify": "rn-nodeify --hack --yarn --install process,crypto,events,constant,console,stream,url,util", + "postinstall": "yarn nodeify" + }, + "engines": { + "node": ">= 12" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/lyswhut/lx-music-mobile.git" + }, + "keywords": [ + "music-player", + "react-native-app" + ], + "author": { + "name": "lyswhut", + "email": "lyswhut@qq.com" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/lyswhut/lx-music-mobile/issues" + }, + "homepage": "https://github.com/lyswhut/lx-music-mobile#readme", + "dependencies": { + "@react-native-async-storage/async-storage": "^1.15.4", + "@react-native-community/checkbox": "^0.5.7", + "buffer": "^6.0.3", + "console-browserify": "^1.2.0", + "events": "^3.3.0", + "i18next": "^20.2.2", + "js-htmlencode": "^0.3.0", + "lrc-file-parser": "^1.0.7", + "pako": "^2.0.3", + "process": "^0.11.10", + "prop-types": "^15.7.2", + "react": "17.0.1", + "react-i18next": "^11.8.15", + "react-native": "0.64.0", + "react-native-background-timer": "^2.4.1", + "react-native-crypto": "^2.2.0", + "react-native-fs": "^2.18.0", + "react-native-navigation": "^7.14.0", + "react-native-pager-view": "^5.1.8", + "react-native-randombytes": "^3.6.1", + "react-native-splash-screen": "^3.2.0", + "react-native-track-player": "lyswhut/react-native-track-player#63d6e5147bba3ce476ee751756d0a7de5fe88757", + "react-native-vector-icons": "^8.1.0", + "react-redux": "^7.2.4", + "readable-stream": "1.0.33", + "redux": "^4.1.0", + "redux-subscriber": "^1.1.0", + "redux-thunk": "^2.3.0", + "reselect": "^4.0.0", + "stream-browserify": "^1.0.0", + "url": "~0.10.1", + "util": "~0.10.3" + }, + "devDependencies": { + "@babel/core": "^7.14.2", + "@babel/runtime": "^7.14.0", + "babel-eslint": "^10.1.0", + "babel-jest": "^26.6.3", + "babel-plugin-module-resolver": "^4.1.0", + "changelog-parser": "^2.8.0", + "cross-env": "^7.0.3", + "eslint": "^7.26.0", + "eslint-config-standard": "^16.0.2", + "eslint-plugin-html": "^6.1.2", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^5.1.0", + "eslint-plugin-react": "^7.23.2", + "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-standard": "^5.0.0", + "jest": "^26.6.3", + "metro-react-native-babel-preset": "^0.64.0", + "react-devtools": "^4.13.2", + "react-native-clean-project": "^3.6.3", + "react-test-renderer": "17.0.1", + "redux-logger": "^3.0.6", + "rn-nodeify": "^10.3.0" + }, + "jest": { + "preset": "react-native" + }, + "react-native": { + "console": "console-browserify", + "crypto": "react-native-crypto", + "_stream_transform": "readable-stream/transform", + "_stream_readable": "readable-stream/readable", + "_stream_writable": "readable-stream/writable", + "_stream_duplex": "readable-stream/duplex", + "_stream_passthrough": "readable-stream/passthrough", + "stream": "stream-browserify" + }, + "browser": { + "console": "console-browserify", + "crypto": "react-native-crypto", + "_stream_transform": "readable-stream/transform", + "_stream_readable": "readable-stream/readable", + "_stream_writable": "readable-stream/writable", + "_stream_duplex": "readable-stream/duplex", + "_stream_passthrough": "readable-stream/passthrough", + "stream": "stream-browserify" + } +} diff --git a/publish/changeLog.md b/publish/changeLog.md new file mode 100644 index 0000000..918a250 --- /dev/null +++ b/publish/changeLog.md @@ -0,0 +1,3 @@ + +lx-music移动端v0.1.1版本发布 🎊 🎉 + diff --git a/publish/index.js b/publish/index.js new file mode 100644 index 0000000..6793f6c --- /dev/null +++ b/publish/index.js @@ -0,0 +1,50 @@ +// const fs = require('fs') +// const path = require('path') +const chalk = require('chalk') +// const clearAssets = require('./utils/clearAssets') +// const packAssets = require('./utils/packAssets') +// const compileAssets = require('./utils/compileAssets') +const updateVersionFile = require('./utils/updateChangeLog') +// const copyFile = require('./utils/copyFile') +// const githubRelease = require('./utils/githubRelease') +// const { parseArgv } = require('./utils') + +const run = async() => { + // const params = parseArgv(process.argv.slice(2)) + // const bak = await updateVersionFile(params.ver) + await updateVersionFile(process.argv.slice(2)[0]) + console.log(chalk.green('日志更新完成~')) + + // try { + // console.log(chalk.blue('Clearing assets...')) + // await clearAssets() + // console.log(chalk.green('Assets clear completed...')) + + // // console.log(chalk.blue('Compileing assets...')) + // // await compileAssets() + // // console.log(chalk.green('Asset compiled successfully.')) + + // // console.log(chalk.blue('Building assets...')) + // // await packAssets() + // // console.log(chalk.green('Asset build successfully.')) + + // // console.log(chalk.blue('Copy files...')) + // // await copyFile() + // // console.log(chalk.green('Complete copy of all files.')) + + // // console.log(chalk.blue('Create release...')) + // // await githubRelease(params) + // // console.log(chalk.green('Release created.')) + + // } catch (error) { + // console.log(error) + // console.log(chalk.red('程序发布失败')) + // console.log(chalk.blue('正在还原版本信息')) + // fs.writeFileSync(path.join(__dirname, './version.json'), bak.version_bak + '\n', 'utf-8') + // fs.writeFileSync(path.join(__dirname, '../package.json'), bak.pkg_bak + '\n', 'utf-8') + // console.log(chalk.blue('版本信息还原完成')) + // } +} + + +run() diff --git a/publish/utils/index.js b/publish/utils/index.js new file mode 100644 index 0000000..24e495e --- /dev/null +++ b/publish/utils/index.js @@ -0,0 +1,62 @@ +const fs = require('fs') +const path = require('path') + +exports.jp = (...p) => p.length ? path.join(__dirname, ...p) : __dirname + +exports.copyFile = (source, target) => new Promise((resolve, reject) => { + const rd = fs.createReadStream(source) + rd.on('error', err => reject(err)) + const wr = fs.createWriteStream(target) + wr.on('error', err => reject(err)) + wr.on('close', () => resolve()) + rd.pipe(wr) +}) + +/** + * 时间格式化 + * @param {Date} d 格式化的时间 + * @param {boolean} b 是否精确到秒 + */ +exports.formatTime = (d, b) => { + const _date = d == null ? new Date() : typeof d == 'string' ? new Date(d) : d + const year = _date.getFullYear() + const month = fm(_date.getMonth() + 1) + const day = fm(_date.getDate()) + if (!b) return year + '-' + month + '-' + day + return year + '-' + month + '-' + day + ' ' + fm(_date.getHours()) + ':' + fm(_date.getMinutes()) + ':' + fm(_date.getSeconds()) +} + +function fm(value) { + if (value < 10) return '0' + value + return value +} + +exports.sizeFormate = size => { + // https://gist.github.com/thomseddon/3511330 + if (!size) return '0 b' + let units = ['b', 'kB', 'MB', 'GB', 'TB'] + let number = Math.floor(Math.log(size) / Math.log(1024)) + return `${(size / Math.pow(1024, Math.floor(number))).toFixed(2)} ${units[number]}` +} + +exports.parseArgv = argv => { + const params = {} + argv.forEach(item => { + const argv = item.split('=') + switch (argv[0]) { + case 'ver': + params.ver = argv[1] + break + case 'draft': + params.isDraft = argv[1] === 'true' || argv[1] === undefined + break + case 'prerelease': + params.isPrerelease = argv[1] === 'true' || argv[1] === undefined + break + case 'target_commitish': + params.target_commitish = argv[1] + break + } + }) + return params +} diff --git a/publish/utils/updateChangeLog.js b/publish/utils/updateChangeLog.js new file mode 100644 index 0000000..4d1b0c3 --- /dev/null +++ b/publish/utils/updateChangeLog.js @@ -0,0 +1,54 @@ +const fs = require('fs') +const { jp, formatTime } = require('./index') +const pkgDir = '../../package.json' +const pkg = require(pkgDir) +const version = require('../version.json') +const chalk = require('chalk') +const pkg_bak = JSON.stringify(pkg, null, 2) +const version_bak = JSON.stringify(version, null, 2) +const parseChangelog = require('changelog-parser') +const changelogPath = jp('../../CHANGELOG.md') + +const getPrevVer = () => parseChangelog(changelogPath).then(res => { + if (!res.versions.length) throw new Error('CHANGELOG 无法解析到版本号') + return res.versions[0].version +}) + +const updateChangeLog = async(newVerNum, newChangeLog) => { + let changeLog = fs.readFileSync(changelogPath, 'utf-8') + const prevVer = await getPrevVer() + const log = `## [${newVerNum}](${pkg.repository.url.replace(/^git\+(http.+)\.git$/, '$1')}/compare/v${prevVer}...v${newVerNum}) - ${formatTime()}\n\n${newChangeLog}` + fs.writeFileSync(changelogPath, changeLog.replace(/(## [?0.1.1]?)/, log + '\n$1'), 'utf-8') +} + + +module.exports = async newVerNum => { + if (!newVerNum) { + let verArr = pkg.version.split('.') + verArr[verArr.length - 1] = parseInt(verArr[verArr.length - 1]) + 1 + newVerNum = verArr.join('.') + } + const newMDChangeLog = fs.readFileSync(jp('../changeLog.md'), 'utf-8') + version.history.unshift({ + version: version.version, + desc: version.desc, + }) + version.version = newVerNum + version.desc = newMDChangeLog.replace(/(?:^|(\n))#{1,6} (.+)\n/g, '$1$2').trim() + pkg.version = newVerNum + pkg.versionCode = pkg.versionCode + 1 + + console.log(chalk.blue('new version: ') + chalk.green(newVerNum)) + + fs.writeFileSync(jp('../version.json'), JSON.stringify(version) + '\n', 'utf-8') + + fs.writeFileSync(jp(pkgDir), JSON.stringify(pkg, null, 2) + '\n', 'utf-8') + + await updateChangeLog(newVerNum, newMDChangeLog) + + return { + pkg_bak, + version_bak, + } +} + diff --git a/publish/version.json b/publish/version.json new file mode 100644 index 0000000..28a375a --- /dev/null +++ b/publish/version.json @@ -0,0 +1,5 @@ +{ + "version":"0.1.1", + "desc":"lx-music移动端v0.1.1版本发布 🎊 🎉", + "history":[] +} diff --git a/shim.js b/shim.js new file mode 100644 index 0000000..9d79f38 --- /dev/null +++ b/shim.js @@ -0,0 +1,26 @@ +if (typeof __dirname === 'undefined') global.__dirname = '/' +if (typeof __filename === 'undefined') global.__filename = '' +if (typeof process === 'undefined') { + global.process = require('process') +} else { + const bProcess = require('process') + for (let p in bProcess) { + if (!(p in process)) { + process[p] = bProcess[p] + } + } +} + +process.browser = false +if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer + +// global.location = global.location || { port: 80 } +const isDev = typeof __DEV__ === 'boolean' && __DEV__ +process.env.NODE_ENV = isDev ? 'development' : 'production' +if (typeof localStorage !== 'undefined') { + localStorage.debug = isDev ? '*' : '' +} + +// If using the crypto shim, uncomment the following line to ensure +// crypto is loaded first, so it can populate global.crypto +require('crypto') diff --git a/src/components/ListItem/index.js b/src/components/ListItem/index.js new file mode 100644 index 0000000..87d3dee --- /dev/null +++ b/src/components/ListItem/index.js @@ -0,0 +1,71 @@ +import React from 'react' +import { View, Text, StyleSheet, TouchableOpacity } from 'react-native' +import PropTypes from 'prop-types' +import { BorderWidths } from '@/theme' +import { useGetter } from '@/store' + +const ListItem = ({ data, onPress, badge }) => { + const theme = useGetter('common', 'theme') + return ( + + + + {data.title} + {!!data.badge && {data.badge}} + + {!!data.desc && {data.desc}} + + {!!data.right && {data.right}} + + ) +} + +// class ListItem extends Component { +// state = { + +// } + +// static propTypes = { +// data: PropTypes.object.isRequired, +// onPress: PropTypes.func, +// } + +// render() { +// const { data, onPress, badge } = this.props + +// } +// } + +const styles = StyleSheet.create({ + container: { + width: '100%', + flexDirection: 'row', + flexWrap: 'nowrap', + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 10, + paddingRight: 10, + }, + left: { + flex: 1, + }, + title: { + fontSize: 16, + }, + desc: { + color: '#888', + }, + badge: { + + }, + right: { + flexGrow: 0, + flexShrink: 0, + flexBasis: 'auto', + justifyContent: 'center', + }, + +}) + +export default ListItem + diff --git a/src/components/MusicAddModal.js b/src/components/MusicAddModal.js new file mode 100644 index 0000000..e870f93 --- /dev/null +++ b/src/components/MusicAddModal.js @@ -0,0 +1,112 @@ +import React, { useCallback, useMemo, memo } from 'react' +import { View, StyleSheet, Text, ScrollView } from 'react-native' +import Dialog from '@/components/common/Dialog' +import Button from '@/components/common/Button' +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' +import { useDimensions } from '@/utils/hooks' + + +const ListItem = ({ list, onPress, musicInfo, width }) => { + const theme = useGetter('common', 'theme') + const isDisabled = useMemo(() => { + return list.list.some(s => s.songmid == musicInfo.songmid) + }, [list, musicInfo]) + + return ( + + + + ) +} + +const Title = ({ musicInfo, isMove }) => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + return ( + musicInfo + ? {t(isMove ? 'list_add_title_first_move' : 'list_add_title_first_add')} {musicInfo.name} {t('list_add_title_last')} + : null + ) +} + +export default memo(({ visible, hideModal, musicInfo, listId, isMove = false }) => { + const allList = useGetter('list', 'allList') + const addMusicToList = useDispatch('list', 'listAdd') + const moveMusicToList = useDispatch('list', 'listMove') + const { window } = useDimensions() + + const itemWidth = useMemo(() => { + let w = window.width * 0.9 - 20 + let n = 1 + while (true) { + if (w / n < 100 + n * 30 || n > 9) return parseInt(w / n) + n++ + } + }, [window]) + + const handleSelect = useCallback(list => { + if (isMove) { + moveMusicToList({ + fromId: listId, + toId: list.id, + musicInfo, + }) + } else { + addMusicToList({ + musicInfo, + id: list.id, + }) + } + hideModal() + }, [addMusicToList, hideModal, isMove, listId, moveMusicToList, musicInfo]) + + return ( +

+ + <View style={{ flexShrink: 1 }} onStartShouldSetResponder={() => true}> + <ScrollView style={{ flexGrow: 0 }} keyboardShouldPersistTaps={'always'}> + <View style={{ ...styles.list }}> + { allList.map(list => <ListItem key={list.id} list={list} musicInfo={musicInfo} onPress={handleSelect} width={itemWidth} />) } + </View> + </ScrollView> + </View> + </Dialog> + ) +}) + +const styles = StyleSheet.create({ + title: { + textAlign: 'center', + padding: 15, + }, + list: { + paddingLeft: 15, + paddingRight: 5, + paddingBottom: 5, + flexDirection: 'row', + flexWrap: 'wrap', + // backgroundColor: 'rgba(0,0,0,0.2)' + }, + listItem: { + // width: '50%', + paddingRight: 10, + }, + button: { + paddingTop: 9, + paddingBottom: 9, + paddingLeft: 10, + paddingRight: 10, + marginRight: 10, + marginBottom: 10, + borderRadius: 4, + width: '100%', + alignItems: 'center', + }, +}) diff --git a/src/components/MusicMultiAddModal.js b/src/components/MusicMultiAddModal.js new file mode 100644 index 0000000..62d1ec0 --- /dev/null +++ b/src/components/MusicMultiAddModal.js @@ -0,0 +1,113 @@ +import React, { useCallback, useMemo, memo } from 'react' +import { View, StyleSheet, Text, ScrollView } from 'react-native' +import Dialog from '@/components/common/Dialog' +import Button from '@/components/common/Button' +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' +import { useDimensions } from '@/utils/hooks' + + +const ListItem = ({ list, onPress, width }) => { + const theme = useGetter('common', 'theme') + + return ( + <View style={{ ...styles.listItem, width: width }}> + <Button + style={{ ...styles.button, backgroundColor: theme.secondary45 }} + onPress={() => { onPress(list) }} + > + <Text numberOfLines={1} style={{ fontSize: 12, color: theme.secondary }}>{list.name}</Text> + </Button> + </View> + ) +} + +const Title = ({ list, isMove }) => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + return ( + list.length + ? <Text style={styles.title}>{t(isMove ? 'list_multi_add_title_first_move' : 'list_multi_add_title_first_add')} <Text style={{ color: theme.secondary }} >{list.length}</Text> {t('list_multi_add_title_last')}</Text> + : null + ) +} + +export default memo(({ visible, hideModal, list, onAdd, excludeList = [], listId, isMove = false }) => { + const allList = useGetter('list', 'allList') + const addMultiMusicToList = useDispatch('list', 'listAddMultiple') + const moveMultiMusicToList = useDispatch('list', 'listMoveMultiple') + const { window } = useDimensions() + + const itemWidth = useMemo(() => { + let w = window.width * 0.9 - 20 + let n = 1 + while (true) { + if (w / n < 100 + n * 30 || n > 9) return parseInt(w / n) + n++ + } + }, [window]) + + const handleSelect = useCallback(({ id }) => { + if (isMove) { + moveMultiMusicToList({ + fromId: listId, + toId: id, + list, + }) + } else { + addMultiMusicToList({ + list, + id, + }) + } + hideModal() + onAdd() + }, [isMove, hideModal, onAdd, addMultiMusicToList, list, moveMultiMusicToList, listId]) + + const filteredList = useMemo(() => { + return allList.filter(({ id }) => !excludeList.includes(id)) + }, [allList, excludeList]) + + return ( + <Dialog visible={visible} hideDialog={hideModal}> + <Title list={list} isMove={isMove} /> + <View style={{ flexShrink: 1 }} onStartShouldSetResponder={() => true}> + <ScrollView style={{ flexGrow: 0 }} keyboardShouldPersistTaps={'always'}> + <View style={{ ...styles.list }}> + { filteredList.map(list => <ListItem key={list.id} list={list} onPress={handleSelect} width={itemWidth} />) } + </View> + </ScrollView> + </View> + </Dialog> + ) +}) + +const styles = StyleSheet.create({ + title: { + textAlign: 'center', + padding: 15, + }, + list: { + paddingLeft: 15, + paddingRight: 5, + paddingBottom: 5, + flexDirection: 'row', + flexWrap: 'wrap', + // backgroundColor: 'rgba(0,0,0,0.2)' + }, + listItem: { + // width: '50%', + paddingRight: 10, + }, + button: { + paddingTop: 9, + paddingBottom: 9, + paddingLeft: 10, + paddingRight: 10, + marginRight: 10, + marginBottom: 10, + borderRadius: 4, + width: '100%', + alignItems: 'center', + }, +}) diff --git a/src/components/OnlineList/ExitMultipleModeBar.js b/src/components/OnlineList/ExitMultipleModeBar.js new file mode 100644 index 0000000..57bc104 --- /dev/null +++ b/src/components/OnlineList/ExitMultipleModeBar.js @@ -0,0 +1,142 @@ +import React, { useState, useRef, useEffect, useCallback, useMemo, memo } from 'react' +import { Text, StyleSheet, Animated, View, TouchableOpacity } from 'react-native' +import { useTranslation } from '@/plugins/i18n' + +import Button from '@/components/common/Button' +import { useGetter } from '@/store' + + +export default memo(({ multipleMode, onCancel, onSelectAll, selectMode, onSwitchMode, isSelectAll }) => { + const { t } = useTranslation() + // const isGetDetailFailedRef = useRef(false) + const [visible, setVisible] = useState(false) + const [animatePlayed, setAnimatPlayed] = useState(true) + const animFade = useRef(new Animated.Value(0)).current + const animTranslateY = useRef(new Animated.Value(0)).current + + const theme = useGetter('common', 'theme') + + useEffect(() => { + setAnimatPlayed(true) + if (multipleMode) { + animFade.setValue(0.92) + animTranslateY.setValue(0) + setVisible(true) + } else { + animFade.setValue(0) + animTranslateY.setValue(20) + setVisible(false) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const showList = useCallback(() => { + // console.log('show List') + setVisible(true) + setAnimatPlayed(false) + animTranslateY.setValue(20) + + Animated.parallel([ + Animated.timing(animFade, { + toValue: 0.92, + duration: 200, + useNativeDriver: true, + }), + Animated.timing(animTranslateY, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }), + ]).start(() => { + setAnimatPlayed(true) + }) + }, [animFade, animTranslateY]) + + const hideList = useCallback(() => { + setAnimatPlayed(false) + Animated.parallel([ + Animated.timing(animFade, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }), + Animated.timing(animTranslateY, { + toValue: 20, + duration: 200, + useNativeDriver: true, + }), + ]).start(finished => { + if (!finished) return + setVisible(false) + setAnimatPlayed(true) + }) + }, [animFade, animTranslateY]) + + useEffect(() => { + if (multipleMode) { + showList() + } else { + hideList() + } + }, [hideList, multipleMode, showList]) + + + const animaStyle = useMemo(() => StyleSheet.compose(styles.container, { + backgroundColor: theme.secondary45, + opacity: animFade, // Bind opacity to animated value + transform: [ + { translateY: animTranslateY }, + ], + }), [animFade, animTranslateY, theme]) + + const switchModeSingle = useCallback(() => { + onSwitchMode('single') + }, [onSwitchMode]) + const switchModeRange = useCallback(() => { + onSwitchMode('range') + }, [onSwitchMode]) + + const component = useMemo(() => ( + <Animated.View style={animaStyle}> + <View style={styles.switchBtn}> + <Button onPress={switchModeSingle} style={{ ...styles.btn, backgroundColor: selectMode == 'single' ? theme.secondary40 : 'rgba(0,0,0,0)' }}> + <Text style={{ color: theme.secondary }}>{t('list_select_single')}</Text> + </Button> + <Button onPress={switchModeRange} style={{ ...styles.btn, backgroundColor: selectMode == 'range' ? theme.secondary40 : 'rgba(0,0,0,0)' }}> + <Text style={{ color: theme.secondary }}>{t('list_select_range')}</Text> + </Button> + </View> + <TouchableOpacity onPress={onSelectAll} style={styles.btn}> + <Text style={{ color: theme.secondary }}>{t(isSelectAll ? 'list_select_unall' : 'list_select_all')}</Text> + </TouchableOpacity> + <TouchableOpacity onPress={onCancel} style={styles.btn}> + <Text style={{ color: theme.secondary }}>{t('list_select_cancel')}</Text> + </TouchableOpacity> + </Animated.View> + ), [animaStyle, isSelectAll, selectMode, onCancel, onSelectAll, switchModeRange, switchModeSingle, t, theme]) + + return !visible && animatePlayed ? null : component +}) + +const styles = StyleSheet.create({ + container: { + flex: 1, + position: 'absolute', + left: 0, + bottom: 0, + width: '100%', + height: 40, + flexDirection: 'row', + }, + switchBtn: { + flexDirection: 'row', + flex: 1, + }, + btn: { + // flex: 1, + paddingLeft: 15, + paddingRight: 15, + alignItems: 'center', + justifyContent: 'center', + }, +}) diff --git a/src/components/OnlineList/Footer.js b/src/components/OnlineList/Footer.js new file mode 100644 index 0000000..fd58c0f --- /dev/null +++ b/src/components/OnlineList/Footer.js @@ -0,0 +1,26 @@ +import React, { memo } from 'react' +import { View, Text } from 'react-native' +import { useGetter } from '@/store' +import { useTranslation } from '@/plugins/i18n' + +export const Loading = memo(() => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + return ( + <View style={{ alignItems: 'center', padding: 10 }}> + <Text style={{ color: theme.normal30 }}>{t('list_loading')}</Text> + </View> + ) +}) + + +export const End = memo(() => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + return ( + <View style={{ alignItems: 'center', padding: 10 }}> + <Text style={{ color: theme.normal30 }}>{t('list_end')}</Text> + </View> + ) +}) + diff --git a/src/components/OnlineList/ListItem.js b/src/components/OnlineList/ListItem.js new file mode 100644 index 0000000..5f3cda1 --- /dev/null +++ b/src/components/OnlineList/ListItem.js @@ -0,0 +1,130 @@ +import React, { useCallback, memo, useRef, useMemo } from 'react' +import { StyleSheet, View, Text, TouchableOpacity } from 'react-native' +import { useGetter } from '@/store' +import Button from '@/components/common/Button' +import Badge from '@/components/common/Badge' +import { BorderWidths } from '@/theme' +import { useTranslation } from '@/plugins/i18n' +import Icon from '@/components/common/Icon' + +const useQualityTag = musicInfo => { + const { t } = useTranslation() + let info = {} + if (musicInfo._types.ape || musicInfo._types.flac) { + info.type = 'secondary' + info.text = t('quality_lossless') + } else if (musicInfo._types['320k']) { + info.type = 'tertiary' + info.text = t('quality_high_quality') + } else info = null + + return info +} + +export default memo(({ item, index, onPress, showMenu, handleLongPress, selectedList }) => { + const theme = useGetter('common', 'theme') + + const isSelected = selectedList.indexOf(item) != -1 + + const moreButtonRef = useRef() + const handleShowMenu = useCallback(() => { + if (moreButtonRef.current && moreButtonRef.current.measure) { + moreButtonRef.current.measure((fx, fy, width, height, px, py) => { + // console.log(fx, fy, width, height, px, py) + showMenu(item, index, { x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + }) + } + }, [item, index, showMenu]) + const tagInfo = useQualityTag(item) + + return ( + <View style={{ ...styles.listItem, backgroundColor: isSelected ? theme.secondary45 : theme.primary, borderBottomColor: theme.secondary45 }}> + <TouchableOpacity style={styles.listItemLeft} onPress={ () => { onPress(item, index) }} onLongPress={() => { handleLongPress(item, index) }}> + <Text style={{ ...styles.sn, color: theme.normal50 }}>{index + 1}</Text> + <View style={styles.itemInfo}> + <View style={styles.listItemTitle}> + <Text style={{ ...styles.listItemTitleText, color: theme.normal }}>{item.name}</Text> + { tagInfo ? <Badge type={tagInfo.type}>{tagInfo.text}</Badge> : null } + </View> + <View style={styles.row2}><Text style={{ ...styles.listItemSingle, color: theme.normal40 }}>{item.singer}</Text></View> + </View> + </TouchableOpacity> + <View style={styles.listItemRight}> + <TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.moreButton}> + <Icon name="dots-vertical" style={{ color: theme.normal35 }} size={16} /> + </TouchableOpacity> + </View> + </View> + ) +}, (prevProps, nextProps) => { + return !!(prevProps.item === nextProps.item && + prevProps.index === nextProps.index && + nextProps.selectedList.includes(nextProps.item) == prevProps.selectedList.includes(nextProps.item) + ) +}) + +const styles = StyleSheet.create({ + listItem: { + width: '100%', + flexDirection: 'row', + flexWrap: 'nowrap', + borderBottomWidth: BorderWidths.normal, + // paddingLeft: 10, + paddingRight: 10, + }, + listItemLeft: { + flex: 1, + flexGrow: 1, + flexShrink: 1, + flexDirection: 'row', + alignItems: 'center', + // backgroundColor: 'rgba(0,0,0,0.1)', + }, + sn: { + width: 32, + fontSize: 11, + textAlign: 'center', + // backgroundColor: 'rgba(0,0,0,0.2)', + paddingLeft: 3, + paddingRight: 3, + }, + itemInfo: { + flexGrow: 0, + flexShrink: 1, + paddingTop: 10, + paddingBottom: 10, + }, + listItemTitle: { + flexDirection: 'row', + alignItems: 'flex-end', + }, + listItemTitleText: { + // backgroundColor: 'rgba(0,0,0,0.2)', + flexGrow: 0, + flexShrink: 1, + fontSize: 14, + }, + listItemSingle: { + fontSize: 12, + paddingTop: 2, + }, + listItemBadge: { + fontSize: 10, + paddingLeft: 5, + paddingBottom: 2, + }, + listItemRight: { + flexGrow: 0, + flexShrink: 0, + flexBasis: 'auto', + justifyContent: 'center', + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + moreButton: { + paddingLeft: 10, + paddingRight: 10, + paddingTop: 10, + paddingBottom: 10, + }, +}) + diff --git a/src/components/OnlineList/index.js b/src/components/OnlineList/index.js new file mode 100644 index 0000000..cc8792f --- /dev/null +++ b/src/components/OnlineList/index.js @@ -0,0 +1,279 @@ +import React, { useState, useCallback, memo, useMemo, useRef, useEffect } from 'react' +import { StyleSheet, FlatList, View } from 'react-native' +import { useGetter, useDispatch } from '@/store' +import Menu from '@/components/common/Menu' +import MusicAddModal from '@/components/MusicAddModal' +import MusicMultiAddModal from '@/components/MusicMultiAddModal' +import ListItem from './ListItem' +import ExitMultipleModeBar from './ExitMultipleModeBar' +import LoadingMask from '@/components/common/LoadingMask' +import { useTranslation } from '@/plugins/i18n' +import { Loading as FooterLoading, End as FooterEnd } from './Footer' +import { LIST_ID_PLAY_LATER } from '@/config/constant' + +export default memo(({ + list, + isEnd, + page, + isListRefreshing, + // visibleLoadingMask, + onRefresh, + onLoadMore, + isLoading, + progressViewOffset, + ListHeaderComponent, +}) => { + const defaultList = useGetter('list', 'defaultList') + const defaultListRef = useRef(defaultList) + const addMusicToList = useDispatch('list', 'listAdd') + const setPlayList = useDispatch('player', 'setList') + const setTempPlayList = useDispatch('player', 'setTempPlayList') + const [buttonPosition, setButtonPosition] = useState({ w: 0, h: 0, x: 0, y: 0 }) + const selectedData = useRef({ data: null, index: -1 }) + const [visibleMenu, setVisibleMenu] = useState(false) + const [visibleLoadingMask, setVisibleLoadingMask] = useState(false) + const flatListRef = useRef() + const { t } = useTranslation() + const [visibleMusicAddModal, setVisibleMusicAddModal] = useState(false) + const [isMultiSelectMode, setIsMultiSelectMode] = useState(false) + const isMultiSelectModeRef = useRef(isMultiSelectMode) + const [selectedList, setSelectedList] = useState([]) + const selectedListRef = useRef([]) + const [visibleMusicMultiAddModal, setVisibleMusicMultiAddModal] = useState(false) + const listRef = useRef([]) + const [selectMode, setSelectMode] = useState('single') + const selectModeRef = useRef('single') + const prevSelectIndexRef = useRef(-1) + + useEffect(() => { + defaultListRef.current = defaultList + }, [defaultList]) + useEffect(() => { + listRef.current = list + }, [list]) + + const handlePlay = useCallback((targetSong, index) => { + addMusicToList({ + musicInfo: targetSong, + id: defaultListRef.current.id, + }) + + const targetIndex = defaultListRef.current.list.findIndex(s => s.songmid === targetSong.songmid) + if (targetIndex > -1) { + setPlayList({ + list: defaultListRef.current, + index: targetIndex, + }) + } + }, [addMusicToList, setPlayList]) + + const handleSelect = useCallback((item, index) => { + if (selectModeRef.current == 'single') { + const index = selectedListRef.current.indexOf(item) + if (index < 0) { + selectedListRef.current.push(item) + // setSelectedItem({ item, isChecked: true }) + } else { + selectedListRef.current.splice(index, 1) + // setSelectedItem({ item, isChecked: false }) + } + } else { + if (selectedListRef.current.length) { + const prevIndex = prevSelectIndexRef.current + const currentIndex = index + if (prevIndex == currentIndex) { + selectedListRef.current = [] + } else if (currentIndex > prevIndex) { + selectedListRef.current = listRef.current.slice(prevIndex, currentIndex + 1) + } else { + selectedListRef.current = listRef.current.slice(currentIndex, prevIndex + 1) + selectedListRef.current.reverse() + } + } else { + selectedListRef.current.push(item) + prevSelectIndexRef.current = index + } + } + setSelectedList([...selectedListRef.current]) + }, []) + const handleSelectAll = useCallback(() => { + if (!listRef.current.length) return + if (selectedListRef.current.length == listRef.current.length) { + selectedListRef.current = [] + } else { + selectedListRef.current = [...listRef.current] + } + setSelectedList([...selectedListRef.current]) + }, []) + + const handleSetSelectMode = useCallback(mode => { + setSelectMode(mode) + selectModeRef.current = mode + if (mode == 'range' && selectedListRef.current.length) { + prevSelectIndexRef.current = listRef.current.indexOf(selectedListRef.current[selectedListRef.current.length - 1]) + } + }, []) + + const handleCancelMultiSelect = useCallback(() => { + setIsMultiSelectMode(false) + isMultiSelectModeRef.current = false + selectedListRef.current = [] + setSelectedList([]) + }, []) + const handlePress = useCallback((item, index) => { + if (isMultiSelectModeRef.current) { + handleSelect(item, index) + } else { + handlePlay(item, index) + } + }, [handlePlay, handleSelect]) + + const handleLongPress = useCallback((item, index) => { + setIsMultiSelectMode(true) + isMultiSelectModeRef.current = true + handleSelect(item, index) + }, [handleSelect]) + + const menus = useMemo(() => { + return [ + { action: 'play', label: t('play') }, + { action: 'playLater', label: t('play_later') }, + // { action: 'copyName', label: t('copy_name') }, + // { action: 'download', label: '下载' }, + // { action: 'add', label: '添加到...' }, + // { action: 'move', label: '移动到...' }, + { action: 'add', label: t('add_to') }, + ] + }, [t]) + const showMenu = useCallback((item, index, position) => { + setButtonPosition({ ...position }) + selectedData.current.data = item + selectedData.current.index = index + setVisibleMenu(true) + }, [setButtonPosition]) + const hideMenu = useCallback(() => { + setVisibleMenu(false) + }, [setVisibleMenu]) + const handleMenuPress = useCallback(({ action }) => { + switch (action) { + case 'play': + handlePlay(selectedData.current.data, selectedData.current.index) + break + case 'playLater': + if (selectedListRef.current.length) { + setTempPlayList(selectedListRef.current.map(s => ({ listId: LIST_ID_PLAY_LATER, musicInfo: s }))) + handleCancelMultiSelect() + } else { + setTempPlayList([{ listId: LIST_ID_PLAY_LATER, musicInfo: selectedData.current.data }]) + } + break + // case 'copyName': + // break + case 'add': + console.log(selectedListRef.current.length) + selectedListRef.current.length + ? setVisibleMusicMultiAddModal(true) + : setVisibleMusicAddModal(true) + break + default: + break + } + }, [handleCancelMultiSelect, handlePlay, setTempPlayList]) + + useEffect(() => { + if (isLoading && page == 1) { + setVisibleLoadingMask(true) + } else { + setVisibleLoadingMask(false) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isLoading]) + + useEffect(() => { + if (!flatListRef.current) return + if (page == 1) flatListRef.current.scrollToOffset({ offset: 0, animated: true }) + }, [list, page]) + + const hideMusicAddModal = useCallback(() => { + setVisibleMusicAddModal(false) + }, []) + + const hideMusicMultiAddModal = useCallback(() => { + setVisibleMusicMultiAddModal(false) + }, []) + + const loadingMaskmomponent = useMemo(() => ( + <LoadingMask visible={visibleLoadingMask} /> + ), [visibleLoadingMask]) + const exitMultipleModeBtn = useMemo(() => ( + <ExitMultipleModeBar + multipleMode={isMultiSelectMode} + onCancel={handleCancelMultiSelect} + onSwitchMode={handleSetSelectMode} + onSelectAll={handleSelectAll} + selectMode={selectMode} + isSelectAll={selectedList.length && list.length == selectedList.length} /> + ), [handleCancelMultiSelect, handleSelectAll, handleSetSelectMode, isMultiSelectMode, list, selectMode, selectedList]) + + const renderItem = useCallback(({ item, index }) => ( + <ListItem + item={item} + index={index} + onPress={handlePress} + showMenu={showMenu} + selectedList={selectedList} + handleLongPress={handleLongPress} /> + ), [handleLongPress, handlePress, selectedList, showMenu]) + + return ( + <View style={{ flex: 1 }}> + <FlatList + ref={flatListRef} + style={styles.list} + keyboardShouldPersistTaps={'always'} + data={list} + renderItem={renderItem} + keyExtractor={item => item.songmid.toString()} + onRefresh={onRefresh} + refreshing={isListRefreshing} + maxToRenderPerBatch={8} + updateCellsBatchingPeriod={80} + windowSize={18} + removeClippedSubviews={true} + initialNumToRender={15} + onEndReached={onLoadMore} + progressViewOffset={progressViewOffset} + ListHeaderComponent={ListHeaderComponent} + ListFooterComponent={<View style={{ paddingBottom: isMultiSelectMode ? 40 : 0 }}>{isLoading ? <FooterLoading /> : isEnd ? <FooterEnd /> : null}</View>} + /> + { exitMultipleModeBtn } + <Menu + menus={menus} + buttonPosition={buttonPosition} + onPress={handleMenuPress} + visible={visibleMenu} + hideMenu={hideMenu} /> + <MusicAddModal + visible={visibleMusicAddModal} + hideModal={hideMusicAddModal} + musicInfo={selectedData.current.data} /> + <MusicMultiAddModal + visible={visibleMusicMultiAddModal} + hideModal={hideMusicMultiAddModal} + list={selectedListRef.current} + onAdd={handleCancelMultiSelect} /> + { loadingMaskmomponent } + </View> + ) +}) + + +const styles = StyleSheet.create({ + list: { + flex: 1, + }, + exitMultipleModeBtn: { + height: 40, + }, +}) + diff --git a/src/components/SearchInput.js b/src/components/SearchInput.js new file mode 100644 index 0000000..654e7c9 --- /dev/null +++ b/src/components/SearchInput.js @@ -0,0 +1,35 @@ +import React, { useRef, forwardRef, useImperativeHandle } from 'react' +import { View, StyleSheet } from 'react-native' +import Input from './common/Input' + +const SearchInput = (props, ref) => { + const textInputRef = useRef() + + useImperativeHandle(ref, () => ({ + blur() { + if (!textInputRef.current) return + textInputRef.current.blur() + }, + })) + + return ( + <View style={{ ...styles.container, ...props.styles }}> + <Input {...props} ref={textInputRef} /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + // backgroundColor: AppColors.secondary40, + paddingTop: 5, + paddingBottom: 5, + paddingLeft: 10, + paddingRight: 10, + width: '100%', + // borderBottomLeftRadius: 10, + // borderBottomRightRadius: 10, + }, +}) + +export default forwardRef(SearchInput) diff --git a/src/components/common/Badge.js b/src/components/common/Badge.js new file mode 100644 index 0000000..1e02a64 --- /dev/null +++ b/src/components/common/Badge.js @@ -0,0 +1,46 @@ +import React, { memo, useMemo } from 'react' +import { StyleSheet, Text } from 'react-native' +import { useGetter } from '@/store' +// const menuItemHeight = 42 +// const menuItemWidth = 100 + +const styles = StyleSheet.create({ + text: { + // paddingLeft: 4, + // paddingRight: 4, + fontSize: 9, + // borderRadius: 2, + // lineHeight: 12, + marginTop: 2, + marginLeft: 5, + marginBottom: 2, + alignSelf: 'flex-start', + }, +}) + + +export default memo(({ type, children }) => { + const theme = useGetter('common', 'theme') + // console.log(visible) + const colors = useMemo(() => { + const colors = {} + switch (type) { + case 'normal': + // colors.bgColor = theme.primary + colors.textColor = theme.normal10 + break + case 'secondary': + // colors.bgColor = theme.primary + colors.textColor = theme.secondary10 + break + case 'tertiary': + // colors.bgColor = theme.primary + colors.textColor = theme.tertiary10 + break + } + return colors + }, [type, theme]) + + return <Text style={{ ...styles.text, color: colors.textColor }}>{children}</Text> +}) + diff --git a/src/components/common/Button.js b/src/components/common/Button.js new file mode 100644 index 0000000..a690bdf --- /dev/null +++ b/src/components/common/Button.js @@ -0,0 +1,30 @@ +import React, { useMemo, useRef, useImperativeHandle, forwardRef } from 'react' +import { Pressable } from 'react-native' +import { useGetter } from '@/store' +// import { AppColors } from '@/theme' + +const Btn = ({ ripple: propsRipple, children, disabled, style, ...props }, ref) => { + const theme = useGetter('common', 'theme') + const btnRef = useRef() + const ripple = useMemo(() => ({ + color: theme.secondary30, + ...(propsRipple || {}), + }), [theme, propsRipple]) + + useImperativeHandle(ref, () => ({ + measure(callback) { + if (!btnRef.current) return + btnRef.current.measure(callback) + }, + })) + + return ( + <Pressable android_ripple={ripple} disabled={disabled} style={{ opacity: disabled ? 0.5 : 1, ...style }} {...props} ref={btnRef}> + {children} + </Pressable> + ) +} + + +export default forwardRef(Btn) + diff --git a/src/components/common/CheckBox.js b/src/components/common/CheckBox.js new file mode 100644 index 0000000..e446a4b --- /dev/null +++ b/src/components/common/CheckBox.js @@ -0,0 +1,89 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react' +import { StyleSheet, View, TouchableOpacity, Text } from 'react-native' +import CheckBox from '@react-native-community/checkbox' + +import { useGetter } from '@/store' + +export default ({ check, label, children, onChange, disabled = false, need = false, marginRight = 0, marginBottom = 0 }) => { + const theme = useGetter('common', 'theme') + const [isDisabled, setDisabled] = useState(false) + const tintColors = useMemo(() => { + return { + true: theme.secondary, + false: theme.normal35, + } + }, [theme]) + const disabledTintColors = useMemo(() => { + return { + true: theme.secondary30, + false: theme.normal60, + } + }, [theme]) + + useEffect(() => { + if (need) { + if (check) { + if (!isDisabled) setDisabled(true) + } else { + if (isDisabled) setDisabled(false) + } + } else { + isDisabled && setDisabled(false) + } + }, [check, need, isDisabled]) + + const handleLabelPress = useCallback(() => { + if (isDisabled) return + onChange && onChange(!check) + }, [isDisabled, onChange, check]) + + + const contentStyle = StyleSheet.compose(styles.content, { marginBottom }) + const labelStyle = StyleSheet.compose(styles.label, { marginRight }) + + return ( + disabled + ? ( + <View style={contentStyle}> + <CheckBox style={styles.checkbox} value={check} disabled={true} tintColors={disabledTintColors} /> + <View style={labelStyle}>{label ? <Text style={{ ...styles.name, color: theme.normal40 }}>{label}</Text> : children}</View> + </View> + ) + : ( + <View style={contentStyle}> + <CheckBox value={check} disabled={isDisabled} onValueChange={onChange} tintColors={tintColors} /> + <TouchableOpacity style={labelStyle} activeOpacity={0.5} onPress={handleLabelPress}> + {label ? <Text style={{ ...styles.name, color: theme.normal }}>{label}</Text> : children} + </TouchableOpacity> + </View> + ) + ) +} + +const styles = StyleSheet.create({ + content: { + flexGrow: 0, + flexShrink: 1, + marginRight: 15, + alignItems: 'center', + flexDirection: 'row', + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + checkbox: { + flex: 0, + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + label: { + flexGrow: 0, + flexShrink: 1, + // marginRight: 15, + // alignItems: 'center', + // backgroundColor: 'rgba(0,0,0,0.2)', + // paddingRight: 8, + }, + name: { + marginTop: 2, + fontSize: 13, + }, +}) + diff --git a/src/components/common/ChoosePath/List.js b/src/components/common/ChoosePath/List.js new file mode 100644 index 0000000..38a0dcd --- /dev/null +++ b/src/components/common/ChoosePath/List.js @@ -0,0 +1,128 @@ +import React, { useEffect, useState, useRef, useCallback, useMemo } from 'react' +import { View, StyleSheet, FlatList, Text } from 'react-native' +import { readDir, externalStorageDirectoryPath } from '@/utils/fs' +import { toast } from '@/utils/tools' +import { useTranslation } from '@/plugins/i18n' +import { useGetter, useDispatch } from '@/store' +import Modal from '@/components/common/Modal' + +import Header from './components/Header' +import Main from './components/Main' +import Footer from './components/Footer' +import { sizeFormate } from '@/utils' +// let prevPath = externalStorageDirectoryPath + +const caches = {} + +const handleReadDir = (path, dirOnly, filter, isRefresh = false) => { + const cacheKey = `${path}_${dirOnly ? 'true' : 'false'}_${filter ? filter.toString() : 'null'}` + if (!isRefresh && caches[cacheKey]) return Promise.resolve(caches[cacheKey]) + return readDir(path).then(paths => { + // console.log('read') + // prevPath = path + const list = [] + // console.log(paths) + for (const path of paths) { + // console.log(path) + const isDirectory = path.isDirectory() + if (dirOnly) { + if (!isDirectory) continue + list.push({ + name: path.name, + path: path.path, + mtime: path.mtime, + size: path.size, + isDir: true, + }) + } else { + if (filter != null && path.isFile() && !filter.test(path.name)) continue + + list.push({ + name: path.name, + path: path.path, + mtime: path.mtime, + size: path.size, + isDir: isDirectory, + sizeText: isDirectory ? '' : sizeFormate(path.size), + }) + } + } + + list.sort((a, b) => a.name.charCodeAt(0) - b.name.charCodeAt(0)) + caches[cacheKey] = list + return list + }) +} + +export default ({ dirOnly = false, filter, onConfirm, title, granted, visible, hide }) => { + const [path, setPath] = useState(externalStorageDirectoryPath) + const [list, setList] = useState([]) + const isUnmountedRef = useRef(true) + const isReadingDir = useRef(false) + const theme = useGetter('common', 'theme') + + useEffect(() => { + isUnmountedRef.current = false + return () => isUnmountedRef.current = true + }, []) + + const readDir = useCallback((path, dirOnly, filter, isRefresh) => { + if (isReadingDir.current) return + isReadingDir.current = true + return handleReadDir(path, dirOnly, filter, isRefresh).then(list => { + if (isUnmountedRef.current) return + setList(list) + setPath(path) + }).catch(err => { + toast(`Read dir error: ${err.message}`, 'long') + // console.log('prevPath', prevPath) + // if (isReadingDir.current) return + // setPath(prevPath) + }).finally(() => { + isReadingDir.current = false + }) + }, [setPath]) + + useEffect(() => { + // console.log(granted) + if (!granted) return + readDir(path, dirOnly, filter) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [granted, filter, dirOnly]) + + const onSetPath = useCallback(pathInfo => { + // console.log('onSetPath') + if (pathInfo.isDir) { + readDir(pathInfo.path, dirOnly, filter) + } else { + onConfirm(pathInfo.path) + // setPath(pathInfo.path) + } + }, [dirOnly, filter, onConfirm, readDir]) + + + const toParentDir = useCallback(() => { + const parentPath = path.substring(0, path.lastIndexOf('/')) + readDir(parentPath.length ? parentPath : externalStorageDirectoryPath, dirOnly, filter) + }, [dirOnly, filter, path, readDir]) + + // const dirList = useMemo(() => [parentDir, ...list], [list, parentDir]) + + return ( + <Modal visible={visible} hideModal={hide} bgHide={false}> + <View style={{ ...styles.container, backgroundColor: theme.primary }}> + <Header refreshDir={path => readDir(path, dirOnly, filter, true)} title={title} path={path} /> + <Main list={list} granted={granted} toParentDir={toParentDir} onSetPath={onSetPath} /> + <Footer onConfirm={() => onConfirm(path)} hide={hide} dirOnly={dirOnly} /> + </View> + </Modal> + ) +} + + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}) + diff --git a/src/components/common/ChoosePath/components/Footer.js b/src/components/common/ChoosePath/components/Footer.js new file mode 100644 index 0000000..bc1819e --- /dev/null +++ b/src/components/common/ChoosePath/components/Footer.js @@ -0,0 +1,40 @@ +import React, { memo } from 'react' +import { View, StyleSheet, Text } from 'react-native' +import { useTranslation } from '@/plugins/i18n' +import { useGetter } from '@/store' +import Button from '@/components/common/Button' +import { BorderWidths } from '@/theme' + +export default memo(({ onConfirm, hide, dirOnly }) => { + const { t } = useTranslation() + const theme = useGetter('common', 'theme') + + return ( + <View style={{ ...styles.footer, borderTopColor: theme.secondary30 }} > + <Button style={{ ...styles.footerBtn, backgroundColor: theme.secondary45, width: dirOnly ? '50%' : '100%' }} onPress={hide}> + <Text style={{ color: theme.secondary_5 }}>{t('cancel')}</Text> + </Button> + {dirOnly + ? <Button style={{ ...styles.footerBtn, backgroundColor: theme.secondary45 }} onPress={onConfirm}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>{t('confirm')}</Text> + </Button> + : null + } + </View> + ) +}) + +const styles = StyleSheet.create({ + footer: { + flexGrow: 0, + flexShrink: 0, + flexDirection: 'row', + borderTopWidth: BorderWidths.normal2, + }, + footerBtn: { + width: '50%', + paddingTop: 15, + paddingBottom: 15, + alignItems: 'center', + }, +}) diff --git a/src/components/common/ChoosePath/components/Header.js b/src/components/common/ChoosePath/components/Header.js new file mode 100644 index 0000000..fe45f26 --- /dev/null +++ b/src/components/common/ChoosePath/components/Header.js @@ -0,0 +1,127 @@ +import React, { useCallback, memo, useRef, useState } from 'react' +import { StyleSheet, View, Text, TouchableOpacity, StatusBar, InteractionManager } from 'react-native' +import { useGetter } from '@/store' +import Icon from '@/components/common/Icon' +import Input from '@/components/common/Input' +import ConfirmAlert from '@/components/common/ConfirmAlert' +import { useTranslation } from '@/plugins/i18n' +import { toast } from '@/utils/tools' +import { mkdir } from '@/utils/fs' +const filterFileName = /[\\/:*?#"<>|]/ + +export default memo(({ title, path, refreshDir }) => { + const theme = useGetter('common', 'theme') + const [visibleNewFolder, setVisibleNewFolder] = useState(false) + const { t } = useTranslation() + const [text, setText] = useState('') + // const moreButtonRef = useRef() + // const handleShowMenu = useCallback(() => { + // if (moreButtonRef.current && moreButtonRef.current.measure) { + // moreButtonRef.current.measure((fx, fy, width, height, px, py) => { + // // console.log(fx, fy, width, height, px, py) + // showMenu(item, index, { x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + // }) + // } + // }, [item, index, showMenu]) + + const refresh = useCallback(() => { + InteractionManager.runAfterInteractions(() => { + refreshDir(path) + }) + }, [refreshDir, path]) + + const handleCancelNewFolderAlert = useCallback(() => { + setVisibleNewFolder(false) + setText('') + }, []) + const handleConfirmNewFolderAlert = useCallback(() => { + if (filterFileName.test(text)) { + toast(t('create_new_folder_error_tip'), 'long') + return + } + const newPath = `${path}/${text}` + mkdir(newPath).then(() => { + refreshDir(path).then(() => { + refreshDir(newPath) + }) + setText('') + }).catch(err => { + toast('Create failed: ' + err.message) + }) + setVisibleNewFolder(false) + }, [path, refreshDir, t, text]) + + return ( + <> + <View style={{ ...styles.header, backgroundColor: theme.secondary }} onStartShouldSetResponder={() => true}> + <View style={styles.titleContent}> + <Text style={{ ...styles.title, color: theme.primary }} numberOfLines={1}>{title}</Text> + <Text style={{ color: theme.primary, fontSize: 12 }} numberOfLines={1}>{path}</Text> + </View> + <View style={styles.actions}> + <TouchableOpacity style={styles.actionBtn} onPress={() => setVisibleNewFolder(true)}><Icon name="folder-plus" style={{ color: theme.primary, fontSize: 20 }} /></TouchableOpacity> + <TouchableOpacity style={styles.actionBtn} onPress={refresh}><Icon name="autorenew" style={{ color: theme.primary, fontSize: 20 }} /></TouchableOpacity> + </View> + </View> + <ConfirmAlert + visible={visibleNewFolder} + onCancel={handleCancelNewFolderAlert} + onConfirm={handleConfirmNewFolderAlert} + > + <View style={styles.newFolderContent}> + <Text style={{ color: theme.normal, marginBottom: 5 }}>{t('create_new_folder')}</Text> + <Input + placeholder={t('create_new_folder_tip')} + value={text} + onChangeText={setText} + style={{ ...styles.input, backgroundColor: theme.secondary40 }} + /> + </View> + </ConfirmAlert> + </> + ) +}) + +const styles = StyleSheet.create({ + header: { + flexGrow: 0, + flexShrink: 0, + flexDirection: 'row', + paddingLeft: 15, + paddingRight: 15, + paddingTop: StatusBar.currentHeight, + alignItems: 'center', + }, + titleContent: { + flexGrow: 1, + flexShrink: 1, + height: 57, + paddingRight: 5, + // paddingBottom: 10, + }, + title: { + fontSize: 16, + paddingTop: 10, + }, + actions: { + flexDirection: 'row', + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + actionBtn: { + padding: 8, + }, + newFolderContent: { + flexShrink: 1, + flexDirection: 'column', + }, + input: { + flexGrow: 1, + flexShrink: 1, + minWidth: 240, + borderRadius: 4, + paddingTop: 2, + paddingBottom: 2, + fontSize: 12, + }, +}) + diff --git a/src/components/common/ChoosePath/components/ListItem.js b/src/components/common/ChoosePath/components/ListItem.js new file mode 100644 index 0000000..f75b54b --- /dev/null +++ b/src/components/common/ChoosePath/components/ListItem.js @@ -0,0 +1,72 @@ +import React, { useCallback, memo, useRef } from 'react' +import { StyleSheet, View, Text, TouchableOpacity } from 'react-native' +import { useGetter } from '@/store' +import { BorderWidths } from '@/theme' +import Icon from '@/components/common/Icon' + + +export default memo(({ item, onPress }) => { + const theme = useGetter('common', 'theme') + + // const moreButtonRef = useRef() + // const handleShowMenu = useCallback(() => { + // if (moreButtonRef.current && moreButtonRef.current.measure) { + // moreButtonRef.current.measure((fx, fy, width, height, px, py) => { + // // console.log(fx, fy, width, height, px, py) + // showMenu(item, index, { x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + // }) + // } + // }, [item, index, showMenu]) + + return ( + <View style={{ ...styles.listItem, borderBottomWidth: BorderWidths.normal, borderBottomColor: theme.borderColor2 }}> + <TouchableOpacity style={styles.listItem} onPress={ () => { onPress(item) } }> + <View style={styles.itemInfo}> + <View style={styles.listItemTitle}> + <Text style={{ ...styles.listItemTitleText, color: theme.normal }}>{item.name}</Text> + </View> + <View style={styles.row2}><Text style={{ ...styles.listItemDesc, color: theme.normal50 }} numberOfLines={1}>{item.mtime ? new Date(item.mtime).toLocaleString() : item.desc}</Text></View> + </View> + {item.isDir ? <Icon name="chevron-right" style={{ color: theme.secondary20, fontSize: 18 }} /> : <Text style={{ ...styles.size, color: theme.normal40 }}>{item.sizeText}</Text>} + </TouchableOpacity> + </View> + ) +}) + +const styles = StyleSheet.create({ + listItem: { + width: '100%', + flexDirection: 'row', + flexWrap: 'nowrap', + paddingLeft: 10, + paddingRight: 10, + alignItems: 'center', + // backgroundColor: 'rgba(0,0,0,0.1)', + }, + itemInfo: { + flexGrow: 1, + flexShrink: 1, + paddingTop: 10, + paddingBottom: 10, + }, + listItemTitle: { + flexDirection: 'row', + alignItems: 'flex-end', + }, + listItemTitleText: { + // backgroundColor: 'rgba(0,0,0,0.2)', + flexGrow: 0, + flexShrink: 1, + fontSize: 15, + }, + listItemDesc: { + fontSize: 11, + paddingTop: 2, + }, + size: { + fontSize: 11, + alignSelf: 'flex-end', + marginBottom: 10, + }, +}) + diff --git a/src/components/common/ChoosePath/components/Main.js b/src/components/common/ChoosePath/components/Main.js new file mode 100644 index 0000000..5224c95 --- /dev/null +++ b/src/components/common/ChoosePath/components/Main.js @@ -0,0 +1,57 @@ +import React, { useMemo } from 'react' +import { View, StyleSheet, FlatList, Text } from 'react-native' +import { useTranslation } from '@/plugins/i18n' + +import ListItem from './ListItem' + + +export default ({ granted, list, onSetPath, toParentDir }) => { + const { t } = useTranslation() + + const ParentItemComponent = useMemo(() => ( + <ListItem style={{ flexGrow: 0, flexShrink: 0 }} item={{ + name: '..', + desc: t('parent_dir_name'), + isDir: true, + }} onPress={toParentDir} /> + ), [t, toParentDir]) + + const ListComponent = useMemo(() => ( + <FlatList + keyboardShouldPersistTaps={'always'} + style={styles.list} + data={list} + renderItem={({ item }) => <ListItem item={item} onPress={onSetPath} />} + keyExtractor={item => item.path + '/' + item.name} + removeClippedSubviews={true} + /> + ), [list, onSetPath]) + + // const dirList = useMemo(() => [parentDir, ...list], [list, parentDir]) + + return ( + <View style={styles.main}> + { + granted + ? <> + {ParentItemComponent} + {ListComponent} + </> + : null + } + </View> + ) +} + + +const styles = StyleSheet.create({ + main: { + flexGrow: 1, + flexShrink: 1, + }, + list: { + flexGrow: 1, + flexShrink: 1, + }, +}) + diff --git a/src/components/common/ChoosePath/index.js b/src/components/common/ChoosePath/index.js new file mode 100644 index 0000000..c65729e --- /dev/null +++ b/src/components/common/ChoosePath/index.js @@ -0,0 +1,78 @@ +import React, { memo, useCallback, useEffect, useState, useRef } from 'react' +import { StyleSheet, View, Text, StatusBar, ScrollView } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import List from './List' + +import { useTranslation } from '@/plugins/i18n' +import { checkStoragePermissions, requestStoragePermission } from '@/utils/common' +import ConfirmAlert from '@/components/common/ConfirmAlert' +import { toast } from '@/utils/tools' + + +export default ({ + visible = false, + hide = () => {}, + dirOnly = false, + title = '', + filter, + onConfirm = () => {}, +}) => { + const { t } = useTranslation() + const [granted, setGranted] = useState(false) + const [visibleTips, setVisibleTips] = useState(false) + + useEffect(() => { + if (visible) { + checkStoragePermissions().then(isGranted => { + // console.log(isGranted) + if (isGranted) { + setGranted(isGranted) + } else { + setVisibleTips(true) + } + }) + } + }, [visible]) + + const handleTipsCancel = useCallback(() => { + toast(t('disagree_tip'), 'long') + setVisibleTips(false) + hide() + }, [t, hide]) + const handleTipsConfirm = useCallback(() => { + setVisibleTips(false) + if (granted === null) return hide() + requestStoragePermission().then(result => { + // console.log(result) + setGranted(result) + if (!result) { + setVisibleTips(true) + toast(t('storage_permission_tip_disagree'), 'long') + } + }) + }, [granted, t, hide]) + + return ( + <> + <List + dirOnly={dirOnly} + filter={filter} + title={title} + granted={granted} + hide={hide} + onConfirm={onConfirm} + visible={visible} /> + <ConfirmAlert + visible={visibleTips} + onCancel={handleTipsCancel} + onConfirm={handleTipsConfirm} + bgHide={false} + closeBtn={false} + showCancel={granted !== null} + cancelText={t('disagree')} + confirmText={t('agree')} + text={t(granted === null ? 'storage_permission_tip_disagree_ask_again' : 'storage_permission_tip_request')} /> + </> + ) +} diff --git a/src/components/common/ConfirmAlert.js b/src/components/common/ConfirmAlert.js new file mode 100644 index 0000000..6c70306 --- /dev/null +++ b/src/components/common/ConfirmAlert.js @@ -0,0 +1,79 @@ +import React, { useMemo } from 'react' +import { StyleSheet, View, Text, ScrollView } from 'react-native' +import { useTranslation } from '@/plugins/i18n' +import Dialog from './Dialog' +import Button from './Button' +import { useGetter } from '@/store' + +const styles = StyleSheet.create({ + main: { + // flexGrow: 0, + flexShrink: 1, + marginTop: 15, + marginLeft: 15, + marginRight: 15, + marginBottom: 25, + }, + content: { + flexGrow: 0, + }, + title: { + fontSize: 14, + }, + btns: { + flexDirection: 'row', + justifyContent: 'center', + paddingBottom: 15, + paddingLeft: 15, + // paddingRight: 15, + }, + btn: { + flex: 1, + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 10, + paddingRight: 10, + alignItems: 'center', + borderRadius: 4, + marginRight: 15, + }, +}) + + +export default ({ + visible = false, + onCancel = () => {}, + onConfirm = () => {}, + keyHide, + bgHide, + closeBtn, + title = '', + text = '', + cancelText = '', + confirmText = '', + showCancel = true, + children, +}) => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + + return ( + <Dialog visible={visible} hideDialog={onCancel} keyHide={keyHide} bgHide={bgHide} closeBtn={closeBtn} title={title}> + <View style={styles.main}> + <ScrollView style={styles.content} keyboardShouldPersistTaps={'always'}> + {children || <Text style={{ ...styles.title, color: theme.normal }}>{text}</Text>} + </ScrollView> + </View> + <View style={styles.btns}> + {showCancel + ? <Button style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={onCancel}> + <Text style={{ color: theme.secondary_5 }}>{cancelText || t('cancel')}</Text> + </Button> + : null} + <Button style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={onConfirm}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>{confirmText || t('confirm')}</Text> + </Button> + </View> + </Dialog> + ) +} diff --git a/src/components/common/Dialog.js b/src/components/common/Dialog.js new file mode 100644 index 0000000..7bc84b9 --- /dev/null +++ b/src/components/common/Dialog.js @@ -0,0 +1,84 @@ +import React, { useMemo } from 'react' +import { StyleSheet, View, Text, TouchableHighlight } from 'react-native' + +import Modal from './Modal' +import Icon from './Icon' +import { useGetter } from '@/store' + +const styles = StyleSheet.create({ + centeredView: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'rgba(0,0,0,0.2)', + }, + modalView: { + maxWidth: '90%', + minWidth: '50%', + maxHeight: '78%', + backgroundColor: 'white', + borderRadius: 4, + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.25, + // shadowRadius: 4, + elevation: 3, + }, + header: { + flexGrow: 0, + flexShrink: 0, + flexDirection: 'row', + borderTopLeftRadius: 4, + borderTopRightRadius: 4, + height: 20, + }, + title: { + fontSize: 13, + paddingLeft: 5, + paddingRight: 25, + lineHeight: 20, + }, + closeBtn: { + position: 'absolute', + right: 0, + borderTopRightRadius: 4, + flexGrow: 0, + flexShrink: 0, + height: 20, + width: 20, + justifyContent: 'center', + alignItems: 'center', + }, +}) + + +export default ({ + visible = false, + hideDialog = () => {}, + keyHide = true, + bgHide = true, + closeBtn = true, + title = '', + children, +}) => { + const theme = useGetter('common', 'theme') + + const closeBtnComponent = useMemo(() => closeBtn ? <TouchableHighlight style={styles.closeBtn} underlayColor={theme.secondary_5} onPress={hideDialog}><Icon name="close" style={{ color: theme.secondary40, fontSize: 10 }} /></TouchableHighlight> : null, [closeBtn, hideDialog, theme]) + + return ( + <Modal visible={visible} hideModal={hideDialog} keyHide={keyHide} bgHide={bgHide}> + <View style={{ ...styles.centeredView }}> + <View style={styles.modalView} onStartShouldSetResponder={() => true}> + <View style={{ ...styles.header, backgroundColor: theme.secondary }}> + <Text style={{ ...styles.title, color: theme.primary }} numberOfLines={1}>{title}</Text> + {closeBtnComponent} + </View> + {children} + </View> + </View> + </Modal> + ) +} diff --git a/src/components/common/DorpDownMenu.js b/src/components/common/DorpDownMenu.js new file mode 100644 index 0000000..29e85d5 --- /dev/null +++ b/src/components/common/DorpDownMenu.js @@ -0,0 +1,56 @@ +import React, { useState, useCallback, useRef } from 'react' +// import { View } from 'react-native' + +import Menu from './Menu' +import Button from './Button' + + +export default ({ + children, + menus = [], + onPress, + longPress, + width, + height, + center, +}) => { + const [visible, setVisible] = useState(false) + const [buttonPosition, setButtonPosition] = useState({}) + + const hideMenu = useCallback(() => { + setVisible(false) + }, [setVisible]) + + const buttonRef = useRef() + const setPosition = useCallback((callback = () => {}) => { + if (buttonRef.current && buttonRef.current.measure) { + buttonRef.current.measure((fx, fy, width, height, px, py) => { + // console.log(fx, fy, width, height, px, py) + setButtonPosition({ x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + callback() + }) + } + }, []) + + const showMenu = useCallback(() => { + setPosition(() => { + setVisible(true) + }) + }, [setPosition, setVisible]) + + return ( + <Button ref={buttonRef} onPress={showMenu}> + {children} + <Menu menus={menus} + buttonPosition={buttonPosition} + center={center} + onPress={onPress} + longPress={longPress} + visible={visible} + hideMenu={hideMenu} + width={width} + height={height} + /> + </Button> + ) +} diff --git a/src/components/common/DorpDownPanel/Panel.js b/src/components/common/DorpDownPanel/Panel.js new file mode 100644 index 0000000..2ee9a98 --- /dev/null +++ b/src/components/common/DorpDownPanel/Panel.js @@ -0,0 +1,98 @@ +import React, { useMemo, useCallback, memo } from 'react' +import { StyleSheet, View, Text, ScrollView, TouchableHighlight } from 'react-native' +import { useDimensions } from '@/utils/hooks' + +import Modal from '@/components/common/Modal' +// import { useGetter } from '@/store' + +// const menuItemHeight = 42 +// const menuItemWidth = 100 + +const styles = StyleSheet.create({ + menu: { + position: 'absolute', + // borderWidth: StyleSheet.hairlineWidth, + // borderColor: 'lightgray', + // borderRadius: 2, + backgroundColor: 'rgba(0,0,0,0)', + }, + menuItem: { + paddingLeft: 10, + paddingRight: 10, + // height: menuItemHeight, + // width: menuItemWidth, + // alignItems: 'center', + justifyContent: 'center', + // backgroundColor: '#ccc', + }, + menuText: { + // textAlign: 'center', + }, +}) + +const Panel = ({ + buttonPosition, + panelStyle = {}, + children, +}) => { + const dimensions = useDimensions() + // const theme = useGetter('common', 'theme') + // const fadeAnim = useRef(new Animated.Value(0)).current + // console.log(buttonPosition) + + const screenSize = useMemo(() => { + const screenSize = {} + if (dimensions.window.height > dimensions.window.width) { + screenSize.height = dimensions.screen.height + screenSize.width = dimensions.screen.width + } else { + screenSize.height = dimensions.screen.width + screenSize.width = dimensions.screen.height + } + return screenSize + }, [dimensions]) + + const style = useMemo(() => { + const isBottom = buttonPosition.y > screenSize.height / 2 + let top + let height + let justifyContent + if (isBottom) { + height = buttonPosition.y - screenSize.height * 0.3 + top = buttonPosition.y - height + justifyContent = 'flex-end' + } else { + top = buttonPosition.y + buttonPosition.h + height = screenSize.height * 0.7 - top + justifyContent = 'flex-start' + } + const frameStyle = { + flex: 1, + height, + top, + justifyContent, + width: screenSize.width, + } + return frameStyle + }, [screenSize, buttonPosition]) + + return ( + <View style={{ ...styles.menu, ...style }}> + {children} + </View> + ) +} + +export default memo(({ visible, hidePanel, buttonPosition, children, panelStyle }) => { + // console.log(visible) + return ( + <Modal visible={visible} hideModal={hidePanel} onStartShouldSetResponder={() => true}> + <View style={{ flex: 1 }}> + <Panel buttonPosition={buttonPosition} panelStyle={panelStyle} visible={visible} hidePanel={hidePanel}> + {children} + </Panel> + </View> + </Modal> + ) +}) + diff --git a/src/components/common/DorpDownPanel/index.js b/src/components/common/DorpDownPanel/index.js new file mode 100644 index 0000000..151be63 --- /dev/null +++ b/src/components/common/DorpDownPanel/index.js @@ -0,0 +1,51 @@ +import React, { useState, useCallback, useRef } from 'react' +// import { View } from 'react-native' + +import Panel from './Panel' +import Button from '@/components/common/Button' + + +export default ({ + children, + panelStyle, + PanelContent, + visible, + setVisible, +}) => { + const [buttonPosition, setButtonPosition] = useState({}) + + const hidePanel = useCallback(() => { + setVisible(false) + }, [setVisible]) + + const buttonRef = useRef() + const setPosition = useCallback((callback = () => {}) => { + if (buttonRef.current && buttonRef.current.measure) { + buttonRef.current.measure((fx, fy, width, height, px, py) => { + // console.log(fx, fy, width, height, px, py) + setButtonPosition({ x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + callback() + }) + } + }, []) + + const showMenu = useCallback(() => { + setPosition(() => { + setVisible(true) + }) + }, [setPosition, setVisible]) + + return ( + <Button ref={buttonRef} onPress={showMenu}> + {children} + <Panel + buttonPosition={buttonPosition} + visible={visible} + panelStyle={panelStyle} + hidePanel={hidePanel} + > + {PanelContent} + </Panel> + </Button> + ) +} diff --git a/src/components/common/Icon.js b/src/components/common/Icon.js new file mode 100644 index 0000000..43ca456 --- /dev/null +++ b/src/components/common/Icon.js @@ -0,0 +1,7 @@ +import { createIconSetFromIcoMoon } from 'react-native-vector-icons' +import icoMoonConfig from '@/resources/fonts/selection.json' + +const Icon = createIconSetFromIcoMoon(icoMoonConfig) + +export default Icon + diff --git a/src/components/common/Input.js b/src/components/common/Input.js new file mode 100644 index 0000000..8da9eb4 --- /dev/null +++ b/src/components/common/Input.js @@ -0,0 +1,113 @@ +import React, { useRef, useImperativeHandle, forwardRef, useCallback, useEffect, useState } from 'react' +import { TextInput, StyleSheet, View, TouchableOpacity, Animated } from 'react-native' +import Icon from './Icon' +import { useGetter } from '@/store' + +const Input = ({ onChangeText, onClearText, clearBtn, ...props }, ref) => { + const inputRef = useRef() + const theme = useGetter('common', 'theme') + // const scaleClearBtn = useRef(new Animated.Value(0)).current + + useImperativeHandle(ref, () => ({ + blur() { + if (!inputRef.current) return + inputRef.current.blur() + }, + focus() { + if (!inputRef.current) return + inputRef.current.focus() + }, + clear() { + inputRef.current.clear() + }, + isFocused() { + return inputRef.current.isFocused() + }, + })) + + // const showClearBtn = useCallback(() => { + // Animated.timing(scaleClearBtn, { + // toValue: 1, + // duration: 200, + // useNativeDriver: true, + // }).start() + // }, [scaleClearBtn]) + // const hideClearBtn = useCallback(() => { + // Animated.timing(scaleClearBtn, { + // toValue: 0, + // duration: 200, + // useNativeDriver: true, + // }).start() + // }, [scaleClearBtn]) + + const clearText = useCallback(() => { + inputRef.current.clear() + // hideClearBtn() + onClearText && onClearText() + }, [inputRef, onClearText]) + + const changeText = useCallback(text => { + // if (text.length) { + // showClearBtn() + // } else { + // hideClearBtn() + // } + onChangeText && onChangeText(text) + }, [onChangeText]) + + return ( + <View style={styles.content}> + <TextInput autoCapitalize="none" onChangeText={changeText} autoCompleteType="off" style={styles.input} ref={inputRef} {...props} /> + {/* <View style={styles.clearBtnContent}> + <Animated.View style={{ ...styles.clearBtnContent, transform: [{ scale: scaleClearBtn }] }}> */} + {clearBtn + ? <View style={styles.clearBtnContent}> + <TouchableOpacity style={styles.clearBtn} onPress={clearText}> + <Icon name="remove" style={{ fontSize: 14, color: theme.normal20 }} /> + </TouchableOpacity> + </View> + : null + } + {/* </Animated.View> + </View> */} + </View> + ) +} + +const styles = StyleSheet.create({ + content: { + flexDirection: 'row', + // backgroundColor: 'rgba(0,0,0,0.1)', + flexGrow: 1, + flexShrink: 1, + height: 38, + alignItems: 'center', + // paddingRight: 5, + }, + input: { + // backgroundColor: 'rgba(0,0,0,0.1)', + // backgroundColor: 'white', + borderRadius: 2, + paddingTop: 2, + paddingBottom: 2, + paddingLeft: 5, + paddingRight: 0, + flexGrow: 1, + flexShrink: 1, + height: '100%', + }, + clearBtnContent: { + flexGrow: 0, + flexShrink: 0, + }, + clearBtn: { + height: '70%', + paddingLeft: 5, + paddingRight: 5, + justifyContent: 'center', + // backgroundColor: 'rgba(0,0,0,0.2)', + }, +}) + +export default forwardRef(Input) + diff --git a/src/components/common/LoadingMask.js b/src/components/common/LoadingMask.js new file mode 100644 index 0000000..642a469 --- /dev/null +++ b/src/components/common/LoadingMask.js @@ -0,0 +1,69 @@ +import React, { useState, useCallback, memo, useMemo, useRef, useEffect } from 'react' +import { StyleSheet, Animated, Text } from 'react-native' +import { useGetter } from '@/store' +import { useTranslation } from '@/plugins/i18n' + +export default memo(({ visible }) => { + const theme = useGetter('common', 'theme') + const animFade = useRef(new Animated.Value(0)).current + const [maskVisible, setMaskVisible] = useState(false) + const { t } = useTranslation() + + const handleShow = useCallback(() => { + // console.log('handleShow') + setMaskVisible(true) + + Animated.parallel([ + Animated.timing(animFade, { + toValue: 1, + duration: 200, + useNativeDriver: true, + }), + ]).start() + }, [animFade]) + + const handleHide = useCallback(() => { + // Will change fadeAnim value to 0 in 5 seconds + // console.log('handleHide') + Animated.parallel([ + Animated.timing(animFade, { + toValue: 0, + duration: 300, + useNativeDriver: true, + }), + ]).start((finished) => { + // console.log(finished) + if (!finished) return + setMaskVisible(false) + }) + }, [animFade]) + + useEffect(() => { + if (visible === maskVisible) return + visible ? handleShow() : handleHide() + }, [handleHide, handleShow, maskVisible, visible]) + + const maskComponent = useMemo(() => ( + <Animated.View style={{ ...styles.container, backgroundColor: theme.primary, opacity: animFade }}> + <Text style={{ ...styles.text, color: theme.normal40 }}>{t('list_loading')}</Text> + </Animated.View> + ), [animFade, t, theme]) + + return maskVisible ? maskComponent : null +}) + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + left: 0, + top: 0, + width: '100%', + height: '100%', + zIndex: 10, + justifyContent: 'center', + alignItems: 'center', + }, + text: { + fontSize: 20, + }, +}) diff --git a/src/components/common/Menu.js b/src/components/common/Menu.js new file mode 100644 index 0000000..53ac57b --- /dev/null +++ b/src/components/common/Menu.js @@ -0,0 +1,127 @@ +import React, { useMemo, useCallback, memo } from 'react' +import { StyleSheet, View, Text, Animated, useWindowDimensions, TouchableHighlight } from 'react-native' +import { useDimensions } from '@/utils/hooks' + +import Modal from './Modal' +import { useGetter } from '@/store' + +// const menuItemHeight = 42 +// const menuItemWidth = 100 + +const styles = StyleSheet.create({ + menu: { + position: 'absolute', + borderWidth: StyleSheet.hairlineWidth, + borderColor: 'lightgray', + borderRadius: 2, + backgroundColor: 'white', + elevation: 1, + }, + menuItem: { + paddingLeft: 10, + paddingRight: 10, + // height: menuItemHeight, + // width: menuItemWidth, + // alignItems: 'center', + justifyContent: 'center', + // backgroundColor: '#ccc', + }, + menuText: { + // textAlign: 'center', + }, +}) + +const Menu = ({ + buttonPosition, + menus, + onPress = () => {}, + longPress = () => {}, + center = false, + hideMenu, + width = 100, + height = 42, +}) => { + const dimensions = useDimensions() + const theme = useGetter('common', 'theme') + // const fadeAnim = useRef(new Animated.Value(0)).current + // console.log(buttonPosition) + const screenSize = useMemo(() => { + const screenSize = {} + if (dimensions.window.height > dimensions.window.width) { + screenSize.height = dimensions.screen.height + screenSize.width = dimensions.screen.width + } else { + screenSize.height = dimensions.screen.width + screenSize.width = dimensions.screen.height + } + return screenSize + }, [dimensions]) + + const menuStyle = useMemo(() => { + let menuHeight = menus.length * height + 1 + const topHeight = buttonPosition.y - 20 + const bottomHeight = screenSize.height - buttonPosition.y - buttonPosition.h - 20 + if (menuHeight > topHeight && menuHeight > bottomHeight) menuHeight = Math.max(topHeight, bottomHeight) + + const menuWidth = width + const bottomSpace = screenSize.height - buttonPosition.y - buttonPosition.h - 20 + const rightSpace = screenSize.width - buttonPosition.x - menuWidth - 20 + const showInBottom = bottomSpace >= menuHeight + const showInRight = rightSpace >= menuWidth + const frameStyle = { + height: menuHeight, + top: showInBottom ? buttonPosition.y + buttonPosition.h : buttonPosition.y - menuHeight, + } + if (showInRight) { + frameStyle.left = buttonPosition.x + } else { + frameStyle.right = screenSize.width - buttonPosition.x - buttonPosition.w + } + return frameStyle + }, [screenSize, buttonPosition, menus, width, height]) + + const menuPress = useCallback((menu, index) => { + if (menu.disabled) return + onPress(menu, index) + hideMenu() + }, [onPress, hideMenu]) + + const menuLongPress = useCallback((menu, index) => { + if (menu.disabled) return + longPress(menu, index) + // hideMenu() + }, [longPress]) + + // console.log(menuStyle) + return ( + <View style={{ ...styles.menu, ...menuStyle, backgroundColor: theme.primary }} onStartShouldSetResponder={() => true}> + <Animated.ScrollView keyboardShouldPersistTaps={'always'}> + { + menus.map((menu, index) => ( + <TouchableHighlight + key={menu.action} + style={{ ...styles.menuItem, width: width, height: height }} + underlayColor={theme.secondary40} + onPress={() => { menuPress(menu, index) }} + onLongPress={() => { menuLongPress(menu, index) }} + > + <Text style={{ ...styles.menuText, textAlign: center ? 'center' : 'left', color: theme.normal }} numberOfLines={1}>{menu.label}</Text> + </TouchableHighlight> + )) + } + </Animated.ScrollView> + </View> + ) +} + +export default memo(({ visible, hideMenu, buttonPosition, menus, longPress, onPress, width, height }) => { + // console.log(visible) + return ( + <Modal visible={visible} hideModal={hideMenu} onStartShouldSetResponder={() => true}> + <View style={{ flex: 1 }}> + <Menu menus={menus} buttonPosition={buttonPosition} longPress={longPress} onPress={onPress} visible={visible} hideMenu={hideMenu} width={width} height={height} /> + </View> + </Modal> + ) +}) + diff --git a/src/components/common/Modal.js b/src/components/common/Modal.js new file mode 100644 index 0000000..342d804 --- /dev/null +++ b/src/components/common/Modal.js @@ -0,0 +1,32 @@ +import React, { memo, useCallback } from 'react' +import { Modal, TouchableWithoutFeedback } from 'react-native' + +export default memo(({ + visible = false, + hideModal = () => {}, + keyHide = true, + bgHide = true, + children, +}) => { + const handleRequestClose = useCallback(() => { + if (keyHide) hideModal(false) + }, [hideModal, keyHide]) + const handleBgClose = useCallback(() => { + if (bgHide) hideModal(false) + }, [hideModal, bgHide]) + + return ( + <Modal + animationType="fade" + transparent={true} + hardwareAccelerated={true} + statusBarTranslucent={true} + visible={visible} + onRequestClose={handleRequestClose} + > + <TouchableWithoutFeedback onPress={handleBgClose}> + {children} + </TouchableWithoutFeedback> + </Modal> + ) +}) diff --git a/src/components/layout/Header.js b/src/components/layout/Header.js new file mode 100644 index 0000000..30d72b0 --- /dev/null +++ b/src/components/layout/Header.js @@ -0,0 +1,51 @@ +import React from 'react' +import { View, Text, StyleSheet, SafeAreaView, StatusBar } from 'react-native' + +const Header = state => { + return ( + <View style={style.header}> + <StatusBar backgroundColor="rgba(0,0,0,0)" barStyle="dark-content" translucent={true} /> + <SafeAreaView style={style.container}> + {state.menu.map((item, index) => <View style={style.btn} key={item.id}><Text style={style.btnText} onPress={() => this.handlePress(item, index)}>{item.name}</Text></View>)} + </SafeAreaView> + </View> + ) +} + + +const style = StyleSheet.create({ + header: { + backgroundColor: '#fff', + height: 50 + StatusBar.currentHeight, + paddingTop: StatusBar.currentHeight, + // Android shadow + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.23, + // shadowRadius: 2.62, + // elevation: 4, + }, + container: { + // width: '100%', + flexDirection: 'row', + }, + btn: { + // flex: 1, + paddingLeft: 10, + paddingRight: 10, + backgroundColor: 'rgba(0,0,0,0);', + alignItems: 'center', + justifyContent: 'center', + height: 50, + }, + btnText: { + fontSize: 16, + color: 'white', + }, +}) + + +export default Header diff --git a/src/components/player/Progress.js b/src/components/player/Progress.js new file mode 100644 index 0000000..108825e --- /dev/null +++ b/src/components/player/Progress.js @@ -0,0 +1,87 @@ +import React, { memo } from 'react' +import { View, StyleSheet, TouchableOpacity, Pressable } from 'react-native' +import { useLayout } from '@/utils/hooks' +import { useGetter, useDispatch } from '@/store' +// import { AppColors } from '@/theme' + + +const DefaultBar = memo(() => { + const theme = useGetter('common', 'theme') + + return <View style={{ ...styles.progressBar, backgroundColor: theme.borderColor2, position: 'absolute', width: '100%', left: 0, top: 0 }}></View> +}) + +const BufferedBar = memo(({ bufferedProgress }) => { + const theme = useGetter('common', 'theme') + return <View style={{ ...styles.progressBar, backgroundColor: theme.borderColor2, position: 'absolute', width: bufferedProgress + '%', left: 0, top: 0 }}></View> +}) + +const PreassBar = memo(({ duration }) => { + const { onLayout, ...layout } = useLayout() + const setProgress = useDispatch('player', 'setProgress') + const handlePress = event => { + setProgress(event.nativeEvent.locationX / layout.width * duration) + } + + return <Pressable onPress={handlePress} onLayout={onLayout} style={styles.pressBar} /> +}) + + +const Progress = ({ progress, bufferedProgress, duration }) => { + // const { progress } = usePlayTimeBuffer() + const theme = useGetter('common', 'theme') + // console.log(progress) + const progressStr = progress + '%' + + return ( + <View style={styles.progress}> + <View> + <DefaultBar /> + <BufferedBar bufferedProgress={bufferedProgress} /> + <View style={{ ...styles.progressBar, backgroundColor: theme.secondary30, width: progressStr, position: 'absolute', left: 0, top: 0 }}> + <Pressable style={{ ...styles.progressDot, backgroundColor: theme.secondary10 }}></Pressable> + </View> + </View> + <PreassBar duration={duration} /> + {/* <View style={{ ...styles.progressBar, height: '100%', width: progressStr }}><Pressable style={styles.progressDot}></Pressable></View> */} + </View> + ) +} + + +const progressContentPadding = 10 +const progressHeight = 2 +const progressDotSize = 8 +const styles = StyleSheet.create({ + progress: { + width: '100%', + height: progressContentPadding * 2 + progressHeight, + // backgroundColor: 'rgba(0,0,0,0.5)', + paddingTop: progressContentPadding, + paddingBottom: progressContentPadding, + zIndex: 1, + }, + progressBar: { + height: progressHeight, + borderRadius: 4, + }, + progressDot: { + width: progressDotSize, + height: progressDotSize, + borderRadius: progressDotSize, + position: 'absolute', + right: -progressDotSize / 2, + top: -(progressDotSize - progressHeight) / 2, + zIndex: 9, + }, + pressBar: { + position: 'absolute', + // backgroundColor: 'rgba(0,0,0,0.5)', + left: 0, + top: 0, + height: progressContentPadding * 2 + progressHeight, + width: '100%', + }, +}) + +export default Progress diff --git a/src/components/searchTipList.js b/src/components/searchTipList.js new file mode 100644 index 0000000..0a10bfe --- /dev/null +++ b/src/components/searchTipList.js @@ -0,0 +1,131 @@ +import React, { useRef, useState, useEffect, useCallback, useMemo } from 'react' +import Button from '@/components/common/Button' +import { StyleSheet, View, ScrollView, Animated, Text } from 'react-native' +// import PropTypes from 'prop-types' +// import { AppColors } from '@/theme' +import { useGetter } from '@/store' +// import InsetShadow from 'react-native-inset-shadow' + + +export default ({ list, visible, onPress, height, hideList }) => { + const translateY = useRef(new Animated.Value(0)).current + const scaleY = useRef(new Animated.Value(0)).current + const theme = useGetter('common', 'theme') + // const isShowRef = useRef(false) + const [tipListVisible, setTipListVisible] = useState(false) + + + const handleShowList = useCallback(() => { + // console.log('handleShowList', height, visible) + if (!height) return + setTipListVisible(true) + + translateY.setValue(-height / 2) + scaleY.setValue(0) + + Animated.parallel([ + // Animated.timing(fade, { + // toValue: 1, + // duration: 300, + // useNativeDriver: true, + // }), + Animated.timing(translateY, { + toValue: 0, + duration: 300, + useNativeDriver: true, + }), + Animated.timing(scaleY, { + toValue: 1, + duration: 300, + useNativeDriver: true, + }), + ]).start() + }, [translateY, scaleY, height]) + + const handleHideList = useCallback(() => { + // Will change fadeAnim value to 0 in 5 seconds + // console.log('handleHideList') + Animated.parallel([ + // Animated.timing(fade, { + // toValue: 0, + // duration: 200, + // useNativeDriver: true, + // }), + Animated.timing(translateY, { + toValue: -height / 2, + duration: 300, + useNativeDriver: true, + }), + Animated.timing(scaleY, { + toValue: 0, + duration: 300, + useNativeDriver: true, + }), + ]).start((finished) => { + // console.log(finished) + if (!finished) return + setTipListVisible(false) + hideList() + }) + }, [translateY, scaleY, hideList, height]) + + useEffect(() => { + if (visible === tipListVisible) return + visible ? handleShowList() : handleHideList() + }, [tipListVisible, visible, handleShowList, handleHideList]) + + const listComponent = useMemo(() => ( + <Animated.View + style={{ + ...styles.anima, + transform: [ + { translateY: translateY }, + { scaleY: scaleY }, + ], + }}> + <View + style={{ + ...styles.container, + backgroundColor: theme.secondary40, + }}> + <ScrollView keyboardShouldPersistTaps={'always'}> + {list.map((item, index) => ( + <Button onPress={() => onPress(item)} key={index}> + <Text style={{ ...styles.text, color: theme.normal }}>{item}</Text> + </Button> + ))} + </ScrollView> + </View> + <View style={styles.blank} onTouchStart={handleHideList}></View> + </Animated.View> + ), [handleHideList, list, onPress, scaleY, theme, translateY]) + + return tipListVisible ? listComponent : null +} + +const styles = StyleSheet.create({ + anima: { + position: 'absolute', + left: 0, + top: 0, + height: '100%', + width: '100%', + zIndex: 10, + }, + container: { + flexGrow: 0, + }, + blank: { + flex: 1, + flexGrow: 1, + backgroundColor: 'transparent', + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + text: { + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 10, + paddingRight: 10, + // color: 'white', + }, +}) diff --git a/src/config/constant.js b/src/config/constant.js new file mode 100644 index 0000000..4a0cef3 --- /dev/null +++ b/src/config/constant.js @@ -0,0 +1,25 @@ + +export const LIST_ID_PLAY_TEMP = null +export const LIST_ID_PLAY_LATER = '__LATER__' +export const LIST_ITEM_HEIGHT = 56 +export const LIST_SCROLL_POSITION_KEY = '__LIST_SCROLL_POSITION_KEY__' + +export const APP_PROVIDER_NAME = 'cn.toside.music.mobile.provider' + +export const VERSION_STATUS = { + checking: 'Checking', + latest: 'Latest', + downloading: 'Downloading', + downloaded: 'Downloaded', + unknown: 'Unknown', + failed: 'Failed', + available: 'Available', +} + +export const NAV_VIEW_NAMES = { + search: 0, + songList: 1, + top: 2, + list: 3, + setting: 4, +} diff --git a/src/config/defaultSetting.js b/src/config/defaultSetting.js new file mode 100644 index 0000000..8f1cbad --- /dev/null +++ b/src/config/defaultSetting.js @@ -0,0 +1,89 @@ +// const path = require('path') +// const os = require('os') +// const { isMac } = require('./utils') + +const defaultSetting = { + version: '1.2', + player: { + togglePlayMethod: 'listLoop', + highQuality: false, + isSavePlayTime: false, + cacheSize: 1024, // unit MB + }, + list: { + isShowSource: true, + prevSelectListId: 'default', + isSaveScrollLocation: true, + }, + download: { + enable: false, + // savePath: path.join(os.homedir(), 'Desktop'), + fileName: '歌名 - 歌手', + maxDownloadNum: 3, + isDownloadLrc: false, + isEmbedPic: true, + isEmbedLyric: false, + }, + leaderboard: { + source: 'kw', + tabId: 'kw__16', + }, + songList: { + source: 'kw', + sortId: 'new', + tagInfo: { + name: '默认', + id: null, + }, + }, + odc: { + isAutoClearSearchInput: false, + isAutoClearSearchList: false, + }, + search: { + searchSource: 'kw', + tempSearchSource: 'kw', + isShowHotSearch: false, + isShowHistorySearch: false, + isFocusSearchBox: false, + }, + // network: { + // proxy: { + // enable: false, + // host: '', + // port: '', + // username: '', + // password: '', + // }, + // }, + themeId: 'green', + langId: null, + sourceId: 'kw', + apiSource: 'temp', + sourceNameType: 'alias', + // randomAnimate: true, + ignoreVersion: null, + isAgreePact: false, +} + +const overwriteSetting = { + // songList: { + // source: 'kw', + // sortId: '', + // }, + // search: { + // searchSource: 'kw', + // }, + // player: { + // cacheSize: 1024, + // }, +} + +// 使用新年皮肤 +// if (new Date().getMonth() < 2) defaultSetting.themeId = 9 + + +export { + defaultSetting, + overwriteSetting, +} diff --git a/src/config/globalData.js b/src/config/globalData.js new file mode 100644 index 0000000..3a3bb17 --- /dev/null +++ b/src/config/globalData.js @@ -0,0 +1,14 @@ +import { version } from '../../package.json' +process.versions.app = version + +global.playerStatus = { + isInitialized: false, + isRegisteredService: false, + isIniting: false, +} + +global.restorePlayInfo = null +global.allList = null +global.globalObj = null +global.listScrollPosition = {} +global.listSort = {} diff --git a/src/config/index.js b/src/config/index.js new file mode 100644 index 0000000..3ae6017 --- /dev/null +++ b/src/config/index.js @@ -0,0 +1,20 @@ +// import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource' +import defaultUrl from '@/resources/medias/Silence02s.mp3' +// const defaultUrl = resolveAssetSource(resourceDefaultUrl).uri + +export { + defaultUrl, +} +// export const defaultUrl = require('@/resources/medias/Silence02s.mp3') + +export const storageDataPrefix = { + setting: '@setting', + list: '@list__', + listPosition: '@listposition__', + listSort: '@listsort__', + lyric: '@lyric__', + musicUrl: '@music_url__', + playInfo: '@play_info', +} + +export const ITEM_HEIGHT = 60 diff --git a/src/config/setting.js b/src/config/setting.js new file mode 100644 index 0000000..25c4431 --- /dev/null +++ b/src/config/setting.js @@ -0,0 +1,42 @@ +import { compareVer, objectDeepMerge } from '../utils' +import { defaultSetting, overwriteSetting } from './defaultSetting' +import apiSource from '../utils/music/api-source-info' + +export const mergeSetting = setting => { + const defaultSettingCopy = JSON.parse(JSON.stringify(defaultSetting)) + const overwriteSettingCopy = JSON.parse(JSON.stringify(overwriteSetting)) + + if (!setting) { + setting = defaultSettingCopy + } else if (compareVer(setting.version, defaultSettingCopy.version) < 0) { + objectDeepMerge(defaultSettingCopy, setting) + objectDeepMerge(defaultSettingCopy, overwriteSettingCopy) + setting = defaultSettingCopy + } + + if (!apiSource.some(api => api.id === setting.apiSource && !api.disabled)) { + const api = apiSource.find(api => !api.disabled) + if (api) setting.apiSource = api.id + } + + return setting +} + +/** + * 初始化设置 + * @param {*} setting + */ + +export const initSetting = () => { + // const { version: settingVersion, setting: newSetting } = mergeSetting(setting, electronStore_config.get('version')) + + + // newSetting.controlBtnPosition = 'right' + // electronStore_config.set('version', settingVersion) + // electronStore_config.set('setting', newSetting) + // return newSetting + return { + setting: defaultSetting, + settingVersion: defaultSetting.version, + } +} diff --git a/src/lang/Readme.md b/src/lang/Readme.md new file mode 100644 index 0000000..532bd85 --- /dev/null +++ b/src/lang/Readme.md @@ -0,0 +1,39 @@ +新增语言时创建的语言文件夹需要与以下列表对应: + +- `ar_sa` - Arabic Saudi Arabia +- `cs_cz` - Czech Czech Republic +- `da_dk` - Danish Denmark +- `de_de` - German Germany +- `el_gr` - Modern Greek Greece +- `en_au` - English Australia +- `en_gb` - English United Kingdom +- `en_ie` - English Ireland +- `en_us` - English United States +- `en_za` - English South Africa +- `es_es` - Spanish Spain +- `es_mx` - Spanish Mexico +- `fi_fi` - Finnish Finland +- `fr_ca` - French Canada +- `fr_fr` - French France +- `he_il` - Hebrew Israel +- `hi_in` - Hindi India +- `hu_hu` - Hungarian Hungary +- `id_id` - Indonesian Indonesia +- `it_it` - Italian Italy +- `ja_jp` - Japanese Japan +- `ko_kr` - Korean Republic of Korea +- `nl_be` - Dutch Belgium +- `nl_nl` - Dutch Netherlands +- `no_no` - Norwegian Norway +- `pl_pl` - Polish Poland +- `pt_br` - Portuguese Brazil +- `pt_pt` - Portuguese Portugal +- `ro_ro` - Romanian Romania +- `ru_ru` - Russian Russian Federation +- `sk_sk` - Slovak Slovakia +- `sv_se` - Swedish Sweden +- `th_th` - Thai Thailand +- `tr_tr` - Turkish Turkey +- `zh_cn` - Chinese China +- `zh_hk` - Chinese Hong Kong +- `zh_tw` - Chinese Taiwan diff --git a/src/lang/en_us.json b/src/lang/en_us.json new file mode 100644 index 0000000..7fa9ec4 --- /dev/null +++ b/src/lang/en_us.json @@ -0,0 +1,173 @@ +{ + "play": "Play", + "play_later": "Play later", + "copy_name": "Copy name", + "pause": "Pause", + "stop": "Stop", + "play_next": "Next song", + "play_prev": "Previous song", + "add_to": "Add to...", + "move_to": "Move to...", + "delete": "Delete", + "loading": "Loading...", + "list_loading": "Loading...", + "list_end": "In The End", + "list_select_single": "Single Select", + "list_select_range": "range", + "list_select_all": "Select All", + "list_select_unall": "Reverse Selection", + "list_select_cancel": "Cancel", + + "list_rename": "Rename", + "list_rename_title": "Rename List", + "list_sync": "Sync list", + "change_position": "Change Position", + "change_position_tip": "Please enter a new position", + "change_position_list_title": "Change the position of the list", + "change_position_music_title": "Adjust the position of {{name}} to", + "change_position_music_multi_title": "Adjust the position of the selected {{num}} song to", + "list_remove": "Remove", + + "play_detail_todo_tip": "What do you want? No, this function has not been implemented yet 😛, But you can try to locate the currently playing song by long pressing (only valid for playing songs in \"My List\")", + + "collect_success": "Collection success", + "collect_songlist": "Collection Songlist", + "play_all": "Play all", + "back": "Back", + + "cancel": "Cancel", + "confirm": "Confirm", + "agree": "Agree", + "disagree": "Disagree", + "disagree_tip": "Cancelled...", + + "storage_permission_tip_request": "To use this function, you need to allow LX to access the phone storage. Do you agree and continue?", + "storage_permission_tip_disagree": "User Disagree", + "storage_permission_tip_disagree_ask_again": "This feature cannot be used because you have permanently denied LX access to the phone storage.\nIf you want to continue, you need to go to System Permission Management Set Luo Xue’s storage permission to allow.", + + "parent_dir_name": "Parent directory", + "create_new_folder": "Create new folder", + "create_new_folder_tip": "Please enter a new folder name", + "create_new_folder_error_tip": "The name entered is invalid", + + "source_real_kw": "Kuwo", + "source_real_kg": "Kugou", + "source_real_tx": "Tencent", + "source_real_wy": "Netease", + "source_real_mg": "Migu", + "source_real_bd": "Baidu", + "source_real_all": "Aggregated", + + "source_alias_kw": "KW Music", + "source_alias_kg": "KG Music", + "source_alias_tx": "TX Music", + "source_alias_wy": "WY Music", + "source_alias_mg": "MG Music", + "source_alias_bd": "BD Music", + + "source_alias_all": "Aggregated", + + "songlist_recommend": "Recommend", + "songlist_hot": "Hot", + "songlist_new": "New", + "songlist_hot_collect": "Hot Collect", + "songlist_rise": "Rise", + + "list_add_title_first_add": "Add", + "list_add_title_first_move": "Move", + "list_add_title_last": "to...", + "list_multi_add_title_first_add": "Add selected", + "list_multi_add_title_first_move": "Move the selected one", + "list_multi_add_title_last": "First song to...", + "list_add_btn_title": "Add the song(s) to {{name}}", + + "quality_lossless": "SQ", + "quality_high_quality": "HQ", + + "theme_green": "Green", + "theme_blue": "Blue", + "theme_yellow": "Yellow", + "theme_orange": "Orange", + "theme_red": "Red", + "theme_pink": "Pink", + "theme_purple": "Purple", + "theme_grey": "Grey", + "theme_ming": "Ming", + "theme_blue2": "Purple Blue", + "theme_mid_autumn": "Mid-Autumn", + "theme_naruto": "Naruto", + + "version_label_latest_ver": "Latest version:", + "version_label_current_ver": "Current version:", + "version_label_change_log": "Update description:", + "version_label_history": "History version:", + "version_tip_checking": "Checking for updates...⏳", + "version_tip_downloaded": "The installation package has been downloaded.", + "version_tip_failed": "The installation package download failed. You can try again or go to the project address to manually download the new version update.", + "version_tip_unknown": "Failed to obtain the latest version information, it is recommended to manually go to the project address to check if there is a new version", + "version_tip_latest": "The software is up to date, please enjoy it~🥂", + "version_btn_new": "Update", + "version_btn_downloading": "I am trying to download...{{total}}/{{current}} ({{progress}}%)", + "version_btn_update": "Install", + "version_btn_failed": "Retry", + "version_btn_unknown": "Project Homepage", + "version_btn_ignore": "Ignore", + "version_btn_close": "Close", + "version_title_latest": "🎉 The current version is already the latest 🎊", + "version_title_checking": "⏳ Checking for updates ⏳", + "version_title_new": "🌟 New version found 🌟", + "version_title_update": "🚀 Program update 🚀", + "version_title_failed": "❌ Download failed ❌", + "version_title_unknown": "❓ Failed to get the latest version information ❓", + + + "setting_basic": "General", + "setting_basic_theme": "Theme", + "setting_basic_show_animation": "Show switching animation", + "setting_basic_animation": "Random pop-up animation", + "setting_basic_source_title": "Choose a music source", + "setting_basic_source_test": "Test API (Available for most software features)", + "setting_basic_source_temp": "Temporary API (some features not available; workaround if Test API unavailable)", + "setting_basic_source": "Music source", + "setting_basic_sourcename_title": "Select the name of music source", + "setting_basic_sourcename_real": "Original", + "setting_basic_sourcename_alias": "Aliases", + "setting_basic_sourcename": "Source name", + "setting_basic_lang": "Language", + + "setting_play": "Play", + "setting_play_cache_size": "Maximum cache size (MB)", + "setting_play_cache_size_no_cache": "Disabled cache", + "setting_play_cache_size_save_tip": "The cache setting is completed, it will take effect after restarting the application", + "setting_play_save_play_time": "Remember playback progress", + "setting_play_lyric_transition": "Show lyrics translation", + "setting_play_quality": "Play 320K quality songs first (if supported)", + + "setting_backup": "Backup and restore", + "setting_backup_part": "List data (common with PC-side list backup files)", + "setting_backup_part_import_list": "Import lists", + "setting_backup_part_export_list": "Export lists", + "setting_backup_part_import_setting": "Import settings", + "setting_backup_part_export_setting": "Export settings", + "setting_backup_all": "All data (list data and setting data)", + "setting_backup_all_import": "Import", + "setting_backup_all_export": "Export", + "setting_backup_all_import_desc": "Select a backup file", + "setting_backup_all_export_desc": "Select the backup to...", + "setting_backup_part_import_setting_desc": "Select the Settings file", + "setting_backup_part_export_setting_desc": "Save the list to...", + "setting_backup_part_import_list_desc": "Select the list of backup files", + "setting_backup_part_export_list_desc": "Select the save location of the playlist backup file", + + "setting_other": "Extras", + "setting_other_cache": "Cache management (including the cache of songs, lyrics, etc., it is not recommended to clean up if there is no problem related to song playback)", + "setting_other_cache_size": "Currently used cache size: ", + "setting_other_cache_clear_btn": "Clear Cache", + "setting_other_cache_clear_success_tip": "Cache clearing completed", + + "setting_version": "Software Update", + "setting_version_show_ver_modal": "Open the update window 🚀", + + "setting_about": "About LX Music" + +} diff --git a/src/lang/index.js b/src/lang/index.js new file mode 100644 index 0000000..8700adc --- /dev/null +++ b/src/lang/index.js @@ -0,0 +1,15 @@ +import zh_cn from './zh_cn.json' +import en_us from './en_us.json' + +export default [ + { + id: 'zh_cn', + name: '简体中文', + translation: zh_cn, + }, + { + id: 'en_us', + name: 'English', + translation: en_us, + }, +] diff --git a/src/lang/zh_cn.json b/src/lang/zh_cn.json new file mode 100644 index 0000000..992de05 --- /dev/null +++ b/src/lang/zh_cn.json @@ -0,0 +1,173 @@ +{ + "play": "播放", + "play_later": "稍后播放", + "copy_name": "复制歌曲名", + "pause": "暂停", + "stop": "停止", + "play_next": "下一曲", + "play_prev": "上一曲", + "add_to": "添加到...", + "move_to": "移动到...", + "delete": "删除", + "loading": "加载中...", + "list_loading": "加载中...", + "list_end": "到底啦~", + "list_select_single": "单选", + "list_select_range": "区间", + "list_select_all": "全选", + "list_select_unall": "反选", + "list_select_cancel": "取消", + + "list_rename": "重命名", + "list_rename_title": "重命名列表", + "list_sync": "同步列表", + "change_position": "调整位置", + "change_position_tip": "请输入新的位置", + "change_position_list_title": "调整列表位置", + "change_position_music_title": "将 {{name}} 的位置调整到", + "change_position_music_multi_title": "将已选的 {{num}} 首歌曲的位置调整到", + "list_remove": "移除", + + "play_detail_todo_tip": "你想干嘛?不可以的,这个功能还没有实现哦😛,不过你可以试着长按来定位当前播放的歌曲(仅对播放“我的列表”里的歌曲有效哦)", + + "collect_success": "收藏成功", + "collect_songlist": "收藏歌单", + "play_all": "播放全部", + "back": "返回", + + "cancel": "取消", + "confirm": "确认", + "agree": "行行行", + "disagree": "我就不", + "disagree_tip": "那算了... 🙄", + + "storage_permission_tip_request": "使用此功能需要允许洛雪访问手机存储,是否同意并继续?", + "storage_permission_tip_disagree": "你个骗纸,刚刚问你,你都说同意的,最后又拒绝,哼 🥺", + "storage_permission_tip_disagree_ask_again": "此功能无法使用,因为你已经永久拒绝洛雪访问手机存储😫。\n若想继续,你需要去👉系统权限管理👈将洛雪的存储权限设置为允许", + + "parent_dir_name": "父级目录", + "create_new_folder": "新建文件夹", + "create_new_folder_tip": "请输入新文件夹名", + "create_new_folder_error_tip": "输入的名称不合法", + + "source_real_kw": "酷我音乐", + "source_real_kg": "酷狗音乐", + "source_real_tx": "企鹅音乐", + "source_real_wy": "网易音乐", + "source_real_mg": "咪咕音乐", + "source_real_bd": "百度音乐", + "source_real_all": "聚合搜索", + + "source_alias_kw": "小蜗音乐", + "source_alias_kg": "小枸音乐", + "source_alias_tx": "小秋音乐", + "source_alias_wy": "小芸音乐", + "source_alias_mg": "小蜜音乐", + "source_alias_bd": "小杜音乐", + + "source_alias_all": "聚合大会", + + "songlist_recommend": "推荐", + "songlist_hot": "最热", + "songlist_new": "最新", + "songlist_hot_collect": "热藏", + "songlist_rise": "飙升", + + "list_add_title_first_add": "添加", + "list_add_title_first_move": "移动", + "list_add_title_last": "到...", + "list_multi_add_title_first_add": "添加已选的", + "list_multi_add_title_first_move": "移动已选的", + "list_multi_add_title_last": "首歌曲到...", + "list_add_btn_title": "把该歌曲添加到 {name}", + + "quality_lossless": "无损", + "quality_high_quality": "高品质", + + "theme_green": "绿意盎然", + "theme_blue": "蓝田生玉", + "theme_yellow": "信口雌黄", + "theme_orange": "橙黄橘绿", + "theme_red": "热情似火", + "theme_pink": "粉装玉琢", + "theme_purple": "重斤球紫", + "theme_grey": "灰常美丽", + "theme_ming": "青出于黑", + "theme_blue2": "清热版蓝", + "theme_mid_autumn": "月里嫦娥", + "theme_naruto": "木叶之村", + + "version_label_latest_ver": "最新版本:", + "version_label_current_ver": "当前版本:", + "version_label_change_log": "更新说明:", + "version_label_history": "历史版本:", + "version_tip_checking": "检查更新中...⏳", + "version_tip_downloaded": "安装包已经下载完毕。", + "version_tip_failed": "安装包下载失败,你可以重试或者去项目地址手动下载新版更新。", + "version_tip_unknown": "获取最新版本信息失败,建议手动去项目地址检查是否有新版本", + "version_tip_latest": "软件已是最新,尽情地体验吧~🥂", + "version_btn_new": "更新", + "version_btn_downloading": "正在努力下载中...{{total}}/{{current}} ({{progress}}%)", + "version_btn_update": "安装", + "version_btn_failed": "重试", + "version_btn_unknown": "项目首页", + "version_btn_ignore": "忽略", + "version_btn_close": "关闭", + "version_title_latest": "🎉 当前版本已是最新 🎊", + "version_title_checking": "⏳ 检查更新中 ⏳", + "version_title_new": "🌟 发现新版本 🌟", + "version_title_update": "🚀 程序更新 🚀", + "version_title_failed": "❌ 下载失败 ❌", + "version_title_unknown": "❓ 获取最新版本信息失败 ❓", + + + "setting_basic": "基本设置", + "setting_basic_theme": "主题颜色", + "setting_basic_animation": "弹出层随机动画", + "setting_basic_show_animation": "显示切换动画", + "setting_basic_source_title": "选择音乐来源", + "setting_basic_source_test": "测试接口(几乎软件的所有功能都可用)", + "setting_basic_source_temp": "临时接口(软件的某些功能不可用,建议测试接口不可用再使用本接口)", + "setting_basic_source": "音乐来源", + "setting_basic_sourcename_title": "选择音源名字类型", + "setting_basic_sourcename_real": "原名", + "setting_basic_sourcename_alias": "别名", + "setting_basic_sourcename": "音源名字", + "setting_basic_lang": "语言", + + "setting_play": "播放设置", + "setting_play_cache_size": "最大缓存大小(MB)", + "setting_play_cache_size_no_cache": "禁用缓存", + "setting_play_cache_size_save_tip": "缓存设置完毕,重启应用后生效", + "setting_play_save_play_time": "记住播放进度", + "setting_play_lyric_transition": "显示歌词翻译", + "setting_play_quality": "优先播放320K品质的歌曲(如果支持)", + + "setting_backup": "备份与恢复", + "setting_backup_part": "列表数据(与PC端列表备份文件通用)", + "setting_backup_part_import_list": "导入列表", + "setting_backup_part_export_list": "导出列表", + "setting_backup_part_import_setting": "导入设置", + "setting_backup_part_export_setting": "导出设置", + "setting_backup_all": "所有数据(列表数据与设置数据)", + "setting_backup_all_import": "导入", + "setting_backup_all_export": "导出", + "setting_backup_all_import_desc": "选择备份文件", + "setting_backup_all_export_desc": "选择备份保存位置", + "setting_backup_part_import_setting_desc": "选择配置文件", + "setting_backup_part_export_setting_desc": "选择设置保存位置", + "setting_backup_part_import_list_desc": "选择列表备份文件", + "setting_backup_part_export_list_desc": "选择歌单备份文件保存位置", + + "setting_other": "其他", + "setting_other_cache": "缓存管理(包括歌曲、歌词等缓存,没有歌曲播放相关的问题不建议清理)", + "setting_other_cache_size": "当前已用缓存大小:", + "setting_other_cache_clear_btn": "清理缓存", + "setting_other_cache_clear_success_tip": "缓存清理完成", + + "setting_version": "软件更新", + "setting_version_show_ver_modal": "打开更新窗口 🚀", + + "setting_about": "关于洛雪音乐" + +} diff --git a/src/navigation/components/PactModal.js b/src/navigation/components/PactModal.js new file mode 100644 index 0000000..6f4648d --- /dev/null +++ b/src/navigation/components/PactModal.js @@ -0,0 +1,220 @@ +import React, { useMemo, useState, useEffect } from 'react' +import { StyleSheet, View, Text, ScrollView, TouchableOpacity } from 'react-native' +import { Navigation } from 'react-native-navigation' + +import Button from '@/components/common/Button' +import { useGetter, useDispatch } from '@/store' +import { openUrl } from '@/utils/tools' +import { exitApp } from '@/utils/utils' + +const VersionModal = ({ componentId }) => { + const theme = useGetter('common', 'theme') + const isAgreePact = useGetter('common', 'isAgreePact') + const setAgreePact = useDispatch('common', 'setAgreePact') + const checkVersion = useDispatch('common', 'checkVersion') + const [time, setTime] = useState(20) + + const handleRejct = () => { + exitApp() + Navigation.dismissOverlay(componentId) + } + + const handleConfirm = () => { + if (!isAgreePact) setAgreePact(true) + checkVersion() + Navigation.dismissOverlay(componentId) + } + + const openHomePage = () => { + openUrl('https://github.com/lyswhut/lx-music-mobile#readme') + } + const openLicensePage = () => { + openUrl('http://www.apache.org/licenses/LICENSE-2.0') + } + + const textStyle = StyleSheet.compose(styles.text, { + color: theme.normal, + }) + const textLinkStyle = StyleSheet.compose(styles.text, { + textDecorationLine: 'underline', + color: theme.secondary, + fontSize: 15, + }) + + const confirmBtn = useMemo(() => { + if (isAgreePact) return { disabled: false, text: '关闭' } + return time ? { disabled: true, text: `同意(${time})` } : { disabled: false, text: '同意' } + }, [isAgreePact, time]) + + useEffect(() => { + if (isAgreePact) return + const timeoutTools = { + timeout: null, + start() { + this.timeout = setTimeout(() => { + setTime(time => { + time-- + if (time > 0) this.start() + return time + }) + }, 1000) + }, + clear() { + clearTimeout(this.timeout) + }, + } + timeoutTools.start() + return () => timeoutTools.clear() + }, []) + + return ( + <View style={{ ...styles.centeredView }}> + <View style={styles.modalView}> + <View style={{ ...styles.header, backgroundColor: theme.secondary }}></View> + <View style={styles.main}> + <Text style={{ ...styles.title, color: theme.normal }}>许可协议</Text> + <ScrollView style={styles.content} keyboardShouldPersistTaps={'always'}> + <View style={styles.part}> + <Text style={textStyle} >本项目(软件)基于 <Text onPress={openLicensePage} style={textLinkStyle}>Apache License 2.0</Text> 许可证发行,在使用本软件前,你(使用者)需签署本协议才可继续使用,以下协议是对于 Apache License 2.0 的补充,如有冲突,以以下协议为准。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} >词语约定:本协议中的“本软件”指洛雪音乐桌面版项目;“使用者”指签署本协议的使用者;“官方音乐平台”指对本软件内置的包括酷我、酷狗、咪咕等音乐源的官方平台统称;“版权数据”指包括但不限于图像、音频、名字等在内的他人拥有所属版权的数据。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>1.</Text> 本软件的数据来源原理是从各官方音乐平台的公开服务器中拉取数据,经过对数据简单地筛选与合并后进行展示,因此本软件不对数据的准确性负责。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>2.</Text> 使用本软件的过程中可能会产生版权数据,对于这些版权数据,本软件不拥有它们的所有权,为了避免造成侵权,使用者务必在 <Text style={styles.bold}>24小时内</Text> 清除使用本软件的过程中所产生的版权数据。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>3.</Text> 本软件内的官方音乐平台别名为本软件内对官方音乐平台的一个称呼,不包含恶意,如果官方音乐平台觉得不妥,可联系本软件更改或移除。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>4.</Text> 本软件内使用的部分包括但不限于字体、图片等资源来源于互联网,如果出现侵权可联系本软件移除。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>5.</Text> 由于使用本软件产生的包括由于本协议或由于使用或无法使用本软件而引起的任何性质的任何直接、间接、特殊、偶然或结果性损害(包括但不限于因商誉损失、停工、计算机故障或故障引起的损害赔偿,或任何及所有其他商业损害或损失)由使用者负责。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>6.</Text> 本项目完全免费,且开源发布于 <Text onPress={openHomePage} style={textLinkStyle}>GitHub</Text> 面向全世界人用作对技术的学习交流,本软件不对项目内的技术可能存在违反当地法律法规的行为作保证,<Text style={styles.bold}>禁止在违反当地法律法规的情况下使用本软件</Text>,对于使用者在明知或不知当地法律法规不允许的情况下使用本软件所造成的任何违法违规行为由使用者承担,本软件不承担由此造成的任何直接、间接、特殊、偶然或结果性责任。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>*</Text> 若协议更新,恕不另行通知,可到开源地址查看。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>*</Text> 本软件的初衷是帮助官方音乐平台简化数据后代为展示,帮助使用者根据歌曲名、艺术家等关键字快速地定位所需内容所在的音乐平台。</Text> + </View> + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={textStyle} ><Text style={styles.bold}>*</Text> 音乐平台不易,建议到对应音乐平台支持正版资源。</Text> + </View> + { + isAgreePact + ? null + : ( + <View style={{ ...styles.part, flexDirection: 'row', flexWrap: 'wrap' }}> + <Text style={{ ...styles.text, ...styles.bold, color: theme.normal }} >若你(使用者)接受以上协议,请点击下面的“接受”按钮签署本协议,若不接受,请点击“不接受”后退出软件并清除本软件的所有数据。</Text> + </View> + ) + } + </ScrollView> + </View> + <View style={styles.btns}> + { + isAgreePact + ? null + : ( + <Button style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={handleRejct}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>不同意</Text> + </Button> + ) + } + <Button disabled={confirmBtn.disabled} style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={handleConfirm}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>{confirmBtn.text}</Text> + </Button> + </View> + </View> + </View> + ) +} + +const styles = StyleSheet.create({ + centeredView: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'rgba(0,0,0,0.2)', + }, + modalView: { + maxWidth: '90%', + minWidth: '75%', + // minHeight: '36%', + maxHeight: '78%', + backgroundColor: 'white', + borderRadius: 4, + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.25, + // shadowRadius: 4, + elevation: 3, + }, + header: { + flexGrow: 0, + flexShrink: 0, + flexDirection: 'row', + borderTopLeftRadius: 4, + borderTopRightRadius: 4, + height: 20, + }, + + main: { + // flexGrow: 0, + flexShrink: 1, + marginTop: 15, + marginBottom: 20, + }, + content: { + flexGrow: 0, + marginLeft: 5, + marginRight: 5, + paddingLeft: 10, + paddingRight: 10, + }, + title: { + fontSize: 18, + textAlign: 'center', + marginBottom: 15, + }, + part: { + marginBottom: 10, + }, + text: { + fontSize: 14, + textAlignVertical: 'bottom', + }, + bold: { + fontWeight: 'bold', + }, + btns: { + flexDirection: 'row', + justifyContent: 'center', + paddingBottom: 15, + paddingLeft: 15, + // paddingRight: 15, + }, + btn: { + flex: 1, + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 10, + paddingRight: 10, + alignItems: 'center', + borderRadius: 4, + marginRight: 15, + }, +}) + +export default VersionModal + diff --git a/src/navigation/components/Toast.js b/src/navigation/components/Toast.js new file mode 100644 index 0000000..a8771ce --- /dev/null +++ b/src/navigation/components/Toast.js @@ -0,0 +1,64 @@ +import React from 'react' +import { View, Text, StyleSheet, TouchableOpacity } from 'react-native' +import { useGetter } from '@/store' +import { Navigation } from 'react-native-navigation' + + +const Toast = ({ componentId }) => { + const theme = useGetter('common', 'theme') + + return ( + <View style={styles.root}> + <View style={{ ...styles.toast, backgroundColor: theme.secondary10 }}> + <Text style={styles.text}>This a very important message!</Text> + <TouchableOpacity + style={styles.button} + onPress={() => Navigation.dismissOverlay(componentId)} + > + <Text style={styles.buttonText}>OK</Text> + </TouchableOpacity> + </View> + </View> + ) +} + +const styles = StyleSheet.create({ + root: { + flex: 1, + flexDirection: 'column-reverse', + }, + toast: { + elevation: 2, + flexDirection: 'row', + height: 40, + margin: 16, + borderRadius: 20, + alignItems: 'center', + justifyContent: 'space-between', + }, + text: { + color: 'white', + fontSize: 16, + marginLeft: 16, + }, + button: { + marginRight: 16, + }, + buttonText: { + color: 'white', + fontSize: 16, + fontWeight: 'bold', + }, +}) + +Toast.options = { + layout: { + componentBackgroundColor: 'transparent', + }, + overlay: { + interceptTouchOutside: false, + }, +} + +export default Toast + diff --git a/src/navigation/components/VersionModal.js b/src/navigation/components/VersionModal.js new file mode 100644 index 0000000..c07e752 --- /dev/null +++ b/src/navigation/components/VersionModal.js @@ -0,0 +1,305 @@ +import React, { useMemo, useState, useEffect } from 'react' +import { StyleSheet, View, Text, ScrollView } from 'react-native' +import { Navigation } from 'react-native-navigation' + +import { compareVer, sizeFormate } from '@/utils' + +import Button from '@/components/common/Button' +import { useTranslation } from '@/plugins/i18n' +import { useGetter, useDispatch } from '@/store' +import { VERSION_STATUS } from '@/config/constant' +import { downloadNewVersion, updateApp } from '@/utils/version' +import { openUrl } from '@/utils/tools' + +const VersionItem = ({ version, desc }) => { + const theme = useGetter('common', 'theme') + return ( + <View style={{ marginBottom: 10 }}> + <Text style={{ ...styles.label, color: theme.normal, marginBottom: 2 }}>v{version}</Text> + <Text style={{ ...styles.desc, color: theme.normal }}>{desc}</Text> + </View> + ) +} + +const currentVer = process.versions.app +const VersionModal = ({ componentId }) => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + const versionInfo = useGetter('common', 'versionInfo') + const setVersionInfo = useDispatch('common', 'setVersionInfo') + const setIgnoreVersion = useDispatch('common', 'setIgnoreVersion') + const [ignoreBtn, setIgnoreBtn] = useState({ text: t('version_btn_ignore'), show: true, disabled: false }) + // const [closeBtn, setCloseBtn] = useState({ text: t('version_btn_close'), show: true, disabled: false }) + const [confirmBtn, setConfirmBtn] = useState({ text: t('version_btn_confirm'), show: true, disabled: false }) + const [title, setTitle] = useState('') + const [tip, setTip] = useState('') + + const history = useMemo(() => { + if (!versionInfo.history) return [] + let arr = [] + for (const ver of versionInfo.history) { + if (compareVer(currentVer, ver.version) < 0) arr.push(ver) + } + return arr + }, [versionInfo]) + + const handleCancel = () => { + setVersionInfo({ showModal: false }) + Navigation.dismissOverlay(componentId) + } + + const handleIgnore = () => { + setIgnoreVersion(versionInfo.version) + handleCancel() + } + + const handleDownload = () => { + setVersionInfo({ + status: VERSION_STATUS.downloading, + downloadProgress: { + total: 0, + current: 0, + }, + }) + downloadNewVersion(versionInfo.version, (total, current) => { + // console.log(total, current) + setVersionInfo({ + status: VERSION_STATUS.downloading, + downloadProgress: { + total, + current, + }, + }) + }).then(() => { + setVersionInfo({ + status: VERSION_STATUS.downloaded, + }) + }).catch(err => { + console.log(err) + setVersionInfo({ + status: VERSION_STATUS.failed, + }) + }) + } + const handleConfirm = () => { + switch (versionInfo.status) { + case VERSION_STATUS.available: + handleDownload() + break + case VERSION_STATUS.downloaded: + updateApp().catch(() => { + setVersionInfo({ + status: VERSION_STATUS.failed, + }) + }) + break + case VERSION_STATUS.failed: + handleDownload() + break + + case VERSION_STATUS.unknown: + default: + openUrl('https://reactnative.dev/') + break + } + // setVersionInfo({ showModal: false }) + // Navigation.dismissOverlay(componentId) + } + + useEffect(() => { + switch (versionInfo.status) { + case VERSION_STATUS.available: + setTitle(t('version_title_new')) + setTip('') + setIgnoreBtn({ text: t('version_btn_ignore'), show: true, disabled: false }) + setConfirmBtn({ text: t('version_btn_new'), show: true, disabled: false }) + // setTip(t('version_btn_new')) + break + case VERSION_STATUS.downloading: + setTitle(t('version_title_new')) + setTip(t('version_btn_downloading', { + total: sizeFormate(versionInfo.downloadProgress.total), + current: sizeFormate(versionInfo.downloadProgress.current), + progress: versionInfo.downloadProgress.total ? (versionInfo.downloadProgress.current / versionInfo.downloadProgress.total * 100).toFixed(2) : '0', + })) + if (ignoreBtn.show) setIgnoreBtn({ text: t('version_btn_ignore'), show: false, disabled: true }) + if (!confirmBtn.disabled) setConfirmBtn({ text: t('version_btn_update'), show: true, disabled: true }) + break + case VERSION_STATUS.downloaded: + setTitle(t('version_title_update')) + setTip('') + if (ignoreBtn.show) setIgnoreBtn({ text: t('version_btn_ignore'), show: false, disabled: true }) + setConfirmBtn({ text: t('version_btn_update'), show: true, disabled: false }) + break + case VERSION_STATUS.checking: + setTitle(t('version_title_checking')) + setTip(t('')) + setIgnoreBtn({ text: t('version_btn_ignore'), show: false, disabled: true }) + setConfirmBtn({ text: t('version_btn_new'), show: false, disabled: true }) + break + case VERSION_STATUS.failed: + setTitle(t('version_title_failed')) + setTip(t('version_tip_failed')) + setIgnoreBtn({ text: t('version_btn_ignore'), show: true, disabled: false }) + setConfirmBtn({ text: t('version_btn_failed'), show: true, disabled: false }) + break + case VERSION_STATUS.unknown: + setTitle(t('version_title_unknown')) + setTip(t('version_tip_unknown')) + setIgnoreBtn({ text: t('version_btn_ignore'), show: false, disabled: true }) + setConfirmBtn({ text: t('version_btn_unknown'), show: true, disabled: false }) + break + case VERSION_STATUS.latest: + default: + setTitle(t('version_title_latest')) + setTip('') + setIgnoreBtn({ text: t('version_btn_ignore'), show: false, disabled: true }) + setConfirmBtn({ text: t('version_btn_new'), show: false, disabled: true }) + break + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [t, versionInfo]) + + return ( + <View style={{ ...styles.centeredView }}> + <View style={styles.modalView}> + <View style={{ ...styles.header, backgroundColor: theme.secondary }}></View> + <View style={styles.main}> + <Text style={{ ...styles.title, color: theme.normal }}>{title}</Text> + <ScrollView style={styles.content} keyboardShouldPersistTaps={'always'}> + <Text style={{ ...styles.label, color: theme.normal }}>{t('version_label_latest_ver')}{versionInfo.version}</Text> + <Text style={{ ...styles.label, color: theme.normal }}>{t('version_label_current_ver')}{currentVer}</Text> + { + versionInfo.desc + ? ( + <View> + <Text style={{ ...styles.label, color: theme.normal }}>{t('version_label_change_log')}</Text> + <View style={{ paddingLeft: 10, marginTop: 5 }}> + <Text style={{ ...styles.desc, color: theme.normal }}>{versionInfo.desc}</Text> + </View> + </View> + ) + : null + } + { + history.length + ? ( + <View style={styles.history}> + <Text style={{ ...styles.label, color: theme.normal }}>{t('version_label_history')}</Text> + <View style={{ paddingLeft: 10, marginTop: 5 }}> + {history.map((item, index) => <VersionItem key={index} version={item.version} desc={item.desc} />)} + </View> + </View> + ) + : null + } + </ScrollView> + { tip.length ? <Text style={{ marginTop: 10, fontSize: 14, color: theme.secondary }}>{tip}</Text> : null } + </View> + <View style={styles.btns}> + { + ignoreBtn.show + ? ( + <Button disabled={ignoreBtn.disabled} style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={handleIgnore}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>{ignoreBtn.text}</Text> + </Button> + ) + : null + } + <Button style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={handleCancel}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>{t('version_btn_close')}</Text> + </Button> + { + confirmBtn.show + ? ( + <Button disabled={confirmBtn.disabled} style={{ ...styles.btn, backgroundColor: theme.secondary45 }} onPress={handleConfirm}> + <Text style={{ fontSize: 14, color: theme.secondary_5 }}>{confirmBtn.text}</Text> + </Button> + ) + : null + } + </View> + </View> + </View> + ) +} + +const styles = StyleSheet.create({ + centeredView: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'rgba(0,0,0,0.2)', + }, + modalView: { + maxWidth: '90%', + minWidth: '75%', + // minHeight: '36%', + maxHeight: '78%', + backgroundColor: 'white', + borderRadius: 4, + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.25, + // shadowRadius: 4, + elevation: 3, + }, + header: { + flexGrow: 0, + flexShrink: 0, + flexDirection: 'row', + borderTopLeftRadius: 4, + borderTopRightRadius: 4, + height: 20, + }, + + main: { + // flexGrow: 0, + flexShrink: 1, + marginTop: 15, + marginLeft: 15, + marginRight: 15, + marginBottom: 20, + }, + content: { + flexGrow: 0, + }, + title: { + fontSize: 18, + textAlign: 'center', + marginBottom: 15, + }, + history: { + marginTop: 15, + }, + label: { + fontSize: 14, + }, + desc: { + fontSize: 13, + lineHeight: 18, + }, + btns: { + flexDirection: 'row', + justifyContent: 'center', + paddingBottom: 15, + paddingLeft: 15, + // paddingRight: 15, + }, + btn: { + flex: 1, + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 10, + paddingRight: 10, + alignItems: 'center', + borderRadius: 4, + marginRight: 15, + }, +}) + +export default VersionModal + diff --git a/src/navigation/index.js b/src/navigation/index.js new file mode 100644 index 0000000..c3b6131 --- /dev/null +++ b/src/navigation/index.js @@ -0,0 +1,37 @@ +import { Navigation } from 'react-native-navigation' +import * as screenNames from './screenNames' +import * as navigations from './navigation' + +import registerScreens from './registerScreens' + +// let unRegisterEvent + +const init = callback => { + // Register all screens on launch + registerScreens() + + // if (unRegisterEvent) unRegisterEvent() + + Navigation.setDefaultOptions({ + animations: { + setRoot: { + waitForRender: true, + }, + }, + }) + // unRegisterEvent = Navigation.events().registerCommandListener((name, params) => { + // console.log(name, params) + // }) + Navigation.events().registerAppLaunchedListener(() => { + console.log('Register app launched listener') + callback() + }) +} + +export * from './utils' + +export { + init, + screenNames, + navigations, +} diff --git a/src/navigation/navigation.js b/src/navigation/navigation.js new file mode 100644 index 0000000..3dba241 --- /dev/null +++ b/src/navigation/navigation.js @@ -0,0 +1,260 @@ +import { Navigation } from 'react-native-navigation' +// import { Dimensions } from 'react-native' + +import { + HOME_SCREEN, + // SETTING_SCREEN, +} from './screenNames' + + +export function pushHomeScreen() { + /* + Navigation.setDefaultOptions({ + topBar: { + background: { + color: '#039893', + }, + title: { + color: 'white', + }, + backButton: { + title: '', // Remove previous screen name from back button + color: 'white', + }, + buttonColor: 'white', + }, + statusBar: { + style: 'light', + }, + layout: { + orientation: ['portrait'], + }, + bottomTabs: { + titleDisplayMode: 'alwaysShow', + }, + bottomTab: { + textColor: 'gray', + selectedTextColor: 'black', + iconColor: 'gray', + selectedIconColor: 'black', + }, + }) + */ + + Navigation.setRoot({ + root: { + stack: { + children: [{ + component: { + name: HOME_SCREEN, + options: { + topBar: { + visible: false, + height: 0, + drawBehind: false, + }, + statusBar: { + drawBehind: true, + visible: true, + style: 'dark', + backgroundColor: 'transparent', + }, + }, + }, + }], + }, + }, + }) +} +// export function pushSettingScreen(componentId) { +// /* +// Navigation.setDefaultOptions({ +// topBar: { +// background: { +// color: '#039893', +// }, +// title: { +// color: 'white', +// }, +// backButton: { +// title: '', // Remove previous screen name from back button +// color: 'white', +// }, +// buttonColor: 'white', +// }, +// statusBar: { +// style: 'light', +// }, +// layout: { +// orientation: ['portrait'], +// }, +// bottomTabs: { +// titleDisplayMode: 'alwaysShow', +// }, +// bottomTab: { +// textColor: 'gray', +// selectedTextColor: 'black', +// iconColor: 'gray', +// selectedIconColor: 'black', +// }, +// }) +// */ + +// Navigation.push(componentId, { +// component: { +// name: SETTING_SCREEN, +// options: { +// topBar: { +// visible: false, +// height: 0, +// drawBehind: false, +// }, +// statusBar: { +// drawBehind: true, +// visible: true, +// style: 'dark', +// backgroundColor: 'transparent', +// }, +// animations: { +// push: { +// content: { +// translationX: { +// from: Dimensions.get('window').width, +// to: 0, +// duration: 300, +// }, +// }, +// }, +// pop: { +// content: { +// translationX: { +// from: 0, +// to: Dimensions.get('window').width, +// duration: 300, +// }, +// }, +// }, +// }, +// }, +// }, +// }) +// } +/* +export function pushSingleScreenApp() { + Navigation.setRoot({ + root: { + stack: { + children: [{ + component: { + name: SINGLE_APP_SCREEN, + options: { + topBar: { + title: { + text: 'SINGLE SCREEN APP', + }, + leftButtons: [ + { + id: 'nav_user_btn', + icon: require('assets/icons/ic_nav_user.png'), + color: 'white', + }, + ], + rightButtons: [ + { + id: 'nav_logout_btn', + icon: require('assets/icons/ic_nav_logout.png'), + color: 'white', + }, + ], + }, + }, + }, + }], + }, + }, + }) +} + +export function pushTabBasedApp() { + Navigation.setRoot({ + root: { + bottomTabs: { + children: [{ + stack: { + children: [{ + component: { + name: TAB1_SCREEN, + options: { + topBar: { + title: { + text: 'TAB 1', + }, + leftButtons: [ + { + id: 'nav_user_btn', + icon: require('assets/icons/ic_nav_user.png'), + color: 'white', + }, + ], + rightButtons: [ + { + id: 'nav_logout_btn', + icon: require('assets/icons/ic_nav_logout.png'), + color: 'white', + }, + ], + }, + }, + }, + }], + options: { + bottomTab: { + icon: require('assets/icons/ic_tab_home.png'), + testID: 'FIRST_TAB_BAR_BUTTON', + text: 'Tab1', + }, + }, + }, + }, + { + stack: { + children: [{ + component: { + name: TAB2_SCREEN, + options: { + topBar: { + title: { + text: 'TAB 2', + }, + leftButtons: [ + { + id: 'nav_user_btn', + icon: require('assets/icons/ic_nav_user.png'), + color: 'white', + }, + ], + rightButtons: [ + { + id: 'nav_logout_btn', + icon: require('assets/icons/ic_nav_logout.png'), + color: 'white', + }, + ], + }, + }, + }, + }], + options: { + bottomTab: { + icon: require('assets/icons/ic_tab_menu.png'), + testID: 'SECOND_TAB_BAR_BUTTON', + text: 'Tab2', + }, + }, + }, + }], + }, + }, + }) +} + */ diff --git a/src/navigation/registerScreens.js b/src/navigation/registerScreens.js new file mode 100644 index 0000000..1669df2 --- /dev/null +++ b/src/navigation/registerScreens.js @@ -0,0 +1,41 @@ +// @flow + +import React from 'react' +import { Navigation } from 'react-native-navigation' + +import { + Home, + // Setting, +} from '@/screens' +import { Provider } from '@/store' + +import { + HOME_SCREEN, + VERSION_MODAL, + PACT_MODAL, + // SETTING_SCREEN, +} from './screenNames' +import VersionModal from './components/VersionModal' +import PactModal from './components/PactModal' + +function WrappedComponent(Component) { + return function inject(props) { + const EnhancedComponent = () => ( + <Provider> + <Component + {...props} + /> + </Provider> + ) + + return <EnhancedComponent /> + } +} + +export default () => { + Navigation.registerComponent(HOME_SCREEN, () => WrappedComponent(Home)) + Navigation.registerComponent(VERSION_MODAL, () => WrappedComponent(VersionModal)) + Navigation.registerComponent(PACT_MODAL, () => WrappedComponent(PactModal)) + + console.info('All screens have been registered...') +} diff --git a/src/navigation/screenNames.js b/src/navigation/screenNames.js new file mode 100644 index 0000000..c8f524b --- /dev/null +++ b/src/navigation/screenNames.js @@ -0,0 +1,6 @@ +export const HOME_SCREEN = 'lxm.HomeScreen' +export const VERSION_MODAL = 'lxm.VersionModal' +export const PACT_MODAL = 'lxm.PactModal' +// export const TOAST_SCREEN = 'lxm.ToastScreen' +// export const SETTING_SCREEN = 'lxm.SettingScreen' + diff --git a/src/navigation/utils.js b/src/navigation/utils.js new file mode 100644 index 0000000..0e2a25a --- /dev/null +++ b/src/navigation/utils.js @@ -0,0 +1,100 @@ +import { Navigation } from 'react-native-navigation' +import { VERSION_MODAL, PACT_MODAL } from './screenNames' + +export const dismissOverlay = compId => Navigation.dismissOverlay(compId) + +export const showPactModal = () => { + Navigation.showOverlay({ + component: { + name: PACT_MODAL, + options: { + layout: { + componentBackgroundColor: 'transparent', + }, + overlay: { + interceptTouchOutside: true, + }, + statusBar: { + drawBehind: true, + visible: true, + style: 'dark', + backgroundColor: 'transparent', + animate: true, + }, + // animations: { + + // showModal: { + // enter: { + // enabled: true, + // alpha: { + // from: 0, + // to: 1, + // duration: 300, + // }, + // }, + // exit: { + // enabled: true, + // alpha: { + // from: 1, + // to: 0, + // duration: 300, + // }, + // }, + // }, + // }, + }, + }, + }) +} + +export const showVersionModal = () => { + Navigation.showOverlay({ + component: { + name: VERSION_MODAL, + options: { + layout: { + componentBackgroundColor: 'transparent', + }, + overlay: { + interceptTouchOutside: true, + }, + statusBar: { + drawBehind: true, + visible: true, + style: 'dark', + backgroundColor: 'transparent', + animate: true, + }, + // animations: { + + // showModal: { + // enter: { + // enabled: true, + // alpha: { + // from: 0, + // to: 1, + // duration: 300, + // }, + // }, + // exit: { + // enabled: true, + // alpha: { + // from: 1, + // to: 0, + // duration: 300, + // }, + // }, + // }, + // }, + }, + }, + }) +} + +// export const showToast = (text) => { +// Navigation.showOverlay({ +// component: { +// name: TOAST_SCREEN, +// }, +// }) +// } diff --git a/src/plugins/i18n.js b/src/plugins/i18n.js new file mode 100644 index 0000000..182c867 --- /dev/null +++ b/src/plugins/i18n.js @@ -0,0 +1,44 @@ +import i18n from 'i18next' +import { useTranslation, initReactI18next } from 'react-i18next' +import langs from '@/lang' + +const resources = {} +const supportedLngs = [] +const langList = [] +for (const { id, name, translation } of langs) { + resources[id] = { + id, + name, + translation, + } + langList.push({ + id, + name, + }) + supportedLngs.push(id) +} +// console.log(resources) +export const init = (lang = 'zh_cn') => { + return i18n + .use(initReactI18next) // passes i18n down to react-i18next + .init({ + // debug: true, + resources, + lng: lang, + fallbackLng: 'en_us', + keySeparator: false, + lowerCaseLng: true, + interpolation: { + escapeValue: false, + }, + }) +} + +export const changeLanguage = lang => i18n.changeLanguage(lang) + +export { + useTranslation, + langList, + i18n, + supportedLngs, +} diff --git a/src/plugins/lyric.js b/src/plugins/lyric.js new file mode 100644 index 0000000..4394584 --- /dev/null +++ b/src/plugins/lyric.js @@ -0,0 +1,95 @@ +import { useEffect, useState } from 'react' +import Lyric from 'lrc-file-parser' +// import { getStore, subscribe } from '@/store' + +const lrcTools = { + isInited: false, + lrc: null, + currentLineData: { line: 0, text: '' }, + currentLines: [], + playHooks: [], + setLyricHooks: [], + isPlay: false, + init() { + if (this.isInited) return + this.isInited = true + this.lrc = new Lyric({ + onPlay: this.onPlay.bind(this), + onSetLyric: this.onSetLyric.bind(this), + offset: 100, // offset time(ms), default is 150 ms + }) + }, + onPlay(line, text) { + this.currentLineData.line = line + // console.log(line) + this.currentLineData.text = text + for (const hook of this.playHooks) hook(line, text) + }, + onSetLyric(lines) { + this.currentLines = lines + for (const hook of this.setLyricHooks) hook(lines) + }, + addPlayHook(callback) { + this.playHooks.push(callback) + callback(this.currentLineData.line, this.currentLineData.text) + }, + removePlayHook(callback) { + this.playHooks.splice(this.playHooks.indexOf(callback), 1) + }, + addSetLyricHook(callback) { + this.setLyricHooks.push(callback) + callback(this.currentLines) + }, + removeSetLyricHook(callback) { + this.setLyricHooks.splice(this.setLyricHooks.indexOf(callback), 1) + }, +} + + +export const init = async() => { + lrcTools.init() +} + +export const setLyric = lyric => { + lrcTools.isPlay = false + lrcTools.lrc.setLyric(lyric) +} +export const play = time => { + // console.log(time) + lrcTools.isPlay = true + lrcTools.lrc.play(time) +} +export const pause = () => { + // console.log('pause') + lrcTools.isPlay = false + lrcTools.lrc.pause() +} + +// on lyric play hook +export const useLrcPlay = () => { + const [lrcInfo, setLrcInfo] = useState({ line: 0, text: '' }) + useEffect(() => { + const callback = (line, text) => { + setLrcInfo({ line, text }) + } + lrcTools.addPlayHook(callback) + return () => lrcTools.removePlayHook(callback) + }, [setLrcInfo]) + + return lrcInfo +} + +// on lyric set hook +export const useLrcSet = () => { + const [lines, setLines] = useState([]) + useEffect(() => { + const callback = lines => { + setLines(lines) + } + lrcTools.addSetLyricHook(callback) + return () => lrcTools.removeSetLyricHook(callback) + }, [setLines]) + + return lines +} + diff --git a/src/plugins/player/Player.js b/src/plugins/player/Player.js new file mode 100644 index 0000000..e69de29 diff --git a/src/plugins/player/hook.js b/src/plugins/player/hook.js new file mode 100644 index 0000000..1e12796 --- /dev/null +++ b/src/plugins/player/hook.js @@ -0,0 +1,104 @@ +import { useRef, useEffect, useState, useCallback } from 'react' +import { + getState, + getPosition, + getBufferedPosition, + getDuration, + TrackPlayerEvents, + useTrackPlayerEvents, + STATE_PLAYING, + STATE_BUFFERING, +} from 'react-native-track-player' + +const useWhenPlaybackStateChanges = callback => { + useTrackPlayerEvents( + [TrackPlayerEvents.PLAYBACK_STATE], + ({ state }) => { + callback(state) + }, + ) + useEffect(() => { + let didCancel = false + const fetchPlaybackState = async() => { + const playbackState = await getState() + if (!didCancel) { + callback(playbackState) + } + } + fetchPlaybackState() + return () => { didCancel = true } + }, [callback]) +} + +const usePlaybackStateIs = states => { + const [is, setIs] = useState() + useWhenPlaybackStateChanges(state => { + const newIs = !!states && states.includes(state) + if (is != newIs) setIs(newIs) + }) + + return is +} + +// const useInterval = (callback, delay) => { +// const savedCallback = useRef() + +// useEffect(() => { +// savedCallback.current = callback +// }) + +// useEffect(() => { +// if (!delay) return +// savedCallback.current() +// const id = setInterval(savedCallback.current, delay) +// return () => clearInterval(id) +// }, [delay]) +// } + +const pollTrackPlayerStates = [ + STATE_PLAYING, + STATE_BUFFERING, +] + +export const useTrackPlayerProgress = time => { + const [state, setState] = useState({ + position: 0, + bufferedPosition: 0, + duration: 0, + }) + const isUnmountedRef = useRef(true) + const intervalRef = useRef(null) + + useEffect(() => { + isUnmountedRef.current = false + return () => { isUnmountedRef.current = true } + }) + + const getProgress = useCallback(() => { + Promise.all([ + getPosition(), + getBufferedPosition(), + getDuration(), + ]).then(([position, bufferedPosition, duration]) => { + if (isUnmountedRef.current) return + setState({ position, bufferedPosition, duration }) + }) + }, []) + + const needsPoll = usePlaybackStateIs(pollTrackPlayerStates) + + useEffect(() => { + if (needsPoll) { + if (intervalRef.current == null) { + intervalRef.current = setInterval(getProgress, time) + } + } else { + if (intervalRef.current != null) { + clearInterval(intervalRef.current) + intervalRef.current = null + } + } + }, [getProgress, needsPoll, time]) + + return state +} diff --git a/src/plugins/player/index.js b/src/plugins/player/index.js new file mode 100644 index 0000000..12e3f16 --- /dev/null +++ b/src/plugins/player/index.js @@ -0,0 +1,46 @@ +import TrackPlayer from 'react-native-track-player' +import service from './service' +import { updateOptions } from './utils' + +// const listenEvent = () => { +// TrackPlayer.addEventListener('playback-error', err => { +// console.log('playback-error', err) +// }) +// TrackPlayer.addEventListener('playback-state', info => { +// console.log('playback-state', info) +// }) +// TrackPlayer.addEventListener('playback-track-changed', info => { +// console.log('playback-track-changed', info) +// }) +// TrackPlayer.addEventListener('playback-queue-ended', info => { +// console.log('playback-queue-ended', info) +// }) +// } + +const initial = async(cacheSize) => { + if (global.playerStatus.isIniting || global.playerStatus.isInitialized) return + global.playerStatus.isIniting = true + console.log('Cache Size', cacheSize * 1024) + await TrackPlayer.setupPlayer({ maxCacheSize: cacheSize * 1024, maxBuffer: 1000, waitForBuffer: true }) + global.playerStatus.isInitialized = true + global.playerStatus.isIniting = false + await updateOptions() + // listenEvent() +} + + +const registerPlaybackService = async() => { + if (global.playerStatus.isRegisteredService) return + console.log('handle registerPlaybackService...') + await TrackPlayer.registerPlaybackService(() => service) + global.playerStatus.isRegisteredService = true +} + +const isInitialized = () => global.playerStatus.isInitialized + + +export { + registerPlaybackService, + initial, + isInitialized, +} diff --git a/src/plugins/player/service.js b/src/plugins/player/service.js new file mode 100644 index 0000000..c794e0c --- /dev/null +++ b/src/plugins/player/service.js @@ -0,0 +1,245 @@ +import TrackPlayer from 'react-native-track-player' +import { getStore } from '@/store' +import { action as playerAction, STATUS } from '@/store/modules/player' +import { isTempTrack } from './utils' +import { play as lrcPlay, pause as lrcPause } from '@/plugins/lyric' +import { exitApp } from '@/utils/tools' + +const store = getStore() + +let isInitialized = false + +let retryTrack = null +let retryGetUrlId = null +let retryGetUrlNum = 0 +let trackId = '' +let errorTime = 0 + +// const updateTrackUrl = async track => { +// const playInfo = track.id.split('__//') +// const type = playInfo[2] +// let url +// const newMusicInfo = { ...track.original } +// try { +// url = await store.dispatch(playerAction.getUrl({ +// musicInfo: newMusicInfo, +// type, +// })) +// } catch (err) { +// console.log('err', err) +// retryGetUrlNum++ +// if (retryGetUrlNum > 2) throw err +// if (retryGetUrlId != track.id) throw new Error('跳过播放') +// return updateTrackUrl(track) +// } +// newMusicInfo.typeUrl[type] = url +// const newTrack = buildTrack(newMusicInfo) +// await replacePlayTrack(newTrack, track) +// return newTrack +// } +// const eventTool = { +// events: { + +// }, +// addEventListener(name, handler) { +// if (this.events[name]) return +// TrackPlayer.addEventListener(name, handler) +// }, +// clearEventListeners() { + +// }, +// } + +export default async() => { + if (isInitialized) return + + console.log('reg services...') + TrackPlayer.addEventListener('remote-play', () => { + // console.log('remote-play') + // TrackPlayer.play() + store.dispatch(playerAction.playMusic()) + }) + + TrackPlayer.addEventListener('remote-pause', () => { + console.log('remote-pause') + store.dispatch(playerAction.pauseMusic()) + // TrackPlayer.pause() + }) + + TrackPlayer.addEventListener('remote-next', () => { + console.log('remote-next') + store.dispatch(playerAction.playNext()) + // TrackPlayer.skipToNext() + }) + + TrackPlayer.addEventListener('remote-previous', () => { + console.log('remote-previous') + store.dispatch(playerAction.playPrev()) + // TrackPlayer.skipToPrevious() + }) + + TrackPlayer.addEventListener('remote-stop', async() => { + console.log('remote-stop') + await store.dispatch(playerAction.destroy()) + exitApp() + }) + + TrackPlayer.addEventListener('playback-error', async err => { + console.log('playback-error', err) + // console.log((await TrackPlayer.getQueue())) + lrcPause() + if (!retryTrack) errorTime = await TrackPlayer.getPosition() + retryTrack = await TrackPlayer.getTrack(await TrackPlayer.getCurrentTrack()) + await TrackPlayer.skipToNext() + }) + TrackPlayer.addEventListener('playback-state', async info => { + const state = store.getState() + if (state.player.isGettingUrl) return + // let trackInfo = await TrackPlayer.getCurrentTrack() + // console.log(trackId) + if (trackId && trackId.endsWith('//default')) return + switch (info.state) { + case TrackPlayer.STATE_NONE: + // console.log('state', 'STATE_NONE') + break + case TrackPlayer.STATE_READY: + // console.log('state', 'STATE_READY') + // store.dispatch(playerAction.setStatus({ status: STATUS.pause, text: '已暂停' })) + lrcPause() + break + case TrackPlayer.STATE_PLAYING: + retryTrack = null + // console.log('state', 'STATE_PLAYING') + store.dispatch(playerAction.setStatus({ status: STATUS.playing, text: '播放中...' })) + TrackPlayer.getPosition().then(position => { + lrcPlay(position * 1000) + }) + break + case TrackPlayer.STATE_PAUSED: + // console.log('state', 'STATE_PAUSED') + store.dispatch(playerAction.setStatus({ status: STATUS.pause, text: '已暂停' })) + lrcPause() + break + case TrackPlayer.STATE_STOPPED: + switch (state.player.status) { + case STATUS.none: + break + + default: + store.dispatch(playerAction.setStatus({ status: STATUS.stop, text: '已停止' })) + break + } + // console.log('state', 'STATE_STOPPED') + lrcPause() + break + case TrackPlayer.STATE_BUFFERING: + store.dispatch(playerAction.setStatus({ status: STATUS.buffering, text: '缓冲中...' })) + // console.log('state', 'STATE_BUFFERING') + lrcPause() + break + case TrackPlayer.STATE_CONNECTING: + switch (state.player.status) { + case STATUS.none: + case STATUS.pause: + case STATUS.stop: + break + + default: + store.dispatch(playerAction.setStatus({ text: '加载中...' })) + break + } + lrcPause() + // console.log('state', 'STATE_CONNECTING') + break + + default: + console.log('playback-state', info) + break + } + }) + TrackPlayer.addEventListener('playback-track-changed', async info => { + // console.log('nextTrack====>', info) + trackId = await TrackPlayer.getCurrentTrack() + if (trackId && isTempTrack(trackId)) { + console.log('====TEMP PAUSE====') + TrackPlayer.pause() + if (retryTrack) { + if (retryTrack.id == retryGetUrlId) { + if (++retryGetUrlNum > 1) { + store.dispatch(playerAction.playNext()) + retryGetUrlId = null + retryTrack = null + return + } + } else { + retryGetUrlId = retryTrack.id + retryGetUrlNum = 0 + } + store.dispatch(playerAction.refreshMusicUrl(retryTrack.original, errorTime)) + } else { + store.dispatch(playerAction.playNext()) + } + } + // // if (!info.nextTrack) return + // // if (info.track) { + // // const track = info.track.substring(0, info.track.lastIndexOf('__//')) + // // const nextTrack = info.track.substring(0, info.nextTrack.lastIndexOf('__//')) + // // console.log(nextTrack, track) + // // if (nextTrack == track) return + // // } + // // const track = await TrackPlayer.getTrack(info.nextTrack) + // // if (!track) return + // // let newTrack + // // if (track.url == defaultUrl) { + // // TrackPlayer.pause().then(async() => { + // // isRefreshUrl = true + // // retryGetUrlId = track.id + // // retryGetUrlNum = 0 + // // try { + // // newTrack = await updateTrackUrl(track) + // // console.log('++++newTrack++++', newTrack) + // // } catch (error) { + // // console.log('error', error) + // // if (error.message != '跳过播放') TrackPlayer.skipToNext() + // // isRefreshUrl = false + // // retryGetUrlId = null + // // return + // // } + // // retryGetUrlId = null + // // isRefreshUrl = false + // // console.log(await TrackPlayer.getQueue(), null, 2) + // // await TrackPlayer.play() + // // }) + // // } + // // store.dispatch(playerAction.playNext()) + }) + // TrackPlayer.addEventListener('playback-queue-ended', async info => { + // // console.log('playback-queue-ended', info) + // store.dispatch(playerAction.playNext()) + // // if (!info.nextTrack) return + // // const track = await TrackPlayer.getTrack(info.nextTrack) + // // if (!track) return + // // // if (track.url == defaultUrl) { + // // // TrackPlayer.pause() + // // // getMusicUrl(track.original).then(url => { + // // // TrackPlayer.updateMetadataForTrack(info.nextTrack, { + // // // url, + // // // }) + // // // TrackPlayer.play() + // // // }) + // // // } + // // if (!track.artwork) { + // // getMusicPic(track.original).then(url => { + // // console.log(url) + // // TrackPlayer.updateMetadataForTrack(info.nextTrack, { + // // artwork: url, + // // }) + // // }) + // // } + // }) + // TrackPlayer.addEventListener('playback-destroy', async() => { + // console.log('playback-destroy') + // store.dispatch(playerAction.destroy()) + // }) + isInitialized = true +} diff --git a/src/plugins/player/utils.js b/src/plugins/player/utils.js new file mode 100644 index 0000000..c51beb7 --- /dev/null +++ b/src/plugins/player/utils.js @@ -0,0 +1,304 @@ +import TrackPlayer, { useTrackPlayerProgress } from 'react-native-track-player' +import BackgroundTimer from 'react-native-background-timer' +import { defaultUrl } from '@/config' + +const defaultUserAgent = 'Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Mobile Safari/537.36' + +export const buildTracks = (musicInfo, type, url) => { + const track = [] + if (url) { + track.push({ + id: `${musicInfo.source}__//${musicInfo.songmid}__//${type}__//${url}`, + url, + title: musicInfo.name, + artist: musicInfo.singer, + album: musicInfo.albumName || null, + artwork: musicInfo.img || null, + userAgent: defaultUserAgent, + original: { ...musicInfo }, + }) + } + track.push({ + id: `${musicInfo.source}__//${musicInfo.songmid}__//${type}__//${Math.random()}__//default`, + url: defaultUrl, + title: musicInfo.name, + artist: musicInfo.singer, + album: musicInfo.albumName || null, + artwork: musicInfo.img || null, + original: { ...musicInfo }, + }) + return track + // console.log('buildTrack', musicInfo.name, url) +} +export const buildTrack = (musicInfo, type, url) => { + return url + ? { + id: `${musicInfo.source}__//${musicInfo.songmid}__//${type}__//${url}`, + url, + title: musicInfo.name, + artist: musicInfo.singer, + album: musicInfo.albumName || null, + artwork: musicInfo.img || null, + userAgent: defaultUserAgent, + original: { ...musicInfo }, + } + : { + id: `${musicInfo.source}__//${musicInfo.songmid}__//${type}__//${Math.random()}__//default`, + url: defaultUrl, + title: musicInfo.name, + artist: musicInfo.singer, + album: musicInfo.albumName || null, + artwork: musicInfo.img || null, + original: { ...musicInfo }, + } +} + +export const isTempTrack = trackId => /\/\/default$/.test(trackId) + +export const replacePlayTrack = async(newTrack, oldTrack) => { + console.log('replaceTrack') + await TrackPlayer.add(newTrack) + await TrackPlayer.skip(newTrack.id) + await TrackPlayer.remove(oldTrack.id) +} + +// let timeout +// let isFirstPlay = true +// const updateInfo = async track => { +// if (isFirstPlay) { +// // timeout = setTimeout(() => { +// await updateMusicInfo(track) +// isFirstPlay = false +// // }, 500) +// } +// } + +const handlePlayMusic = async(tracks, time) => { + // console.log('playMusic=========>', tracks.map(track => track.id)) + // if (timeout) { + // clearTimeout(timeout) + // timeout = null + // } + // console.log(tracks) + // console.log(tracks.map(track => track.id)) + // console.log(time) + const track = tracks[0] + const currentTrackId = await TrackPlayer.getCurrentTrack() + await TrackPlayer.add(tracks) + await TrackPlayer.skip(track.id) + + if (currentTrackId) { + if (isTempTrack(track.id)) { + await TrackPlayer.pause() + } else { + await TrackPlayer.seekTo(time) + await TrackPlayer.play() + } + } else { + if (!isTempTrack(track.id)) { + if (time) await TrackPlayer.seekTo(time) + if (global.restorePlayInfo) { + await TrackPlayer.pause() + global.restorePlayInfo = null + } else { + await TrackPlayer.play() + } + } + } + + const queue = await TrackPlayer.getQueue() + if (queue.length > 3) { + TrackPlayer.remove(queue.slice(0, queue.length - 3).map(t => t.id)) + } + + // if (!currentTrackId) { + // await TrackPlayer.add(track) + // await TrackPlayer.pause() + // await TrackPlayer.skip(track.id) + // if (track.url !== defaultUrl) { + // await TrackPlayer.play() + // } + // const trackIds = (await TrackPlayer.getQueue()).filter(s => s.id !== track.id).map(s => s.id) + // if (trackIds.length) await TrackPlayer.remove(trackIds) + // await updateInfo(track) + // return + // } + // // const currentTrack = await TrackPlayer.getTrack(currentTrackId) + // await TrackPlayer.pause() + // await TrackPlayer.seekTo(0) + // if (currentTrackId == track.id) { + // if (track.url !== defaultUrl) { + // await TrackPlayer.play() + // } + // await updateInfo(track) + // return + // } + // await TrackPlayer.add(track) + // await TrackPlayer.skip(track.id) + // if (track.url !== defaultUrl) { + // await TrackPlayer.play() + // } + // await TrackPlayer.remove(currentTrackId) + // await updateInfo(track) +} + + +// 解决快速切歌导致的通知栏歌曲信息与当前播放歌曲对不上的问题 +const debouncePlayMusicTools = { + prevPlayMusicPromise: Promise.resolve(), + trackInfo: {}, + isDebounced: false, + delay: 1000, + delayTimer: null, + debounce(fn, delay = 100) { + let timer = null + let _args = null + return (...args) => { + if (!this.isDebounced && _args != null) this.isDebounced = true + _args = args + if (this.delayTimer) { + BackgroundTimer.clearTimeout(this.delayTimer) + this.delayTimer = null + } + if (timer) BackgroundTimer.clearTimeout(timer) + timer = BackgroundTimer.setTimeout(() => { + timer = null + let args = _args + _args = null + fn(...args) + }, delay) + } + }, + delayUpdateMusicInfo() { + if (this.delayTimer) BackgroundTimer.clearTimeout(this.delayTimer) + this.delayTimer = BackgroundTimer.setTimeout(() => { + this.delayTimer = null + if (this.trackInfo.tracks && this.trackInfo.tracks.length) updateMusicInfo(this.trackInfo.tracks[0]) + }, this.delay) + }, + init() { + return this.debounce((tracks, time) => { + tracks = [...tracks] + this.trackInfo.tracks = tracks + this.trackInfo.time = time + return this.prevPlayMusicPromise.then(() => { + // console.log('run') + if (this.trackInfo.tracks === tracks) { + this.prevPlayMusicPromise = handlePlayMusic(tracks, time).then(() => { + if (this.isDebounced) { + this.delayUpdateMusicInfo() + this.isDebounced = false + } + }) + } + }) + }, 200) + }, +} + +export const playMusic = debouncePlayMusicTools.init() + +export const updateMusicInfo = async track => { + const queue = await TrackPlayer.getQueue() + const targetTrack = queue.find(t => t.id === track.id) + if (!targetTrack) return + console.log('+++++updateMusicPic+++++', track.artwork) + await TrackPlayer.updateMetadataForTrack(track.id, { + title: track.title, + artist: track.artist, + album: track.album, + artwork: track.artwork, + original: { ...track.original }, + }) +} + + +export const play = () => TrackPlayer.play() +export const getPosition = () => TrackPlayer.getPosition() +export const stop = () => TrackPlayer.stop() +export const pause = () => TrackPlayer.pause() +// export const skipToNext = () => TrackPlayer.skipToNext() +export const seekTo = time => TrackPlayer.seekTo(time) + +export const resetPlay = async() => Promise.all([pause(), seekTo(0)]) + +export const destroy = async() => { + if (global.playerStatus.isIniting || !global.playerStatus.isInitialized) return + await TrackPlayer.destroy() + global.playerStatus.isInitialized = false +} + + +/** + * Subscription player state chuange event + * @param {*} callback state change event + * @returns remove event function + */ +export const playState = callback => TrackPlayer.addEventListener('playback-state', callback) + +export const updateOptions = (options = { + // Whether the player should stop running when the app is closed on Android + // stopWithApp: true, + + // An array of media controls capabilities + // Can contain CAPABILITY_PLAY, CAPABILITY_PAUSE, CAPABILITY_STOP, CAPABILITY_SEEK_TO, + // CAPABILITY_SKIP_TO_NEXT, CAPABILITY_SKIP_TO_PREVIOUS, CAPABILITY_SET_RATING + capabilities: [ + TrackPlayer.CAPABILITY_PLAY, + TrackPlayer.CAPABILITY_PAUSE, + TrackPlayer.CAPABILITY_STOP, + TrackPlayer.CAPABILITY_SKIP_TO_NEXT, + TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS, + ], + + notificationCapabilities: [ + TrackPlayer.CAPABILITY_PLAY, + TrackPlayer.CAPABILITY_PAUSE, + TrackPlayer.CAPABILITY_STOP, + TrackPlayer.CAPABILITY_SKIP_TO_NEXT, + TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS, + ], + + // // An array of capabilities that will show up when the notification is in the compact form on Android + compactCapabilities: [ + TrackPlayer.CAPABILITY_PLAY, + TrackPlayer.CAPABILITY_STOP, + TrackPlayer.CAPABILITY_PAUSE, + TrackPlayer.CAPABILITY_SKIP_TO_NEXT, + ], + + // Icons for the notification on Android (if you don't like the default ones) + // playIcon: require('./play-icon.png'), + // pauseIcon: require('./pause-icon.png'), + // stopIcon: require('./stop-icon.png'), + // previousIcon: require('./previous-icon.png'), + // nextIcon: require('./next-icon.png'), + // icon: require('./notification-icon.png'), // The notification icon +}) => { + return TrackPlayer.updateOptions(options) +} + +// export const setMaxCache = async size => { +// // const currentTrack = await TrackPlayer.getCurrentTrack() +// // if (!currentTrack) return +// // console.log(currentTrack) +// // const currentTime = await TrackPlayer.getPosition() +// // const state = await TrackPlayer.getState() +// // await stop() +// // await TrackPlayer.destroy() +// // await TrackPlayer.setupPlayer({ maxCacheSize: size * 1024, maxBuffer: 1000, waitForBuffer: true }) +// // await updateOptions() +// // await TrackPlayer.seekTo(currentTime) +// // switch (state) { +// // case TrackPlayer.STATE_PLAYING: +// // case TrackPlayer.STATE_BUFFERING: +// // await TrackPlayer.play() +// // break +// // default: +// // break +// // } +// } + +export { + useTrackPlayerProgress, +} diff --git a/src/plugins/storage.js b/src/plugins/storage.js new file mode 100644 index 0000000..72d9648 --- /dev/null +++ b/src/plugins/storage.js @@ -0,0 +1,93 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' + +export const setData = async(key, value) => { + try { + await AsyncStorage.setItem(key, JSON.stringify(value)) + } catch (e) { + // saving error + console.log(e.message) + throw e + } +} + +export const getData = async key => { + let value + try { + value = await AsyncStorage.getItem(key) + } catch (e) { + // error reading value + console.log(e.message) + throw e + } + if (value) value = JSON.parse(value) + return value +} + +export const removeData = async key => { + try { + await AsyncStorage.removeItem(key) + } catch (e) { + // remove error + console.log(e.message) + throw e + } +} + +export const getAllKeys = async() => { + let keys + try { + keys = await AsyncStorage.getAllKeys() + } catch (e) { + // read key error + console.log(e.message) + throw e + } + + return keys +} + +export const getDataMultiple = async keys => { + let values + try { + values = await AsyncStorage.multiGet(keys) + } catch (e) { + // read error + console.log(e.message) + throw e + } + return values.map(([key, value]) => ({ key, value: JSON.parse(value) })) +} + +export const setDataMultiple = async datas => { + try { + await AsyncStorage.multiSet(datas.map(({ key, value }) => ([key, JSON.stringify(value)]))) + } catch (e) { + // save error + console.log(e.message) + throw e + } +} + + +export const removeDataMultiple = async keys => { + if (!keys.length) return + try { + await AsyncStorage.multiRemove(keys) + } catch (e) { + // remove error + console.log(e.message) + throw e + } +} + +export const clearAll = async() => { + try { + await AsyncStorage.clear() + } catch (e) { + // clear error + console.log(e.message) + throw e + } +} + +export const useAsyncStorage = AsyncStorage.useAsyncStorage diff --git a/src/resources/fonts/icomoon.ttf b/src/resources/fonts/icomoon.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8faca2a2f3bd5a8e683236e3eda3d0a0ee8c34bf GIT binary patch literal 4356 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 P0Z2!yw!i(uEXV%`NQxAS literal 0 HcmV?d00001 diff --git a/src/resources/fonts/selection.json b/src/resources/fonts/selection.json new file mode 100644 index 0000000..27abe04 --- /dev/null +++ b/src/resources/fonts/selection.json @@ -0,0 +1 @@ +{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M512 682.667c47.128 0 85.333 38.205 85.333 85.333v0c0 47.128-38.205 85.333-85.333 85.333v0c-47.128 0-85.333-38.205-85.333-85.333v0c0-47.128 38.205-85.333 85.333-85.333v0zM512 426.667c47.128 0 85.333 38.205 85.333 85.333v0c0 47.128-38.205 85.333-85.333 85.333v0c-47.128 0-85.333-38.205-85.333-85.333v0c0-47.128 38.205-85.333 85.333-85.333v0zM512 170.667c47.128 0 85.333 38.205 85.333 85.333v0c0 47.128-38.205 85.333-85.333 85.333v0c-47.128 0-85.333-38.205-85.333-85.333v0c0-47.128 38.205-85.333 85.333-85.333v0z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-dots-vertical"]},"attrs":[{}],"properties":{"order":833,"id":21,"name":"dots-vertical","prevSize":32,"code":59667},"setIdx":0,"setId":3,"iconIdx":0},{"icon":{"paths":["M256 512h128l-170.667-170.667-170.667 170.667h128c0 188.513 152.82 341.333 341.333 341.333v0c66.987 0 129.28-19.627 181.76-52.907l-62.293-62.293c-35.413 19.2-76.8 29.867-119.467 29.867-141.385 0-256-114.615-256-256v0zM330.24 223.573l62.293 62.293c35.84-18.773 76.8-29.867 119.467-29.867 141.385 0 256 114.615 256 256v0h-128l170.667 170.667 170.667-170.667-128 0c0-188.513-152.82-341.333-341.333-341.333v0c-66.987 0-129.28 19.627-181.76 52.907z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-autorenew"]},"attrs":[{}],"properties":{"order":832,"id":20,"name":"autorenew","prevSize":32,"code":59665},"setIdx":0,"setId":3,"iconIdx":1},{"icon":{"paths":["M426.667 170.667l85.333 85.333h341.333c47.128 0 85.333 38.205 85.333 85.333v0 426.667c0 47.128-38.205 85.333-85.333 85.333v0h-682.667c-47.36 0-85.333-38.4-85.333-85.333v-512c0-47.36 37.973-85.333 85.333-85.333h256zM640 384v128h-128v85.333h128v128h85.333v-128h128v-85.333h-128v-128h-85.333z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-folder-plus"]},"attrs":[{}],"properties":{"order":831,"id":19,"name":"folder-plus","prevSize":32,"code":59666},"setIdx":0,"setId":3,"iconIdx":2},{"icon":{"paths":["M570.952 545.942l-388.688 388.686c-18.746 18.746-49.138 18.746-67.882 0l-45.334-45.334c-18.714-18.714-18.75-49.044-0.080-67.802l308.042-309.492-308.042-309.49c-18.67-18.758-18.634-49.088 0.080-67.802l45.334-45.334c18.746-18.746 49.138-18.746 67.882 0l388.686 388.686c18.746 18.744 18.746 49.136 0.002 67.882z"],"attrs":[{}],"width":640,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-chevron-right"]},"attrs":[{}],"properties":{"order":830,"id":18,"name":"chevron-right","prevSize":32,"code":59664},"setIdx":0,"setId":3,"iconIdx":3},{"icon":{"paths":["M842.667 247.937l-66.604-66.604-264.063 264.063-264.063-264.063-66.604 66.604 264.063 264.063-264.063 264.063 66.604 66.604 264.063-264.063 264.063 264.063 66.604-66.604-264.063-264.063 264.063-264.063z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-remove"]},"attrs":[{}],"properties":{"order":828,"id":17,"prevSize":32,"code":59663,"name":"remove"},"setIdx":0,"setId":3,"iconIdx":4},{"icon":{"paths":["M633.703 512l365.094-365.094c33.607-33.607 33.607-88.095 0-121.698-33.607-33.607-88.091-33.607-121.698 0l-365.099 365.099-365.099-365.104c-33.607-33.607-88.091-33.607-121.698 0-33.603 33.607-33.603 88.095 0 121.698l365.099 365.094-365.099 365.099c-33.603 33.607-33.603 88.095 0 121.698 33.607 33.607 88.091 33.607 121.698 0l365.099-365.099 365.099 365.099c33.603 33.607 88.091 33.607 121.698 0s33.607-88.091 0-121.698l-365.094-365.094z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-close"]},"attrs":[{}],"properties":{"order":826,"id":15,"name":"close","prevSize":32,"code":59662},"setIdx":0,"setId":3,"iconIdx":5},{"icon":{"paths":["M52.504 168.606v686.806c0 93.13 61.701 168.588 137.82 168.588 76.127 0 137.865-75.462 137.865-168.588v-686.806c0-93.085-61.738-168.577-137.865-168.577-76.119-0.030-137.82 75.492-137.82 168.577z","M833.635 0c-76.112 0-137.813 75.492-137.813 168.577v686.806c0 93.13 61.701 168.558 137.813 168.558s137.861-75.433 137.861-168.558v-686.776c-0.033-93.085-61.749-168.606-137.861-168.606z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-pause"]},"attrs":[{},{}],"properties":{"order":808,"id":1,"name":"pause","prevSize":32,"code":59661},"setIdx":0,"setId":3,"iconIdx":6},{"icon":{"paths":["M298.667 298.667h426.667v128l170.667-170.667-170.667-170.667v128h-512v256h85.333v-170.667zM725.333 725.333h-426.667v-128l-170.667 170.667 170.667 170.667v-128h512v-256h-85.333v170.667z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-list-loop"],"defaultCode":59648},"attrs":[{}],"properties":{"order":809,"id":2,"name":"list-loop","prevSize":32,"code":59648},"setIdx":0,"setId":3,"iconIdx":7},{"icon":{"paths":["M856 213.862v567.6h-120.4v-303.862c0-45.862 0-68.8 0-80.262s-5.738-17.2-17.2-22.938c-5.738-5.738-28.662-5.738-57.338-5.738h-11.462v-63.062c57.338-17.2 103.2-45.862 131.862-91.738h74.538z","M168 856l487.338-344-487.338-344z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-single"],"defaultCode":59649},"attrs":[{},{}],"properties":{"order":810,"id":3,"name":"single","prevSize":32,"code":59649},"setIdx":0,"setId":3,"iconIdx":8},{"icon":{"paths":["M298.667 298.667h426.667v128l170.667-170.667-170.667-170.667v128h-512v256h85.333v-170.667zM725.333 725.333h-426.667v-128l-170.667 170.667 170.667 170.667v-128h512v-256h-85.333v170.667zM554.667 640v-256h-42.667l-85.333 42.667v42.667h64v170.667h64z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-single-loop"],"defaultCode":59650},"attrs":[{}],"properties":{"order":811,"id":4,"name":"single-loop","prevSize":32,"code":59650},"setIdx":0,"setId":3,"iconIdx":9},{"icon":{"paths":["M167.065 412.951h594.284v99.049h-594.284zM167.065 214.858h594.284v99.049h-594.284zM167.065 611.049h396.191v99.049h-396.191zM662.301 611.049v297.142l247.617-148.574z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-list-order"],"defaultCode":59651},"attrs":[{}],"properties":{"order":812,"id":5,"name":"list-order","prevSize":32,"code":59651},"setIdx":0,"setId":3,"iconIdx":10},{"icon":{"paths":["M451.84 391.253l-221.013-220.587-60.16 60.16 220.587 220.587 60.587-60.16zM618.667 170.667l87.040 87.040-535.040 535.467 60.16 60.16 535.467-535.040 87.040 87.040v-234.667h-234.667zM632.747 572.16l-60.16 60.16 133.547 133.547-87.467 87.467h234.667v-234.667l-87.040 87.040-133.547-133.547z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-list-random"],"defaultCode":59652},"attrs":[{}],"properties":{"order":813,"id":6,"name":"list-random","prevSize":32,"code":59652},"setIdx":0,"setId":3,"iconIdx":11},{"icon":{"paths":["M209.962 21.763c-88.986-51.043-161.129-9.228-161.129 93.323v756.778c0 102.653 72.144 144.414 161.129 93.419l661.462-379.344c89.016-51.061 89.016-133.789 0-184.838l-661.462-379.338z"],"attrs":[{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-play"],"defaultCode":59653},"attrs":[{}],"properties":{"order":814,"id":7,"name":"play","prevSize":32,"code":59653},"setIdx":0,"setId":3,"iconIdx":12},{"icon":{"paths":["M96.902 152.172c-53.489 0-96.898 64.037-96.898 143.005v433.651c0 78.944 43.432 143 96.898 143 53.545 0 96.902-64.056 96.902-143v-119.627l352.203 201.97c67.023 38.471 121.477 8.351 123.795-67l-225.149-129.123c-44.415-25.451-69.917-63.036-69.917-103.083 0-40.084 25.502-77.637 69.917-103.134l225.149-129.072c-2.318-75.295-56.772-105.452-123.795-66.986l-352.203 201.919v-119.515c0.023-78.995-43.358-143.005-96.902-143.005z","M502.256 583.092l397.712 228.079c68.475 39.291 124.032 7.103 124.032-71.883v-454.684c0-78.94-55.557-111.137-124.032-71.832l-397.74 228.019c-68.452 39.301-68.452 103.009 0.028 142.3z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-prevMusic"],"defaultCode":59654},"attrs":[{},{}],"properties":{"order":838,"id":22,"prevSize":32,"code":59668,"name":"prevMusic"},"setIdx":0,"setId":3,"iconIdx":13},{"icon":{"paths":["M927.098 871.828c53.489 0 96.898-64.037 96.898-143.005v-433.651c0-78.944-43.432-143-96.898-143-53.545 0-96.902 64.056-96.902 143v119.627l-352.203-201.97c-67.023-38.471-121.477-8.351-123.795 67l225.149 129.123c44.415 25.451 69.917 63.036 69.917 103.083 0 40.084-25.502 77.637-69.917 103.134l-225.149 129.072c2.318 75.295 56.772 105.452 123.795 66.986l352.203-201.919v119.515c-0.023 78.995 43.358 143.005 96.902 143.005z","M521.744 440.908l-397.712-228.079c-68.475-39.291-124.032-7.103-124.032 71.883v454.684c0 78.94 55.557 111.137 124.032 71.832l397.74-228.019c68.452-39.301 68.452-103.009-0.028-142.3z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-nextMusic"],"defaultCode":59654},"attrs":[{},{}],"properties":{"order":836,"id":8,"name":"nextMusic","prevSize":32,"code":59654},"setIdx":0,"setId":3,"iconIdx":14},{"icon":{"paths":["M583.263 738.762c-122.639 0-222.058-99.419-222.058-222.058s99.419-222.058 222.058-222.058c122.639 0 222.058 99.419 222.058 222.058v-0c-0.147 122.58-99.478 221.911-222.044 222.058l-0.014 0zM583.263 387.95c-71.109 0-128.754 57.645-128.754 128.754s57.645 128.754 128.754 128.754c71.109 0 128.754-57.645 128.754-128.754v0c-0.080-71.076-57.677-128.674-128.746-128.754l-0.008-0z","M1155.053 473.653l-248.686-430.602c-15.186-25.863-42.83-42.97-74.477-43.051l-0.012-0h-497.208c-31.693 0.050-59.378 17.165-74.362 42.646l-0.22 0.405-248.592 430.602c-7.228 12.356-11.496 27.205-11.496 43.051s4.268 30.695 11.717 43.461l-0.221-0.41 248.686 430.602c15.201 25.879 42.875 42.992 74.55 43.051l0.009 0h497.137c31.685-0.054 59.362-17.168 74.339-42.646l0.22-0.405 248.686-430.602c7.206-12.341 11.461-27.168 11.461-42.99 0-15.871-4.281-30.742-11.752-43.521l0.221 0.409zM344.242 930.696l-239.020-413.992 239.020-414.015h478.064l239.020 414.015-239.020 413.992z"],"attrs":[{},{}],"width":1157,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-setting"],"defaultCode":59655},"attrs":[{},{}],"properties":{"order":816,"id":9,"name":"setting","prevSize":32,"code":59655},"setIdx":0,"setId":3,"iconIdx":15},{"icon":{"paths":["M974.751 1024h-925.525c-27.228-0.19-49.226-22.307-49.226-49.561 0-0.119 0-0.238 0.001-0.357l-0 0.018v-414.489c-0.001-0.1-0.001-0.219-0.001-0.338 0-27.254 21.999-49.371 49.208-49.561l0.018-0c27.228 0.19 49.226 22.307 49.226 49.561 0 0.119-0 0.238-0.001 0.357l0-0.018v364.613h827.075v-365.504c0-27.193 22.044-49.237 49.237-49.237s49.237 22.044 49.237 49.237v0 415.38c0 0.007 0 0.016 0 0.025 0 13.741-5.516 26.193-14.456 35.262l0.006-0.006c-8.86 9.010-21.175 14.599-34.796 14.618l-0.004 0z","M512 582.803c-25.964-0.191-46.938-21.283-46.938-47.273 0-0.102 0-0.204 0.001-0.306l-0 0.016v-487.676c0-25.936 21.025-46.961 46.961-46.961s46.961 21.025 46.961 46.961v0 487.58c0.001 0.115 0.002 0.25 0.002 0.386 0 26.008-21.002 47.111-46.972 47.274l-0.016 0z","M512 658.929c-0.024 0-0.052 0-0.080 0-13.966 0-26.633-5.558-35.912-14.582l0.012 0.012-193.361-186.497c-8.999-8.738-14.582-20.95-14.582-34.466 0-12.694 4.925-24.238 12.969-32.824l-0.025 0.027c8.515-9.098 20.596-14.768 34.002-14.768 12.587 0 24.006 4.998 32.382 13.118l164.57 158.742 164.582-158.754c8.364-8.108 19.783-13.106 32.37-13.106 13.406 0 25.487 5.67 33.978 14.742l0.024 0.026c8.019 8.56 12.945 20.104 12.945 32.798 0 13.516-5.584 25.728-14.571 34.454l-0.012 0.011-193.385 186.521c-9.268 8.998-21.928 14.546-35.885 14.546-0.008 0-0.016-0-0.024-0l0.001 0zM540.755 575.41v0z"],"attrs":[{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-download-2"],"defaultCode":59656},"attrs":[{},{},{}],"properties":{"order":817,"id":10,"name":"download-2","prevSize":32,"code":59656},"setIdx":0,"setId":3,"iconIdx":16},{"icon":{"paths":["M582.103 1024c-0.017 0-0.037 0-0.057 0-9.91 0-19.136-2.929-26.859-7.969l0.189 0.116-0.366-0.236c-37.015-20.471-322.346-182.272-474.148-387.423-50.493-68.213-80.822-154.009-80.822-246.889 0-19.705 1.365-39.091 4.006-58.069l-0.25 2.192c14.345-104.709 67.040-196.329 148.372-258.055 92.563-70.286 201.617-86.228 315.357-45.862 43.793 16.084 81.686 36.311 116.214 60.949l-1.48-1.003c33.049-23.635 70.942-43.862 111.376-58.855l3.359-1.091c113.792-40.339 222.847-24.423 315.383 45.862 81.333 61.831 134.027 153.477 148.372 258.055 2.401 16.819 3.771 36.243 3.771 55.988 0 92.855-30.315 178.629-81.587 247.965l0.802-1.136c-152.718 206.198-440.432 368.811-474.802 387.658-7.598 4.896-16.87 7.819-26.822 7.853l-0.009 0zM347.581 105.677c-43.428 0-89.997 12.46-135.598 47.119-59.056 44.894-97.353 111.593-107.798 187.821-1.757 12.365-2.76 26.647-2.76 41.162 0 68.642 22.432 132.045 60.365 183.279l-0.591-0.835c123.426 166.67 348.157 304.781 421.087 347.031 73.008-42.171 297.661-180.361 421.087-347.031 37.343-50.395 59.775-113.796 59.775-182.436 0-14.518-1.004-28.802-2.945-42.786l0.184 1.616c-10.471-76.202-48.742-142.901-107.824-187.821-159.131-120.939-330.121 28.271-337.398 34.685-8.691 7.859-20.269 12.668-32.97 12.668s-24.279-4.809-33.013-12.706l0.043 0.038c-5.052-4.555-93.557-81.804-201.643-81.804z"],"attrs":[{}],"width":1165,"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-love"],"defaultCode":59657},"attrs":[{}],"properties":{"order":818,"id":11,"name":"love","prevSize":32,"code":59657},"setIdx":0,"setId":3,"iconIdx":17},{"icon":{"paths":["M968.321 913.171h-912.93c-30.591 0-55.39 24.799-55.39 55.39s24.799 55.39 55.39 55.39v0h912.93c30.591 0 55.39-24.799 55.39-55.39s-24.799-55.39-55.39-55.39v0z","M931.065 848.942c30.591 0 55.39-24.799 55.39-55.39v0-738.161c0-30.591-24.799-55.39-55.39-55.39s-55.39 24.799-55.39 55.39v0 738.137c-0 0.007-0 0.016-0 0.024 0 30.591 24.799 55.39 55.39 55.39l0-0z","M511.735 848.942c30.591 0 55.39-24.799 55.39-55.39v0-504.896c0-30.591-24.799-55.39-55.39-55.39s-55.39 24.799-55.39 55.39v0 504.871c-0 0.007-0 0.016-0 0.024 0 30.591 24.799 55.39 55.39 55.39l0-0z","M92.406 848.942c30.591 0 55.39-24.799 55.39-55.39v0-331.62c0-30.591-24.799-55.39-55.39-55.39s-55.39 24.799-55.39 55.39v0 331.596c-0 0.007-0 0.016-0 0.024 0 30.591 24.799 55.39 55.39 55.39l0-0z"],"attrs":[{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-leaderboard"],"defaultCode":59658},"attrs":[{},{},{},{}],"properties":{"order":819,"id":12,"name":"leaderboard","prevSize":32,"code":59658},"setIdx":0,"setId":3,"iconIdx":18},{"icon":{"paths":["M48.166 895.663c-26.601 0-48.166-21.564-48.166-48.166v0-799.332c0-26.601 21.564-48.166 48.166-48.166v0h755.983c26.601 0 48.166 21.564 48.166 48.166s-21.564 48.166-48.166 48.166v0h-707.817v751.166c0 26.601-21.564 48.166-48.166 48.166v0z","M975.834 1024h-736.933c-26.601 0-48.166-21.564-48.166-48.166v0-354.499c0-26.601 21.564-48.166 48.166-48.166s48.166 21.564 48.166 48.166v0 306.333h640.602v-633.859h-515.372c-26.601 0-48.166-21.564-48.166-48.166s21.564-48.166 48.166-48.166v0h563.537c26.601 0 48.166 21.564 48.166 48.166v0 730.19c0 26.601-21.564 48.166-48.166 48.166v0z","M623.744 786.76c-23.941 0-43.349-19.408-43.349-43.349v0-346.046c0-23.941 19.408-43.349 43.349-43.349s43.349 19.408 43.349 43.349v0 345.829c0 0.064 0.001 0.141 0.001 0.217 0 23.941-19.408 43.349-43.349 43.349-0 0-0-0-0.001-0l0 0z","M764.002 581.238c-0.010 0-0.022 0-0.034 0-11.992 0-22.847-4.869-30.695-12.739l-0.001-0.001-140.306-140.306c-7.864-7.864-12.729-18.729-12.729-30.73 0-24.001 19.457-43.458 43.458-43.458 12.001 0 22.865 4.864 30.73 12.729l140.306 140.33c7.964 7.864 12.896 18.781 12.896 30.851 0 23.941-19.408 43.349-43.349 43.349-0.097 0-0.195-0-0.292-0.001l0.015 0z","M537.239 867.414c-0.021 0-0.047 0-0.072 0-71.756 0-129.927-58.17-129.927-129.927s58.17-129.927 129.927-129.927c71.756 0 129.927 58.17 129.927 129.927l-0-0c-0.068 71.704-58.157 129.817-129.844 129.927l-0.010 0zM537.239 694.499c-23.741 0-42.988 19.246-42.988 42.988s19.246 42.988 42.988 42.988c23.741 0 42.988-19.246 42.988-42.988h0c-0.027-23.73-19.257-42.96-42.985-42.988l-0.003-0z"],"attrs":[{},{},{},{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-album"],"defaultCode":59659},"attrs":[{},{},{},{},{}],"properties":{"order":820,"id":13,"name":"album","prevSize":32,"code":59659},"setIdx":0,"setId":3,"iconIdx":19},{"icon":{"paths":["M743.965 130.818c-78.798-80.684-188.672-130.72-310.232-130.72-239.41 0-433.49 194.080-433.49 433.49s194.080 433.49 433.49 433.49c117.777 0 224.584-46.97 302.71-123.199l-0.089 0.086c81.075-78.661 131.39-188.632 131.39-310.355 0-117.951-47.245-224.867-123.843-302.857l0.063 0.064zM669.092 675.089c-60.675 59.106-143.667 95.56-235.173 95.56-186.208 0-337.159-150.951-337.159-337.159 0-186.057 150.707-336.914 336.707-337.159l0.023-0c0.077-0 0.168-0 0.258-0 186.208 0 337.159 150.951 337.159 337.159 0 94.665-39.014 180.218-101.841 241.457l-0.071 0.069z","M1007.214 928.873l-159.5-163.763c-10.070-10.316-24.114-16.714-39.652-16.714-30.592 0-55.391 24.8-55.391 55.391 0 15.053 6.005 28.704 15.75 38.688l-0.011-0.011 160.536 164.823c10.025 10.268 24.006 16.636 39.474 16.636 2.35 0 4.666-0.147 6.939-0.432l-0.271 0.028c10.465-1.218 19.813-5.231 27.5-11.264l-0.118 0.089c13.151-10.191 21.535-25.989 21.535-43.745 0-0.259-0.002-0.517-0.005-0.775l0 0.039c-0.431-15.266-6.763-28.973-16.785-38.99l-0-0z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"grid":0,"tags":["icon-search-2"],"defaultCode":59660},"attrs":[{},{}],"properties":{"order":821,"id":14,"name":"search-2","prevSize":32,"code":59660},"setIdx":0,"setId":3,"iconIdx":20}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon","majorVersion":1,"minorVersion":0},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false,"autoHost":false,"noie8":true,"ie7":false,"showSelector":false,"showMetrics":false,"showMetadata":false,"showVersion":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon","name":"icomoon"},"historySize":50,"showCodes":true,"gridSize":16,"showGrid":false,"quickUsageToken":{"UntitledProject":"N2VjNTI2ODAzZWI0N2M1NzhlMjNhYzY3OTEwMWRiMDEjMSMxNjA0MzkyNDUxIyMj"},"showLiga":false}} \ No newline at end of file diff --git a/src/resources/medias/Silence02s.mp3 b/src/resources/medias/Silence02s.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5d384dda2c22e6332fa09b497fdc53b93b70c2c2 GIT binary patch literal 2194 zcmezWSl|Ey0|Vn8AVDnn57eVhh8{nX^#~m(B~cFp$Z>N?)CAIVgbY2eN!BBD;6I6a qz#bx16UamK(KG5HhS3-T6&#~Uj_g1f%|rA|KID{)qcKFk7y<zC5Vl?b literal 0 HcmV?d00001 diff --git a/src/screens/Home/Download/index.js b/src/screens/Home/Download/index.js new file mode 100644 index 0000000..7f816ec --- /dev/null +++ b/src/screens/Home/Download/index.js @@ -0,0 +1,15 @@ +import React from 'react' +import { + // StyleSheet, + View, + // Button, + Text, +} from 'react-native' + +// import Menu from '@/components/Menu' + +export default () => { + return <View> + <Text>下载</Text> + </View> +} diff --git a/src/screens/Home/List/components/ExitMultipleModeBar.js b/src/screens/Home/List/components/ExitMultipleModeBar.js new file mode 100644 index 0000000..e976c17 --- /dev/null +++ b/src/screens/Home/List/components/ExitMultipleModeBar.js @@ -0,0 +1,142 @@ +import React, { useState, useRef, useEffect, useCallback, useMemo, memo } from 'react' +import { Text, StyleSheet, Animated, View, TouchableOpacity } from 'react-native' +import { useTranslation } from '@/plugins/i18n' + +import Button from '@/components/common/Button' +import { useGetter } from '@/store' + + +export default memo(({ multipleMode, onCancel, onSelectAll, selectMode, onSwitchMode, isSelectAll }) => { + const { t } = useTranslation() + // const isGetDetailFailedRef = useRef(false) + const [visible, setVisible] = useState(false) + const [animatePlayed, setAnimatPlayed] = useState(true) + const animFade = useRef(new Animated.Value(0)).current + const animTranslateY = useRef(new Animated.Value(0)).current + + const theme = useGetter('common', 'theme') + + useEffect(() => { + setAnimatPlayed(true) + if (multipleMode) { + animFade.setValue(0.92) + animTranslateY.setValue(0) + setVisible(true) + } else { + animFade.setValue(0) + animTranslateY.setValue(20) + setVisible(false) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const showList = useCallback(() => { + // console.log('show List') + setVisible(true) + setAnimatPlayed(false) + animTranslateY.setValue(20) + + Animated.parallel([ + Animated.timing(animFade, { + toValue: 0.92, + duration: 200, + useNativeDriver: true, + }), + Animated.timing(animTranslateY, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }), + ]).start(() => { + setAnimatPlayed(true) + }) + }, [animFade, animTranslateY]) + + const hideList = useCallback(() => { + setAnimatPlayed(false) + Animated.parallel([ + Animated.timing(animFade, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }), + Animated.timing(animTranslateY, { + toValue: 20, + duration: 200, + useNativeDriver: true, + }), + ]).start(finished => { + if (!finished) return + setVisible(false) + setAnimatPlayed(true) + }) + }, [animFade, animTranslateY]) + + useEffect(() => { + if (multipleMode) { + showList() + } else { + hideList() + } + }, [hideList, multipleMode, showList]) + + + const animaStyle = useMemo(() => StyleSheet.compose(styles.container, { + backgroundColor: theme.secondary45, + opacity: animFade, // Bind opacity to animated value + transform: [ + { translateY: animTranslateY }, + ], + }), [animFade, animTranslateY, theme]) + + const switchModeSingle = useCallback(() => { + onSwitchMode('single') + }, [onSwitchMode]) + const switchModeRange = useCallback(() => { + onSwitchMode('range') + }, [onSwitchMode]) + + const component = useMemo(() => ( + <Animated.View style={animaStyle}> + <View style={styles.switchBtn}> + <Button onPress={switchModeSingle} style={{ ...styles.btn, backgroundColor: selectMode == 'single' ? theme.secondary40 : 'rgba(0,0,0,0)' }}> + <Text style={{ color: theme.secondary }}>{t('list_select_single')}</Text> + </Button> + <Button onPress={switchModeRange} style={{ ...styles.btn, backgroundColor: selectMode == 'range' ? theme.secondary40 : 'rgba(0,0,0,0)' }}> + <Text style={{ color: theme.secondary }}>{t('list_select_range')}</Text> + </Button> + </View> + <TouchableOpacity onPress={onSelectAll} style={styles.btn}> + <Text style={{ color: theme.secondary }}>{t(isSelectAll ? 'list_select_unall' : 'list_select_all')}</Text> + </TouchableOpacity> + <TouchableOpacity onPress={onCancel} style={styles.btn}> + <Text style={{ color: theme.secondary }}>{t('list_select_cancel')}</Text> + </TouchableOpacity> + </Animated.View> + ), [animaStyle, isSelectAll, selectMode, onCancel, onSelectAll, switchModeRange, switchModeSingle, t, theme]) + + return !visible && animatePlayed ? null : component +}) + +const styles = StyleSheet.create({ + container: { + flex: 1, + position: 'absolute', + left: 0, + top: 0, + width: '100%', + height: '100%', + flexDirection: 'row', + }, + switchBtn: { + flexDirection: 'row', + flex: 1, + }, + btn: { + // flex: 1, + paddingLeft: 15, + paddingRight: 15, + alignItems: 'center', + justifyContent: 'center', + }, +}) diff --git a/src/screens/Home/List/components/ListItem.js b/src/screens/Home/List/components/ListItem.js new file mode 100644 index 0000000..0915a8e --- /dev/null +++ b/src/screens/Home/List/components/ListItem.js @@ -0,0 +1,121 @@ +import React, { useMemo, useCallback, memo, useRef, useState, useEffect } from 'react' +import { View, Text, StyleSheet, TouchableOpacity } from 'react-native' +import { LIST_ITEM_HEIGHT } from '@/config/constant' +import { BorderWidths } from '@/theme' +import { useAssertApiSupport } from '@/utils/hooks' +import { useGetter, useDispatch } from '@/store' +import Button from '@/components/common/Button' +import Icon from '@/components/common/Icon' + +export default memo(({ item, index, activeIndex, onPress, showMenu, handleLongPress, selectedList }) => { + const theme = useGetter('common', 'theme') + + const isSelected = selectedList.indexOf(item) != -1 + // console.log(item.name, selectedList, selectedList.includes(item)) + const isSupported = useAssertApiSupport(item.source) + const moreButtonRef = useRef() + const handleShowMenu = useCallback(() => { + if (moreButtonRef.current && moreButtonRef.current.measure) { + moreButtonRef.current.measure((fx, fy, width, height, px, py) => { + // console.log(fx, fy, width, height, px, py) + showMenu(item, index, { x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + }) + } + }, [item, index, showMenu]) + + return ( + <View style={{ ...styles.listItem, backgroundColor: isSelected ? theme.secondary45 : theme.primary, borderBottomColor: theme.secondary45, opacity: isSupported ? 1 : 0.5 }}> + <TouchableOpacity style={styles.listItemLeft} onPress={() => { onPress(item, index) }} onLongPress={() => { handleLongPress(item, index) }}> + <Text style={{ ...styles.sn, color: theme.normal50 }}>{index + 1}</Text> + <View style={styles.itemInfo}> + <View style={styles.listItemTitle}> + <Text style={{ ...styles.listItemTitleText, color: activeIndex == index ? theme.secondary : theme.normal }} numberOfLines={1}>{item.name}</Text> + <Text style={{ ...styles.listItemBadge, color: theme.secondary20 }}>{item.source}</Text> + </View> + <View style={styles.row2}> + <Text style={{ ...styles.listItemSingle, color: activeIndex == index ? theme.secondary20 : theme.normal40 }} numberOfLines={1}>{item.singer}</Text> + </View> + </View> + </TouchableOpacity> + <View style={styles.listItemRight}> + <TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.moreButton}> + <Icon name="dots-vertical" style={{ color: theme.normal35 }} size={16} /> + </TouchableOpacity> + </View> + </View> + ) +}, (prevProps, nextProps) => { + return !!(prevProps.item === nextProps.item && + prevProps.index === nextProps.index && + prevProps.activeIndex != nextProps.index && + nextProps.activeIndex != nextProps.index && + nextProps.selectedList.includes(nextProps.item) == prevProps.selectedList.includes(nextProps.item) + ) +}) + + +const styles = StyleSheet.create({ + listItem: { + width: '100%', + flexDirection: 'row', + flexWrap: 'nowrap', + // paddingLeft: 10, + paddingRight: 10, + height: LIST_ITEM_HEIGHT, + borderBottomWidth: BorderWidths.normal, + }, + listItemLeft: { + flex: 1, + flexGrow: 1, + flexShrink: 1, + flexDirection: 'row', + alignItems: 'center', + }, + sn: { + width: 32, + fontSize: 11, + textAlign: 'center', + // backgroundColor: 'rgba(0,0,0,0.2)', + paddingLeft: 3, + paddingRight: 3, + }, + itemInfo: { + flexGrow: 0, + flexShrink: 1, + paddingTop: 10, + paddingBottom: 10, + }, + listItemTitle: { + flexDirection: 'row', + alignItems: 'flex-end', + }, + listItemTitleText: { + // backgroundColor: 'rgba(0,0,0,0.2)', + flexGrow: 0, + flexShrink: 1, + fontSize: 14, + }, + listItemSingle: { + fontSize: 12, + paddingTop: 2, + }, + listItemBadge: { + fontSize: 10, + paddingLeft: 5, + paddingTop: 2, + alignSelf: 'flex-start', + }, + listItemRight: { + flexGrow: 0, + flexShrink: 0, + flexBasis: 'auto', + justifyContent: 'center', + }, + + moreButton: { + paddingLeft: 10, + paddingRight: 10, + paddingTop: 10, + paddingBottom: 10, + }, +}) diff --git a/src/screens/Home/List/components/MusicPositionModal.js b/src/screens/Home/List/components/MusicPositionModal.js new file mode 100644 index 0000000..397906c --- /dev/null +++ b/src/screens/Home/List/components/MusicPositionModal.js @@ -0,0 +1,92 @@ +import React, { memo, useMemo, useEffect, useCallback, useState, useRef } from 'react' +import { StyleSheet, Text, View } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' +import ConfirmAlert from '@/components/common/ConfirmAlert' +import Input from '@/components/common/Input' + +export default memo(({ visible, hideModal, onConfirm, selectedList, selectedData }) => { + const [text, setText] = useState('') + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + const inputRef = useRef() + + const title = useMemo(() => { + return selectedList.length + ? t('change_position_music_multi_title', { num: selectedList.length }) + : t('change_position_music_title', { name: selectedData ? selectedData.name : '' }) + }, [selectedData, selectedList, t]) + + const verify = useCallback(() => { + let num = /^[1-9]\d*/.exec(text) + num = num ? parseInt(num[0]) : '' + setText(num.toString()) + return num + }, [text]) + const handleSetMusicPosition = useCallback(() => { + let num = verify() + if (num == '') return + onConfirm(num) + }, [onConfirm, verify]) + useEffect(() => { + if (!visible) return + + setText('') + inputRef.current.focus() + }, [visible]) + + + return ( + <ConfirmAlert + visible={visible} + onCancel={hideModal} + onConfirm={handleSetMusicPosition} + > + <View style={styles.content}> + <Text style={{ color: theme.normal, marginBottom: 5 }}>{title}</Text> + <Input + placeholder={t('change_position_tip')} + value={text} + onChangeText={setText} + ref={inputRef} + style={{ ...styles.input, backgroundColor: theme.secondary40 }} + /> + </View> + </ConfirmAlert> + ) +}) + +const styles = StyleSheet.create({ + content: { + flexGrow: 1, + flexShrink: 1, + flexDirection: 'column', + }, + input: { + flexGrow: 1, + flexShrink: 1, + minWidth: 240, + borderRadius: 4, + paddingTop: 2, + paddingBottom: 2, + fontSize: 12, + }, + + // tagTypeList: { + // flexDirection: 'row', + // flexWrap: 'wrap', + // }, + // tagButton: { + // // marginRight: 10, + // borderRadius: 4, + // marginRight: 10, + // marginBottom: 10, + // }, + // tagButtonText: { + // paddingLeft: 12, + // paddingRight: 12, + // paddingTop: 8, + // paddingBottom: 8, + // }, +}) diff --git a/src/screens/Home/List/components/MyList.js b/src/screens/Home/List/components/MyList.js new file mode 100644 index 0000000..67ad1a7 --- /dev/null +++ b/src/screens/Home/List/components/MyList.js @@ -0,0 +1,259 @@ +import React, { memo, useMemo, useEffect, useCallback, useState, useRef } from 'react' +import { StyleSheet, Text, View, TouchableOpacity, ScrollView } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' +import DorpDownPanel from '@/components/common/DorpDownPanel' +import Icon from '@/components/common/Icon' +// import Button from '@/components/common/Button' +import { BorderWidths } from '@/theme' +import Menu from '@/components/common/Menu' +import ConfirmAlert from '@/components/common/ConfirmAlert' +import Input from '@/components/common/Input' +import { getListScrollPosition, saveListScrollPosition } from '@/utils/tools' +import { LIST_SCROLL_POSITION_KEY } from '@/config/constant' + +const ListItem = ({ onPress, name, id, showMenu, activeId }) => { + const theme = useGetter('common', 'theme') + const moreButtonRef = useRef() + const handleShowMenu = useCallback(() => { + if (moreButtonRef.current && moreButtonRef.current.measure) { + moreButtonRef.current.measure((fx, fy, width, height, px, py) => { + // console.log(fx, fy, width, height, px, py) + showMenu(id, name, { x: Math.ceil(px), y: Math.ceil(py), w: Math.ceil(width), h: Math.ceil(height) }) + }) + } + }, [showMenu, id, name]) + + return ( + <View style={{ ...styles.listItem, borderBottomColor: theme.secondary45 }}> + <TouchableOpacity style={styles.listName} onPress={onPress}> + <Text numberOfLines={1} style={{ color: theme.normal }}>{name}</Text> + </TouchableOpacity> + <TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.listMoreBtn}> + <Icon name="dots-vertical" style={{ color: theme.normal35 }} size={16} /> + </TouchableOpacity> + </View> + ) +} + +const List = memo(({ setVisiblePanel, currentList, activeListIdRef }) => { + const theme = useGetter('common', 'theme') + const defaultList = useGetter('list', 'defaultList') + const loveList = useGetter('list', 'loveList') + const userListRef = useRef([]) + const userList = useGetter('list', 'userList') + const setPrevSelectListId = useDispatch('common', 'setPrevSelectListId') + const setUserListName = useDispatch('list', 'setUserListName') + // const setUserListPosition = useDispatch('list', 'setUserListPosition') + const removeUserList = useDispatch('list', 'removeUserList') + const [visibleMenu, setVisibleMenu] = useState(false) + // const activeListId = useGetter('common', 'prevSelectListId') + const selectedListRef = useRef({}) + const { t } = useTranslation() + const [buttonPosition, setButtonPosition] = useState({ w: 0, h: 0, x: 0, y: 0 }) + const [visibleRename, setVisibleRename] = useState(false) + const [listNameText, setListNameText] = useState('') + const scrollViewRef = useRef() + + useEffect(() => { + userListRef.current = userList + }, [userList]) + + const handleToggleList = useCallback(({ id }) => { + setVisiblePanel(false) + setPrevSelectListId(id) + }, [setPrevSelectListId, setVisiblePanel]) + + const handleRemoveList = useCallback(id => { + if (id == activeListIdRef.current) setPrevSelectListId(userList[0].id) + removeUserList(id) + }, [activeListIdRef, userList, removeUserList, setPrevSelectListId]) + + const showMenu = useCallback((id, name, position) => { + // console.log(position) + if (id == 'default' || id == 'love') return + setButtonPosition({ ...position }) + selectedListRef.current.id = id + selectedListRef.current.name = name + setVisibleMenu(true) + }, [setButtonPosition]) + const hideMenu = useCallback(() => { + setVisibleMenu(false) + }, [setVisibleMenu]) + const handleMenuPress = useCallback(({ action }) => { + switch (action) { + case 'rename': + setListNameText(selectedListRef.current.name) + setVisibleRename(true) + break + // case 'sync': + + // break + case 'changePosition': + + break + case 'remove': + handleRemoveList(selectedListRef.current.id) + break + + default: + break + } + }, [handleRemoveList]) + + const menus = useMemo(() => { + return [ + { action: 'rename', label: t('list_rename') }, + // { action: 'sync', label: t('list_sync') }, + // { action: 'changePosition', label: t('change_position') }, + { action: 'remove', label: t('list_remove') }, + ] + }, [t]) + + const handleCancelRename = useCallback(() => { + setVisibleRename(false) + }, []) + const handleRename = useCallback(() => { + if (!listNameText.length) return + setUserListName({ id: selectedListRef.current.id, name: listNameText }) + setVisibleRename(false) + }, [listNameText, setUserListName]) + + const handleToggleDefaultList = () => { + handleToggleList(defaultList) + } + const handleToggleLoveList = () => { + handleToggleList(loveList) + } + + const handleScroll = useCallback(({ nativeEvent }) => { + saveListScrollPosition(LIST_SCROLL_POSITION_KEY, nativeEvent.contentOffset.y) + }, []) + + useEffect(() => { + const offset = getListScrollPosition(LIST_SCROLL_POSITION_KEY) + scrollViewRef.current.scrollTo({ x: 0, y: offset, animated: false }) + }) + + return ( + <View style={{ ...styles.container, borderTopColor: theme.secondary10 }}> + <ScrollView style={{ flexShrink: 1, flexGrow: 0 }} onScroll={handleScroll} ref={scrollViewRef} keyboardShouldPersistTaps={'always'}> + <View style={{ ...styles.listContainer, backgroundColor: theme.primary }} onStartShouldSetResponder={() => true}> + <View style={{ ...styles.listItem, borderBottomColor: theme.secondary45 }}> + <TouchableOpacity style={styles.listName} onPress={handleToggleDefaultList}> + <Text numberOfLines={1} style={{ color: theme.normal }}>{defaultList.name}</Text> + </TouchableOpacity> + </View> + <View style={{ ...styles.listItem, borderBottomColor: theme.secondary45 }}> + <TouchableOpacity style={styles.listName} onPress={handleToggleLoveList}> + <Text numberOfLines={1} style={{ color: theme.normal }}>{loveList.name}</Text> + </TouchableOpacity> + </View> + {userList.map(({ id, name }) => <ListItem key={id} name={name} id={id} onPress={() => handleToggleList({ id, name })} activeId={currentList.id} showMenu={showMenu} />)} + </View> + </ScrollView> + <Menu menus={menus} buttonPosition={buttonPosition} onPress={handleMenuPress} visible={visibleMenu} hideMenu={hideMenu} /> + <ConfirmAlert + visible={visibleRename} + onCancel={handleCancelRename} + onConfirm={handleRename} + > + <View style={styles.renameContent}> + <Text style={{ color: theme.normal, marginBottom: 5 }}>{t('list_rename_title')}</Text> + <Input + placeholder={selectedListRef.current.name} + value={listNameText} + onChangeText={setListNameText} + style={{ ...styles.input, backgroundColor: theme.secondary40 }} + /> + </View> + </ConfirmAlert> + </View> + ) +}) + + +export default memo(({ currentList, activeListIdRef }) => { + const theme = useGetter('common', 'theme') + const [visiblePanel, setVisiblePanel] = useState(false) + + return ( + <DorpDownPanel + visible={visiblePanel} + setVisible={setVisiblePanel} + PanelContent={<List setVisiblePanel={setVisiblePanel} currentList={currentList} activeListIdRef={activeListIdRef} />} + > + <Text style={{ ...styles.sourceMenu, color: theme.secondary }}>{currentList.name}</Text> + </DorpDownPanel> + ) +}) + + +const styles = StyleSheet.create({ + sourceMenu: { + height: 38, + lineHeight: 38, + minWidth: 70, + paddingLeft: 10, + paddingRight: 10, + }, + + container: { + borderTopWidth: BorderWidths.normal2, + }, + listContainer: { + // borderTopWidth: BorderWidths.normal2, + }, + listItem: { + flexDirection: 'row', + alignItems: 'center', + borderBottomWidth: BorderWidths.normal, + }, + listName: { + height: 46, + justifyContent: 'center', + flexGrow: 1, + flexShrink: 1, + paddingLeft: 10, + }, + listMoreBtn: { + width: 50, + height: 46, + justifyContent: 'center', + alignItems: 'center', + }, + + + renameContent: { + flexGrow: 1, + flexShrink: 1, + flexDirection: 'column', + }, + input: { + flexGrow: 1, + flexShrink: 1, + minWidth: 240, + borderRadius: 4, + paddingTop: 2, + paddingBottom: 2, + fontSize: 12, + }, + + // tagTypeList: { + // flexDirection: 'row', + // flexWrap: 'wrap', + // }, + // tagButton: { + // // marginRight: 10, + // borderRadius: 4, + // marginRight: 10, + // marginBottom: 10, + // }, + // tagButtonText: { + // paddingLeft: 12, + // paddingRight: 12, + // paddingTop: 8, + // paddingBottom: 8, + // }, +}) diff --git a/src/screens/Home/List/index.js b/src/screens/Home/List/index.js new file mode 100644 index 0000000..3bdab0b --- /dev/null +++ b/src/screens/Home/List/index.js @@ -0,0 +1,354 @@ +import React, { useMemo, useCallback, memo, useRef, useState, useEffect } from 'react' +import { View, Text, StyleSheet, FlatList } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import Menu from '@/components/common/Menu' +import MusicAddModal from '@/components/MusicAddModal' +import MusicMultiAddModal from '@/components/MusicMultiAddModal' +import ExitMultipleModeBar from './components/ExitMultipleModeBar' +import MyList from './components/MyList' +import ListItem from './components/ListItem' +import { getListScrollPosition, saveListScrollPosition } from '@/utils/tools' +import { useTranslation } from '@/plugins/i18n' +import { LIST_ITEM_HEIGHT } from '@/config/constant' +import MusicPositionModal from './components/MusicPositionModal' +// const shadow = { +// shadowOffset: 2, +// shadowOpacity: 0.23, +// shadowRadius: 0, +// elevation: 4, +// } + + +const List = () => { + const allList = useGetter('list', 'allList') + const isJumpPosition = useGetter('list', 'isJumpPosition') + const playInfo = useGetter('player', 'playInfo') + const playListInfo = useGetter('player', 'listInfo') + const playListInfoRef = useRef(playListInfo) + const activeListId = useGetter('common', 'prevSelectListId') + const activeListIdRef = useRef(activeListId) + const [buttonPosition, setButtonPosition] = useState({ w: 0, h: 0, x: 0, y: 0 }) + const selectedDataRef = useRef({ data: null, index: -1 }) + const flatListRef = useRef() + const isMoveRef = useRef(false) + const [visibleMenu, setVisibleMenu] = useState(false) + const [isMultiSelectMode, setIsMultiSelectMode] = useState(false) + const isMultiSelectModeRef = useRef(false) + const [selectedList, setSelectedList] = useState([]) + const selectedListRef = useRef([]) + const [selectMode, setSelectMode] = useState('single') + const selectModeRef = useRef('single') + const prevSelectIndexRef = useRef(-1) + const activeIndexRef = useRef(-1) + const activeIndex = useMemo(() => { + const index = playInfo.listId === activeListId ? playInfo.playIndex : -1 + activeIndexRef.current = index + return index + }, [playInfo.listId, activeListId, playInfo.playIndex]) + const currentListRef = useRef({}) + const currentList = useMemo(() => currentListRef.current = (allList.find(l => l.id == activeListId) || allList[0]), [allList, activeListId]) + const activeItemId = useMemo(() => currentList.list && activeIndex > -1 && currentList.list[activeIndex] ? String(currentList.list[activeIndex].songmid) : null, [currentList, activeIndex]) + const setPlayList = useDispatch('player', 'setList') + const playMusic = useDispatch('player', 'playMusic') + const setTempPlayList = useDispatch('player', 'setTempPlayList') + const removeListItem = useDispatch('list', 'listRemove') + const removeListMultiItem = useDispatch('list', 'listRemoveMultiple') + const setJumpPosition = useDispatch('list', 'setJumpPosition') + const { t } = useTranslation() + const [visibleMusicAddModal, setVisibleMusicAddModal] = useState(false) + const [visibleMusicMultiAddModal, setVisibleMusicMultiAddModal] = useState(false) + const [visibleMusicPosition, setVIsibleMusicPosition] = useState(false) + const setMusicPosition = useDispatch('list', 'setMusicPosition') + const theme = useGetter('common', 'theme') + + useEffect(() => { + activeListIdRef.current = activeListId + }, [activeListId]) + useEffect(() => { + playListInfoRef.current = playListInfo + }, [playListInfo]) + + const handlePlay = useCallback(async(data, index) => { + if (playListInfoRef.current.id != activeListIdRef.current) { + setPlayList({ + list: currentListRef.current, + index, + }) + } else { + playMusic({ + musicInfo: data, + listId: activeListIdRef.current, + }) + } + }, [setPlayList, playMusic]) + + const handleSelect = useCallback((item, index) => { + if (selectModeRef.current == 'single') { + const index = selectedListRef.current.indexOf(item) + if (index < 0) { + selectedListRef.current.push(item) + // setSelectedItem({ item, isChecked: true }) + } else { + selectedListRef.current.splice(index, 1) + // setSelectedItem({ item, isChecked: false }) + } + } else { + if (selectedListRef.current.length) { + const prevIndex = prevSelectIndexRef.current + const currentIndex = index + if (prevIndex == currentIndex) { + selectedListRef.current = [] + } else if (currentIndex > prevIndex) { + selectedListRef.current = currentListRef.current.list.slice(prevIndex, currentIndex + 1) + } else { + selectedListRef.current = currentListRef.current.list.slice(currentIndex, prevIndex + 1) + selectedListRef.current.reverse() + } + } else { + selectedListRef.current.push(item) + prevSelectIndexRef.current = index + } + } + setSelectedList([...selectedListRef.current]) + }, []) + const handleSelectAll = useCallback(() => { + if (!currentListRef.current.list.length) return + if (selectedListRef.current.length == currentListRef.current.list.length) { + selectedListRef.current = [] + } else { + selectedListRef.current = [...currentListRef.current.list] + } + setSelectedList([...selectedListRef.current]) + }, []) + + const handleSetSelectMode = useCallback(mode => { + setSelectMode(mode) + selectModeRef.current = mode + if (mode == 'range' && selectedListRef.current.length) { + prevSelectIndexRef.current = currentListRef.current.list.indexOf(selectedListRef.current[selectedListRef.current.length - 1]) + } + }, []) + + const handleCancelMultiSelect = useCallback(() => { + setIsMultiSelectMode(false) + isMultiSelectModeRef.current = false + selectedListRef.current = [] + setSelectedList([]) + }, []) + + const handlePress = useCallback((item, index) => { + if (isMultiSelectModeRef.current) { + handleSelect(item, index) + } else { + handlePlay(item, index) + } + }, [handlePlay, handleSelect]) + + const handleLongPress = useCallback((item, index) => { + setIsMultiSelectMode(true) + isMultiSelectModeRef.current = true + handleSelect(item, index) + }, [handleSelect]) + + const menus = useMemo(() => { + return [ + { action: 'play', label: t('play') }, + { action: 'playLater', label: t('play_later') }, + // { action: 'copyName', label: t('copy_name') }, + // { action: 'download', label: '下载' }, + // { action: 'add', label: t('add_to') }, + // { action: 'move', label: '移动到...' }, + // { action: 'download', label: '下载' }, + { action: 'add', label: t('add_to') }, + { action: 'move', label: t('move_to') }, + { action: 'changePosition', label: t('change_position') }, + // { action: 'move', label: '移动到...' }, + { action: 'remove', label: t('delete') }, + ] + }, [t]) + + const showMenu = useCallback((item, index, position) => { + // console.log(position) + setButtonPosition({ ...position }) + selectedDataRef.current.data = item + selectedDataRef.current.index = index + setVisibleMenu(true) + }, [setButtonPosition]) + + const hideMenu = useCallback(() => { + setVisibleMenu(false) + }, [setVisibleMenu]) + + const handleMenuPress = useCallback(({ action }) => { + switch (action) { + case 'play': + handlePlay(selectedDataRef.current.data, selectedDataRef.current.index) + break + case 'playLater': + if (selectedListRef.current.length) { + setTempPlayList(selectedListRef.current.map(s => ({ listId: activeListIdRef.current, musicInfo: s }))) + handleCancelMultiSelect() + } else { + setTempPlayList([{ listId: activeListIdRef.current, musicInfo: selectedDataRef.current.data }]) + } + break + // case 'copyName': + // break + case 'add': + isMoveRef.current = false + selectedListRef.current.length + ? setVisibleMusicMultiAddModal(true) + : setVisibleMusicAddModal(true) + break + case 'move': + isMoveRef.current = true + selectedListRef.current.length + ? setVisibleMusicMultiAddModal(true) + : setVisibleMusicAddModal(true) + break + case 'changePosition': + setVIsibleMusicPosition(true) + break + case 'remove': + if (selectedListRef.current.length) { + removeListMultiItem({ id: activeListIdRef.current, list: selectedListRef.current }) + handleCancelMultiSelect() + } else { + removeListItem({ id: activeListIdRef.current, index: selectedDataRef.current.index }) + } + break + default: + break + } + }, [handleCancelMultiSelect, handlePlay, removeListItem, removeListMultiItem, setTempPlayList]) + + const handleScroll = useCallback(({ nativeEvent }) => { + saveListScrollPosition(currentListRef.current.id, nativeEvent.contentOffset.y) + }, []) + + const hideMusicAddModal = useCallback(() => { + setVisibleMusicAddModal(false) + }, []) + + const hideMusicMultiAddModal = useCallback(() => { + setVisibleMusicMultiAddModal(false) + }, []) + + const jumpPosition = useCallback(() => { + if (activeIndexRef.current < 0) return + global.requestAnimationFrame(() => { + flatListRef.current.scrollToIndex({ index: activeIndexRef.current, viewPosition: 0.3, animated: true }) + setJumpPosition(false) + }) + }, [setJumpPosition]) + + const hideMusicPositionModal = useCallback(() => { + setVIsibleMusicPosition(false) + }, []) + const handleSetMusicPosition = useCallback(num => { + num = Math.min(parseInt(num), currentListRef.current.list.length) + setMusicPosition({ + id: activeListIdRef.current, + position: num, + list: selectedListRef.current.length ? [...selectedListRef.current] : [selectedDataRef.current.data], + }) + setVIsibleMusicPosition(false) + handleCancelMultiSelect() + }, [handleCancelMultiSelect, setMusicPosition]) + + useEffect(() => { + const offset = getListScrollPosition(currentList.id) + flatListRef.current.scrollToOffset({ offset, animated: false }) + // global.requestAnimationFrame(() => { + // flatListRef.current.scrollToOffset({ offset, animated: false }) + // }) + }, [currentList.id]) + useEffect(() => { + if (!isJumpPosition) return + jumpPosition() + }, [isJumpPosition, jumpPosition]) + + const renderItem = useCallback(({ item, index }) => ( + <ListItem + item={item} + index={index} + activeIndex={activeIndex} + onPress={handlePress} + showMenu={showMenu} + selectedList={selectedList} + handleLongPress={handleLongPress} /> + ), [activeIndex, handleLongPress, handlePress, selectedList, showMenu]) + + const listComponent = useMemo(() => ( + <FlatList + ref={flatListRef} + onScroll={handleScroll} + style={styles.list} + data={currentList.list} + maxToRenderPerBatch={8} + updateCellsBatchingPeriod={80} + windowSize={18} + removeClippedSubviews={true} + initialNumToRender={12} + renderItem={renderItem} + keyExtractor={item => String(item.songmid)} + extraData={activeItemId} + getItemLayout={(data, index) => ({ length: LIST_ITEM_HEIGHT, offset: LIST_ITEM_HEIGHT * index, index })} /> + ), [activeItemId, currentList.list, handleScroll, renderItem]) + + return ( + <View style={styles.container}> + {listComponent} + <View style={{ backgroundColor: theme.secondary45 }}> + <MyList currentList={currentList} activeListIdRef={activeListIdRef} /> + <ExitMultipleModeBar + multipleMode={isMultiSelectMode} + onCancel={handleCancelMultiSelect} + onSwitchMode={handleSetSelectMode} + onSelectAll={handleSelectAll} + selectMode={selectMode} + isSelectAll={selectedList.length && currentList.list.length == selectedList.length} /> + </View> + <Menu menus={menus} buttonPosition={buttonPosition} onPress={handleMenuPress} visible={visibleMenu} hideMenu={hideMenu} /> + <MusicPositionModal + selectedList={selectedListRef.current} + selectedData={selectedDataRef.current.data} + visible={visibleMusicPosition} + hideModal={hideMusicPositionModal} + onConfirm={handleSetMusicPosition} /> + <MusicAddModal + visible={visibleMusicAddModal} + listId={activeListIdRef.current} + isMove={isMoveRef.current} + hideModal={hideMusicAddModal} + musicInfo={selectedDataRef.current.data} /> + <MusicMultiAddModal + visible={visibleMusicMultiAddModal} + hideModal={hideMusicMultiAddModal} + list={selectedListRef.current} + listId={activeListIdRef.current} + isMove={isMoveRef.current} + excludeList={[activeListIdRef.current]} + onAdd={handleCancelMultiSelect} /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + list: { + flexGrow: 1, + flexShrink: 1, + }, + lists: { + height: 50, + flexGrow: 0, + flexShrink: 0, + flexDirection: 'row', + }, +}) + +export default List diff --git a/src/screens/Home/Search/components/Input.js b/src/screens/Home/Search/components/Input.js new file mode 100644 index 0000000..dead3db --- /dev/null +++ b/src/screens/Home/Search/components/Input.js @@ -0,0 +1,82 @@ +import React, { useCallback, useRef, forwardRef, useImperativeHandle } from 'react' +// import { StyleSheet } from 'react-native' +import Input from '@/components/common/Input' + +import music from '@/utils/music' +import { useGetter, useDispatch } from '@/store' +import { debounce } from '@/utils' + +const debounceTipSearch = debounce((str, tempSearchSource, callback) => { + return music[tempSearchSource].tempSearch.search(str).then(callback) +}, 200) + +export default forwardRef(({ onSetTipList, setPage }, ref) => { + const searchInputRef = useRef() + const text = useGetter('search', 'text') + + const tempSearchSource = useGetter('search', 'tempSearchSource') + // const searchSource = useGetter('search', 'searchSource') + const listInfo = useGetter('search', 'listInfo') + const setText = useDispatch('search', 'setText') + const search = useDispatch('search', 'search') + + const tipListVisible = useGetter('search', 'tipListVisible') + const setVisibleTipList = useDispatch('search', 'setVisibleTipList') + + + useImperativeHandle(ref, () => { + return { + blur() { + searchInputRef.current.blur() + }, + isFocused() { + return searchInputRef.current.isFocused() + }, + } + }) + + const showTipList = useCallback(() => { + if (tipListVisible || !text.length) return + setVisibleTipList(true) + }, [tipListVisible, setVisibleTipList, text]) + + const hideTipList = useCallback(() => { + if (!tipListVisible) return + setVisibleTipList(false) + }, [tipListVisible, setVisibleTipList]) + + const handleSearchInput = useCallback(str => { + setText(str) + if (str.length) { + debounceTipSearch(str, tempSearchSource, onSetTipList) + } else { + music[tempSearchSource].tempSearch.search('') + hideTipList() + } + }, [setText, hideTipList, tempSearchSource, onSetTipList]) + + const handleSearch = useCallback((text) => { + setText(text.trim()) + setPage(1) + return search({ page: 1, limit: listInfo.limit }) + }, [setText, setPage, search, listInfo.limit]) + + const onClearText = useCallback(() => { + handleSearchInput('') + handleSearch('') + }, [handleSearchInput, handleSearch]) + + return ( + <Input + onChangeText={handleSearchInput} + placeholder="Search for something..." + value={text} + // onFocus={showTipList} + clearBtn + ref={searchInputRef} + onBlur={hideTipList} + onSubmitEditing={ ({ nativeEvent: { text } }) => handleSearch(text) } + onClearText={onClearText} + onTouchStart={showTipList} /> + ) +}) diff --git a/src/screens/Home/Search/components/MusicList.js b/src/screens/Home/Search/components/MusicList.js new file mode 100644 index 0000000..b3b8b05 --- /dev/null +++ b/src/screens/Home/Search/components/MusicList.js @@ -0,0 +1,67 @@ +import React, { useState, useCallback, memo, useEffect, useRef } from 'react' +import { InteractionManager } from 'react-native' +import { useGetter, useDispatch } from '@/store' +import OnlineList from '@/components/OnlineList' + +export default memo(({ page, setPage }) => { + const [isListRefreshing, setIsListRefreshing] = useState(false) + const [visibleLoadingMask, setVisibleLoadingMask] = useState(false) + const text = useGetter('search', 'text') + const textRef = useRef(text) + const searchSource = useGetter('search', 'searchSource') + const listInfo = useGetter('search', 'listInfo') + const isLoading = useGetter('search', 'isLoading') + const isEnd = useGetter('search', 'isEnd') + const search = useDispatch('search', 'search') + const listInfoRef = useRef(listInfo) + + useEffect(() => { + textRef.current = text + }, [text]) + + const handleRefresh = useCallback(() => { + setIsListRefreshing(true) + setVisibleLoadingMask(true) + setPage(1) + search({ page: 1, limit: listInfoRef.current.limit }).finally(() => { + setIsListRefreshing(false) + setVisibleLoadingMask(false) + }) + }, [search, setPage]) + + const handleLoadMore = useCallback(() => { + if (isLoading || isEnd || !textRef.current.length) return + setPage(listInfoRef.current.page + 1) + search({ page: listInfoRef.current.page + 1, limit: listInfoRef.current.limit }) + }, [isLoading, isEnd, setPage, search]) + + useEffect(() => { + listInfoRef.current = listInfo + }, [listInfo]) + + useEffect(() => { + InteractionManager.runAfterInteractions(() => { + setVisibleLoadingMask(true) + setPage(1) + search({ page: 1, limit: listInfo.limit }).finally(() => { + setIsListRefreshing(false) + setVisibleLoadingMask(false) + }) + }) + }, [searchSource, search, setIsListRefreshing, listInfo.limit, setPage]) + + return ( + <OnlineList + list={listInfo.list} + isEnd={isEnd} + page={page} + isListRefreshing={isListRefreshing} + onRefresh={handleRefresh} + onLoadMore={handleLoadMore} + // progressViewOffset={20} + isLoading={isLoading} + visibleLoadingMask={isLoading && visibleLoadingMask} + /> + ) +}) + diff --git a/src/screens/Home/Search/components/SourceSelector.js b/src/screens/Home/Search/components/SourceSelector.js new file mode 100644 index 0000000..b9af473 --- /dev/null +++ b/src/screens/Home/Search/components/SourceSelector.js @@ -0,0 +1,40 @@ +import React, { memo, useMemo } from 'react' +import { StyleSheet, Text } from 'react-native' + +import DorpDownMenu from '@/components/common/DorpDownMenu' +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' + + +export default memo(() => { + const setSearchSource = useDispatch('common', 'setSearchSource') + const sourceList = useGetter('search', 'sources') + const searchSource = useGetter('search', 'searchSource') + const sourceNameType = useGetter('common', 'sourceNameType') + // const currentSourceName = useGetter('search', 'currentSourceName') + const { t } = useTranslation() + + const sourceList_t = useMemo(() => { + return sourceList.map(s => ({ label: t(`source_${sourceNameType}_${s.id}`), action: s.id })) + }, [sourceNameType, sourceList, t]) + + return ( + <DorpDownMenu + menus={sourceList_t} + width={80} + onPress={({ action }) => setSearchSource({ searchSource: action })} + > + <Text style={styles.sourceMenu}>{t(`source_${sourceNameType}_${searchSource}`)}</Text> + </DorpDownMenu> + ) +}) + + +const styles = StyleSheet.create({ + sourceMenu: { + height: 38, + lineHeight: 38, + textAlign: 'center', + width: 80, + }, +}) diff --git a/src/screens/Home/Search/components/TipList.js b/src/screens/Home/Search/components/TipList.js new file mode 100644 index 0000000..fd15db9 --- /dev/null +++ b/src/screens/Home/Search/components/TipList.js @@ -0,0 +1,37 @@ +import React, { useCallback, memo, useEffect, useState, useMemo } from 'react' + +import SearchTipList from '@/components/searchTipList' +import { useGetter, useDispatch } from '@/store' + +export default memo(({ onTipPress, height }) => { + // const tipList = useGetter('search', 'tipList') + + const text = useGetter('search', 'text') + const list = useGetter('search', 'tipList') + const visible = useGetter('search', 'tipListVisible') + const setVisibleTipList = useDispatch('search', 'setVisibleTipList') + + const hideTipList = useCallback(() => { + setVisibleTipList(false) + }, []) + + useEffect(() => { + if (visible && !text.length) hideTipList() + }, []) + + const handleTipPress = useCallback(text => { + hideTipList() + onTipPress(text) + }, [onTipPress, hideTipList]) + + // console.log(visible) + return ( + <SearchTipList + list={list} + visible={visible} + onPress={handleTipPress} + height={height} + hideList={hideTipList} + /> + ) +}) diff --git a/src/screens/Home/Search/index.js b/src/screens/Home/Search/index.js new file mode 100644 index 0000000..5dc8f23 --- /dev/null +++ b/src/screens/Home/Search/index.js @@ -0,0 +1,87 @@ +import React, { useCallback, useRef, useState, useEffect } from 'react' +import { StyleSheet, View } from 'react-native' + +import music from '@/utils/music' +import { useGetter, useDispatch } from '@/store' +import { BorderWidths } from '@/theme' +// import InsetShadow from 'react-native-inset-shadow' +import SourceSelector from './components/SourceSelector' +import Input from './components/Input' +import TipList from './components/TipList' +import MusicList from './components/MusicList' +import { useLayout } from '@/utils/hooks' + + +export default () => { + const searchInputRef = useRef() + const theme = useGetter('common', 'theme') + const tempSearchSource = useGetter('search', 'tempSearchSource') + const tempSearchSourceRef = useRef('') + const listInfo = useGetter('search', 'listInfo') + const listInfoRef = useRef({}) + const tipListVisible = useGetter('search', 'tipListVisible') + const tipListVisibleRef = useRef('') + const setText = useDispatch('search', 'setText') + const setTipList = useDispatch('search', 'setTipList') + const setVisibleTipList = useDispatch('search', 'setVisibleTipList') + const search = useDispatch('search', 'search') + const { onLayout, ...listLayout } = useLayout() + const [page, setPage] = useState(0) + + useEffect(() => { + listInfoRef.current = listInfo + }, [listInfo]) + useEffect(() => { + tempSearchSourceRef.current = tempSearchSource + }, [tempSearchSource]) + useEffect(() => { + tipListVisibleRef.current = tipListVisible + }, [tipListVisible]) + + const handleTipPress = useCallback(text => { + if (tipListVisibleRef.current) setVisibleTipList(false) + text = text.trim() + music[tempSearchSourceRef.current].tempSearch.search(text).then(tipList => setTipList(tipList)) + searchInputRef.current.blur() + setText(text) + setPage(1) + search({ page: 1, limit: listInfoRef.current.limit }) + }, []) + + const onSetTipList = list => { + setTipList(list) + if (list.length) { + if (tipListVisibleRef.current) return + } else if (!tipListVisibleRef.current) return + if (searchInputRef.current.isFocused()) setVisibleTipList(true) + } + + return ( + <View style={styles.container}> + <View style={{ ...styles.searchBar, backgroundColor: theme.primary, borderBottomColor: theme.borderColor, borderBottomWidth: BorderWidths.normal }}> + <SourceSelector /> + <Input ref={searchInputRef} onSetTipList={onSetTipList} setPage={setPage} /> + </View> + <View style={styles.content} onLayout={onLayout}> + <TipList onTipPress={handleTipPress} height={listLayout.height} /> + <MusicList page={page} setPage={setPage} /> + </View> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + width: '100%', + flex: 1, + }, + content: { + flex: 1, + }, + searchBar: { + flexDirection: 'row', + height: 38, + zIndex: 2, + paddingRight: 5, + }, +}) diff --git a/src/screens/Home/Setting/About.js b/src/screens/Home/Setting/About.js new file mode 100644 index 0000000..57cae37 --- /dev/null +++ b/src/screens/Home/Setting/About.js @@ -0,0 +1,112 @@ +import React, { useMemo, memo, useState, useEffect } from 'react' +import { StyleSheet, View, Text, TouchableOpacity } from 'react-native' + +import Section from './components/Section' +// import Button from './components/Button' + +import { useTranslation } from '@/plugins/i18n' +import { useGetter, useDispatch } from '@/store' +import { openUrl } from '@/utils/tools' +import { showPactModal } from '@/navigation' + +const qqGroupUrl = 'mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26jump_from%3Dwebapi%26k%3Du1zyxek8roQAwic44nOkBXtG9CfbAxFw' +const qqGroupWebUrl = 'https://qm.qq.com/cgi-bin/qm/qr?k=jRZkyFSZ4FmUuTHA3P_RAXbbUO_Rrn5e&jump_from=webapi' + +export default memo(() => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + const openHomePage = () => { + openUrl('https://github.com/lyswhut/lx-music-mobile#readme') + } + const openNetdiskPage = () => { + openUrl('https://www.lanzous.com/b0bf2cfa/') + } + const openFAQPage = () => { + openUrl('https://github.com/lyswhut/lx-music-mobile/blob/master/FAQ.md') + } + // const openIssuesPage = () => { + // openUrl('https://github.com/lyswhut/lx-music-mobile/issues') + // } + const openPactModal = () => { + showPactModal() + } + const openPartPage = () => { + openUrl('https://github.com/lyswhut/lx-music-mobile#%E9%A1%B9%E7%9B%AE%E5%8D%8F%E8%AE%AE') + } + + const goToQQQroup = () => { + openUrl(qqGroupUrl).catch(() => { + openUrl(qqGroupWebUrl) + }) + } + + const textStyle = StyleSheet.compose(styles.text, { + color: theme.normal, + }) + const textLinkStyle = StyleSheet.compose(styles.text, { + textDecorationLine: 'underline', + color: theme.secondary, + fontSize: 14, + }) + + + return ( + <Section title={t('setting_about')}> + <View style={styles.part}> + <Text style={textStyle} >本软件完全免费,代码已开源,开源地址:</Text> + <TouchableOpacity onPress={openHomePage}> + <Text style={textLinkStyle}>https://github.com/lyswhut/lx-music-mobile</Text> + </TouchableOpacity> + </View> + <View style={styles.part}> + <Text style={textStyle} >最新版网盘下载地址:</Text> + <TouchableOpacity onPress={openNetdiskPage}> + <Text style={textLinkStyle}>网盘地址(密码:glqw)</Text> + </TouchableOpacity> + </View> + <View style={styles.part}> + <Text style={textStyle} >软件的常见问题可转至:</Text> + <TouchableOpacity onPress={openFAQPage}> + <Text style={textLinkStyle}>常见问题</Text> + </TouchableOpacity> + </View> + <View style={styles.part}> + <Text style={textStyle}><Text style={{ fontWeight: 'bold' }} >仔细 仔细 仔细 </Text>地阅读常见问题后,</Text> + <Text style={textStyle}>仍有问题可加企鹅群 </Text> + <TouchableOpacity onPress={goToQQQroup}><Text style={textLinkStyle}>830125506</Text></TouchableOpacity> + <Text style={textStyle}> 反馈。</Text> + <Text style={textStyle}>注意:<Text style={{ fontWeight: 'bold' }}>为免满人,无事勿加,入群先看群公告</Text></Text> + </View> + <View style={styles.part}> + <Text style={textStyle}>由于软件开发的初衷仅是为了对新技术的学习与研究,因此软件直至停止维护都将会一直保持纯净。</Text> + </View> + <View style={styles.part}> + <Text style={textStyle}>你已签署本软件的</Text> + <TouchableOpacity onPress={openPactModal}><Text style={{ ...styles.text, color: theme.secondary }}>许可协议</Text></TouchableOpacity> + <Text style={textStyle}>,协议的在线版本在</Text> + <TouchableOpacity onPress={openPartPage}><Text style={textLinkStyle}>这里</Text></TouchableOpacity> + </View> + <View style={styles.part}> + <Text style={{ ...styles.text, color: theme.normal, fontSize: 12 }}>By:</Text> + <Text style={textStyle}>落雪无痕</Text> + </View> + </Section> + ) +}) + +const styles = StyleSheet.create({ + part: { + marginLeft: 15, + marginRight: 15, + marginBottom: 10, + flexDirection: 'row', + flexWrap: 'wrap', + }, + text: { + fontSize: 13, + textAlignVertical: 'bottom', + }, + btn: { + flexDirection: 'row', + }, +}) diff --git a/src/screens/Home/Setting/Backup/All.js b/src/screens/Home/Setting/Backup/All.js new file mode 100644 index 0000000..e69de29 diff --git a/src/screens/Home/Setting/Backup/Part.js b/src/screens/Home/Setting/Backup/Part.js new file mode 100644 index 0000000..1456bdf --- /dev/null +++ b/src/screens/Home/Setting/Backup/Part.js @@ -0,0 +1,157 @@ +import React, { memo, useCallback, useState, useRef } from 'react' +import { StyleSheet, View, Text, InteractionManager } from 'react-native' +import { readFile, writeFile, temporaryDirectoryPath, unlink } from '@/utils/fs' + +import { useGetter, useDispatch } from '@/store' +// import { gzip, ungzip } from 'pako' + +import SubTitle from '../components/SubTitle' +import Button from '../components/Button' +import ChoosePath from '@/components/common/ChoosePath' +import { useTranslation } from '@/plugins/i18n' +import { toast } from '@/utils/tools' +import { gzip, ungzip } from '@/utils/gzip' + +const lxmFileExt = /\.(json|lxmc)$/ + +const handleSaveFile = async(path, data) => { + // if (!path.endsWith('.json')) path += '.json' + // const buffer = gzip(data) + const tempFilePath = `${temporaryDirectoryPath}/tempFile.json` + await writeFile(tempFilePath, data, 'utf8') + await gzip(tempFilePath, path) + await unlink(tempFilePath) +} +const handleReadFile = async(path) => { + let isJSON = path.endsWith('.json') + let data + if (isJSON) { + data = await readFile(path, 'utf8') + } else { + const tempFilePath = `${temporaryDirectoryPath}/tempFile.json` + await ungzip(path, tempFilePath) + data = await readFile(tempFilePath, 'utf8') + await unlink(tempFilePath) + } + return data +} +const exportList = async(allList, path) => { + const data = JSON.parse(JSON.stringify({ + type: 'playList', + data: allList, + })) + for (const list of data.data) { + for (const item of list.list) { + if (item.otherSource) delete item.otherSource + } + } + await handleSaveFile(path + '/lx_list.lxmc', JSON.stringify(data)) + toast('导出完成') +} +const importList = async path => { + let listData + try { + listData = JSON.parse(await handleReadFile(path)) + } catch (error) { + return + } + console.log(listData.type) + return listData +} + +export default memo(() => { + const { t } = useTranslation() + const [isShowChoosePath, setShowChoosePath] = useState(false) + const [title, setTitle] = useState('') + const [dirOnly, setDirOnly] = useState(false) + const actionTypeRef = useRef('') + // const setting = useGetter('common', 'setting') + const allList = useGetter('list', 'allList') + const setList = useDispatch('list', 'setList') + + const importAndExportData = useCallback(async(action, type) => { + setDirOnly(action == 'export') + actionTypeRef.current = `${action}_${type}` + switch (type) { + case 'list': + setTitle(t(`setting_backup_part_${action}_list_desc`)) + break + case 'setting': + setTitle(t(`setting_backup_part_${action}_setting_desc`)) + break + default: + setTitle(t(`setting_backup_all_${action}_desc`)) + break + } + + setShowChoosePath(true) + }, [t]) + + const onConfirmPath = useCallback(path => { + setShowChoosePath(false) + switch (actionTypeRef.current) { + case 'import_list': + importList(path).then(listData => { + // 兼容0.6.2及以前版本的列表数据 + if (listData.type === 'defautlList') return setList({ id: 'default', list: listData.data.list, name: '试听列表' }) + + if (listData.type !== 'playList') return + + for (const list of listData.data) setList(list) + toast('导入完成') + }) + break + // case 'import_setting': + // setTitle(t('setting_backup_part_import_setting_desc')) + // break + // case 'import_all': + // setTitle(t('setting_backup_part_import_setting_desc')) + // break + case 'export_list': + exportList(allList, path) + break + // case 'export_setting': + // setTitle(t('setting_backup_part_import_setting_desc')) + // break + // case 'export_all': + // setTitle(t('setting_backup_part_import_setting_desc')) + // break + // default: + // setTitle(t('setting_backup_all_import_desc')) + // break + } + }, [allList, setList]) + + + return ( + <> + <SubTitle title={t('setting_backup_part')}> + <View style={styles.list}> + <Button onPress={() => importAndExportData('import', 'list')}>{t('setting_backup_part_import_list')}</Button> + <Button onPress={() => importAndExportData('export', 'list')}>{t('setting_backup_part_export_list')}</Button> + {/* <Button onPress={() => importAndExportData('import', 'setting')}>{t('setting_backup_part_import_setting')}</Button> + <Button onPress={() => importAndExportData('export', 'setting')}>{t('setting_backup_part_export_setting')}</Button> */} + </View> + </SubTitle> + {/* <SubTitle title={t('setting_backup_all')}> + <View style={styles.list}> + <Button onPress={() => importAndExportData('import', 'all')}>{t('setting_backup_all_import')}</Button> + <Button onPress={() => importAndExportData('export', 'all')}>{t('setting_backup_all_export')}</Button> + </View> + </SubTitle> */} + <ChoosePath + visible={isShowChoosePath} + hide={() => setShowChoosePath(false)} + title={title} + dirOnly={dirOnly} + filter={lxmFileExt} + onConfirm={onConfirmPath} /> + </> + ) +}) + +const styles = StyleSheet.create({ + list: { + flexDirection: 'row', + }, +}) diff --git a/src/screens/Home/Setting/Backup/index.js b/src/screens/Home/Setting/Backup/index.js new file mode 100644 index 0000000..47ad5e9 --- /dev/null +++ b/src/screens/Home/Setting/Backup/index.js @@ -0,0 +1,17 @@ +import React, { memo } from 'react' + +import Section from '../components/Section' +import Part from './Part' +// import MaxCache from './MaxCache' +import { useTranslation } from '@/plugins/i18n' + +export default memo(() => { + const { t } = useTranslation() + + return ( + <Section title={t('setting_backup')}> + <Part /> + {/* <MaxCache /> */} + </Section> + ) +}) diff --git a/src/screens/Home/Setting/Basic/Language.js b/src/screens/Home/Setting/Basic/Language.js new file mode 100644 index 0000000..dfc0591 --- /dev/null +++ b/src/screens/Home/Setting/Basic/Language.js @@ -0,0 +1,47 @@ +import React, { memo, useCallback, useMemo } from 'react' + +import { StyleSheet, View, InteractionManager } from 'react-native' +import { useGetter, useDispatch } from '@/store' + +import SubTitle from '../components/SubTitle' +import { useTranslation, langList } from '@/plugins/i18n' +import CheckBox from '@/components/common/CheckBox' + +const useActive = id => { + const activeLangId = useGetter('common', 'activeLangId') + const isActive = useMemo(() => activeLangId == id, [activeLangId, id]) + return isActive +} + +const Item = ({ id, name, setLang }) => { + const isActive = useActive(id) + // const [toggleCheckBox, setToggleCheckBox] = useState(false) + return <CheckBox marginRight={8} check={isActive} label={name} onChange={() => setLang(id)} need /> +} + +export default memo(() => { + const { t } = useTranslation() + const setLang = useDispatch('common', 'setLang') + const setLangId = useCallback((id) => { + InteractionManager.runAfterInteractions(() => { + setLang(id) + }) + }, [setLang]) + + return ( + <SubTitle title={t('setting_basic_lang')}> + <View style={styles.list}> + { + langList.map(({ id, name }) => <Item name={name} id={id} key={id} setLang={setLangId} />) + } + </View> + </SubTitle> + ) +}) + +const styles = StyleSheet.create({ + list: { + flexDirection: 'row', + flexWrap: 'wrap', + }, +}) diff --git a/src/screens/Home/Setting/Basic/Source.js b/src/screens/Home/Setting/Basic/Source.js new file mode 100644 index 0000000..684f785 --- /dev/null +++ b/src/screens/Home/Setting/Basic/Source.js @@ -0,0 +1,54 @@ +import React, { memo, useCallback, useMemo } from 'react' + +import { StyleSheet, View, InteractionManager } from 'react-native' +import { useGetter, useDispatch } from '@/store' + +import SubTitle from '../components/SubTitle' +import { useTranslation } from '@/plugins/i18n' +import CheckBox from '@/components/common/CheckBox' + +const useActive = id => { + const activeLangId = useGetter('common', 'activeApiSourceId') + const isActive = useMemo(() => activeLangId == id, [activeLangId, id]) + return isActive +} + +const Item = ({ id, name, change }) => { + const isActive = useActive(id) + // const [toggleCheckBox, setToggleCheckBox] = useState(false) + return <CheckBox marginBottom={3} check={isActive} label={name} onChange={() => change(id)} need /> +} + +export default memo(() => { + const { t } = useTranslation() + const setApiSource = useDispatch('common', 'setApiSource') + const apiSourceList = useGetter('common', 'apiSourceList') + const list = useMemo(() => apiSourceList.map(s => ({ + name: t(`setting_basic_source_${s.id}`) || s.name, + id: s.id, + })), [apiSourceList, t]) + const setApiSourceId = useCallback((id) => { + InteractionManager.runAfterInteractions(() => { + setApiSource(id) + }) + }, [setApiSource]) + + return ( + <SubTitle title={t('setting_basic_source')}> + <View style={styles.list}> + { + list.map(({ id, name }) => <Item name={name} id={id} key={id} change={setApiSourceId} />) + } + </View> + </SubTitle> + ) +}) + +const styles = StyleSheet.create({ + list: { + flexGrow: 0, + flexShrink: 1, + flexDirection: 'row', + flexWrap: 'wrap', + }, +}) diff --git a/src/screens/Home/Setting/Basic/SourceName.js b/src/screens/Home/Setting/Basic/SourceName.js new file mode 100644 index 0000000..e50f609 --- /dev/null +++ b/src/screens/Home/Setting/Basic/SourceName.js @@ -0,0 +1,59 @@ +import React, { memo, useCallback, useMemo } from 'react' + +import { StyleSheet, View, InteractionManager } from 'react-native' +import { useGetter, useDispatch } from '@/store' + +import SubTitle from '../components/SubTitle' +import { useTranslation } from '@/plugins/i18n' +import CheckBox from '@/components/common/CheckBox' + +const useActive = id => { + const activeId = useGetter('common', 'sourceNameType') + const isActive = useMemo(() => activeId == id, [activeId, id]) + return isActive +} + +const Item = ({ id, name, change }) => { + const isActive = useActive(id) + // const [toggleCheckBox, setToggleCheckBox] = useState(false) + return <CheckBox marginBottom={3} check={isActive} label={name} onChange={() => change(id)} need /> +} + +export default memo(() => { + const { t } = useTranslation() + const setSourceNameType = useDispatch('common', 'setSourceNameType') + const list = useMemo(() => [ + { + id: 'real', + name: t('setting_basic_sourcename_real'), + }, + { + id: 'alias', + name: t('setting_basic_sourcename_alias'), + }, + ], [t]) + const setSourceNameTypeId = useCallback((id) => { + InteractionManager.runAfterInteractions(() => { + setSourceNameType(id) + }) + }, [setSourceNameType]) + + return ( + <SubTitle title={t('setting_basic_sourcename')}> + <View style={styles.list}> + { + list.map(({ id, name }) => <Item name={name} id={id} key={id} change={setSourceNameTypeId} />) + } + </View> + </SubTitle> + ) +}) + +const styles = StyleSheet.create({ + list: { + flexGrow: 0, + flexShrink: 1, + flexDirection: 'row', + flexWrap: 'wrap', + }, +}) diff --git a/src/screens/Home/Setting/Basic/Theme.js b/src/screens/Home/Setting/Basic/Theme.js new file mode 100644 index 0000000..8494816 --- /dev/null +++ b/src/screens/Home/Setting/Basic/Theme.js @@ -0,0 +1,83 @@ +import React, { memo, useCallback, useMemo } from 'react' + +import { StyleSheet, View, Text, ImageBackground, TouchableOpacity, InteractionManager } from 'react-native' +import { useGetter, useDispatch } from '@/store' + +import SubTitle from '../components/SubTitle' +import { useTranslation } from '@/plugins/i18n' + +const useActive = id => { + const activeThemeId = useGetter('common', 'activeThemeId') + const isActive = useMemo(() => activeThemeId == id, [activeThemeId, id]) + return isActive +} + +const ThemeItem = ({ id, color, image, setTheme }) => { + const theme = useGetter('common', 'theme') + const isActive = useActive(id) + const { t } = useTranslation() + return ( + <TouchableOpacity style={styles.item} activeOpacity={0.5} onPress={() => setTheme(id)}> + <View style={{ ...styles.colorContent, backgroundColor: theme.primary, borderColor: isActive ? color : 'transparent' }}> + { + image + ? <ImageBackground source={image} style={styles.image} /> + : <View style={{ ...styles.image, backgroundColor: color }}></View> + } + </View> + <Text style={{ ...styles.name, color: isActive ? color : theme.normal }} numberOfLines={1}>{t(`theme_${id}`)}</Text> + </TouchableOpacity> + ) +} + +export default memo(() => { + const { t } = useTranslation() + const themeList = useGetter('common', 'themeList') + const themes = useMemo(() => themeList.map(theme => ({ id: theme.id, color: theme.colors.secondary })), [themeList]) + const setTheme = useDispatch('common', 'setTheme') + const setThemeId = useCallback((id) => { + InteractionManager.runAfterInteractions(() => { + setTheme(id) + }) + }, [setTheme]) + + return ( + <SubTitle title={t('setting_basic_theme')}> + <View style={styles.list}> + { + themes.map(({ id, color, image }) => <ThemeItem key={id} color={color} image={image} id={id} setTheme={setThemeId} />) + } + </View> + </SubTitle> + ) +}) + +const styles = StyleSheet.create({ + list: { + flexDirection: 'row', + marginTop: 5, + }, + item: { + marginRight: 15, + alignItems: 'center', + width: 54, + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + colorContent: { + width: 32, + height: 32, + borderRadius: 4, + borderWidth: 1.6, + alignItems: 'center', + justifyContent: 'center', + }, + image: { + width: 26, + height: 26, + borderRadius: 4, + }, + name: { + marginTop: 2, + fontSize: 13, + }, +}) diff --git a/src/screens/Home/Setting/Basic/index.js b/src/screens/Home/Setting/Basic/index.js new file mode 100644 index 0000000..d979ed4 --- /dev/null +++ b/src/screens/Home/Setting/Basic/index.js @@ -0,0 +1,22 @@ +import React, { memo } from 'react' + +import Section from '../components/Section' +import Theme from './Theme' +import Source from './Source' +import SourceName from './SourceName' +import Language from './Language' +import { useTranslation } from '@/plugins/i18n' + +export default memo(() => { + const { t } = useTranslation() + + + return ( + <Section title={t('setting_basic')}> + <Theme /> + <Source /> + <Language /> + <SourceName /> + </Section> + ) +}) diff --git a/src/screens/Home/Setting/Other/Cache.js b/src/screens/Home/Setting/Other/Cache.js new file mode 100644 index 0000000..9a97a8d --- /dev/null +++ b/src/screens/Home/Setting/Other/Cache.js @@ -0,0 +1,70 @@ +import React, { memo, useCallback, useState, useEffect } from 'react' +import { StyleSheet, View, Text, InteractionManager } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +// import { gzip, ungzip } from 'pako' + +import SubTitle from '../components/SubTitle' +import Button from '../components/Button' +import { useTranslation } from '@/plugins/i18n' +import { toast } from '@/utils/tools' +import { getAppCacheSize, clearAppCache } from '@/utils/cache' +import { sizeFormate } from '@/utils' + +export default memo(() => { + const { t } = useTranslation() + const [cleaning, setCleaning] = useState(false) + const [cacheSize, setCacheSize] = useState(null) + // const setting = useGetter('common', 'setting') + const theme = useGetter('common', 'theme') + const clearCache = useDispatch('list', 'clearCache') + + const handleGetAppCacheSize = useCallback(() => { + getAppCacheSize().then(size => { + setCacheSize(sizeFormate(size)) + }) + }, []) + + const handleCleanCache = useCallback(() => { + if (cacheSize == null) return + setCleaning(true) + InteractionManager.runAfterInteractions(() => { + Promise.all([ + clearAppCache(), + clearCache(), + ]).then(() => { + toast(t('setting_other_cache_clear_success_tip')) + }).finally(() => { + handleGetAppCacheSize() + setCleaning(false) + }) + }) + }, [cacheSize, clearCache, handleGetAppCacheSize, t]) + + + useEffect(() => { + handleGetAppCacheSize() + }, []) + + return ( + <> + <SubTitle title={t('setting_other_cache')}> + <View style={styles.cacheSize}> + <Text style={{ color: theme.normal }}>{cacheSize == null ? t('setting_other_cache_getting') : t('setting_other_cache_size') + cacheSize}</Text> + </View> + <View style={styles.clearBtn}> + <Button disabled={cleaning} onPress={handleCleanCache}>{t('setting_other_cache_clear_btn')}</Button> + </View> + </SubTitle> + </> + ) +}) + +const styles = StyleSheet.create({ + cacheSize: { + marginBottom: 5, + }, + clearBtn: { + flexDirection: 'row', + }, +}) diff --git a/src/screens/Home/Setting/Other/index.js b/src/screens/Home/Setting/Other/index.js new file mode 100644 index 0000000..71fa21e --- /dev/null +++ b/src/screens/Home/Setting/Other/index.js @@ -0,0 +1,17 @@ +import React, { memo } from 'react' + +import Section from '../components/Section' +import Cache from './Cache' +// import MaxCache from './MaxCache' +import { useTranslation } from '@/plugins/i18n' + +export default memo(() => { + const { t } = useTranslation() + + return ( + <Section title={t('setting_other')}> + <Cache /> + {/* <MaxCache /> */} + </Section> + ) +}) diff --git a/src/screens/Home/Setting/Player/IsPlayHighQuality.js b/src/screens/Home/Setting/Player/IsPlayHighQuality.js new file mode 100644 index 0000000..fa52990 --- /dev/null +++ b/src/screens/Home/Setting/Player/IsPlayHighQuality.js @@ -0,0 +1,20 @@ +import React, { memo } from 'react' +import { View } from 'react-native' + +import { useGetter, useDispatch } from '@/store' + +import CheckBoxItem from '../components/CheckBoxItem' +import { useTranslation } from '@/plugins/i18n' + +export default memo(() => { + const { t } = useTranslation() + const isPlayHighQuality = useGetter('common', 'isPlayHighQuality') + const setIsPlayHighQuality = useDispatch('common', 'setIsPlayHighQuality') + + + return ( + <View style={{ marginTop: 5 }}> + <CheckBoxItem check={isPlayHighQuality} label={t('setting_play_quality')} onChange={setIsPlayHighQuality} /> + </View> + ) +}) diff --git a/src/screens/Home/Setting/Player/MaxCache.js b/src/screens/Home/Setting/Player/MaxCache.js new file mode 100644 index 0000000..9d5ec98 --- /dev/null +++ b/src/screens/Home/Setting/Player/MaxCache.js @@ -0,0 +1,40 @@ +import React, { memo, useMemo, useCallback } from 'react' +import { View } from 'react-native' + +import { useGetter, useDispatch } from '@/store' + +import InputItem from '../components/InputItem' +import { useTranslation } from '@/plugins/i18n' +import { toast } from '@/utils/tools' + +export default memo(() => { + const { t } = useTranslation() + const playerCacheSize = useGetter('common', 'playerCacheSize') + const setPlayerCacheSize = useDispatch('common', 'setPlayerCacheSize') + + const size = useMemo(() => { + let size = parseInt(playerCacheSize) + if (size == 0 || Number.isNaN(size)) size = '' + return size.toString() + }, [playerCacheSize]) + + const setSize = useCallback((value, callback) => { + let size = parseInt(value) + if (Number.isNaN(size)) size = 0 + callback(size) + if (playerCacheSize == size) return + setPlayerCacheSize(size) + toast(t('setting_play_cache_size_save_tip')) + }, [playerCacheSize, setPlayerCacheSize, t]) + + return ( + <View style={{ marginTop: 15 }} > + <InputItem + value={size} + label={t('setting_play_cache_size')} + onChange={setSize} + keyboardType="number-pad" + placeholder={t('setting_play_cache_size_no_cache')} /> + </View> + ) +}) diff --git a/src/screens/Home/Setting/Player/index.js b/src/screens/Home/Setting/Player/index.js new file mode 100644 index 0000000..053ef81 --- /dev/null +++ b/src/screens/Home/Setting/Player/index.js @@ -0,0 +1,51 @@ +import React, { memo, useMemo } from 'react' +import { + View, + Text, +} from 'react-native' + +import Section from '../components/Section' +import IsPlayHighQuality from './IsPlayHighQuality' +import MaxCache from './MaxCache' +import { useTranslation } from '@/plugins/i18n' + +import DorpDownMenu from '@/components/common/DorpDownMenu' +import { useGetter, useDispatch } from '@/store' + +const playNextModes = [ + { label: '列表循环', action: 'listLoop' }, + { label: '列表随机', action: 'random' }, + { label: '顺序播放', action: 'list' }, + { label: '单曲循环', action: 'singleLoop' }, +] + +export default memo(() => { + const { t } = useTranslation() + + // const [isShowModal, setIsShowModal] = useState(false) + // const hideDialog = useCallback(() => setIsShowModal(false), [setIsShowModal]) + const togglePlayMethod = useGetter('common', 'togglePlayMethod') + + const togglePlayMethodName = useMemo(() => { + const method = playNextModes.find(m => m.action == togglePlayMethod) + return method ? method.label : '未知' + }, [togglePlayMethod]) + const setPlayNextMode = useDispatch('common', 'setPlayNextMode') + // console.log(themeList) + // const handlePress = id => { + // setTheme(id) + // // console.log(AppColors) + // } + const handleToggleMethodPress = ({ action }) => setPlayNextMode(action) + + return ( + <Section title={t('setting_play')}> + <IsPlayHighQuality /> + <MaxCache /> + <View style={{ marginLeft: 15, marginBottom: 15 }}> + <Text>播放歌曲切换方式</Text> + <DorpDownMenu menus={playNextModes} onPress={handleToggleMethodPress}><Text style={{ padding: 10 }}>{togglePlayMethodName}</Text></DorpDownMenu> + </View> + </Section> + ) +}) diff --git a/src/screens/Home/Setting/Version.js b/src/screens/Home/Setting/Version.js new file mode 100644 index 0000000..4011dc5 --- /dev/null +++ b/src/screens/Home/Setting/Version.js @@ -0,0 +1,79 @@ +import React, { useMemo, memo, useState, useEffect } from 'react' +import { StyleSheet, View, Text } from 'react-native' + +import Section from './components/Section' +import SubTitle from './components/SubTitle' +import Button from './components/Button' +import { showVersionModal } from '@/navigation' + +import { useTranslation } from '@/plugins/i18n' +import { useGetter, useDispatch } from '@/store' +import { VERSION_STATUS } from '@/config/constant' + +const currentVer = process.versions.app +export default memo(() => { + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + const versionInfo = useGetter('common', 'versionInfo') + const setVersionInfo = useDispatch('common', 'setVersionInfo') + const [title, setTitle] = useState('') + const handleOpenVersionModal = () => { + setVersionInfo({ showModal: true }) + showVersionModal() + } + + useEffect(() => { + switch (versionInfo.status) { + case VERSION_STATUS.available: + setTitle(t('version_title_new')) + // setTip(t('version_btn_new')) + break + case VERSION_STATUS.downloading: + setTitle(t('version_title_new')) + break + case VERSION_STATUS.downloaded: + setTitle(t('version_title_update')) + break + case VERSION_STATUS.checking: + setTitle(t('version_title_checking')) + break + case VERSION_STATUS.failed: + setTitle(t('version_title_failed')) + break + case VERSION_STATUS.unknown: + setTitle(t('version_title_unknown')) + break + case VERSION_STATUS.latest: + default: + setTitle(t('version_tip_latest')) + break + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [t, versionInfo]) + + return ( + <Section title={t('setting_version')}> + <SubTitle title={title}> + <View style={styles.desc}> + <Text style={{ ...styles.label, color: theme.normal }}>{t('version_label_latest_ver')}{versionInfo.version}</Text> + <Text style={{ ...styles.label, color: theme.normal }}>{t('version_label_current_ver')}{currentVer}</Text> + </View> + <View style={styles.btn}> + <Button onPress={handleOpenVersionModal}>{t('setting_version_show_ver_modal')}</Button> + </View> + </SubTitle> + </Section> + ) +}) + +const styles = StyleSheet.create({ + desc: { + marginBottom: 5, + }, + label: { + fontSize: 14, + }, + btn: { + flexDirection: 'row', + }, +}) diff --git a/src/screens/Home/Setting/components/Button.js b/src/screens/Home/Setting/components/Button.js new file mode 100644 index 0000000..1e9f9a1 --- /dev/null +++ b/src/screens/Home/Setting/components/Button.js @@ -0,0 +1,31 @@ +import React, { memo } from 'react' + +import { StyleSheet, View, Text } from 'react-native' + +import Button from '@/components/common/Button' +import { useGetter } from '@/store' + + +export default memo(({ children, disabled, onPress }) => { + const theme = useGetter('common', 'theme') + + return ( + <Button style={{ ...styles.button, backgroundColor: theme.secondary40 }} onPress={onPress} disabled={disabled}> + <Text style={{ ...styles.text, color: theme.secondary_5 }}>{children}</Text> + </Button> + ) +}) + +const styles = StyleSheet.create({ + button: { + paddingLeft: 10, + paddingRight: 10, + paddingTop: 5, + paddingBottom: 5, + borderRadius: 4, + marginRight: 10, + }, + text: { + fontSize: 12, + }, +}) diff --git a/src/screens/Home/Setting/components/CheckBoxItem.js b/src/screens/Home/Setting/components/CheckBoxItem.js new file mode 100644 index 0000000..2c6c877 --- /dev/null +++ b/src/screens/Home/Setting/components/CheckBoxItem.js @@ -0,0 +1,22 @@ +import React, { memo } from 'react' + +import { StyleSheet, View } from 'react-native' + +import CheckBox from '@/components/common/CheckBox' + + +export default memo(({ check, label, onChange, disabled }) => { + return ( + <View style={styles.container}> + <CheckBox check={check} label={label} onChange={onChange} disabled={disabled} /> + </View> + ) +}) + +const styles = StyleSheet.create({ + container: { + paddingLeft: 25, + marginTop: -10, + marginBottom: -5, + }, +}) diff --git a/src/screens/Home/Setting/components/InputItem.js b/src/screens/Home/Setting/components/InputItem.js new file mode 100644 index 0000000..12fdae2 --- /dev/null +++ b/src/screens/Home/Setting/components/InputItem.js @@ -0,0 +1,53 @@ +import React, { memo, useState, useCallback, useEffect, useRef } from 'react' + +import { StyleSheet, View, Text } from 'react-native' +import { useGetter } from '@/store' +import Input from '@/components/common/Input' + + +export default memo(({ value, label, onChange, ...props }) => { + const [text, setText] = useState(value) + const isMountRef = useRef(false) + const theme = useGetter('common', 'theme') + const saveValue = useCallback(() => { + onChange && onChange(text, value => { + if (!isMountRef.current) return + setText(String(value)) + }) + }, [onChange, text]) + useEffect(() => { + isMountRef.current = true + return () => isMountRef.current = false + }) + return ( + <View style={styles.container}> + <Text style={{ ...styles.label, color: theme.normal }}>{label}</Text> + <Input + value={text} + onChangeText={setText} + style={{ ...styles.input, backgroundColor: theme.secondary40 }} + {...props} + onBlur={saveValue} + /> + </View> + ) +}) + +const styles = StyleSheet.create({ + container: { + paddingLeft: 25, + marginBottom: 15, + }, + label: { + fontSize: 12, + }, + input: { + backgroundColor: 'rgba(0,0,0,0.2)', + flexGrow: 1, + flexShrink: 1, + borderRadius: 4, + paddingTop: 2, + paddingBottom: 2, + fontSize: 12, + }, +}) diff --git a/src/screens/Home/Setting/components/Section.js b/src/screens/Home/Setting/components/Section.js new file mode 100644 index 0000000..057e4ec --- /dev/null +++ b/src/screens/Home/Setting/components/Section.js @@ -0,0 +1,32 @@ +import React, { memo } from 'react' + +import { StyleSheet, View, Text } from 'react-native' +import { useGetter } from '@/store' + +export default memo(({ title, children }) => { + const theme = useGetter('common', 'theme') + + return ( + <View style={styles.container}> + <Text style={{ ...styles.title, borderLeftColor: theme.secondary, color: theme.normal }}>{title}</Text> + <View> + {children} + </View> + </View> + ) +}) + + +const styles = StyleSheet.create({ + container: { + // paddingLeft: 10, + // backgroundColor: 'rgba(0,0,0,0.2)', + }, + title: { + borderLeftWidth: 5, + fontSize: 16, + paddingLeft: 10, + marginBottom: 10, + // lineHeight: 16, + }, +}) diff --git a/src/screens/Home/Setting/components/SubTitle.js b/src/screens/Home/Setting/components/SubTitle.js new file mode 100644 index 0000000..d2b528e --- /dev/null +++ b/src/screens/Home/Setting/components/SubTitle.js @@ -0,0 +1,29 @@ +import React, { memo } from 'react' + +import { StyleSheet, View, Text } from 'react-native' +import { useGetter } from '@/store' + +export default memo(({ title, children }) => { + const theme = useGetter('common', 'theme') + + return ( + <View style={styles.container}> + <Text style={{ ...styles.title, color: theme.normal }}>{title}</Text> + {children} + </View> + ) +}) + + +const styles = StyleSheet.create({ + container: { + paddingLeft: 25, + marginBottom: 20, + }, + title: { + fontSize: 14, + marginLeft: -10, + marginBottom: 10, + // lineHeight: 16, + }, +}) diff --git a/src/screens/Home/Setting/index.js b/src/screens/Home/Setting/index.js new file mode 100644 index 0000000..6a7514a --- /dev/null +++ b/src/screens/Home/Setting/index.js @@ -0,0 +1,46 @@ +import React from 'react' +import { + StyleSheet, + View, + ScrollView, +} from 'react-native' +// import { AppColors } from '@/theme' + +import Basic from './Basic' +import Player from './Player' +import Backup from './Backup' +import Other from './Other' +import Version from './Version' +import About from './About' + +const styles = StyleSheet.create({ + scrollView: { + }, + content: { + padding: 15, + flex: 0, + }, +}) + +export default () => { + return ( + <ScrollView style={styles.scrollView} keyboardShouldPersistTaps={'always'}> + <View style={styles.content}> + <Basic /> + <Player /> + <Backup /> + <Other /> + <Version /> + <About /> + {/* <Text>setting</Text> */} + {/* <View><Menu menus={[ + { name: '播放', id: '456' }, + { name: '删除', id: '432' }, + { name: '添加', id: '4561' }, + { name: '打开详情页', id: '4356' }, + { name: '移动', id: '4564' }, + ]}>123</Menu></View> */} + </View> + </ScrollView> + ) +} diff --git a/src/screens/Home/SongList/List/List.js b/src/screens/Home/SongList/List/List.js new file mode 100644 index 0000000..fa79aa3 --- /dev/null +++ b/src/screens/Home/SongList/List/List.js @@ -0,0 +1,128 @@ +import React, { useRef, useState, useEffect, useMemo, useCallback } from 'react' +import { Text, StyleSheet, FlatList, View } from 'react-native' + +import ListItem from './ListItem' +import LoadingMask from '@/components/common/LoadingMask' +import { useTranslation } from '@/plugins/i18n' +import { useDispatch, useGetter, subscribe } from '@/store' + +export default ({ width }) => { + const unSubscribeRef = useRef() + const initedRef = useRef(false) + const isLoading = useRef(false) + const [isListRefreshing, setIsListRefreshing] = useState(false) + const listInfo = useGetter('songList', 'listInfo') + const getList = useDispatch('songList', 'getList') + const setSelectListInfo = useDispatch('songList', 'setSelectListInfo') + const setVisibleListDetail = useDispatch('songList', 'setVisibleListDetail') + const theme = useGetter('common', 'theme') + const songListSource = useGetter('songList', 'songListSource') + const songListSortId = useGetter('songList', 'songListSortId') + const songListTagInfo = useGetter('songList', 'songListTagInfo') + const [page, setPage] = useState(0) + const { t } = useTranslation() + + useEffect(() => { + if (!initedRef.current) return + setPage(1) + getList({ page: 1 }) + }, [songListSource, songListSortId, songListTagInfo, getList]) + + useEffect(() => { + unSubscribeRef.current = subscribe('common.nav.navActiveIndex', () => { + if (!isListRefreshing) return + setIsListRefreshing(false) + }) + + setPage(1) + getList({ page: 1 }) + initedRef.current = true + return unSubscribeRef.current + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + + const handleListLoadMore = useCallback(() => { + if (listInfo.isLoading || listInfo.isEnd) return + isLoading.current = true + setPage(listInfo.page + 1) + getList({ page: listInfo.page + 1 }).finally(() => { + isLoading.current = false + }) + }, [getList, listInfo]) + + const handleListRefresh = useCallback(() => { + setIsListRefreshing(true) + setPage(1) + getList({ pahe: 1, isRefresh: true }).finally(() => { + setIsListRefreshing(false) + }) + }, [getList]) + + const handleListPress = useCallback((item, index) => { + // console.log(item) + setSelectListInfo(item) + setVisibleListDetail(true) + }, [setSelectListInfo, setVisibleListDetail]) + + const itemWidth = useMemo(() => Math.max(parseInt(width * 0.125), 110), [width]) + const rowNum = useMemo(() => Math.floor(width / itemWidth), [itemWidth, width]) + const list = useMemo(() => { + const list = [...listInfo.list] + let whiteItemNum = (list.length % rowNum) + if (whiteItemNum > 0) whiteItemNum = rowNum - whiteItemNum + for (let i = 0; i < whiteItemNum; i++) list.push({ id: `white__${i}` }) + return list + }, [listInfo, rowNum]) + // console.log(listInfo.list.map((item) => item.id)) + + const renderItem = useCallback(data => ( + <ListItem data={data} width={itemWidth} onPress={handleListPress} /> + ), [handleListPress, itemWidth]) + + const ListComponent = useMemo(() => <FlatList + style={styles.list} + columnWrapperStyle={{ justifyContent: 'space-evenly' }} + numColumns={rowNum} + data={list} + renderItem={renderItem} + keyExtractor={item => String(item.id)} + key={rowNum} + onRefresh={handleListRefresh} + refreshing={isListRefreshing} + onEndReached={handleListLoadMore} + // onEndReachedThreshold={0.5} + ListFooterComponent={ + listInfo.isEnd + ? null + : <View style={{ alignItems: 'center', padding: 10 }}><Text style={{ color: theme.normal30 }}>{t('loading')}</Text></View> + } + removeClippedSubviews={true} + />, [rowNum, list, renderItem, handleListRefresh, isListRefreshing, handleListLoadMore, listInfo, theme, t]) + + const visibleLoadingMask = useMemo(() => page == 1 && listInfo.isLoading, [listInfo.isLoading, page]) + + const loadingMaskmomponent = useMemo(() => ( + <LoadingMask visible={visibleLoadingMask} /> + ), [visibleLoadingMask]) + + // console.log('render song list') + return ( + <View style={styles.container}> + { width == 0 ? null : ListComponent} + { loadingMaskmomponent } + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + list: { + flex: 1, + paddingLeft: 10, + paddingRight: 10, + }, +}) + diff --git a/src/screens/Home/SongList/List/ListItem.js b/src/screens/Home/SongList/List/ListItem.js new file mode 100644 index 0000000..f1d8ea1 --- /dev/null +++ b/src/screens/Home/SongList/List/ListItem.js @@ -0,0 +1,57 @@ +import React, { memo } from 'react' +import { View, Text, Image, StyleSheet, Platform, TouchableOpacity } from 'react-native' +import { AppColors } from '@/theme' + +export default memo(({ data: { index, item }, width, onPress = () => {} }) => { + const handlePress = () => { + onPress(item, index) + } + return ( + item.source + ? ( + <View style={{ ...styles.listItem, width: width - 20 }}> + <View style={{ ...styles.listItemImg, backgroundColor: AppColors.primary }}> + <TouchableOpacity activeOpacity={0.5} onPress={handlePress}> + <Image source={{ uri: item.img }} style={{ width: width - 20, height: width - 20 }} borderRadius={4} /> + </TouchableOpacity> + </View> + <TouchableOpacity activeOpacity={0.5} onPress={handlePress}> + <Text style={{ ...styles.listItemTitle, color: AppColors.normal }} numberOfLines={ 2 }>{item.name}</Text> + </TouchableOpacity> + {/* <Text>{JSON.stringify(item)}</Text> */} + </View> + ) + : <View style={styles.listItem} /> + ) +}) + +const styles = StyleSheet.create({ + listItem: { + width: 90, + margin: 10, + }, + listItemImg: { + backgroundColor: '#eee', + borderRadius: 4, + marginBottom: 5, + ...Platform.select({ + ios: { + shadowColor: '#000', + shadowOffset: { + width: 0, + height: 1, + }, + shadowOpacity: 0.20, + shadowRadius: 1.41, + }, + android: { + elevation: 2, + }, + }), + }, + listItemTitle: { + fontSize: 12, + // overflow: 'hidden', + marginBottom: 5, + }, +}) diff --git a/src/screens/Home/SongList/List/MenuBar.js b/src/screens/Home/SongList/List/MenuBar.js new file mode 100644 index 0000000..41b0578 --- /dev/null +++ b/src/screens/Home/SongList/List/MenuBar.js @@ -0,0 +1,31 @@ +import React, { useCallback, useMemo } from 'react' +import { View, Text, StyleSheet } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import SourceSelector from './SourceSelector' +import SortTab from './SortTab' +import Tag from './Tag' +// import { BorderWidths } from '@/theme' + +export default () => { + const theme = useGetter('common', 'theme') + + return ( + <View style={{ ...styles.container }}> + <SortTab /> + <Tag /> + <SourceSelector /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + width: '100%', + flexGrow: 0, + flexShrink: 0, + // borderBottomWidth: BorderWidths.normal, + }, +}) + diff --git a/src/screens/Home/SongList/List/SortTab.js b/src/screens/Home/SongList/List/SortTab.js new file mode 100644 index 0000000..7e3a030 --- /dev/null +++ b/src/screens/Home/SongList/List/SortTab.js @@ -0,0 +1,77 @@ +import React, { memo, useMemo } from 'react' +import { StyleSheet, Text, View, ScrollView, TouchableOpacity } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' + + +export default memo(() => { + const setSongList = useDispatch('common', 'setSongList') + const sortList = useGetter('songList', 'sortList') + const songListSource = useGetter('songList', 'songListSource') + const songListSortId = useGetter('songList', 'songListSortId') + // const currentSourceName = useGetter('search', 'currentSourceName') + const theme = useGetter('common', 'theme') + const { t } = useTranslation() + + const sorts = useMemo(() => { + const list = songListSource ? [...sortList[songListSource]] : [] + // switch (songListSource) { + // case 'wy': + // case 'kw': + // case 'tx': + // case 'mg': + // case 'kg': + // list.push({ + // name: t('view.song_list.open_list', { name: sources.find(s => s.id == songListSource).name }), + // id: 'importSongList', + // }) + // } + return list.map(s => ({ label: t(`songlist_${s.tid}`), id: s.id })) + }, [songListSource, sortList, t]) + + + return ( + <ScrollView style={styles.container} keyboardShouldPersistTaps={'always'} horizontal={true}> + { + sorts.map(s => ( + <TouchableOpacity style={styles.button} onPress={() => setSongList({ sortId: s.id })} key={s.id}> + <Text style={{ ...styles.buttonText, color: songListSortId == s.id ? theme.secondary : theme.normal }}>{s.label}</Text> + </TouchableOpacity> + )) + } + </ScrollView> + // <DorpDownMenu + // menus={sorts} + // width={80} + // onPress={({ id }) => setSongList({ sortId: id })} + // > + // <Text style={styles.sourceMenu}>{currentSortName}</Text> + // </DorpDownMenu> + ) +}) + + +const styles = StyleSheet.create({ + container: { + flexGrow: 1, + flexShrink: 1, + paddingLeft: 5, + paddingRight: 5, + }, + button: { + // height: 38, + // lineHeight: 38, + // textAlign: 'center', + // width: 80, + // backgroundColor: 'rgba(0,0,0,0.1)', + }, + buttonText: { + height: 38, + lineHeight: 38, + textAlign: 'center', + paddingLeft: 15, + paddingRight: 15, + // width: 80, + }, +}) diff --git a/src/screens/Home/SongList/List/SourceSelector.js b/src/screens/Home/SongList/List/SourceSelector.js new file mode 100644 index 0000000..70f15ae --- /dev/null +++ b/src/screens/Home/SongList/List/SourceSelector.js @@ -0,0 +1,47 @@ +import React, { memo, useMemo, useCallback } from 'react' +import { StyleSheet, Text } from 'react-native' + +import DorpDownMenu from '@/components/common/DorpDownMenu' +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' + + +export default memo(() => { + const setSongList = useDispatch('common', 'setSongList') + const sources = useGetter('songList', 'sources') + const songListSource = useGetter('songList', 'songListSource') + // const currentSourceName = useGetter('search', 'currentSourceName') + const { t } = useTranslation() + const sortList = useGetter('songList', 'sortList') + const sourceNameType = useGetter('common', 'sourceNameType') + const theme = useGetter('common', 'theme') + + const sources_t = useMemo(() => { + return sources.map(s => ({ label: t(`source_${sourceNameType}_${s.id}`), action: s.id })) + }, [sourceNameType, sources, t]) + + const handleSetSource = useCallback(({ action }) => { + const sorts = sortList[action] + setSongList({ source: action, sortId: sorts ? sorts[0].id : '', tagInfo: { name: '默认', id: null } }) + }, [setSongList, sortList]) + + return ( + <DorpDownMenu + menus={sources_t} + width={80} + onPress={handleSetSource} + > + <Text style={{ ...styles.sourceMenu, color: theme.normal }}>{t(`source_${sourceNameType}_${songListSource}`)}</Text> + </DorpDownMenu> + ) +}) + + +const styles = StyleSheet.create({ + sourceMenu: { + height: 38, + lineHeight: 38, + textAlign: 'center', + width: 80, + }, +}) diff --git a/src/screens/Home/SongList/List/Tag.js b/src/screens/Home/SongList/List/Tag.js new file mode 100644 index 0000000..9e68e7d --- /dev/null +++ b/src/screens/Home/SongList/List/Tag.js @@ -0,0 +1,127 @@ +import React, { memo, useMemo, useEffect, useCallback, useState } from 'react' +import { StyleSheet, Text, View, ScrollView } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +// import { useTranslation } from '@/plugins/i18n' +import DorpDownPanel from '@/components/common/DorpDownPanel' +import Button from '@/components/common/Button' +import { BorderWidths } from '@/theme' + +const TagType = ({ name, list, setTagInfo, activeId }) => { + const theme = useGetter('common', 'theme') + return ( + <View> + <Text style={{ ...styles.tagTypeTitle, color: theme.normal30 }}>{name}</Text> + <View style={styles.tagTypeList}> + {list.map(item => ( + <Button style={{ ...styles.tagButton, backgroundColor: theme.secondary45 }} key={item.id} onPress={() => setTagInfo(item.name, item.id)}> + <Text style={{ ...styles.tagButtonText, color: activeId == item.id ? theme.secondary : theme.normal10 }}>{item.name}</Text> + </Button> + ))} + </View> + </View> + ) +} + +const Tags = memo(({ setVisiblePanel }) => { + const theme = useGetter('common', 'theme') + const tags = useGetter('songList', 'tags') + const songListSource = useGetter('songList', 'songListSource') + const setSongList = useDispatch('common', 'setSongList') + const songListTagInfo = useGetter('songList', 'songListTagInfo') + // console.log('render') + const tagsList = useMemo(() => { + let tagInfo = tags[songListSource] + return tagInfo ? [{ name: '热门', list: [...tagInfo.hotTag] }, ...tagInfo.tags] : [] + }, [songListSource, tags]) + const setTagInfo = useCallback((name, id) => { + setVisiblePanel(false) + setSongList({ tagInfo: { name, id } }) + }, [setSongList, setVisiblePanel]) + return ( + <View style={{ ...styles.container, borderBottomColor: theme.secondary10 }}> + <ScrollView style={{ flexShrink: 1, flexGrow: 0 }} keyboardShouldPersistTaps={'always'}> + <View style={{ ...styles.tagContainer, backgroundColor: theme.primary }} onStartShouldSetResponder={() => true}> + <View style={{ ...styles.tagTypeList, marginTop: 10 }}> + <Button style={{ ...styles.tagButton, backgroundColor: theme.secondary45 }} onPress={() => setTagInfo('默认', null)}> + <Text style={{ ...styles.tagButtonText, color: songListTagInfo.id == null ? theme.secondary : theme.normal10 }}>默认</Text> + </Button> + </View> + {tagsList.map((type, index) => <TagType key={index} name={type.name} list={type.list} activeId={songListTagInfo.id} setTagInfo={setTagInfo} />)} + </View> + </ScrollView> + </View> + ) +}) + + +export default memo(() => { + const songListSource = useGetter('songList', 'songListSource') + const songListTagInfo = useGetter('songList', 'songListTagInfo') + // const currentSourceName = useGetter('search', 'currentSourceName') + const theme = useGetter('common', 'theme') + const getTags = useDispatch('songList', 'getTags') + const [visiblePanel, setVisiblePanel] = useState(false) + + // useEffect(() => { + // getTags() + // // eslint-disable-next-line react-hooks/exhaustive-deps + // }, []) + useEffect(() => { + getTags() + }, [getTags, songListSource]) + + + // console.log('render tags') + + return ( + <DorpDownPanel + visible={visiblePanel} + setVisible={setVisiblePanel} + PanelContent={<Tags setVisiblePanel={setVisiblePanel} />} + > + <Text style={{ ...styles.sourceMenu, color: theme.normal }}>{songListTagInfo.name}</Text> + </DorpDownPanel> + ) +}) + + +const styles = StyleSheet.create({ + sourceMenu: { + height: 38, + lineHeight: 38, + textAlign: 'center', + minWidth: 70, + paddingLeft: 10, + paddingRight: 10, + }, + + container: { + borderBottomWidth: BorderWidths.normal2, + }, + tagContainer: { + paddingLeft: 15, + paddingBottom: 15, + }, + tagTypeTitle: { + marginTop: 15, + marginBottom: 10, + }, + tagTypeList: { + flexDirection: 'row', + flexWrap: 'wrap', + }, + tagButton: { + // marginRight: 10, + borderRadius: 4, + marginRight: 10, + marginBottom: 10, + }, + tagButtonText: { + fontSize: 13, + paddingLeft: 12, + paddingRight: 12, + paddingTop: 8, + paddingBottom: 8, + }, +}) diff --git a/src/screens/Home/SongList/List/index.js b/src/screens/Home/SongList/List/index.js new file mode 100644 index 0000000..519ba6a --- /dev/null +++ b/src/screens/Home/SongList/List/index.js @@ -0,0 +1,25 @@ +import React from 'react' +import { StyleSheet, View } from 'react-native' + +import List from './List' +import MenuBar from './MenuBar' + +import { useLayout } from '@/utils/hooks' + +export default () => { + const { onLayout, ...layout } = useLayout() + return ( + <View style={styles.container} onLayout={onLayout}> + <MenuBar /> + <List width={layout.width} /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + position: 'relative', + flex: 1, + }, +}) + diff --git a/src/screens/Home/SongList/ListDetail/ButtonBar.js b/src/screens/Home/SongList/ListDetail/ButtonBar.js new file mode 100644 index 0000000..5da13e0 --- /dev/null +++ b/src/screens/Home/SongList/ListDetail/ButtonBar.js @@ -0,0 +1,84 @@ +import React, { useCallback, memo } from 'react' +import { View, Text, StyleSheet } from 'react-native' +import Button from '@/components/common/Button' + +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' +import { toast } from '@/utils/tools' +import { LIST_ID_PLAY_TEMP } from '@/config/constant' + +export default memo(() => { + const selectListInfo = useGetter('songList', 'selectListInfo') + const listDetailData = useGetter('songList', 'listDetailData') + const setPlayList = useDispatch('player', 'setList') + const setVisibleListDetail = useDispatch('songList', 'setVisibleListDetail') + const getListDetailAll = useDispatch('songList', 'getListDetailAll') + const createUserList = useDispatch('list', 'createUserList') + const { t } = useTranslation() + const theme = useGetter('common', 'theme') + + const handlePlayAll = useCallback(async() => { + if (!listDetailData.info.name) return + const list = await getListDetailAll(selectListInfo.id) + setPlayList({ + list: { + list, + id: LIST_ID_PLAY_TEMP, + }, + index: 0, + }) + }, [getListDetailAll, listDetailData.info, selectListInfo.id, setPlayList]) + + const handleCollection = useCallback(async() => { + if (!listDetailData.info.name) return + const list = await getListDetailAll(selectListInfo.id) + createUserList({ + name: listDetailData.info.name, + id: `${listDetailData.source}__${listDetailData.id}`, + list, + source: listDetailData.source, + sourceListId: listDetailData.id, + isShowToast: true, + }) + toast(t('collect_success')) + }, [listDetailData, getListDetailAll, selectListInfo.id, createUserList, t]) + + const handleBack = () => setVisibleListDetail(false) + + return ( + <View style={styles.container}> + <Button onPress={handleCollection} style={styles.controlBtn}> + <Text style={{ ...styles.controlBtnText, color: theme.secondary }}>{t('collect_songlist')}</Text> + </Button> + <Button onPress={handlePlayAll} style={styles.controlBtn}> + <Text style={{ ...styles.controlBtnText, color: theme.secondary }}>{t('play_all')}</Text> + </Button> + <Button onPress={handleBack} style={styles.controlBtn}> + <Text style={{ ...styles.controlBtnText, color: theme.secondary }}>{t('back')}</Text> + </Button> + </View> + ) +}) + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + width: '100%', + flexGrow: 0, + flexShrink: 0, + }, + controlBtn: { + flexGrow: 1, + flexShrink: 1, + width: '33%', + paddingTop: 12, + paddingBottom: 12, + paddingLeft: 10, + paddingRight: 10, + }, + controlBtnText: { + fontSize: 13, + textAlign: 'center', + }, +}) + diff --git a/src/screens/Home/SongList/ListDetail/Header.js b/src/screens/Home/SongList/ListDetail/Header.js new file mode 100644 index 0000000..8bc1063 --- /dev/null +++ b/src/screens/Home/SongList/ListDetail/Header.js @@ -0,0 +1,71 @@ +import React, { memo } from 'react' +import { View, Text, StyleSheet, ImageBackground } from 'react-native' +import { AppColors, BorderWidths } from '@/theme' +import { useGetter } from '@/store' +import ButtonBar from './ButtonBar' + +const Header = memo(() => { + const selectListInfo = useGetter('songList', 'selectListInfo') + const { info: listDetailDataInfo = {} } = useGetter('songList', 'listDetailData') + const playCount = selectListInfo.play_count || listDetailDataInfo.play_count + + return ( + <View style={{ ...styles.container, borderBottomColor: AppColors.borderColor }}> + <View style={{ flexDirection: 'row', flexGrow: 0, flexShrink: 0, padding: 10 }}> + <View style={{ ...styles.listItemImg, backgroundColor: AppColors.primary }}> + <ImageBackground source={{ uri: selectListInfo.img || listDetailDataInfo.img || null }} borderRadius={4} style={{ flex: 1, resizeMode: 'cover', justifyContent: 'flex-end' }}> + { + playCount + ? <Text style={{ fontSize: 12, paddingLeft: 3, paddingRight: 3, backgroundColor: 'rgba(0, 0, 0, 0.5)', color: AppColors.primary, borderBottomLeftRadius: 4, borderBottomRightRadius: 4 }} numberOfLines={ 1 }>{playCount}</Text> + : null + } + </ImageBackground> + </View> + <View style={{ flexDirection: 'column', flexGrow: 1, flexShrink: 1, paddingLeft: 5 }}> + <Text style={{ fontSize: 13, color: AppColors.normal }} numberOfLines={ 1 }>{selectListInfo.name || listDetailDataInfo.name}</Text> + <View style={{ flexGrow: 0, flexShrink: 1 }}> + <Text style={{ fontSize: 10, color: AppColors.normal40 }} numberOfLines={ 4 }>{selectListInfo.desc || listDetailDataInfo.desc}</Text> + </View> + </View> + </View> + <ButtonBar /> + {/* <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}> + <View style={{ flexGrow: 0, flexShrink: 1, paddingTop: 5, paddingRight: 5 }}> + <Text style={{ fontSize: 12, color: AppColors.normal20 }} numberOfLines={ 1 }>{playCount || '-'}</Text> + <Text style={{ fontSize: 12, color: AppColors.normal30 }} numberOfLines={ 1 }>{this.props.selectListInfo.author || this.props.listDetailData.info.author}</Text> + </View> + </View> */} + </View> + ) +}) + +const styles = StyleSheet.create({ + container: { + flexDirection: 'column', + flexWrap: 'nowrap', + borderBottomWidth: BorderWidths.normal, + }, + listItemImg: { + backgroundColor: '#eee', + flexGrow: 0, + flexShrink: 0, + width: 70, + height: 70, + // ...Platform.select({ + // ios: { + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 1, + // }, + // shadowOpacity: 0.20, + // shadowRadius: 1.41, + // }, + // android: { + // elevation: 2, + // }, + // }), + }, +}) + +export default Header diff --git a/src/screens/Home/SongList/ListDetail/List.js b/src/screens/Home/SongList/ListDetail/List.js new file mode 100644 index 0000000..b8af1e9 --- /dev/null +++ b/src/screens/Home/SongList/ListDetail/List.js @@ -0,0 +1,42 @@ +import React, { useState, useCallback, useRef } from 'react' +// import { View, Text, StyleSheet, Animated, FlatList, ImageBackground } from 'react-native' +import ListDetailHeader from './Header' +import { useGetter, useDispatch } from '@/store' +import OnlineList from '@/components/OnlineList' + + +export default ({ animatePlayed }) => { + const [isListRefreshing, setIsListRefreshing] = useState(false) + const isVisibleListDetail = useGetter('songList', 'isVisibleListDetail') + + const selectListInfo = useGetter('songList', 'selectListInfo') + const selectListInfoRef = useRef(selectListInfo) + const listDetailData = useGetter('songList', 'listDetailData') + const getListDetail = useDispatch('songList', 'getListDetail') + + const handleListLoadMore = useCallback(() => { + // console.log(listDetailData) + if (listDetailData.isLoading || listDetailData.isEnd) return + getListDetail({ id: selectListInfoRef.current.id, page: listDetailData.page + 1 }) + }, [getListDetail, listDetailData]) + + const handleListRefresh = useCallback(() => { + setIsListRefreshing(true) + getListDetail({ id: selectListInfoRef.current.id, page: 1, isRefresh: true }).finally(() => { + setIsListRefreshing(false) + }) + }, [getListDetail]) + + return ( + <OnlineList + list={isVisibleListDetail && animatePlayed ? listDetailData.list : []} + page={-1} + // isEnd={listDetailData.isEnd} + isListRefreshing={isListRefreshing} + onRefresh={handleListRefresh} + onLoadMore={handleListLoadMore} + isLoading={listDetailData.isLoading} + ListHeaderComponent={<ListDetailHeader />} + /> + ) +} diff --git a/src/screens/Home/SongList/ListDetail/index.js b/src/screens/Home/SongList/ListDetail/index.js new file mode 100644 index 0000000..4dc8d0a --- /dev/null +++ b/src/screens/Home/SongList/ListDetail/index.js @@ -0,0 +1,137 @@ +import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react' +import { StyleSheet, Animated } from 'react-native' +import List from './List' +// import { requestStoragePermission } from '@/utils/common' +import { useGetter, useDispatch } from '@/store' + + +export default () => { + // const isGetDetailFailedRef = useRef(false) + const [visible, setVisible] = useState(false) + const [animatePlayed, setAnimatPlayed] = useState(true) + const animFade = useRef(new Animated.Value(0)).current + const animScale = useRef(new Animated.Value(0)).current + + const theme = useGetter('common', 'theme') + const isVisibleListDetail = useGetter('songList', 'isVisibleListDetail') + const selectListInfo = useGetter('songList', 'selectListInfo') + const getListDetail = useDispatch('songList', 'getListDetail') + + useEffect(() => { + setAnimatPlayed(true) + if (isVisibleListDetail) { + animFade.setValue(1) + animScale.setValue(1) + setVisible(true) + } else { + animFade.setValue(0) + animScale.setValue(0) + setVisible(false) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const handleGetListDetail = useCallback((id, page) => { + // isGetDetailFailedRef.current = false + return getListDetail({ id, page }).catch(err => { + // isGetDetailFailedRef.current = true + return Promise.reject(err) + }) + }, [getListDetail]) + + const showList = useCallback(() => { + // console.log('show List') + if (selectListInfo.id) { + handleGetListDetail(selectListInfo.id, 1) + } + setVisible(true) + setAnimatPlayed(false) + animScale.setValue(1.2) + + Animated.parallel([ + Animated.timing(animFade, { + toValue: 1, + duration: 200, + useNativeDriver: true, + }), + Animated.timing(animScale, { + toValue: 1, + duration: 200, + useNativeDriver: true, + }), + ]).start(() => { + setAnimatPlayed(true) + }) + }, [animFade, animScale, handleGetListDetail, selectListInfo]) + + const hideList = useCallback(() => { + setAnimatPlayed(false) + Animated.parallel([ + Animated.timing(animFade, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }), + // Animated.timing(this.state.animates.translateY, { + // toValue: 20, + // duration: time, + // useNativeDriver: true, + // }), + // Animated.timing(animFade, { + // toValue: 0.8, + // duration: time, + // useNativeDriver: true, + // }), + ]).start(finished => { + if (!finished) return + setVisible(false) + setAnimatPlayed(true) + }) + }, [animFade]) + + useEffect(() => { + if (isVisibleListDetail) { + showList() + } else { + hideList() + } + }, [hideList, isVisibleListDetail, showList]) + + + const animaStyle = useMemo(() => StyleSheet.compose(styles.container, { + backgroundColor: theme.primary, + opacity: animFade, // Bind opacity to animated value + transform: [ + { scale: animScale }, + // { translateY: this.state.animates.translateY }, + ], + }), [animFade, animScale, theme.primary]) + + const ListComponent = useMemo(() => ( + <Animated.View style={animaStyle}> + <List animatePlayed={animatePlayed} /> + {/* <View style={{ flexDirection: 'row', width: '100%', flexGrow: 0, flexShrink: 0, borderTopWidth: BorderWidths.normal, borderTopColor: AppColors.borderColor }}> + <Button onPress={this.handleCollection} style={{ ...styles.controlBtn }}><Text style={{ ...styles.controlBtnText, color: AppColors.normal }}>收藏</Text></Button> + <Button onPress={this.handlePlayAll} style={{ ...styles.controlBtn }}><Text style={{ ...styles.controlBtnText, color: AppColors.normal }}>播放</Text></Button> + <Button onPress={this.handleBack} style={{ ...styles.controlBtn }}><Text style={{ ...styles.controlBtnText, color: AppColors.normal }}>返回</Text></Button> + </View> */} + </Animated.View> + ), [animaStyle, animatePlayed]) + + return !visible && animatePlayed ? null : ListComponent +} + +const styles = StyleSheet.create({ + container: { + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + flexDirection: 'column', + }, + list: { + flexGrow: 1, + flexShrink: 1, + }, +}) diff --git a/src/screens/Home/SongList/index.js b/src/screens/Home/SongList/index.js new file mode 100644 index 0000000..fc007e3 --- /dev/null +++ b/src/screens/Home/SongList/index.js @@ -0,0 +1,25 @@ +import React from 'react' +import { StyleSheet, View } from 'react-native' + +import List from './List' +import ListDetail from './ListDetail' + +const SongList = () => { + return ( + <View style={styles.container}> + <List /> + <ListDetail /> + </View> + ) +} + + +const styles = StyleSheet.create({ + container: { + position: 'relative', + flex: 1, + }, +}) + +export default SongList + diff --git a/src/screens/Home/Top/BoardsList.js b/src/screens/Home/Top/BoardsList.js new file mode 100644 index 0000000..394bc24 --- /dev/null +++ b/src/screens/Home/Top/BoardsList.js @@ -0,0 +1,77 @@ +import React, { memo, useMemo, useEffect } from 'react' +import { StyleSheet, View, Text, ScrollView } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import Button from '@/components/common/Button' +// import { useTranslation } from '@/plugins/i18n' + + +export default memo(() => { + const theme = useGetter('common', 'theme') + const setTop = useDispatch('common', 'setTop') + const getBoardsList = useDispatch('top', 'getBoardsList') + const boards = useGetter('top', 'boards') + const sourceId = useGetter('top', 'sourceId') + const tabId = useGetter('top', 'tabId') + // const { t } = useTranslation() + + useEffect(() => { + const list = boards[sourceId] + if (list.length && !list.some(b => b.id == tabId)) { + setTop({ tabId: list[0].id }) + } + }, [boards]) + + useEffect(() => { + let list = boards[sourceId] + if (list.length) { + setTop({ tabId: list[0].id }) + return + } + getBoardsList().then(() => { + list = boards[sourceId] + setTop({ tabId: list.length ? list[0].id : null }) + }) + }, [sourceId]) + + const list = useMemo(() => sourceId ? [...boards[sourceId]] : [], [boards, sourceId]) + + return ( + <View style={styles.container}> + <ScrollView style={styles.scrollView} keyboardShouldPersistTaps={'always'}> + <View style={styles.list}> + { + list.map(item => ( + <Button style={styles.button} key={item.id} onPress={() => setTop({ tabId: item.id })}> + <Text style={{ ...styles.buttonText, color: tabId == item.id ? theme.secondary : theme.normal }} numberOfLines={1}>{item.name}</Text> + </Button> + )) + } + </View> + </ScrollView> + </View> + ) +}) + + +const styles = StyleSheet.create({ + container: { + flexGrow: 1, + flexShrink: 1, + }, + scrollView: { + flexShrink: 1, + }, + list: { + + }, + button: { + paddingLeft: 10, + paddingRight: 10, + paddingTop: 10, + paddingBottom: 10, + }, + buttonText: { + fontSize: 12, + }, +}) diff --git a/src/screens/Home/Top/LeftBar.js b/src/screens/Home/Top/LeftBar.js new file mode 100644 index 0000000..3dbde3d --- /dev/null +++ b/src/screens/Home/Top/LeftBar.js @@ -0,0 +1,32 @@ +import React, { useCallback, useMemo } from 'react' +import { View, Text, StyleSheet } from 'react-native' + +import { useGetter, useDispatch } from '@/store' +import SourceSelector from './SourceSelector' +import BoardsList from './BoardsList' +import { BorderWidths } from '@/theme' +import { useLayout } from '@/utils/hooks' + + +export default () => { + const theme = useGetter('common', 'theme') + const { onLayout, ...layout } = useLayout() + + return ( + <View style={{ ...styles.container, borderRightColor: theme.borderColor }} onLayout={onLayout}> + <SourceSelector layout={layout} /> + <BoardsList /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'column', + width: '26%', + flexGrow: 0, + flexShrink: 0, + borderRightWidth: BorderWidths.normal, + }, +}) + diff --git a/src/screens/Home/Top/MusicList.js b/src/screens/Home/Top/MusicList.js new file mode 100644 index 0000000..1969929 --- /dev/null +++ b/src/screens/Home/Top/MusicList.js @@ -0,0 +1,74 @@ +import React, { useState, useCallback, memo, useEffect, useMemo } from 'react' +import { InteractionManager } from 'react-native' +import { useGetter, useDispatch } from '@/store' +import OnlineList from '@/components/OnlineList' + +export default memo(() => { + const [isListRefreshing, setIsListRefreshing] = useState(false) + const [visibleLoadingMask, setVisibleLoadingMask] = useState(false) + const listInfo = useGetter('top', 'listInfo') + const isLoading = useGetter('top', 'isLoading') + const isEnd = useGetter('top', 'isEnd') + const getList = useDispatch('top', 'getList') + const tabId = useGetter('top', 'tabId') + const [page, setPage] = useState(0) + // const getListAll = useDispatch('top', 'getListAll') + // console.log(isLoading) + + const handleRefresh = useCallback(() => { + setIsListRefreshing(true) + setVisibleLoadingMask(true) + setPage(1) + getList({ page: 1, isRefresh: true }).finally(() => { + setVisibleLoadingMask(false) + setIsListRefreshing(false) + }) + }, [getList]) + + const handleLoadMore = useCallback(() => { + if (isLoading || isEnd) return + setPage(listInfo.page + 1) + getList({ page: listInfo.page + 1 }) + }, [isLoading, isEnd, getList, listInfo.page]) + + // useEffect(() => { + // console.log(tabId) + // InteractionManager.runAfterInteractions(() => { + // getList({ page: 1 }).finally(() => { + // setIsListRefreshing(false) + // }) + // }) + // }, [getList]) + + useEffect(() => { + InteractionManager.runAfterInteractions(() => { + setVisibleLoadingMask(true) + setPage(1) + getList({ page: 1 }).finally(() => { + setVisibleLoadingMask(false) + setIsListRefreshing(false) + }) + }) + }, [getList, tabId]) + + const visible = useMemo(() => isLoading && visibleLoadingMask, [isLoading, visibleLoadingMask]) + + const listComponent = useMemo(() => { + return ( + <OnlineList + list={listInfo.list} + isEnd={isEnd} + page={page} + isListRefreshing={isListRefreshing} + onRefresh={handleRefresh} + onLoadMore={handleLoadMore} + // progressViewOffset={20} + visibleLoadingMask={visible} + isLoading={isLoading} + /> + ) + }, [handleLoadMore, handleRefresh, isEnd, isListRefreshing, isLoading, listInfo.list, page, visible]) + + return listComponent +}) + diff --git a/src/screens/Home/Top/SourceSelector.js b/src/screens/Home/Top/SourceSelector.js new file mode 100644 index 0000000..7631b42 --- /dev/null +++ b/src/screens/Home/Top/SourceSelector.js @@ -0,0 +1,42 @@ +import React, { memo, useMemo } from 'react' +import { StyleSheet, Text } from 'react-native' + +import DorpDownMenu from '@/components/common/DorpDownMenu' +import { useGetter, useDispatch } from '@/store' +import { useTranslation } from '@/plugins/i18n' + + +export default memo(({ layout }) => { + const setTop = useDispatch('common', 'setTop') + const sourceNameType = useGetter('common', 'sourceNameType') + const sourceList = useGetter('top', 'sources') + const sourceId = useGetter('top', 'sourceId') + // const currentSourceName = useGetter('search', 'currentSourceName') + const { t } = useTranslation() + + const sourceList_t = useMemo(() => { + return sourceList.map(s => ({ label: t(`source_${sourceNameType}_${s.id}`), action: s.id })) + }, [sourceNameType, sourceList, t]) + + return ( + <DorpDownMenu + menus={sourceList_t} + width={layout.width} + onPress={({ action }) => setTop({ source: action })} + > + <Text style={styles.sourceMenu}>{t(`source_${sourceNameType}_${sourceId}`)}</Text> + </DorpDownMenu> + ) +}) + + +const styles = StyleSheet.create({ + sourceMenu: { + height: 38, + lineHeight: 38, + paddingLeft: 10, + paddingRight: 10, + // textAlign: 'center', + // width: 80, + }, +}) diff --git a/src/screens/Home/Top/index.js b/src/screens/Home/Top/index.js new file mode 100644 index 0000000..245ac0b --- /dev/null +++ b/src/screens/Home/Top/index.js @@ -0,0 +1,26 @@ +import React, { useCallback, useRef } from 'react' +import { StyleSheet, View } from 'react-native' + +import MusicList from './MusicList' +import LeftBar from './LeftBar' + + +export default () => { + return ( + <View style={styles.container}> + <LeftBar /> + <MusicList /> + </View> + ) +} + +const styles = StyleSheet.create({ + container: { + width: '100%', + flex: 1, + flexDirection: 'row', + }, + content: { + flex: 1, + }, +}) diff --git a/src/screens/Home/components/Aside.js b/src/screens/Home/components/Aside.js new file mode 100644 index 0000000..f25cf6b --- /dev/null +++ b/src/screens/Home/components/Aside.js @@ -0,0 +1,172 @@ +import React, { Component } from 'react' +import { View, StyleSheet, ScrollView, Dimensions } from 'react-native' +import Icon from '@/components/common/Icon' +import Button from '@/components/common/Button' + +import { STATUS } from '@/store/modules/player' + +import { connect } from '@/store' + +import { AppColors, BorderWidths } from '@/theme' + +import PlayerPortrait from './PlayerPortrait' +import PlayerLandscape from './PlayerLandscape' + +const playNextModes = [ + 'listLoop', + 'random', + 'list', + 'singleLoop', +] + +const mapStateToProps = state => ({ + homeViewPageIndex: state.common.nav.homeViewPageIndex, + common: state.common, + player: state.player, +}) + +const actions = [ + ['common', ['updateNavHomeViewPageIndex', 'setPlayNextMode']], + ['player', ['playPrev', 'playNext', 'pauseMusic', 'playMusic']], +] + +let timeout + +class Header extends Component { + state = { + menu: [ + { + icon: 'search-2', + name: '搜索', + }, + { + icon: 'album', + name: '歌单', + }, + // { + // icon: 'leaderboard', + // name: '榜单', + // }, + { + icon: 'love', + name: '收藏', + }, + // { + // icon: 'download-2', + // name: '下载', + // }, + { + icon: 'setting', + name: '设置', + }, + ], + asideWidth: 40, + orientation: 'portrait', + } + + componentDidMount() { + const window = Dimensions.get('window') + this.setState({ + orientation: window.width > window.height ? 'landscape' : 'portrait', + }) + } + + handleLayout = event => { + const { width } = event.nativeEvent.layout + const window = Dimensions.get('window') + + this.setState({ + asideWidth: width, + orientation: window.width > window.height ? 'landscape' : 'portrait', + }) + } + + toggleNextPlayMode = () => { + let index = playNextModes.indexOf(this.props.common.setting.player.togglePlayMethod) + if (++index >= playNextModes.length) index = -1 + this.props.actions.setPlayNextMode(playNextModes[index] || '') + } + + handlePress = (item, index) => { + // console.log(item) + this.props.actions.updateNavHomeViewPageIndex(index) + // console.log(this.props.homeViewPageIndex) + } + + render() { + let targetMusic = this.props.player.listInfo.list[this.props.player.playIndex] + if (timeout) { + clearInterval(timeout) + timeout = null + } + if (!targetMusic) { + targetMusic = { + img: null, + name: '~v~', + singer: '~', + } + } + // if (!targetMusic.img) { + // timeout = setInterval(() => { + // let musicInfo = this.props.player.listInfo.list[this.props.player.playIndex] + // if (musicInfo.img) { + // musicInfo.img + // } + // }, 1000) + // } + + let playModeIcon = null + switch (this.props.common.setting.player.togglePlayMethod) { + case 'listLoop': + playModeIcon = 'list-loop' + break + case 'random': + playModeIcon = 'list-random' + break + case 'list': + playModeIcon = 'list-order' + break + case 'singleLoop': + playModeIcon = 'single-loop' + break + default: + playModeIcon = 'single' + break + } + + let playIcon = this.props.player.status === STATUS.playing ? 'pause' : 'play' + // console.log(this.state.orientation) + + const playerProps = { + asideWidth: this.state.asideWidth, + targetMusic, + playIcon, + playModeIcon, + actions: this.props.actions, + menu: this.state.menu, + homeViewPageIndex: this.props.homeViewPageIndex, + togglePlay: () => { + switch (this.props.player.status) { + case STATUS.playing: + this.props.actions.pauseMusic() + break + case STATUS.pause: + this.props.actions.playMusic() + break + default: + this.props.actions.playMusic(this.props.player.playIndex) + break + } + }, + toggleNextPlayMode: () => { + this.toggleNextPlayMode() + }, + } + + return this.state.orientation == 'portrait' + ? <PlayerPortrait {...playerProps} onLayout={this.handleLayout} navPress={this.handlePress} /> + : <PlayerLandscape {...playerProps} onLayout={this.handleLayout} navPress={this.handlePress} /> + } +} + +export default connect(mapStateToProps, actions)(Header) diff --git a/src/screens/Home/components/FooterPlayer.js b/src/screens/Home/components/FooterPlayer.js new file mode 100644 index 0000000..b954b93 --- /dev/null +++ b/src/screens/Home/components/FooterPlayer.js @@ -0,0 +1,11 @@ +import React from 'react' +import PlayerPortrait from './PlayerPortrait' + +const playNextModes = [ + 'listLoop', + 'random', + 'list', + 'singleLoop', +] + +export default () => <PlayerPortrait playNextModes={playNextModes} /> diff --git a/src/screens/Home/components/Header.js b/src/screens/Home/components/Header.js new file mode 100644 index 0000000..a6ec57d --- /dev/null +++ b/src/screens/Home/components/Header.js @@ -0,0 +1,101 @@ +import React, { useMemo } from 'react' +import { View, Text, StyleSheet, SafeAreaView, StatusBar, TouchableOpacity } from 'react-native' +// import Button from '@/components/common/Button' +import Icon from '@/components/common/Icon' +import { useGetter, useDispatch } from '@/store' +// import { navigations } from '@/navigation' + +const useActive = index => { + const activeIndex = useGetter('common', 'navActiveIndex') + return index === activeIndex +} + +const HeaderItem = ({ info, index, onPress }) => { + const theme = useGetter('common', 'theme') + const isActive = useActive(index) + // console.log(theme) + const components = useMemo(() => ( + <TouchableOpacity style={styles.btn} onPress={() => !isActive && onPress(index)}> + <Icon name={info.icon} style={{ ...styles.icon, color: isActive ? theme.secondary : theme.normal10 }} size={18} /> + {/* <Text style={{ ...style.btnText, color: isActive ? theme.secondary : theme.normal10 }}>{info.name}</Text> */} + </TouchableOpacity> + ), [isActive, theme, index, info.icon, onPress]) + + return components +} + +// const settingItem = { +// icon: 'setting', +// } +const Header = ({ componentId }) => { + const menus = useGetter('common', 'navMenus') + const setNavActiveIndex = useDispatch('common', 'setNavActiveIndex') + const theme = useGetter('common', 'theme') + + return ( + <View style={{ ...styles.header, backgroundColor: theme.primary }}> + <StatusBar backgroundColor="rgba(0,0,0,0)" barStyle="dark-content" translucent={true} /> + <SafeAreaView style={styles.container}> + {/* <View style={styles.left}> */} + {menus.map((item, index) => <HeaderItem info={item} index={index} key={item.id} onPress={setNavActiveIndex} />)} + {/* </View> + <View style={styles.right}> + <HeaderItem info={settingItem} index={-1} onPress={() => navigations.pushSettingScreen(componentId)} /> + </View> */} + </SafeAreaView> + </View> + ) +} + + +const styles = StyleSheet.create({ + header: { + // backgroundColor: '#fff', + height: 36 + StatusBar.currentHeight, + paddingTop: StatusBar.currentHeight, + // borderBottomWidth: BorderWidths.normal, + // borderBottomColor: AppColors.borderColor, + // Android shadow + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.23, + // shadowRadius: 2.62, + // elevation: 4, + }, + container: { + // width: '100%', + flexDirection: 'row', + justifyContent: 'center', + }, + left: { + flex: 1, + flexDirection: 'row', + paddingLeft: 5, + }, + btn: { + // flex: 1, + paddingLeft: 10, + paddingRight: 10, + backgroundColor: 'rgba(0,0,0,0)', + alignItems: 'center', + justifyContent: 'center', + height: 36, + }, + btnActive: { + color: 'green', + }, + btnText: { + fontSize: 16, + // color: 'white', + }, + icon: { + paddingLeft: 4, + paddingRight: 4, + }, +}) + + +export default Header diff --git a/src/screens/Home/components/Main.js b/src/screens/Home/components/Main.js new file mode 100644 index 0000000..8530079 --- /dev/null +++ b/src/screens/Home/components/Main.js @@ -0,0 +1,215 @@ +import React, { useEffect, useRef, useMemo, useCallback, memo } from 'react' +import { View, StyleSheet, SafeAreaView } from 'react-native' +import PagerView from 'react-native-pager-view' +import Search from '../Search' +import SongList from '../SongList' +import Top from '../Top' +import List from '../List' +import Download from '../Download' +import Setting from '../Setting' +import { subscribe, useGetter, useDispatch, getStore } from '@/store' +import { AppColors, BorderWidths } from '@/theme' + +// import musicSearch from '../../utils/music/tx/musicSearch' + +const SearchPage = () => { + const activeIndex = useGetter('common', 'navActiveIndex') + const initedRef = useRef(false) + const search = useMemo(() => <Search />, []) + switch (activeIndex) { + case 0: + // case 1: + if (!initedRef.current) initedRef.current = true + return search + case 4: + initedRef.current = false + return null + default: + return initedRef.current ? search : null + } +} +const SongListPage = () => { + const activeIndex = useGetter('common', 'navActiveIndex') + const initedRef = useRef(false) + const songList = useMemo(() => <SongList />, []) + switch (activeIndex) { + // case 0: + case 1: + // case 2: + if (!initedRef.current) initedRef.current = true + return songList + case 4: + initedRef.current = false + return null + default: + return initedRef.current ? songList : null + } + // return activeIndex == 1 || activeIndex == 0 ? SongList : null +} +const TopPage = () => { + const activeIndex = useGetter('common', 'navActiveIndex') + const initedRef = useRef(false) + const top = useMemo(() => <Top />, []) + switch (activeIndex) { + // case 1: + case 2: + // case 3: + if (!initedRef.current) initedRef.current = true + return top + case 4: + initedRef.current = false + return null + default: + return initedRef.current ? top : null + } + // return activeIndex == 0 || activeIndex == 1 ? top : null +} +const ListPage = () => { + const activeIndex = useGetter('common', 'navActiveIndex') + const initedRef = useRef(false) + const list = useMemo(() => <List />, []) + switch (activeIndex) { + // case 2: + case 3: + // case 4: + if (!initedRef.current) initedRef.current = true + return list + default: + return initedRef.current ? list : null + } + // return activeIndex == 0 || activeIndex == 1 ? list : null +} +const SettingPage = () => { + const activeIndex = useGetter('common', 'navActiveIndex') + const initedRef = useRef(false) + const setting = useMemo(() => <Setting />, []) + switch (activeIndex) { + // case 3: + case 4: + if (!initedRef.current) initedRef.current = true + return setting + default: + return initedRef.current ? setting : null + } + // return activeIndex == 0 || activeIndex == 1 ? setting : null +} + + +const Main = () => { + const unSubscribeRef = useRef() + const pagerViewRef = useRef() + // const isScrollingRef = useRef(false) + const scrollPositionRef = useRef(-1) + const activeIndexRef = useRef(getStore().getState().common.nav.activeIndex) + const setNavActiveIndex = useDispatch('common', 'setNavActiveIndex') + + // const handlePageScroll = useCallback(({ nativeEvent }) => { + // console.log(nativeEvent.offset, activeIndexRef.current) + // // if (activeIndexRef.current == -1) return + // // if (nativeEvent.offset == 0) { + // // isScrollingRef.current = false + + // // const index = nativeEvent.position + // // if (activeIndexRef.current == index) return + // // activeIndexRef.current = index + // // setNavActiveIndex(index) + // // } else if (!isScrollingRef.current) { + // // isScrollingRef.current = true + // // } + // }, [setNavActiveIndex]) + + const onPageSelected = useCallback(({ nativeEvent }) => { + scrollPositionRef.current = nativeEvent.position + }, []) + + const onPageScrollStateChanged = useCallback(({ nativeEvent }) => { + // console.log(nativeEvent) + if (nativeEvent.pageScrollState != 'idle') return + if (scrollPositionRef.current != getStore().getState().common.nav.activeIndex) { + setNavActiveIndex(scrollPositionRef.current) + } + // if (activeIndexRef.current == -1) return + // if (nativeEvent.offset == 0) { + // isScrollingRef.current = false + + // const index = nativeEvent.position + // if (activeIndexRef.current == index) return + // activeIndexRef.current = index + // setNavActiveIndex(index) + // } else if (!isScrollingRef.current) { + // isScrollingRef.current = true + // } + }, [setNavActiveIndex]) + + const setActivePage = index => { + // console.log('setActivePage', index) + if (activeIndexRef.current == index) return + activeIndexRef.current = index + // if (index >= pagerViewRef.current.props.children.length) return + pagerViewRef.current.setPage(index) + } + + useEffect(() => { + // window.requestAnimationFrame(() => pagerViewRef.current && pagerViewRef.current.setPage(activeIndexRef.current)) + unSubscribeRef.current = subscribe('common.nav.activeIndex', ({ common: { nav } }) => { + // console.log('subscribe', nav.activeIndex) + setActivePage(nav.activeIndex) + }) + return () => { + unSubscribeRef.current() + } + }, []) + + + const component = useMemo(() => ( + <View style={{ ...styles.container }}> + <PagerView ref={pagerViewRef} + initialPage={activeIndexRef.current} + // onPageScroll={handlePageScroll} + // offscreenPageLimit={2} + onPageSelected={onPageSelected} + onPageScrollStateChanged={onPageScrollStateChanged} + style={styles.pagerView} + > + <View collapsable={false} key="1" style={styles.pageStyle}> + <SearchPage /> + </View> + <View collapsable={false} key="2" style={styles.pageStyle}> + <SongListPage /> + </View> + <View collapsable={false} key="3" style={styles.pageStyle}> + <TopPage /> + </View> + <View collapsable={false} key="4" style={styles.pageStyle}> + <ListPage /> + </View> + {/* <View collapsable={false} key="5" style={styles.pageStyle}> + <Download /> + </View> */} + <View collapsable={false} key="6" style={styles.pageStyle}> + <SettingPage /> + </View> + </PagerView> + </View> + ), [onPageSelected, onPageScrollStateChanged]) + + return component +} + +const styles = StyleSheet.create({ + container: { + flexGrow: 1, + flexShrink: 1, + backgroundColor: '#fff', + }, + pagerView: { + flex: 1, + }, + pageStyle: { + // alignItems: 'center', + // padding: 20, + }, +}) + +export default Main + diff --git a/src/screens/Home/components/PlayerLandscape.js b/src/screens/Home/components/PlayerLandscape.js new file mode 100644 index 0000000..5548506 --- /dev/null +++ b/src/screens/Home/components/PlayerLandscape.js @@ -0,0 +1,125 @@ +import React from 'react' +import { View, ScrollView, Text, StyleSheet, Image, TouchableOpacity } from 'react-native' +import Button from '@/components/common/Button' +import Icon from '@/components/common/Icon' +import { AppColors } from '@/theme' + +export default ({ + asideWidth, targetMusic, toggleNextPlayMode, + togglePlay, playIcon, playModeIcon, actions, + menu, homeViewPageIndex, onLayout = () => {}, navPress = () => {}, +}) => { + const navBtnWidth = asideWidth * 0.5 - 0.1 + const imgWidth = asideWidth * 0.3 + const paddingBottom = asideWidth * 0.05 + const btnStyle = { + width: asideWidth * 0.3, + height: asideWidth * 0.32, + lineHeight: asideWidth * 0.32, + } + const navIconSize = asideWidth * 0.15 + const iconSize = asideWidth * 0.15 + + return <View style={{ ...styles.header, backgroundColor: AppColors.primary }} onLayout={onLayout}> + <ScrollView style={{ ...styles.navBtnContainer }}> + <View style={{ width: '100%', flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between' }}> + { + menu.map((item, index) => + <Button style={{ ...styles.btn, width: navBtnWidth, height: navBtnWidth }} key={index} onPress={() => navPress(item, index)}> + <Icon name={item.icon} style={{ color: homeViewPageIndex == index ? AppColors.secondary : AppColors.normal10 }} size={navIconSize} /> + </Button>) + } + </View> + </ScrollView> + + <View style={{ flexGrow: 0, flexShrink: 1, paddingBottom: paddingBottom, paddingTop: paddingBottom / 2 }}> + <View style={{ flexShrink: 0, width: '100%', flexDirection: 'row', flexWrap: 'wrap' }}> + <TouchableOpacity activeOpacity={0.5} onPress={toggleNextPlayMode}> + <Text style={{ ...styles.cotrolBtn, ...btnStyle }}> + <Icon name={playModeIcon} style={{ color: AppColors.secondary10 }} size={iconSize} /> + </Text> + </TouchableOpacity> + </View> + <View style={{ flexShrink: 0, width: '100%', flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-evenly' }}> + <TouchableOpacity activeOpacity={0.5} onPress={actions.playPrev}> + <Text style={{ ...styles.cotrolBtn, ...btnStyle, transform: [{ rotate: '180deg' }] }}> + <Icon name='nextMusic' style={{ color: AppColors.secondary10 }} size={iconSize} /> + </Text> + </TouchableOpacity> + <TouchableOpacity activeOpacity={0.5} onPress={togglePlay}> + <Text style={{ ...styles.cotrolBtn, ...btnStyle }}> + <Icon name={playIcon} style={{ color: AppColors.secondary10 }} size={iconSize} /> + </Text> + </TouchableOpacity> + <TouchableOpacity activeOpacity={0.5} onPress={actions.playNext}> + <Text style={{ ...styles.cotrolBtn, ...btnStyle }}> + <Icon name='nextMusic' style={{ color: AppColors.secondary10 }} size={iconSize} /> + </Text> + </TouchableOpacity> + </View> + <View style={{ flexDirection: 'row', paddingLeft: paddingBottom }}> + <View style={{ borderRadius: 4, marginTop: paddingBottom / 2 }} elevation={1}> + <Image source={{ uri: targetMusic.img }} borderRadius={4} style={{ + ...styles.playInfoImg, + backgroundColor: AppColors.primary, + width: imgWidth, + height: imgWidth, + }} /> + </View> + <View style={{ flexShrink: 1, flexGrow: 1, flexDirection: 'column', justifyContent: 'space-evenly', paddingLeft: paddingBottom, paddingRight: paddingBottom }}> + <Text style={{ width: '100%', fontSize: 12 }} numberOfLines={1}>{targetMusic.singer}</Text> + <Text style={{ width: '100%', fontSize: 12 }} numberOfLines={1}>{targetMusic.name}</Text> + </View> + </View> + </View> + </View> +} + + +const styles = StyleSheet.create({ + header: { + width: '18%', + minWidth: 40, + height: '100%', + // paddingTop: StatusBar.currentHeight, + // borderRightWidth: 0.4, + // borderLeftWidth: 0.4, + // borderRightColor: '#eee', + // Android shadow + // shadowColor: '#000', + // shadowOffset: { + // width: 0, + // height: 2, + // }, + // shadowOpacity: 0.23, + // shadowRadius: 2.62, + // elevation: 2, + justifyContent: 'space-between', + }, + container: { + // width: '100%', + flexDirection: 'column', + }, + navBtnContainer: { + flexGrow: 0, + flexShrink: 1, + }, + btn: { + // flex: 1, + backgroundColor: 'rgba(0,0,0,0)', + alignItems: 'center', + justifyContent: 'center', + }, + + cotrolBtn: { + width: 32, + height: 32, + textAlign: 'center', + lineHeight: 32, + + // backgroundColor: '#ccc', + shadowOpacity: 1, + textShadowRadius: 2, + // textShadowOffset: { width: 2, height: 2 }, + }, +}) diff --git a/src/screens/Home/components/PlayerPortrait/components/ControlBtn.js b/src/screens/Home/components/PlayerPortrait/components/ControlBtn.js new file mode 100644 index 0000000..b49468e --- /dev/null +++ b/src/screens/Home/components/PlayerPortrait/components/ControlBtn.js @@ -0,0 +1,90 @@ +import React, { useCallback, memo, useMemo, useEffect } from 'react' +import { Text, StyleSheet, TouchableOpacity } from 'react-native' +import Icon from '@/components/common/Icon' +import { useGetter, useDispatch } from '@/store' +import { STATUS } from '@/store/modules/player' + + +export default ({ playNextModes }) => { + const playStatus = useGetter('player', 'status') + const playNext = useDispatch('player', 'playNext') + const playPrev = useDispatch('player', 'playPrev') + // const playMusicInfo = useGetter('player', 'playMusicInfo') + const pauseMusic = useDispatch('player', 'pauseMusic') + const playMusic = useDispatch('player', 'playMusic') + const theme = useGetter('common', 'theme') + + // const togglePlayMethod = useGetter('common', 'togglePlayMethod') + // const setPlayNextMode = useDispatch('common', 'setPlayNextMode') + // const toggleNextPlayMode = useCallback(() => { + // let index = playNextModes.indexOf(togglePlayMethod) + // if (++index >= playNextModes.length) index = -1 + // setPlayNextMode(playNextModes[index] || '') + // }, [setPlayNextMode, togglePlayMethod, playNextModes]) + + const btnPrev = useMemo(() => ( + <TouchableOpacity activeOpacity={0.5} onPress={playPrev}> + <Text style={{ ...styles.cotrolBtn }}> + <Icon name='prevMusic' style={{ color: theme.secondary10 }} size={20} /> + </Text> + </TouchableOpacity> + ), [playPrev, theme]) + + const togglePlay = useCallback(playStatus => { + switch (playStatus) { + case STATUS.playing: + pauseMusic() + break + case STATUS.pause: + case STATUS.stop: + case STATUS.none: + playMusic() + break + // default: + // playMusic(playMusicInfo) + // break + } + }, []) + const btnPlay = useMemo(() => ( + <TouchableOpacity activeOpacity={0.5} onPress={() => togglePlay(playStatus)}> + <Text style={{ ...styles.cotrolBtn }}> + <Icon name={playStatus == STATUS.playing ? 'pause' : 'play'} style={{ color: theme.secondary10 }} size={20} /> + </Text> + </TouchableOpacity> + ), [playStatus, theme, togglePlay]) + const btnNext = useMemo(() => ( + <TouchableOpacity activeOpacity={0.5} onPress={playNext}> + <Text style={{ ...styles.cotrolBtn }}> + <Icon name='nextMusic' style={{ color: theme.secondary10 }} size={20} /> + </Text> + </TouchableOpacity> + ), [playNext, theme]) + + return ( + <> + {/* <TouchableOpacity activeOpacity={0.5} onPress={toggleNextPlayMode}> + <Text style={{ ...styles.cotrolBtn }}> + <Icon name={playModeIcon} style={{ color: theme.secondary10 }} size={18} /> + </Text> + </TouchableOpacity> + */} + {btnPrev} + {btnPlay} + {btnNext} + </> + ) +} + + +const styles = StyleSheet.create({ + cotrolBtn: { + width: 32, + height: 32, + lineHeight: 32, + textAlign: 'center', + + // backgroundColor: '#ccc', + shadowOpacity: 1, + textShadowRadius: 1, + }, +}) diff --git a/src/screens/Home/components/PlayerPortrait/components/Pic.js b/src/screens/Home/components/PlayerPortrait/components/Pic.js new file mode 100644 index 0000000..3e3af15 --- /dev/null +++ b/src/screens/Home/components/PlayerPortrait/components/Pic.js @@ -0,0 +1,55 @@ +import React, { useCallback, memo, useMemo, useEffect, useState } from 'react' +import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native' +import { useGetter, useDispatch } from '@/store' +import { toast } from '@/utils/tools' +import { useTranslation } from '@/plugins/i18n' +import { LIST_ID_PLAY_TEMP, LIST_ID_PLAY_LATER, NAV_VIEW_NAMES } from '@/config/constant' + + +export default () => { + const playMusicInfo = useGetter('player', 'playMusicInfo') + const theme = useGetter('common', 'theme') + const [imgUrl, setImgUrl] = useState(null) + const setNavActiveIndex = useDispatch('common', 'setNavActiveIndex') + const setPrevSelectListId = useDispatch('common', 'setPrevSelectListId') + const setJumpPosition = useDispatch('list', 'setJumpPosition') + const { t } = useTranslation() + const handlePress = useCallback(() => { + // console.log('') + toast(t('play_detail_todo_tip'), 'long') + }, [t]) + const handleLongPress = useCallback(() => { + if (!playMusicInfo || playMusicInfo.listId == LIST_ID_PLAY_TEMP || playMusicInfo.listId == LIST_ID_PLAY_LATER) return + setNavActiveIndex(NAV_VIEW_NAMES.list) + setPrevSelectListId(playMusicInfo.listId) + global.requestAnimationFrame(() => { + setJumpPosition(true) + }) + }, [playMusicInfo, setJumpPosition, setNavActiveIndex, setPrevSelectListId]) + + useEffect(() => { + const url = playMusicInfo ? playMusicInfo.musicInfo.img : null + if (imgUrl == url) return + setImgUrl(url) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [playMusicInfo]) + + const component = useMemo(() => ( + <TouchableOpacity onLongPress={handleLongPress} onPress={handlePress} activeOpacity={0.7} > + <Image source={{ uri: imgUrl }} progressiveRenderingEnabled={true} borderRadius={2} style={{ + // ...styles.playInfoImg, + backgroundColor: theme.primary, + width: 48, + height: 48, + }} /> + </TouchableOpacity> + ), [handleLongPress, handlePress, imgUrl, theme]) + return component +} + + +// const styles = StyleSheet.create({ +// playInfoImg: { + +// }, +// }) diff --git a/src/screens/Home/components/PlayerPortrait/components/PlayInfo.js b/src/screens/Home/components/PlayerPortrait/components/PlayInfo.js new file mode 100644 index 0000000..43af0be --- /dev/null +++ b/src/screens/Home/components/PlayerPortrait/components/PlayInfo.js @@ -0,0 +1,54 @@ +import React, { useCallback, memo, useMemo, useEffect } from 'react' +import { Text, StyleSheet, View } from 'react-native' +import { usePlayTime } from '@/utils/hooks' +import { useGetter } from '@/store' + +import Progress from '@/components/player/Progress' +import Status from './Status' + +const PlayTimeCurrent = ({ timeStr }) => { + const theme = useGetter('common', 'theme') + // console.log(timeStr) + return <Text style={{ fontSize: 12, color: theme.normal10 }}>{timeStr}</Text> +} + +const PlayTimeMax = memo(({ timeStr }) => { + const theme = useGetter('common', 'theme') + return <Text style={{ fontSize: 12, color: theme.normal10 }}>{timeStr}</Text> +}) + +export default () => { + const { curTimeStr, maxTimeStr, progress, bufferedProgress, duration } = usePlayTime() + + return ( + <> + <View style={styles.progress}><Progress progress={progress} bufferedProgress={bufferedProgress} duration={duration} /></View> + <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-end', height: 17 }}> + {/* <MusicName /> */} + <View style={{ flexGrow: 1, flexShrink: 1, paddingRight: 5 }} > + <Status /> + </View> + <View style={{ flexGrow: 0, flexShrink: 0, flexDirection: 'row' }} > + <PlayTimeCurrent timeStr={curTimeStr} /> + <Text style={{ fontSize: 12 }}> / </Text> + <PlayTimeMax timeStr={maxTimeStr} /> + </View> + </View> + </> + ) +} + + +const styles = StyleSheet.create({ + progress: { + height: 12, + flexGrow: 1, + flexShrink: 0, + flexDirection: 'column', + justifyContent: 'center', + // height: + // position: 'absolute', + // width: '100%', + // top: 0, + }, +}) diff --git a/src/screens/Home/components/PlayerPortrait/components/Status.js b/src/screens/Home/components/PlayerPortrait/components/Status.js new file mode 100644 index 0000000..dc66ca9 --- /dev/null +++ b/src/screens/Home/components/PlayerPortrait/components/Status.js @@ -0,0 +1,25 @@ +import React, { useMemo } from 'react' +import { Text } from 'react-native' +import { useGetter } from '@/store' +import { STATUS } from '@/store/modules/player' +import { useLrcPlay } from '@/plugins/lyric' + + +export default () => { + const theme = useGetter('common', 'theme') + const playStatus = useGetter('player', 'status') + const statusText = useGetter('player', 'statusText') + const { text } = useLrcPlay() + const status = useMemo(() => playStatus == STATUS.playing + ? text + : ( + (playStatus == STATUS.pause || playStatus == STATUS.stop) && text + ? text + : statusText + ), [playStatus, statusText, text]) + return <Text numberOfLines={1} style={{ fontSize: 10, color: theme.normal10 }}>{status}</Text> +} + +// const styles = StyleSheet.create({ + +// }) diff --git a/src/screens/Home/components/PlayerPortrait/components/Title.js b/src/screens/Home/components/PlayerPortrait/components/Title.js new file mode 100644 index 0000000..c6d00ed --- /dev/null +++ b/src/screens/Home/components/PlayerPortrait/components/Title.js @@ -0,0 +1,40 @@ +import React, { useCallback, memo, useMemo, useEffect } from 'react' +import { Text, StyleSheet } from 'react-native' +import { useGetter, useDispatch } from '@/store' + + +export default () => { + const theme = useGetter('common', 'theme') + const downloadFileName = useGetter('common', 'downloadFileName') + const playMusicInfo = useGetter('player', 'playMusicInfo') + let title = '^-^' + if (playMusicInfo) { + title = downloadFileName.replace('歌手', playMusicInfo.musicInfo.singer).replace('歌名', playMusicInfo.musicInfo.name) + } + // console.log(playMusicInfo) + return <Text style={{ width: '100%', fontSize: 14, color: theme.normal }} numberOfLines={1}>{title}</Text> +} +// const Singer = () => { +// const playMusicInfo = useGetter('player', 'playMusicInfo') +// return ( +// <View style={{ flexGrow: 0, flexShrink: 0 }}> +// <Text style={{ width: '100%', color: AppColors.normal }} numberOfLines={1}> +// {playMusicInfo ? playMusicInfo.musicInfo.singer : ''} +// </Text> +// </View> +// ) +// } +// const MusicName = () => { +// const playMusicInfo = useGetter('player', 'playMusicInfo') +// return ( +// <View style={{ flexGrow: 0, flexShrink: 1 }}> +// <Text style={{ width: '100%', color: AppColors.normal }} numberOfLines={1}> +// {playMusicInfo ? playMusicInfo.musicInfo.name : '^-^'} +// </Text> +// </View> +// ) +// } + +// const styles = StyleSheet.create({ + +// }) diff --git a/src/screens/Home/components/PlayerPortrait/index.js b/src/screens/Home/components/PlayerPortrait/index.js new file mode 100644 index 0000000..8ce403b --- /dev/null +++ b/src/screens/Home/components/PlayerPortrait/index.js @@ -0,0 +1,81 @@ +import React, { useCallback, memo, useMemo, useEffect } from 'react' +import { View, Text, StyleSheet } from 'react-native' +import { useLayout, useKeyboard } from '@/utils/hooks' +import { useGetter, useDispatch } from '@/store' +import { BorderWidths } from '@/theme' + +import Pic from './components/Pic' +import Title from './components/Title' +import PlayInfo from './components/PlayInfo' +import ControlBtn from './components/ControlBtn' + + +export default ({ playNextModes }) => { + // const { onLayout, ...layout } = useLayout() + const { keyboardShown } = useKeyboard() + const theme = useGetter('common', 'theme') + + const playerComponent = useMemo(() => ( + <View style={{ ...styles.container, backgroundColor: theme.primary, borderTopColor: theme.secondary10 }}> + <View style={styles.left} elevation={1}><Pic /></View> + <View style={styles.center}> + <View style={{ ...styles.row, justifyContent: 'space-between', fontSize: 12, height: 19 }}> + <Title /> + {/* <PlayTime /> */} + </View> + <PlayInfo /> + </View> + <View style={styles.right}> + <ControlBtn playNextModes={playNextModes} /> + </View> + </View> + ), [theme, playNextModes]) + + // console.log(layout) + + return keyboardShown ? null : playerComponent +} + +const styles = StyleSheet.create({ + container: { + width: '100%', + height: 59, + // paddingTop: progressContentPadding, + // marginTop: -progressContentPadding, + // backgroundColor: 'rgba(0, 0, 0, .1)', + borderTopWidth: BorderWidths.normal2, + paddingTop: 5, + paddingBottom: 5, + paddingLeft: 5, + // backgroundColor: AppColors.primary, + // backgroundColor: 'red', + flexDirection: 'row', + alignItems: 'center', + }, + left: { + borderRadius: 3, + flexGrow: 0, + flexShrink: 0, + }, + center: { + flexDirection: 'column', + flexGrow: 1, + flexShrink: 1, + paddingLeft: 5, + justifyContent: 'space-evenly', + height: 48, + }, + right: { + flexDirection: 'row', + alignItems: 'center', + flexGrow: 0, + flexShrink: 0, + paddingLeft: 5, + paddingRight: 5, + }, + row: { + flexDirection: 'row', + flexGrow: 0, + flexShrink: 0, + }, +}) diff --git a/src/screens/Home/index.js b/src/screens/Home/index.js new file mode 100644 index 0000000..63229a9 --- /dev/null +++ b/src/screens/Home/index.js @@ -0,0 +1,20 @@ +import React from 'react' + +import { View } from 'react-native' +import Header from './components/Header' +// import Aside from './components/Aside' +import Main from './components/Main' +import FooterPlayer from './components/FooterPlayer' +import { AppColors } from '@/theme' + + +export default (props) => ( + <> + <Header componentId={props.componentId} /> + <View style={{ flex: 1, flexDirection: 'column', height: '100%', backgroundColor: AppColors.primary }}> + {/* <Aside /> */} + <Main /> + <FooterPlayer /> + </View> + </> +) diff --git a/src/screens/index.js b/src/screens/index.js new file mode 100644 index 0000000..8e4c691 --- /dev/null +++ b/src/screens/index.js @@ -0,0 +1,6 @@ +export { default as Home } from './Home' +// export { default as Setting } from './Setting' +// export { default as LoginScreen } from './LoginScreen/LoginScreen' +// export { default as SingleAppScreen } from './SingleAppScreen/SingleAppScreen' +// export { default as Tab1Screen } from './Tab1Screen/Tab1Screen' +// export { default as Tab2Screen } from './Tab2Screen/Tab2Screen' diff --git a/src/store/.bak/actions/common.js b/src/store/.bak/actions/common.js new file mode 100644 index 0000000..09b20e7 --- /dev/null +++ b/src/store/.bak/actions/common.js @@ -0,0 +1,23 @@ +export const TYPES = { + updateSetting: 'updateSetting', + updateNavHomeViewPageIndex: 'updateNavHomeViewPageIndex', +} + +export const updateSetting = setting => { + return { + type: TYPES.updateSetting, + payload: setting, + } +} + +export const updateNavHomeViewPageIndex = index => ({ + type: TYPES.updateNavHomeViewPageIndex, + payload: index, +}) + +// export const changeCountAsync = count => (dispatch, getState) => { +// console.log(getState()) +// setTimeout(() => { +// dispatch(changeCount(count)) +// }, 1000) +// } diff --git a/src/store/.bak/actions/counts.js b/src/store/.bak/actions/counts.js new file mode 100644 index 0000000..d266a37 --- /dev/null +++ b/src/store/.bak/actions/counts.js @@ -0,0 +1,23 @@ +// import { httpFetch } from '../../utils/request' + +export const TYPES = { + COUNTER_CHANGE: 'COUNTER_CHANGE', +} + +export const changeCount = count => { + return { + type: TYPES.COUNTER_CHANGE, + payload: count, + } +} + +export const changeCountAsync = count => (dispatch, getState) => { + // console.log(getState()) + // const { promise } = httpFetch('https://cdn.stsky.cn/lx-music/desktop/version.json') + // promise.then(resp => { + // console.log(resp) + // }) + setTimeout(() => { + dispatch(changeCount(count)) + }, 1000) +} diff --git a/src/store/.bak/actions/search.js b/src/store/.bak/actions/search.js new file mode 100644 index 0000000..fc54978 --- /dev/null +++ b/src/store/.bak/actions/search.js @@ -0,0 +1,76 @@ +import music from '../../../utils/music' + +export const TYPES = { + loading: 'loading', + setText: 'setText', + addHistory: 'addHistory', + setList: 'setList', + setLists: 'setLists', + clearList: 'clearList', + removeHistory: 'removeHistory', + clearHistory: 'clearHistory', +} + +const sources = [] +for (const source of music.sources) { + const musicSearch = music[source.id].musicSearch + if (!musicSearch) continue + sources.push(source) +} + +export const search = ({ text, page, limit }) => (dispatch, getState) => { + dispatch({ type: TYPES.setText, payload: text }) + dispatch({ type: TYPES.addHistory, payload: text }) + + const state = getState() + + if (state.common.setting.search.searchSource == 'all') { + const task = [] + for (const source of sources) { + if (source.id == 'all') continue + dispatch({ type: TYPES.loading, payload: true }) + task.push(music[source.id].musicSearch.search(text, page).catch(error => { + console.log(error) + return { + allPage: 1, + limit: 30, + list: [], + source: source.id, + total: 0, + } + })) + } + return Promise.all(task).then(results => dispatch({ type: TYPES.setLists, payload: { results, page } })) + .finally(() => dispatch({ type: TYPES.loading, payload: false })) + } else { + dispatch({ type: TYPES.loading, payload: true }) + return music[state.common.setting.search.searchSource].musicSearch.search(text, page, limit).catch(error => { + console.log(error) + return { + allPage: 1, + limit: 30, + list: [], + source: state.common.setting.search.searchSource, + total: 0, + } + }).then(data => dispatch({ type: TYPES.setList, payload: { page, ...data } })) + .finally(() => dispatch({ type: TYPES.loading, payload: false })) + } +} + +export const setText = text => ({ type: TYPES.setText, payload: text }) + +export const clearList = () => ({ + type: TYPES.clearList, +}) +export const addHistory = text => ({ + type: TYPES.addHistory, + payload: text, +}) +export const removeHistory = index => ({ + type: TYPES.addHistory, + payload: index, +}) +export const clearHistory = () => ({ + type: TYPES.addHistory, +}) diff --git a/src/store/.bak/reducers/common.js b/src/store/.bak/reducers/common.js new file mode 100644 index 0000000..66fecee --- /dev/null +++ b/src/store/.bak/reducers/common.js @@ -0,0 +1,34 @@ +import { initSetting } from '../../../config' +import { TYPES } from '../actions/common' + +const initialState = { + ...initSetting(), + nav: { + homeViewPageIndex: 0, + }, +} + +const mutations = { + [TYPES.updateSetting](state, setting) { + return { + ...state, + setting: { + ...setting, + }, + } + }, + [TYPES.updateNavHomeViewPageIndex](state, index) { + return { + ...state, + nav: { + ...state.nav, + homeViewPageIndex: index, + }, + } + }, +} + +export default (state = initialState, action) => + mutations[action.type] + ? mutations[action.type](state, action.payload) + : state diff --git a/src/store/.bak/reducers/count.js b/src/store/.bak/reducers/count.js new file mode 100644 index 0000000..75f8125 --- /dev/null +++ b/src/store/.bak/reducers/count.js @@ -0,0 +1,19 @@ +import { TYPES } from '../actions/counts' + +const initialState = { + count: 0, +} + +const countReducer = (state = initialState, action) => { + switch (action.type) { + case TYPES.COUNTER_CHANGE: + return { + ...state, + count: action.payload, + } + default: + return state + } +} + +export default countReducer diff --git a/src/store/.bak/reducers/index.js b/src/store/.bak/reducers/index.js new file mode 100644 index 0000000..785722c --- /dev/null +++ b/src/store/.bak/reducers/index.js @@ -0,0 +1,19 @@ +import { persistCombineReducers } from 'redux-persist' +import AsyncStorage from '@react-native-async-storage/async-storage' + +import common from './common' +import search from './search' +import count from './count' + +const config = { + key: 'LIFTED_REDUX_STORE', + storage: AsyncStorage, +} + +const appReducer = persistCombineReducers(config, { + common, + search, + count, +}) + +export default (state, action) => appReducer(state, action) diff --git a/src/store/.bak/reducers/search.js b/src/store/.bak/reducers/search.js new file mode 100644 index 0000000..40197ad --- /dev/null +++ b/src/store/.bak/reducers/search.js @@ -0,0 +1,220 @@ +import { TYPES } from '../actions/search' + +import music from '../../../utils/music' + +let historyList +if (historyList == null) { + historyList = [] + // electronStore_data.set('searchHistoryList', historyList) +} + +const sources = [] +const sourceList = {} +const sourceMaxPage = {} +for (const source of music.sources) { + const musicSearch = music[source.id].musicSearch + if (!musicSearch) continue + sources.push(source) + sourceList[source.id] = { + page: 1, + allPage: 0, + limit: 30, + total: 0, + list: [], + } + sourceMaxPage[source.id] = 0 +} + +const initialState = { + isLoading: false, + sourceList, + list: [], + text: '', + page: 1, + limit: 30, + allPage: 1, + total: 0, + sourceMaxPage, + historyList, +} + +sources.push({ + id: 'all', + name: '聚合搜索', +}) + +// https://blog.csdn.net/xcxy2015/article/details/77164126#comments +const similar = (a, b) => { + if (!a || !b) return 0 + if (a.length > b.length) { // 保证 a <= b + const t = b + b = a + a = t + } + const al = a.length + const bl = b.length + const mp = [] // 一个表 + let i, j, ai, lt, tmp // ai:字符串a的第i个字符。 lt:左上角的值。 tmp:暂存新的值。 + for (i = 0; i <= bl; i++) mp[i] = i + for (i = 1; i <= al; i++) { + ai = a.charAt(i - 1) + lt = mp[0] + mp[0] = mp[0] + 1 + for (j = 1; j <= bl; j++) { + tmp = Math.min(mp[j] + 1, mp[j - 1] + 1, lt + (ai == b.charAt(j - 1) ? 0 : 1)) + lt = mp[j] + mp[j] = tmp + } + } + return 1 - (mp[bl] / bl) +} + +const sortInsert = (arr, data) => { + const key = data.num + let left = 0 + let right = arr.length - 1 + + while (left <= right) { + const middle = parseInt((left + right) / 2) + if (key == arr[middle]) { + left = middle + break + } else if (key < arr[middle].num) { + right = middle - 1 + } else { + left = middle + 1 + } + } + while (left > 0) { + if (arr[left - 1].num != key) break + left-- + } + + arr.splice(left, 0, data) +} + +const handleSortList = (list, keyword) => { + const arr = [] + for (const item of list) { + sortInsert(arr, { + num: similar(keyword, `${item.name} ${item.singer}`), + data: item, + }) + } + return arr.map(item => item.data).reverse() +} + +const filterList = list => { + const set = new Set() + for (let i = list.length - 1; i > -1; i--) { + const item = list[i] + if (set.has(item.songmid)) { + list.splice(i, 1) + } else { + set.add(item.songmid) + } + } + return list +} + +const mutations = { + [TYPES.loading](state, isLoading) { + return { + ...state, + isLoading, + } + }, + [TYPES.setText](state, text) { + return { + ...state, + text, + } + }, + [TYPES.addHistory](state, text) { + let historyList = [...state.historyList] + const index = historyList.indexOf(text) + if (index > -1) historyList.splice(index, 1) + if (historyList.length >= 15) historyList = historyList.slice(0, 14) + historyList.unshift(text) + return { + ...state, + historyList, + } + }, + [TYPES.setList](state, datas) { + const source = { ...state.sourceList[datas.source] } + source.list = datas.page > 1 ? filterList([...source.list, ...datas.list]) : datas.list + source.total = datas.total + source.allPage = datas.allPage + source.page = datas.page + source.limit = datas.limit + + return { + ...state, + sourceList: { + ...state.sourceList, + [datas.source]: source, + }, + } + }, + [TYPES.setLists](state, { results, page }) { + const pages = [] + let total = 0 + let limit = 0 + const list = [] + state = { ...state } + state.sourceMaxPage = { ...state.sourceMaxPage } + for (const source of results) { + sourceMaxPage[source.source] = source.allPage + if (source.allPage < page) continue + list.push(...source.list) + pages.push(source.allPage) + total += source.total + limit += source.limit + } + state.allPage = Math.max(...pages) + state.total = total + state.limit = limit + state.page = page + state.list = page > 1 ? filterList([...state.list, ...handleSortList(list, state.text)]) : handleSortList(list, state.text) + return state + }, + [TYPES.clearList](state) { + state = { ...state } + state.sourceMaxPage = { ...state.sourceMaxPage } + state.sourceList = { ...state.sourceList } + for (const source of Object.keys(state.sourceList)) { + state.sourceList[source] = { ...state.sourceList[source] } + state.sourceList[source].list = [] + state.sourceList[source].page = 0 + state.sourceList[source].allPage = 0 + state.sourceList[source].total = 0 + state.sourceMaxPage[source] = 0 + } + state.list = [] + state.page = 0 + state.allPage = 0 + state.total = 0 + state.text = '' + return state + }, + [TYPES.removeHistory](state, index) { + const historyList = [...state.historyList] + historyList.splice(index, 1) + return { + ...state, + historyList, + } + }, + [TYPES.clearHistory](state) { + return { + ...state, + historyList: [], + } + }, +} + +export default (state = initialState, action) => + mutations[action.type] + ? mutations[action.type](state, action.payload) + : state diff --git a/src/store/Provider/Provider.js b/src/store/Provider/Provider.js new file mode 100644 index 0000000..dab0294 --- /dev/null +++ b/src/store/Provider/Provider.js @@ -0,0 +1,32 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import { Provider } from 'react-redux' +import createStore from '../store' + +let store + +class AppStoreProvider extends PureComponent { + getChildContext() { + return { + store, + } + } + + static childContextTypes = { + store: PropTypes.shape({}), + }; + + render() { + const { children } = this.props + + store = store || createStore() + + return ( + <Provider store={store}> + {children} + </Provider> + ) + } +} + +export default AppStoreProvider diff --git a/src/store/Provider/index.js b/src/store/Provider/index.js new file mode 100644 index 0000000..4c1b746 --- /dev/null +++ b/src/store/Provider/index.js @@ -0,0 +1 @@ +export { default as Provider } from './Provider' diff --git a/src/store/connect.js b/src/store/connect.js new file mode 100644 index 0000000..65be30f --- /dev/null +++ b/src/store/connect.js @@ -0,0 +1,23 @@ +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import * as modules from './modules' + + +const mapDispatchToProps = actionCreators => dispatch => ({ + actions: bindActionCreators(actionCreators, dispatch), +}) + +export default (mapStateToProps, mapActions) => { + const mapActionToProps = {} + for (const [moduleName, actions] of mapActions) { + const moduleActions = modules[moduleName].action + if (Array.isArray(actions)) { + for (const action of actions) mapActionToProps[action] = moduleActions[action] + } else { + for (const [key, value] of Object.entries(actions)) { + mapActionToProps[key] = moduleActions[value] + } + } + } + return connect(mapStateToProps, mapDispatchToProps(mapActionToProps)) +} diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..f818990 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,7 @@ +export { Provider } from './Provider' +export { reducers } from './reducer' +export { default as useGetter } from './useGetter' +export { default as useDispatch } from './useDispatch' +export { default as connect } from './connect' +export { default as getStore } from './store' +export { subscribe } from './subscriber' diff --git a/src/store/modules/common/action.js b/src/store/modules/common/action.js new file mode 100644 index 0000000..d15de1e --- /dev/null +++ b/src/store/modules/common/action.js @@ -0,0 +1,238 @@ +import { getData, setData, removeData, getAllKeys, getDataMultiple, setDataMultiple } from '@/plugins/storage' +import { storageDataPrefix } from '@/config' +import { action as playerAction, getter as playerGetter } from '@/store/modules/player' +import { mergeSetting } from '@/config/setting' +import { changeLanguage } from '@/plugins/i18n' +import music from '@/utils/music' +import { getVersionInfo } from '@/utils/version' +import { compareVer } from '@/utils' +// import { setMaxCache } from '@/plugins/player/utils' +import { showVersionModal } from '@/navigation' +import { VERSION_STATUS } from '@/config/constant' + +export const TYPES = { + updateSetting: null, + setNavActiveIndex: null, + setNavScreenName: null, + setPlayNextMode: null, + setPrevSelectListId: null, + setApiSource: null, + setTheme: null, + setSearchSource: null, + setAgreePact: null, + setSongList: null, + setLang: null, + setPlayerCacheSize: null, + setIsPlayHighQuality: null, + setSourceNameType: null, + setTop: null, + setIgnoreVersion: null, + setVersionInfo: null, +} +for (const key of Object.keys(TYPES)) { + TYPES[key] = `common__${key}` +} + +const settingKey = storageDataPrefix.setting + +export const checkVersion = () => async(dispatch, getState) => { + let versionInfo + try { + const { version, desc, history } = await getVersionInfo() + versionInfo = { + version, + desc, + history, + } + } catch (err) { + versionInfo = { + version: '0.0.0', + desc: null, + history: [], + } + } + // const versionInfo = { + // version: '1.9.0', + // desc: '- 更新xxx\n- 修复xxx123的萨达修复xxx123的萨达修复xxx123的萨达修复xxx123的萨达修复xxx123的萨达', + // history: [{ version: '1.8.0', desc: '- 更新xxx22\n- 修复xxx22' }, { version: '1.7.0', desc: '- 更新xxx22\n- 修复xxx22' }], + // } + versionInfo.status = + versionInfo.version == '0.0.0' + ? VERSION_STATUS.unknown + : compareVer(process.versions.app, versionInfo.version) < 0 + ? VERSION_STATUS.available + : VERSION_STATUS.latest + + const { common } = getState() + + if (common.setting.ignoreVersion != versionInfo.version && versionInfo.status == VERSION_STATUS.available) { + versionInfo.showModal = true + dispatch(setVersionInfo(versionInfo)) + showVersionModal() + } else { + versionInfo.showModal = false + dispatch(setVersionInfo(versionInfo)) + } + // console.log(compareVer(process.versions.app, versionInfo.version)) + // console.log(process.versions.app, versionInfo.version) +} + +export const setVersionInfo = versionInfo => { + return { + type: TYPES.setVersionInfo, + payload: versionInfo, + } +} + +export const initSetting = () => async(dispatch, getState) => { + const setting = await getData(settingKey) + if (!setting) return + global.globalObj.qualityList = music.supportQuality[setting.apiSource] + global.globalObj.apiSource = setting.apiSource + await dispatch(updateSetting(mergeSetting(setting))) +} + +export const updateSetting = setting => async(dispatch, getState) => { + dispatch({ + type: TYPES.updateSetting, + payload: setting, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setNavActiveIndex = index => ({ + type: TYPES.setNavActiveIndex, + payload: index, +}) + +export const setPrevSelectListId = id => async(dispatch, getState) => { + dispatch({ + type: TYPES.setPrevSelectListId, + payload: id, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setPlayNextMode = mode => async(dispatch, getState) => { + dispatch({ + type: TYPES.setPlayNextMode, + payload: mode, + }) + dispatch(playerAction.clearPlayedList()) + const state = getState() + if (mode == 'random') dispatch(playerAction.addMusicToPlayedList(playerGetter.playMusicInfo(state))) + await setData(settingKey, state.common.setting) +} + +export const setApiSource = id => async(dispatch, getState) => { + dispatch({ + type: TYPES.setApiSource, + payload: id, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setIgnoreVersion = version => async(dispatch, getState) => { + dispatch({ + type: TYPES.setIgnoreVersion, + payload: version, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setTheme = id => async(dispatch, getState) => { + dispatch({ + type: TYPES.setTheme, + payload: id, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setLang = id => async(dispatch, getState) => { + dispatch({ + type: TYPES.setLang, + payload: id, + }) + changeLanguage(id) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setSourceNameType = id => async(dispatch, getState) => { + dispatch({ + type: TYPES.setSourceNameType, + payload: id, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setSearchSource = ({ searchSource, tempSearchSource }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.setSearchSource, + payload: { searchSource, tempSearchSource }, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setAgreePact = isAgreePact => async(dispatch, getState) => { + dispatch({ + type: TYPES.setAgreePact, + payload: isAgreePact, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setLeaderboard = ({ tabId, source }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.setLeaderboard, + payload: { tabId, source }, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setSongList = ({ sortId, tagInfo, source }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.setSongList, + payload: { sortId, tagInfo, source }, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setTop = ({ tabId, source }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.setTop, + payload: { tabId, source }, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + +export const setPlayerCacheSize = size => async(dispatch, getState) => { + dispatch({ + type: TYPES.setPlayerCacheSize, + payload: size, + }) + const { common } = getState() + await setData(settingKey, common.setting) + // setMaxCache(size) +} + +export const setIsPlayHighQuality = highQuality => async(dispatch, getState) => { + dispatch({ + type: TYPES.setIsPlayHighQuality, + payload: highQuality, + }) + const { common } = getState() + await setData(settingKey, common.setting) +} + diff --git a/src/store/modules/common/getter.js b/src/store/modules/common/getter.js new file mode 100644 index 0000000..e6f1f72 --- /dev/null +++ b/src/store/modules/common/getter.js @@ -0,0 +1,50 @@ +import { createSelector } from 'reselect' +import apiSourceInfo from '@/utils/music/api-source-info' + +// sourceInfo(state, getters, rootState, { sourceNames }) { +// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList } +// }, +// tags: state => state.tags, +// isVisibleListDetail: state => state.isVisibleListDetail, +// selectListInfo: state => state.selectListInfo, +export const common = state => state.common +export const navMenus = state => state.common.nav.menus +export const navActiveIndex = state => state.common.nav.activeIndex + +export const setting = state => state.common.setting + +export const activeLangId = state => state.common.setting.langId + +export const isAgreePact = state => state.common.setting.isAgreePact + +export const isPlayHighQuality = state => state.common.setting.player.highQuality +export const playerCacheSize = state => state.common.setting.player.cacheSize + +export const themes = state => state.common.themes +export const activeThemeId = state => state.common.setting.themeId +export const theme = createSelector( + [themes, activeThemeId], + (themes, activeThemeId) => (themes[activeThemeId] || themes.green).colors) +export const themeList = createSelector(themes, themes => Object.values(themes)) + +export const versionInfo = state => state.common.versionInfo + +export const prevSelectListId = state => state.common.setting.list.prevSelectListId + +export const togglePlayMethod = state => state.common.setting.player.togglePlayMethod + +export const downloadFileName = state => state.common.setting.download.fileName + + +export const sourceNameType = state => state.common.setting.sourceNameType + +export const activeApiSourceId = state => state.common.setting.apiSource + +const apiSourceListFormated = apiSourceInfo.map(api => ({ + id: api.id, + name: api.name, + disabled: api.disabled, +})) +export const apiSourceList = state => apiSourceListFormated + +export const supportQualitys = state => apiSourceInfo.find(s => s.id == state.common.setting.apiSource).supportQualitys diff --git a/src/store/modules/common/index.js b/src/store/modules/common/index.js new file mode 100644 index 0000000..f9cf685 --- /dev/null +++ b/src/store/modules/common/index.js @@ -0,0 +1,5 @@ +import * as action from './action' +import * as getter from './getter' + +export { action, getter } +export { default as reducer } from './reducer' diff --git a/src/store/modules/common/reducer.js b/src/store/modules/common/reducer.js new file mode 100644 index 0000000..d55db18 --- /dev/null +++ b/src/store/modules/common/reducer.js @@ -0,0 +1,244 @@ +import { initSetting } from '@/config/setting' +import { TYPES } from './action' +import music from '@/utils/music' +import { Themes } from '@/theme' +import { NAV_VIEW_NAMES, VERSION_STATUS } from '@/config/constant' + + +const setting = initSetting() + + +global.globalObj = { + qualityList: music.supportQuality[setting.setting.apiSource], + apiSource: setting.setting.apiSource, +} + +const initialState = { + ...setting, + nav: { + activeIndex: 0, + menus: [ + { id: 'search', name: '搜索', icon: 'search-2' }, + { id: 'songList', name: '歌单', icon: 'album' }, + { id: 'top', name: '排行榜', icon: 'leaderboard' }, + { id: 'love', name: '收藏', icon: 'love' }, + // { id: 'download', name: '下载', icon: 'download-2' }, + { id: 'setting', name: '设置', icon: 'setting' }, + ], + }, + qualityList: music.supportQuality[setting.setting.apiSource], + themes: Themes, + versionInfo: { + status: VERSION_STATUS.checking, + downloadProgress: { + total: 0, + current: 0, + }, + showModal: false, + version: null, + desc: '', + history: [], + }, +} + +initialState.nav.menus.forEach(({ id }, index) => { + NAV_VIEW_NAMES[id] = index +}) + +const mutations = { + [TYPES.updateSetting](state, setting) { + return { + ...state, + setting: { + ...state.setting, + ...setting, + }, + } + }, + [TYPES.setNavActiveIndex](state, index) { + if (index === state.nav.activeIndex) return state + return { + ...state, + nav: { + ...state.nav, + activeIndex: index, + }, + } + }, + [TYPES.setPrevSelectListId](state, id) { + return { + ...state, + setting: { + ...state.setting, + list: { + ...state.setting.list, + prevSelectListId: id, + }, + }, + } + }, + [TYPES.setAgreePact](state, isAgreePact) { + return { + ...state, + setting: { + ...state.setting, + isAgreePact, + }, + } + }, + [TYPES.setSearchSource](state, { searchSource, tempSearchSource }) { + const newState = { + ...state, + setting: { + ...state.setting, + search: { + ...state.setting.search, + }, + }, + } + if (searchSource != null) newState.setting.search.searchSource = searchSource + if (tempSearchSource != null) newState.setting.search.tempSearchSource = tempSearchSource + return newState + }, + [TYPES.setLeaderboard](state, { tabId, source }) { + const newState = { + ...state, + setting: { + ...state.setting, + leaderboard: { + ...state.setting.leaderboard, + }, + }, + } + if (tabId != null) newState.setting.leaderboard.tabId = tabId + if (source != null) newState.setting.leaderboard.source = source + return newState + }, + [TYPES.setSongList](state, { sortId, tagInfo, source }) { + const newState = { + ...state, + setting: { + ...state.setting, + songList: { + ...state.setting.songList, + }, + }, + } + if (tagInfo != null) newState.setting.songList.tagInfo = tagInfo + if (sortId != null) newState.setting.songList.sortId = sortId + if (source != null) newState.setting.songList.source = source + return newState + }, + [TYPES.setTop](state, { tabId, source }) { + const newState = { + ...state, + setting: { + ...state.setting, + leaderboard: { + ...state.setting.leaderboard, + }, + }, + } + if (tabId != null) newState.setting.leaderboard.tabId = tabId + if (source != null) newState.setting.leaderboard.source = source + return newState + }, + [TYPES.setApiSource](state, id) { + global.globalObj.apiSource = id + global.globalObj.supportQuality = music.supportQuality[id] + + return { + ...state, + setting: { + ...state.setting, + apiSource: id, + }, + } + }, + [TYPES.setIgnoreVersion](state, version) { + return { + ...state, + setting: { + ...state.setting, + ignoreVersion: version, + }, + } + }, + [TYPES.setTheme](state, id) { + return { + ...state, + setting: { + ...state.setting, + themeId: id, + }, + } + }, + [TYPES.setLang](state, id) { + return { + ...state, + setting: { + ...state.setting, + langId: id, + }, + } + }, + [TYPES.setSourceNameType](state, id) { + return { + ...state, + setting: { + ...state.setting, + sourceNameType: id, + }, + } + }, + [TYPES.setPlayNextMode](state, mode) { + return { + ...state, + setting: { + ...state.setting, + player: { + ...state.setting.player, + togglePlayMethod: mode, + }, + }, + } + }, + [TYPES.setPlayerCacheSize](state, size) { + return { + ...state, + setting: { + ...state.setting, + player: { + ...state.setting.player, + cacheSize: size, + }, + }, + } + }, + [TYPES.setIsPlayHighQuality](state, highQuality) { + return { + ...state, + setting: { + ...state.setting, + player: { + ...state.setting.player, + highQuality, + }, + }, + } + }, + [TYPES.setVersionInfo](state, versionInfo) { + return { + ...state, + versionInfo: { + ...state.versionInfo, + ...versionInfo, + }, + } + }, +} + +export default (state = initialState, action) => + mutations[action.type] + ? mutations[action.type](state, action.payload) + : state diff --git a/src/store/modules/index.js b/src/store/modules/index.js new file mode 100644 index 0000000..6120965 --- /dev/null +++ b/src/store/modules/index.js @@ -0,0 +1,15 @@ +import * as common from './common' +import * as search from './search' +import * as player from './player' +import * as list from './list' +import * as songList from './songList' +import * as top from './top' + +export { + common, + search, + player, + list, + songList, + top, +} diff --git a/src/store/modules/list/action.js b/src/store/modules/list/action.js new file mode 100644 index 0000000..944af53 --- /dev/null +++ b/src/store/modules/list/action.js @@ -0,0 +1,262 @@ +import { action as playerAction } from '@/store/modules/player' +import { findMusic } from '@/utils/music' +import { + getAllListData, + saveList, + removeList, + saveListAllSort, + clearMusicUrlAndLyric, + saveListScrollPosition, + saveListSort, +} from '@/utils/tools' + +export const TYPES = { + initList: null, + setList: null, + listAdd: null, + listMove: null, + listAddMultiple: null, + listMoveMultiple: null, + listRemove: null, + listRemoveMultiple: null, + listClear: null, + updateMusicInfo: null, + createUserList: null, + removeUserList: null, + setUserListName: null, + setUserListPosition: null, + setMusicPosition: null, + setOtherSource: null, + clearCache: null, + jumpPosition: null, +} + +for (const key of Object.keys(TYPES)) { + TYPES[key] = `list__${key}` +} + + +export const initList = listData => async(dispatch, getState) => { + let defaultList + let loveList + let userList + let listPosition + let listSort + if (listData) { + defaultList = listData.defaultList + loveList = listData.loveList + userList = listData.userList + listSort = listData.listSort || {} + } else { + try { + listData = await getAllListData() + } catch (err) { return } + defaultList = listData.defaultList + loveList = listData.loveList + userList = listData.userList + listPosition = listData.listPosition + listSort = listData.listSort + } + global.listScrollPosition = listPosition + global.listSort = listSort + + let isNeedSaveSortInfo = false + userList.sort((a, b) => { + if (listSort[a.id] == null) return listSort[b.id] == null ? -1 : 1 + return listSort[b.id] == null ? 1 : listSort[a.id] - listSort[b.id] + }) + userList.forEach((list, index) => { + if (listSort[list.id] == null) { + isNeedSaveSortInfo = true + listSort[list.id] = index + delete list.location + } + }) + if (isNeedSaveSortInfo) await saveListAllSort(listSort) + + // console.log(userList.map(l => `${listSort[l.id]} - ${l.name}`)) + dispatch({ + type: TYPES.initList, + payload: { defaultList, loveList, userList }, + }) +} + +export const setList = ({ id, list, name, location, source, sourceListId }) => async(dispatch, getState) => { + const targetList = global.allList[id] + if (targetList) { + if (name && targetList.name === name) { + dispatch({ + type: TYPES.listClear, + payload: id, + }) + dispatch(listAddMultiple({ id, list })) + return + } + + id += '_' + Math.random() + } + await dispatch(createUserList({ id, list, name, location, source, sourceListId })) +} + +export const listAdd = ({ musicInfo, id }) => (dispatch, getState) => { + dispatch({ + type: TYPES.listAdd, + payload: { + musicInfo, + id, + }, + }) + dispatch(playerAction.checkPlayList([id])) + saveList(global.allList[id]) +} + +export const listMove = ({ fromId, musicInfo, toId }) => (dispatch, getState) => { + dispatch({ + type: TYPES.listMove, + payload: { fromId, musicInfo, toId }, + }) + dispatch(playerAction.checkPlayList([fromId, musicInfo])) + saveList([global.allList[fromId], global.allList[toId]]) +} + +export const listAddMultiple = ({ id, list }) => (dispatch, getState) => { + dispatch({ + type: TYPES.listAddMultiple, + payload: { id, list }, + }) + dispatch(playerAction.checkPlayList([id])) + saveList(global.allList[id]) +} + +export const listMoveMultiple = ({ fromId, toId, list }) => (dispatch, getState) => { + dispatch({ + type: TYPES.listRemoveMultiple, + payload: { id: fromId, list }, + }) + dispatch({ + type: TYPES.listAddMultiple, + payload: { id: toId, list }, + }) + dispatch(playerAction.checkPlayList([fromId, toId])) + saveList([global.allList[fromId], global.allList[toId]]) +} + +export const listRemove = ({ id, index }) => (dispatch, getState) => { + dispatch({ + type: TYPES.listRemove, + payload: { id, index }, + }) + dispatch(playerAction.checkPlayList([id])) + saveList(global.allList[id]) +} + +export const listRemoveMultiple = ({ id, list }) => (dispatch, getState) => { + dispatch({ + type: TYPES.listRemoveMultiple, + payload: { id, list }, + }) + dispatch(playerAction.checkPlayList([id])) + saveList(global.allList[id]) +} + +export const listClear = id => (dispatch, getState) => { + dispatch({ + type: TYPES.listClear, + payload: id, + }) + dispatch(playerAction.checkPlayList([id])) + saveList(global.allList[id]) +} + +export const updateMusicInfo = ({ id, index, data }) => (dispatch, getState) => { + dispatch({ + type: TYPES.updateMusicInfo, + payload: { id, index, data }, + }) + saveList(global.allList[id]) +} + +export const createUserList = ({ name, id = `userlist_${Date.now()}`, source, sourceListId, list }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.createUserList, + payload: { name, id, source, sourceListId }, + }) + dispatch(listAddMultiple({ id, list })) + await saveList(global.allList[id]) + const state = getState() + await saveListSort(id, state.list.userList.length) + await saveListScrollPosition(id, 0) +} + +export const removeUserList = id => async(dispatch, getState) => { + const { list } = getState() + const index = list.userList.findIndex(l => l.id === id) + if (index < 0) return + dispatch({ + type: TYPES.removeUserList, + payload: index, + }) + await removeList(id) + dispatch(playerAction.checkPlayList([id])) +} + +export const getOtherSource = ({ musicInfo, id }) => (dispatch, getState) => { + return (musicInfo.otherSource && musicInfo.otherSource.length ? Promise.resolve(musicInfo.otherSource) : findMusic(musicInfo)).then(otherSource => { + const targetList = global.allList[id] + if (targetList) { + const index = targetList.indexOf(musicInfo) + if (index > -1) { + dispatch({ + type: TYPES.setOtherSource, + payload: { otherSource, id, index }, + }) + } + } + return otherSource + }) +} + +export const setUserListName = ({ id, name }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.setUserListName, + payload: { id, name }, + }) + await saveList(global.allList[id]) +} +export const setUserListPosition = ({ id, position }) => async(dispatch, getState) => { + dispatch({ + type: TYPES.setUserListPosition, + payload: { id, position }, + }) + await saveList(global.allList[id]) +} +export const setMusicPosition = ({ id, position, list }) => async(dispatch, getState) => { + // const targetList = global.allList[id] + // if (!targetList) return + dispatch({ + type: TYPES.listRemoveMultiple, + payload: { id, list }, + }) + dispatch({ + type: TYPES.setMusicPosition, + payload: { id, position, list }, + }) + dispatch(playerAction.checkPlayList([id])) + await saveList(global.allList[id]) +} + +export const setJumpPosition = isJumpPosition => async(dispatch, getState) => { + dispatch({ + type: TYPES.jumpPosition, + payload: isJumpPosition, + }) +} + +export const clearCache = () => async(dispatch, getState) => { + dispatch({ + type: TYPES.clearCache, + payload: null, + }) + await saveList(Object.values(global.allList)) + await clearMusicUrlAndLyric() +} diff --git a/src/store/modules/list/getter.js b/src/store/modules/list/getter.js new file mode 100644 index 0000000..737909c --- /dev/null +++ b/src/store/modules/list/getter.js @@ -0,0 +1,25 @@ +import { createSelector } from 'reselect' + + +// sourceInfo(state, getters, rootState, { sourceNames }) { +// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList } +// }, +// tags: state => state.tags, +// isVisibleListDetail: state => state.isVisibleListDetail, +// selectListInfo: state => state.selectListInfo, +// listData(state) { +// return state.list +// }, +// listDetail(state) { +// return state.listDetail +// }, + +export const defaultList = state => state.list.defaultList +export const loveList = state => state.list.loveList +export const userList = state => state.list.userList +export const isJumpPosition = state => state.list.isJumpPosition + +export const allList = createSelector([defaultList, loveList, userList], (defaultList, loveList, userList) => { + return [defaultList, loveList, ...userList] +}) + diff --git a/src/store/modules/list/index.js b/src/store/modules/list/index.js new file mode 100644 index 0000000..f9cf685 --- /dev/null +++ b/src/store/modules/list/index.js @@ -0,0 +1,5 @@ +import * as action from './action' +import * as getter from './getter' + +export { action, getter } +export { default as reducer } from './reducer' diff --git a/src/store/modules/list/reducer.js b/src/store/modules/list/reducer.js new file mode 100644 index 0000000..30381f6 --- /dev/null +++ b/src/store/modules/list/reducer.js @@ -0,0 +1,281 @@ +import { TYPES } from './action' + +const allList = global.allList = {} + +const allListInit = (defaultList, loveList, userList) => { + allList[defaultList.id] = defaultList + allList[loveList.id] = loveList + for (const list of userList) allList[list.id] = list +} +const allListUpdate = list => { + allList[list.id] = list +} +const allListRemove = list => { + delete allList[list.id] +} + +// state +const initialState = { + isInitedList: false, + defaultList: { + id: 'default', + name: '试听列表', + list: [], + location: 0, + }, + loveList: { + id: 'love', + name: '我的收藏', + list: [], + location: 0, + }, + tempList: { + id: 'temp', + name: '临时列表', + list: [], + location: 0, + }, + userList: [], + listPosition: {}, + isJumpPosition: false, +} + +const updateStateList = (state, ids) => { + let isClonedUserList = false + let index + for (const id of ids) { + switch (id) { + case state.defaultList.id: + allList[id] = state.defaultList = { ...state.defaultList } + break + case state.loveList.id: + allList[id] = state.loveList = { ...state.loveList } + break + default: + if (!isClonedUserList) { + isClonedUserList = true + state.userList = [...state.userList] + } + index = state.userList.findIndex(l => l.id == id) + if (index < 0) continue + allList[id] = state.userList[index] = { ...state.userList[index] } + break + } + } + return state +} + +const mutations = { + [TYPES.initList](state, { defaultList, loveList, userList }) { + const newState = { ...state } + const ids = [] + if (defaultList != null) { + newState.defaultList = { ...state.defaultList, list: defaultList.list, location: defaultList.location } + ids.push(defaultList.id) + } + if (loveList != null) { + newState.loveList = { ...state.loveList, list: loveList.list, location: loveList.location } + ids.push(loveList.id) + } + if (userList != null) newState.userList = userList + allListInit(newState.defaultList, newState.loveList, newState.userList) + newState.isInitedList = true + return updateStateList(newState, [ids]) + // console.log(allList.default, newState, ids) + // return newState + }, + /* [TYPES.initList](state, { defaultList, loveList, userList }) { + const newState = { ...state } + if (defaultList != null) newState.defaultList = { ...state.defaultList, list: defaultList.list, location: defaultList.location } + if (loveList != null) newState.loveList = { ...state.loveList, list: loveList.list, location: loveList.location } + if (userList != null) newState.userList = userList + allListInit(state.defaultList, state.loveList, state.userList) + state.isInitedList = true + return newState + }, + [TYPES.setList](state, { id, list, name, location }) { + const targetList = allList[id] + if (targetList) { + if (name && targetList.name === name) { + targetList.list.splice(0, targetList.list.length, ...list) + targetList.location = location + return + } + + id += '_' + Math.random() + } + const newList = { + name, + id, + list, + location, + } + allListUpdate(newList) + return { ...state, userList: [...state.userList, newList] } + }, */ + [TYPES.listAdd](state, { id, musicInfo }) { + const targetList = allList[id] + if (!targetList) return state + if (targetList.list.some(s => s.songmid === musicInfo.songmid)) return state + targetList.list = [...targetList.list, musicInfo] + return updateStateList({ ...state }, [id]) + }, + [TYPES.listMove](state, { fromId, musicInfo, toId }) { + const fromList = allList[fromId] + const toList = allList[toId] + if (!fromList || !toList) return state + const newFromList = [...fromList.list] + newFromList.splice(fromList.list.indexOf(musicInfo), 1) + fromList.list = newFromList + const index = toList.list.findIndex(s => s.songmid === musicInfo.songmid) + if (index < 0) { + toList.list = [...toList.list, musicInfo] + } + return updateStateList({ ...state }, [fromId, toId]) + }, + [TYPES.listAddMultiple](state, { id, list }) { + const targetList = allList[id] + if (!targetList) return state + const newList = [...targetList.list, ...list] + const map = {} + const ids = [] + for (const item of newList) { + if (map[item.songmid]) continue + ids.push(item.songmid) + map[item.songmid] = item + } + targetList.list = ids.map(id => map[id]) + return updateStateList({ ...state }, [id]) + }, + [TYPES.listRemove](state, { id, index }) { + const targetList = allList[id] + // console.log(targetList, id, index) + if (!targetList) return state + const newTargetList = [...targetList.list] + newTargetList.splice(index, 1) + targetList.list = newTargetList + return updateStateList({ ...state }, [id]) + }, + [TYPES.listRemoveMultiple](state, { id, list }) { + const targetList = allList[id] + if (!targetList) return state + const map = {} + const ids = [] + for (const item of targetList.list) { + ids.push(item.songmid) + map[item.songmid] = item + } + for (const item of list) { + if (map[item.songmid]) delete map[item.songmid] + } + const newList = [] + for (const id of ids) if (map[id]) newList.push(map[id]) + + targetList.list = newList + return updateStateList({ ...state }, [id]) + }, + [TYPES.listClear](state, id) { + const targetList = allList[id] + if (!targetList) return state + targetList.list = [] + return updateStateList({ ...state }, [id]) + }, + [TYPES.updateMusicInfo](state, { id, index, data }) { + const targetList = allList[id] + if (!targetList) return state + const newTargetList = [...targetList.list] + Object.assign(newTargetList[index], data) + targetList.list = newTargetList + return updateStateList({ ...state }, [id]) + }, + + [TYPES.createUserList](state, { name, id, source, sourceListId }) { + let newList = state.userList.find(item => item.id === id) + if (newList) return state + const newState = { ...state } + newList = { + name, + id, + list: [], + source, + sourceListId, + } + newState.userList = [...state.userList, newList] + allListUpdate(newList) + return newState + }, + [TYPES.removeUserList](state, index) { + const newState = { ...state } + const newUserList = [...newState.userList] + const removedList = newUserList.splice(index, 1)[0] + allListRemove(removedList) + newState.userList = newUserList + return newState + }, + [TYPES.setUserListName](state, { id, name }) { + const targetList = allList[id] + if (!targetList) return state + targetList.name = name + return updateStateList({ ...state }, [id]) + }, + [TYPES.setUserListPosition](state, { id, position }) { + const targetList = allList[id] + if (!targetList) return state + const index = state.userList.findIndex(targetList) + if (index < 0) return state + state.userList.splice(index, 1) + state.userList.splice(index, position, targetList) + return updateStateList({ ...state }, [id]) + }, + [TYPES.setMusicPosition](state, { id, position, list }) { + const targetList = allList[id] + if (!targetList) return state + targetList.list.splice(position - 1, 0, ...list) + return updateStateList({ ...state }, [id]) + }, + // { fromId, toId, list } + // [TYPES.setListScroll](state, { id, location }) { + // const targetList = allList[id] + // if (!targetList) return state + // targetList.location = location + // return updateStateList({ ...state }, [id]) + // }, + [TYPES.setOtherSource](state, { otherSource, id, index }) { + const targetList = allList[id] + if (!targetList) return state + const newTargetList = [...targetList.list] + newTargetList[index].otherSource = otherSource + targetList.list = newTargetList + return updateStateList({ ...state }, [id]) + }, + [TYPES.clearCache](state) { + const lists = Object.values(global.allList) + for (const { list } of lists) { + for (const item of list) { + if (item.otherSource) item.otherSource = null + if (item.typeUrl['128k']) delete item.typeUrl['128k'] + if (item.typeUrl['320k']) delete item.typeUrl['320k'] + if (item.typeUrl.flac) delete item.typeUrl.flac + if (item.typeUrl.wav) delete item.typeUrl.wav + + // PC v1.8.2以前的Lyric + if (item.lxlrc) delete item.lxlrc + if (item.lrc) delete item.lrc + if (item.tlrc) delete item.tlrc + } + } + return state + }, + + [TYPES.jumpPosition](state, isJumpPosition) { + return { + ...state, + isJumpPosition, + } + }, +} + +export default (state = initialState, action) => mutations[action.type] + ? mutations[action.type](state, action.payload) + : state + diff --git a/src/store/modules/player/action.js b/src/store/modules/player/action.js new file mode 100644 index 0000000..b07ae31 --- /dev/null +++ b/src/store/modules/player/action.js @@ -0,0 +1,763 @@ +import { AppState } from 'react-native' +import music from '@/utils/music' +import { initial as msInitial, isInitialized } from '@/plugins/player' +import { + buildTrack, + buildTracks, + playMusic as msPlayMusic, + play, + stop, + pause, + seekTo, + resetPlay, + updateMusicInfo, + getPosition, + destroy as msDestroy, +} from '@/plugins/player/utils' +import { getRandom } from '@/utils' +import { getMusicUrl, saveMusicUrl, getLyric, saveLyric, assertApiSupport, savePlayInfo } from '@/utils/tools' +import { setData } from '@/plugins/storage' +import { storageDataPrefix } from '@/config' +import { playInfo as playInfoGetter } from './getter' +import { play as lrcPlay, setLyric, pause as lrcPause } from '@/plugins/lyric' +import { action as listAction } from '@/store/modules/list' +import { LIST_ID_PLAY_LATER } from '@/config/constant' +import { defaultList } from '../list/getter' + +const listPrefix = storageDataPrefix.list + +export const TYPES = { + setPic: null, + setList: null, + setPlayIndex: null, + addMusicToPlayedList: null, + removeMusicFormPlayedList: null, + clearPlayedList: null, + visiblePlayerDetail: null, + playNext: null, + playPrev: null, + setStatus: null, + setGetingUrlState: null, + setPlayMusicInfo: null, + setTempPlayList: null, + removeTempPlayList: null, + clearTempPlayeList: null, + updateListInfo: null, +} + +export const STATUS = { + none: 'NONE', + playing: 'PLAYING', + pause: 'PAUSE', + stop: 'STOP', + error: 'ERROR', + buffering: 'BUFFERING', + connecting: 'CONNECTING', + gettingUrl: 'GETTING_URL', +} + +for (const key of Object.keys(TYPES)) { + TYPES[key] = `player__${key}` +} + +let timeout +let _playMusicInfo = null +let playMusicId = null +// let nextMusic = null + +const getPlayType = (state, songInfo) => { + let type = '128k' + const list = state.common.qualityList[songInfo.source] + if (state.common.setting.player.isHighQuality && songInfo._types['320k'] && list && list.includes('320k')) type = '320k' + return type +} + +// const handleRestorePlay = (state, dispatch, playMusicInfo, musicInfo) => { +// if (!musicInfo.img) { +// dispatch(getPic(musicInfo)).then(async() => { +// if (playMusicId != id) return +// const musicUrl = await getMusicUrl(musicInfo, type) +// if (musicUrl) { +// console.log('+++updateMusicInfo+++') +// // setTimeout(() => { +// updateMusicInfo(buildTrack(musicInfo, type, musicUrl)) +// // }, 1000) +// } +// }) +// } +// dispatch(getLrc(musicInfo)).then(({ lyric, tlyric }) => { +// if (playMusicId != id) return +// setLyric(lyric) +// const player = getState().player +// if (player.status == STATUS.playing && !player.isGettingUrl) { +// getPosition().then(position => { +// lrcPlay(position * 1000) +// }) +// } +// }) +// if (state.common.setting.player.togglePlayMethod == 'random') dispatch({ type: TYPES.addMusicToPlayedList, payload: playMusicInfo }) +// } + +const handlePlayMusic = async({ getState, dispatch, playMusicInfo, musicInfo, isRefresh = false, time = 0 }) => { + const state = getState() + + // if (global.restorePlayInfo) { + // handleRestorePlay(state, dispatch, playMusicInfo, musicInfo) + + // global.restorePlayInfo = null + // return + // } + + const type = getPlayType(state, musicInfo) + if (timeout) { + clearTimeout(timeout) + timeout = null + } + setLyric('') + console.log('Handle Play Music ====================>', musicInfo.name) + _playMusicInfo = musicInfo + let id = `${musicInfo.source}//${musicInfo.songmid}//${type}` + playMusicId = id + + if (global.restorePlayInfo) { + const track = buildTrack(musicInfo, type) + track.id += track.id + '//restorePlay' + playMusicId = playMusicId + '//restorePlay' + msPlayMusic([track]) + return + } + + dispatch(setGetingUrlState(true)) + dispatch(setStatus({ + status: STATUS.gettingUrl, + text: '加载中...', + })) + Promise.all([ + dispatch(getUrl({ musicInfo, type, isRefresh })), + resetPlay(), + ]).then(([url]) => { + // console.log('url get done', getState().player.status) + if (playMusicId != id) return + switch (getState().player.status) { + case STATUS.stop: + case STATUS.pause: + return + } + msPlayMusic(buildTracks(musicInfo, type, url, true), time) + }).catch(err => { + if (playMusicId != id) return + dispatch(setStatus({ status: STATUS.error, text: err.message })) + if (AppState.currentState == 'active') { + console.log('wait 2s...') + timeout = setTimeout(() => { + console.log('play next music') + dispatch(playNext()) + }, 2000) + } else { + console.log('play next music') + dispatch(playNext()) + } + }).finally(() => { + if (playMusicId != id) return + if (getState().player.isGettingUrl) dispatch(setGetingUrlState(false)) + // console.log('set url getting done') + }) + // console.log(AppState.currentState) + if (!isRefresh && state.common.setting.player.togglePlayMethod == 'random') dispatch({ type: TYPES.addMusicToPlayedList, payload: playMusicInfo }) + + console.log(musicInfo.img) + if (!musicInfo.img) { + dispatch(getPic(musicInfo)).then(async() => { + if (playMusicId != id) return + const musicUrl = await getMusicUrl(musicInfo, type) + if (musicUrl) { + // console.log('+++updateMusicInfo+++') + // setTimeout(() => { + updateMusicInfo(buildTrack(musicInfo, type, musicUrl)) + // }, 1000) + } + }) + } + dispatch(getLrc(musicInfo)).then(({ lyric, tlyric }) => { + if (playMusicId != id) return + setLyric(lyric) + const player = getState().player + if (player.status == STATUS.playing && !player.isGettingUrl) { + getPosition().then(position => { + lrcPlay(position * 1000) + }) + } + }) + + // nextMusic = getNextMusicInfo(state) + const playInfo = playInfoGetter(getState()) + + if (!playInfo.isTempPlay) { + savePlayInfo({ + time: 0, + maxTime: playInfo.musicInfo.interval || 0, + listId: playInfo.listId, + list: playInfo.listId == null ? playInfo.list : null, + index: playInfo.playIndex, + }) + } +} +/* +const getNextMusicInfo = state => { + const currentMusic = state.player.listInfo.list[state.player.playIndex] + let playedList = [...state.player.playedList] + const currentList = state.player.listInfo.list + if (state.common.setting.player.togglePlayMethod == 'random' && state.player.playedList.length) { + let index = playedList.indexOf(currentMusic) + index += 1 + while (true) { + if (index < playedList.length) { + const listIndex = currentList.indexOf(playedList[index]) + if (listIndex < 0) { + playedList.splice(index, 1) + continue + } + return currentList[listIndex] + } + break + } + } + let list + while (true) { + const tempPlayedList = [...playedList] + list = currentList.filter(s => { + const index = tempPlayedList.indexOf(s) + if (index > -1) { + tempPlayedList.splice(index, 1) + return false + } + return assertApiSupport(s.source) + }) + + if (!list.length && playedList.length) { + playedList = [] + continue + } + break + } + + if (!list.length) return null + + const playIndex = list.indexOf(currentMusic) + let index + // console.log(playIndex, list) + switch (state.common.setting.player.togglePlayMethod) { + case 'listLoop': + index = playIndex === list.length - 1 ? 0 : playIndex + 1 + break + case 'random': + index = getRandom(0, list.length) + break + case 'list': + index = playIndex === list.length - 1 ? -1 : playIndex + 1 + break + case 'singleLoop': + index = playIndex + break + default: + return + } + if (index < 0) return null + return list[index] +} + */ +export const stopMusic = () => async(dispatch, getState) => { + _playMusicInfo = null + dispatch(setPlayIndex(-1)) + dispatch(setStatus({ status: STATUS.stop, text: '' })) + await stop() +} + +export const pauseMusic = () => async(dispatch, getState) => { + const state = getState() + if (state.isGettingUrl) { + dispatch(setStatus({ status: STATUS.pause, text: '已暂停' })) + return + } + lrcPause() + dispatch(setStatus({ status: STATUS.pause, text: '已暂停' })) + await pause() +} + +export const setStatus = ({ status, text }) => { + console.log(status, text) + return { + type: TYPES.setStatus, + payload: { status, text }, + } +} + + +const handleGetUrl = function(dispatch, listId, musicInfo, type, retryedSource = [], originMusic) { + // console.log(musicInfo.source) + if (!originMusic) originMusic = musicInfo + let reqPromise + try { + reqPromise = music[musicInfo.source].getMusicUrl(musicInfo, type).promise + } catch (err) { + reqPromise = Promise.reject(err) + } + return reqPromise.catch(err => { + if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) + return dispatch(listAction.getOtherSource({ musicInfo: originMusic, listId })).then(otherSource => { + console.log('find otherSource', otherSource.map(s => s.source)) + if (otherSource.length) { + for (const item of otherSource) { + if (retryedSource.includes(item.source) || !assertApiSupport(item.source)) continue + console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) + return handleGetUrl(dispatch, listId, item, type, retryedSource, originMusic) + } + } + return Promise.reject(err) + }) + }) +} +const handleGetPic = function(dispatch, listId, musicInfo, retryedSource = [], originMusic) { + // console.log(musicInfo.source) + if (!originMusic) originMusic = musicInfo + let reqPromise + try { + reqPromise = music[musicInfo.source].getPic(musicInfo).promise + } catch (err) { + reqPromise = Promise.reject(err) + } + return reqPromise.catch(err => { + if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) + return dispatch(listAction.getOtherSource({ musicInfo: originMusic, listId })).then(otherSource => { + console.log('find otherSource', otherSource.map(s => s.source)) + if (otherSource.length) { + for (const item of otherSource) { + if (retryedSource.includes(item.source)) continue + console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) + return handleGetPic(dispatch, listId, item, retryedSource, originMusic) + } + } + return Promise.reject(err) + }) + }) +} +const handleGetLyric = function(dispatch, listId, musicInfo, retryedSource = [], originMusic) { + if (!originMusic) originMusic = musicInfo + let reqPromise + try { + reqPromise = music[musicInfo.source].getLyric(musicInfo).promise + } catch (err) { + reqPromise = Promise.reject(err) + } + return reqPromise.catch(err => { + if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) + return dispatch(listAction.getOtherSource({ musicInfo: originMusic, listId })).then(otherSource => { + console.log('find otherSource', otherSource.map(s => s.source)) + if (otherSource.length) { + for (const item of otherSource) { + if (retryedSource.includes(item.source)) continue + console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) + return handleGetLyric(dispatch, listId, item, retryedSource, originMusic) + } + } + return Promise.reject(err) + }) + }) +} + +export const getUrl = ({ musicInfo, type, isRefresh }) => async(dispatch, getState) => { + const cachedUrl = await getMusicUrl(musicInfo, type) + if (cachedUrl && !isRefresh) { + if (getState().player.isGettingUrl) dispatch(setGetingUrlState(false)) + return cachedUrl + } + dispatch(setStatus({ + status: STATUS.gettingUrl, + text: isRefresh ? 'URL刷新中...' : 'URL获取中...', + })) + + return handleGetUrl(dispatch, getState().player.listInfo.id, musicInfo, type).then(result => { + saveMusicUrl(musicInfo, type, result.url) + console.log('get' + musicInfo.name + ' url success: ' + result.url) + return result.url + }).catch(err => { + console.log('get' + musicInfo.name + ' url fail: ' + err.message) + return Promise.reject(err) + }) +} + +export const refreshMusicUrl = (musicInfo, restorePlayTime) => (dispatch, getState) => { + const state = getState() + const targetMusic = state.player.listInfo.list.find(s => s.songmid == musicInfo.songmid) + if (!targetMusic) { + console.log('[refreshMusicUrl]Not found target music: ', musicInfo.name) + dispatch(playNext()) + return + } + const index = state.player.listInfo.list.indexOf(targetMusic) + handlePlayMusic({ + getState, + dispatch, + index, + musicInfo: targetMusic, + isRefresh: true, + time: restorePlayTime, + }) +} + +export const playMusic = playMusicInfo => async(dispatch, getState) => { + // console.log(playMusicInfo) + const { player, common } = getState() + + if (!isInitialized()) await msInitial(common.setting.player.cacheSize) + + // 从暂停播放恢复播放 + if (playMusicInfo === undefined) { + if (player.isGettingUrl || !_playMusicInfo) return + // console.log(player.isGettingUrl, _playMusicInfo) + if (/\/\/restorePlay$/.test(playMusicId) || player.status == STATUS.none) { + handlePlayMusic({ + getState, + dispatch, + playMusicInfo: player.playMusicInfo, + musicInfo: player.playMusicInfo.musicInfo, + }) + return + } + console.log('play') + await play() + return + } + + // 停止播放 + let playIndex = player.playIndex + if (playMusicInfo === null) { + playIndex = -1 + dispatch({ + type: TYPES.setPlayMusicInfo, + payload: { + playMusicInfo, + playIndex, + }, + }) + await stop() + } else { // 设置歌曲信息并播放歌曲 + setLyric('') + let listId = playMusicInfo.listId + // console.log(playMusicInfo) + if (listId != LIST_ID_PLAY_LATER && !playMusicInfo.isTempPlay && listId === player.listInfo.id) playIndex = player.listInfo.list.indexOf(playMusicInfo.musicInfo) + dispatch({ + type: TYPES.setPlayMusicInfo, + payload: { + playMusicInfo, + playIndex, + }, + }) + handlePlayMusic({ + getState, + dispatch, + playMusicInfo, + musicInfo: playMusicInfo.musicInfo, + }) + } +} + +export const setProgress = time => async(dispatch, getState) => { + const { player } = getState() + if (player.isGettingUrl || !_playMusicInfo) return + await seekTo(time) + if (player.status != STATUS.playing) dispatch(playMusic()) +} + +export const getPic = musicInfo => (dispatch, getState) => { + return handleGetPic(dispatch, getState().player.listInfo.id, musicInfo).then(url => { + // picRequest = null + dispatch({ type: TYPES.setPic, payload: { musicInfo, url } }) + const state = getState() + if (state.player.listInfo.id) setData(listPrefix + state.player.listInfo.id, global.allList[state.player.listInfo.id]) + }).catch(err => { + // picRequest = null + return Promise.reject(err) + }) +} +export const getLrc = musicInfo => async(dispatch, getState) => { + let lyricInfo = await getLyric(musicInfo) + if (lyricInfo.lyric && lyricInfo.tlyric != null) return lyricInfo + + return handleGetLyric(dispatch, getState().player.listInfo.id, musicInfo).then(({ lyric, tlyric }) => { + // picRequest = null + lyricInfo = { lyric, tlyric } + saveLyric(musicInfo, lyricInfo) + return lyricInfo + }).catch(err => { + // picRequest = null + return Promise.reject(err) + }) +} + +export const setList = ({ list, index }) => (dispatch, getState) => { + dispatch(setListInfo(list)) + + const state = getState() + if (state.player.playedList.length) dispatch({ type: TYPES.clearPlayedList }) + if (state.player.tempPlayList.length) dispatch({ type: TYPES.clearTempPlayeList }) + return dispatch(playMusic({ + musicInfo: list.list[index], + listId: list.id, + })) +} + +const filterList = async({ playedList, listInfo, savePath, dispatch }) => { + // if (this.list.listName === null) return + let list + let canPlayList = [] + const filteredPlayedList = playedList.filter(({ listId, isTempPlay }) => listInfo.id === listId && !isTempPlay).map(({ musicInfo }) => musicInfo) + if (listInfo.id == 'download') { + list = [] + // for (const item of listInfo.list) { + // const filePath = path.join(savePath, item.fileName) + // if (!await checkPath(filePath) || !item.isComplate || /\.ape$/.test(filePath)) continue + + // canPlayList.push(item) + + // // 排除已播放音乐 + // let index = filteredPlayedList.indexOf(item) + // if (index > -1) { + // filteredPlayedList.splice(index, 1) + // continue + // } + // list.push(item) + // } + } else { + list = listInfo.list.filter(s => { + // if (!assertApiSupport(s.source)) return false + canPlayList.push(s) + + let index = filteredPlayedList.indexOf(s) + if (index > -1) { + filteredPlayedList.splice(index, 1) + return false + } + return true + }) + } + if (!list.length && playedList.length) { + dispatch({ type: TYPES.clearPlayedList }) + return canPlayList + } + return list +} + +export const playPrev = () => async(dispatch, getState) => { + const { player, common } = getState() + const currentListId = player.listInfo.id + const currentList = player.listInfo.list + + if (player.playedList.length) { + // 从已播放列表移除播放列表已删除的歌曲 + let index + for (index = player.playedList.indexOf(player.playMusicInfo) - 1; index > -1; index--) { + const playMusicInfo = player.playedList[index] + if (playMusicInfo.listId == currentListId && !currentList.includes(playMusicInfo.musicInfo)) { + dispatch({ type: TYPES.removeMusicFormPlayedList, payload: index }) + continue + } + break + } + + if (index > -1) { + dispatch(playMusic(player.playedList[index])) + return + } + } + + let filteredList = await filterList({ + listInfo: player.listInfo, + playedList: player.playedList, + savePath: common.setting.download.savePath, + dispatch, + }) + + if (!filteredList.length) return dispatch(playMusic(null)) + const playInfo = playInfoGetter(getState()) + let currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex]) + if (currentIndex == -1) currentIndex = 0 + let nextIndex = currentIndex + if (!playInfo.isTempPlay) { + switch (common.setting.player.togglePlayMethod) { + case 'random': + nextIndex = getRandom(0, filteredList.length) + break + case 'listLoop': + case 'list': + nextIndex = currentIndex === 0 ? filteredList.length - 1 : currentIndex - 1 + break + case 'singleLoop': + break + default: + nextIndex = -1 + return + } + if (nextIndex < 0) return + } + + dispatch(playMusic({ + musicInfo: filteredList[nextIndex], + listId: currentListId, + })) +} + +export const playNext = () => async(dispatch, getState) => { + const { player, common } = getState() + if (player.tempPlayList.length) { + const playMusicInfo = player.tempPlayList[0] + dispatch(removeTempPlayList(0)) + dispatch(playMusic(playMusicInfo)) + return + } + const currentListId = player.listInfo.id + const currentList = player.listInfo.list + if (player.playedList.length) { + // 从已播放列表移除播放列表已删除的歌曲 + let index + for (index = player.playedList.indexOf(player.playMusicInfo) + 1; index < player.playedList.length; index++) { + const playMusicInfo = player.playedList[index] + if (playMusicInfo.listId == currentListId && !currentList.includes(playMusicInfo.musicInfo)) { + dispatch({ type: TYPES.removeMusicFormPlayedList, payload: index }) + continue + } + break + } + + if (index < player.playedList.length) { + dispatch(playMusic(player.playedList[index])) + return + } + } + + let filteredList = await filterList({ + listInfo: player.listInfo, + playedList: player.playedList, + savePath: common.setting.download.savePath, + dispatch, + }) + + // console.log(filteredList) + if (!filteredList.length) return dispatch(playMusic(null)) + const playInfo = playInfoGetter(getState()) + const currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex]) + let nextIndex = currentIndex + switch (common.setting.player.togglePlayMethod) { + case 'listLoop': + nextIndex = currentIndex === filteredList.length - 1 ? 0 : currentIndex + 1 + break + case 'random': + nextIndex = getRandom(0, filteredList.length) + break + case 'list': + nextIndex = currentIndex === filteredList.length - 1 ? -1 : currentIndex + 1 + break + case 'singleLoop': + break + default: + nextIndex = -1 + return + } + if (nextIndex < 0) return + + dispatch(playMusic({ + musicInfo: filteredList[nextIndex], + listId: currentListId, + })) +} + + +export const setPlayIndex = index => ({ + type: TYPES.setPlayIndex, + payload: index, +}) + +export const addMusicToPlayedList = playMusicInfo => ({ + type: TYPES.addMusicToPlayedList, + payload: playMusicInfo, +}) + +export const removeMusicFormPlayedList = index => ({ + type: TYPES.removeMusicFormPlayedList, + payload: index, +}) + +export const clearPlayedList = () => ({ + type: TYPES.clearPlayedList, +}) + +export const visiblePlayerDetail = visible => ({ + type: TYPES.visiblePlayerDetail, + payload: visible, +}) + +export const setGetingUrlState = flag => ({ + type: TYPES.setGetingUrlState, + payload: flag, +}) +export const setTempPlayList = list => (dispatch, getState) => { + dispatch({ + type: TYPES.setTempPlayList, + payload: list.map(({ musicInfo, listId }) => ({ musicInfo, listId, isTempPlay: true })), + }) + if (!getState().player.playMusicInfo) dispatch(playNext()) +} +export const removeTempPlayList = index => ({ + type: TYPES.removeTempPlayList, + payload: index, +}) + +export const setListInfo = listInfo => ({ + type: TYPES.setList, + payload: listInfo, +}) + +export const checkPlayList = listIds => async(dispatch, getState) => { + const { player, list: listState } = getState() + if (!_playMusicInfo || !listIds.some(id => player.listInfo.id === id)) return + const listInfo = global.allList[player.listInfo.id] + if (!listInfo) { + if (listState.defaultList.list.length) { + await dispatch(setList({ list: listState.defaultList, index: 0 })) + } else { + await dispatch(stopMusic()) + } + return + } + + const isChnagedList = listInfo !== player.listInfo + + const list = listInfo.list + + // let index = this.listId == 'download' + // ? n.findIndex(s => s.musicInfo.songmid === this.musicInfo.songmid) + // : n.findIndex(s => s.songmid === this.musicInfo.songmid) + let index = list.indexOf(_playMusicInfo) + // console.log(index) + if (index < 0) { + // console.log(this.playIndex) + if (list.length) { + dispatch(setPlayIndex(Math.min(player.playIndex - 1, list.length - 1))) + if (isChnagedList) dispatch(setListInfo(listInfo)) + await dispatch(playNext()) + } else { + if (isChnagedList) dispatch(setListInfo(listInfo)) + await dispatch(stopMusic()) + } + } else { + // console.log(isChnagedList) + if (isChnagedList) dispatch(setListInfo(listInfo)) + dispatch(setPlayIndex(index)) + } + // console.log(this.playIndex) +} + +export const destroy = () => async(dispatch, getState) => { + await msDestroy() + dispatch(setStatus({ status: STATUS.none, text: '' })) +} diff --git a/src/store/modules/player/getter.js b/src/store/modules/player/getter.js new file mode 100644 index 0000000..9efd7a9 --- /dev/null +++ b/src/store/modules/player/getter.js @@ -0,0 +1,63 @@ +import { createSelector } from 'reselect' +import { LIST_ID_PLAY_TEMP, LIST_ID_PLAY_LATER } from '@/config/constant' + + +// sourceInfo(state, getters, rootState, { sourceNames }) { +// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList } +// }, +// tags: state => state.tags, +// isVisibleListDetail: state => state.isVisibleListDetail, +// selectListInfo: state => state.selectListInfo, +// listData(state) { +// return state.list +// }, +// listDetail(state) { +// return state.listDetail +// }, + +export const player = state => state.player + +export const playIndex = state => state.player.playIndex + +export const status = state => state.player.status + +export const isGettingUrl = state => state.player.isGettingUrl + +export const statusText = state => state.player.statusText + +export const listInfo = state => state.player.listInfo + +export const playList = state => state.player.listInfo.list + +export const playMusicInfo = state => state.player.playMusicInfo + +export const playInfo = createSelector([playMusicInfo, listInfo, playIndex], (playMusicInfo, listInfo, playIndex) => { + if (playMusicInfo == null) return { listId: null, playIndex: -1, playListId: null, listPlayIndex: -1, isPlayList: false, musicInfo: null } + const playListId = listInfo.id + let listId = playMusicInfo.listId + const isTempPlay = !!playMusicInfo.isTempPlay + const isPlayList = listId === playListId + let newPlayIndex = -1 + let listPlayIndex = playIndex + + if (listId != LIST_ID_PLAY_LATER) { + if (isPlayList) { + newPlayIndex = listInfo.list.indexOf(playMusicInfo.musicInfo) + if (!isTempPlay) listPlayIndex = newPlayIndex + } else { + let list = global.allList[listId] + if (list) newPlayIndex = list.list.indexOf(playMusicInfo.musicInfo) + } + } + + return { + listId, + list: listInfo.list, + playIndex: newPlayIndex, + playListId, + listPlayIndex, + isPlayList, + isTempPlay, + musicInfo: playMusicInfo.musicInfo, + } +}) diff --git a/src/store/modules/player/index.js b/src/store/modules/player/index.js new file mode 100644 index 0000000..6f426f8 --- /dev/null +++ b/src/store/modules/player/index.js @@ -0,0 +1,7 @@ +import * as actions from './action' +import * as getter from './getter' + +const { STATUS, ...action } = actions + +export { action, getter, STATUS } +export { default as reducer } from './reducer' diff --git a/src/store/modules/player/reducer.js b/src/store/modules/player/reducer.js new file mode 100644 index 0000000..b9cb2d0 --- /dev/null +++ b/src/store/modules/player/reducer.js @@ -0,0 +1,120 @@ +import { TYPES, STATUS } from './action' + +const initialState = { + listInfo: { + list: [], + id: null, + }, + playIndex: -1, + isShowPlayerDetail: false, + playedList: [], + + playMusicInfo: null, + tempPlayList: [], + + statusText: '', + status: STATUS.none, + isGettingUrl: false, +} + + +// mitations +const mutations = { + [TYPES.setPic](state, datas) { + const targetMusic = state.listInfo.list.find(s => s.songmid === datas.musicInfo.songmid) + // console.log('+++++++targetMusic+++++++', targetMusic) + if (!targetMusic) return state + targetMusic.img = datas.url + const newState = { ...state } + if (state.playMusicInfo.musicInfo.source == datas.musicInfo.source && state.playMusicInfo.musicInfo.songmid === datas.musicInfo.songmid) { + const newPlayMusicInfo = { ...newState.playMusicInfo } + let index = newState.playedList.indexOf(newState.playMusicInfo) + if (index > -1) newState.playedList.splice(index, 1, newPlayMusicInfo) + newState.playMusicInfo = newPlayMusicInfo + } + return newState + }, + [TYPES.setList](state, list) { + return { + ...state, + listInfo: list, + } + }, + [TYPES.setPlayIndex](state, index) { + return { + ...state, + playIndex: index, + } + // console.log(state.changePlay) + }, + [TYPES.addMusicToPlayedList](state, playMusicInfo) { + if (state.playedList.includes(playMusicInfo)) return state + state.playedList.push(playMusicInfo) + return { + ...state, + } + }, + [TYPES.removeMusicFormPlayedList](state, index) { + state.playedList.splice(index, 1) + return { + ...state, + } + }, + [TYPES.clearPlayedList](state) { + return { + ...state, + playedList: [], + } + }, + [TYPES.visiblePlayerDetail](state, visible) { + return { + ...state, + isShowPlayerDetail: visible, + } + }, + [TYPES.setStatus](state, { status, text }) { + const newState = { ...state } + if (status != null) newState.status = status + if (text != null) newState.statusText = text + return newState + }, + [TYPES.setGetingUrlState](state, flag) { + return { + ...state, + isGettingUrl: flag, + } + }, + [TYPES.setTempPlayList](state, list) { + return { + ...state, + tempPlayList: [...state.tempPlayList, ...list], + } + }, + [TYPES.removeTempPlayList](state, index) { + const tempPlayList = [...state.tempPlayList] + tempPlayList.splice(index, 1) + return { + ...state, + tempPlayList, + } + }, + [TYPES.clearTempPlayeList](state) { + return { + ...state, + tempPlayList: [], + } + }, + [TYPES.setPlayMusicInfo](state, { playMusicInfo, playIndex }) { + return { + ...state, + playMusicInfo: playMusicInfo, + playIndex: playIndex, + } + }, +} + +export default (state = initialState, action) => + mutations[action.type] + ? mutations[action.type](state, action.payload) + : state + diff --git a/src/store/modules/search/action.js b/src/store/modules/search/action.js new file mode 100644 index 0000000..deabf8a --- /dev/null +++ b/src/store/modules/search/action.js @@ -0,0 +1,88 @@ +import music from '@/utils/music' + +export const TYPES = { + loading: null, + setText: null, + addHistory: null, + setList: null, + setLists: null, + clearList: null, + removeHistory: null, + clearHistory: null, + setTipList: null, + setVisibleTipList: null, +} +for (const key of Object.keys(TYPES)) { + TYPES[key] = `search__${key}` +} + +const sources = [] +for (const source of music.sources) { + const musicSearch = music[source.id].musicSearch + if (!musicSearch) continue + sources.push(source) +} + +export const search = ({ page, limit }) => (dispatch, getState) => { + // dispatch({ type: TYPES.setText, payload: text }) + const state = getState() + const text = state.search.text + if (!text.length) { + dispatch({ type: TYPES.clearList }) + return Promise.resolve() + } + dispatch({ type: TYPES.addHistory, payload: text }) + + + if (state.common.setting.search.searchSource == 'all') { + const task = [] + for (const source of sources) { + if (source.id == 'all') continue + dispatch({ type: TYPES.loading, payload: true }) + task.push(music[source.id].musicSearch.search(text, page).catch(error => { + console.log(error) + return { + allPage: 1, + limit: 30, + list: [], + source: source.id, + total: 0, + } + })) + } + return Promise.all(task).then(results => dispatch({ type: TYPES.setLists, payload: { results, page } })) + .finally(() => dispatch({ type: TYPES.loading, payload: false })) + } else { + dispatch({ type: TYPES.loading, payload: true }) + return music[state.common.setting.search.searchSource].musicSearch.search(text, page, limit).catch(error => { + console.log(error) + return { + allPage: 1, + limit: 30, + list: [], + source: state.common.setting.search.searchSource, + total: 0, + } + }).then(data => dispatch({ type: TYPES.setList, payload: { page, ...data } })) + .finally(() => dispatch({ type: TYPES.loading, payload: false })) + } +} + +export const setText = text => ({ type: TYPES.setText, payload: text }) +export const setTipList = list => ({ type: TYPES.setTipList, payload: list }) +export const setVisibleTipList = visible => ({ type: TYPES.setVisibleTipList, payload: visible }) + +export const clearList = () => ({ + type: TYPES.clearList, +}) +export const addHistory = text => ({ + type: TYPES.addHistory, + payload: text, +}) +export const removeHistory = index => ({ + type: TYPES.addHistory, + payload: index, +}) +export const clearHistory = () => ({ + type: TYPES.addHistory, +}) diff --git a/src/store/modules/search/getter.js b/src/store/modules/search/getter.js new file mode 100644 index 0000000..ebf7266 --- /dev/null +++ b/src/store/modules/search/getter.js @@ -0,0 +1,33 @@ +import { createSelector } from 'reselect' + + +export const text = state => state.search.text +export const sourceList = state => state.search.sourceList +export const aggregationListInfo = state => state.search.aggregationListInfo +export const isEnd = state => state.search.isEnd +export const isLoading = state => state.search.isLoading + +export const tipList = state => state.search.tipInfo.list +export const tipListVisible = state => state.search.tipInfo.visible + + +export const rawSources = state => state.search.sources +export const tempSearchSource = state => state.common.setting.search.tempSearchSource +export const searchSource = state => state.common.setting.search.searchSource + + +export const sources = createSelector([rawSources], sources => { + return sources.map(source => ({ label: source.name, id: source.id })) +}) + + +export const currentSourceName = createSelector([rawSources, searchSource], (sources, searchSource) => { + const source = sources.find(s => s.id == searchSource) + return source ? source.name : 'unknown' +}) + +export const listInfo = createSelector([searchSource, sourceList, aggregationListInfo], (searchSource, sourceList, aggregationListInfo) => { + return searchSource == 'all' + ? aggregationListInfo + : sourceList[searchSource] +}) diff --git a/src/store/modules/search/index.js b/src/store/modules/search/index.js new file mode 100644 index 0000000..f9cf685 --- /dev/null +++ b/src/store/modules/search/index.js @@ -0,0 +1,5 @@ +import * as action from './action' +import * as getter from './getter' + +export { action, getter } +export { default as reducer } from './reducer' diff --git a/src/store/modules/search/reducer.js b/src/store/modules/search/reducer.js new file mode 100644 index 0000000..a282f9b --- /dev/null +++ b/src/store/modules/search/reducer.js @@ -0,0 +1,248 @@ +import { TYPES } from './action' + +import music from '@/utils/music' + +let historyList +if (historyList == null) { + historyList = [] + // electronStore_data.set('searchHistoryList', historyList) +} + +const sources = [] +const sourceList = {} +for (const source of music.sources) { + const musicSearch = music[source.id].musicSearch + if (!musicSearch) continue + sources.push(source) + sourceList[source.id] = { + page: 1, + maxPage: 0, + limit: 30, + total: 0, + list: [], + } +} + +// sources.push({ +// id: 'all', +// name: '聚合搜索', +// }) + +const initialState = { + text: '', + historyList, + sources, + isEnd: false, + isLoading: false, + sourceList, + aggregationListInfo: { + list: [], + page: 1, + limit: 30, + maxPage: 1, + total: 0, + }, + tipInfo: { + list: [], + visible: false, + }, +} + + +// https://blog.csdn.net/xcxy2015/article/details/77164126#comments +const similar = (a, b) => { + if (!a || !b) return 0 + if (a.length > b.length) { // 保证 a <= b + const t = b + b = a + a = t + } + const al = a.length + const bl = b.length + const mp = [] // 一个表 + let i, j, ai, lt, tmp // ai:字符串a的第i个字符。 lt:左上角的值。 tmp:暂存新的值。 + for (i = 0; i <= bl; i++) mp[i] = i + for (i = 1; i <= al; i++) { + ai = a.charAt(i - 1) + lt = mp[0] + mp[0] = mp[0] + 1 + for (j = 1; j <= bl; j++) { + tmp = Math.min(mp[j] + 1, mp[j - 1] + 1, lt + (ai == b.charAt(j - 1) ? 0 : 1)) + lt = mp[j] + mp[j] = tmp + } + } + return 1 - (mp[bl] / bl) +} + +const sortInsert = (arr, data) => { + const key = data.num + let left = 0 + let right = arr.length - 1 + + while (left <= right) { + const middle = parseInt((left + right) / 2) + if (key == arr[middle]) { + left = middle + break + } else if (key < arr[middle].num) { + right = middle - 1 + } else { + left = middle + 1 + } + } + while (left > 0) { + if (arr[left - 1].num != key) break + left-- + } + + arr.splice(left, 0, data) +} + +const handleSortList = (list, keyword) => { + const arr = [] + for (const item of list) { + sortInsert(arr, { + num: similar(keyword, `${item.name} ${item.singer}`), + data: item, + }) + } + return arr.map(item => item.data).reverse() +} + +const filterList = list => { + const set = new Set() + for (let i = list.length - 1; i > -1; i--) { + const item = list[i] + if (set.has(item.songmid)) { + list.splice(i, 1) + } else { + set.add(item.songmid) + } + } + return list +} + +const mutations = { + [TYPES.loading](state, isLoading) { + return { + ...state, + isLoading, + } + }, + [TYPES.setText](state, text) { + return { + ...state, + text, + } + }, + [TYPES.addHistory](state, text) { + let historyList = [...state.historyList] + const index = historyList.indexOf(text) + if (index > -1) historyList.splice(index, 1) + if (historyList.length >= 15) historyList = historyList.slice(0, 14) + historyList.unshift(text) + return { + ...state, + historyList, + } + }, + [TYPES.setList](state, datas) { + const source = { ...state.sourceList[datas.source] } + source.list = datas.page > 1 ? filterList([...source.list, ...datas.list]) : datas.list + source.total = datas.total + source.maxPage = datas.allPage + source.page = datas.page + state.isEnd = datas.page >= source.maxPage + // source.limit = datas.limit + + return { + ...state, + sourceList: { + ...state.sourceList, + [datas.source]: source, + }, + } + }, + [TYPES.setLists](state, { results, page }) { + const pages = [] + let total = 0 + // let limit = 0 + let maxPage = 1 + const list = [] + state = { ...state } + const aggregationListInfo = { ...state.aggregationListInfo } + for (const source of results) { + if (source.allPage < page) continue + list.push(...source.list) + pages.push(source.allPage) + total += source.total + // limit = Math.max(source.limit, limit) + maxPage = Math.max(source.allPage, maxPage) + } + aggregationListInfo.maxPage = Math.max(...pages) + aggregationListInfo.total = total + // aggregationListInfo.limit = limit + aggregationListInfo.page = page + aggregationListInfo.maxPage = maxPage + aggregationListInfo.list = page > 1 ? filterList([...aggregationListInfo.list, ...handleSortList(list, state.text)]) : handleSortList(list, state.text) + aggregationListInfo.isEnd = aggregationListInfo.maxPage >= page + return state + }, + [TYPES.clearList](state) { + state = { ...state } + state.sourceList = { ...state.sourceList } + for (const source of Object.keys(state.sourceList)) { + state.sourceList[source] = { ...state.sourceList[source] } + state.sourceList[source].list = [] + state.sourceList[source].page = 0 + state.sourceList[source].maxPage = 1 + state.sourceList[source].total = 0 + } + const aggregationListInfo = { ...state.aggregationListInfo } + aggregationListInfo.list = [] + aggregationListInfo.page = 0 + aggregationListInfo.maxPage = 1 + aggregationListInfo.total = 0 + state.text = '' + state.isEnd = false + return state + }, + [TYPES.removeHistory](state, index) { + const historyList = [...state.historyList] + historyList.splice(index, 1) + return { + ...state, + historyList, + } + }, + [TYPES.clearHistory](state) { + return { + ...state, + historyList: [], + } + }, + [TYPES.setTipList](state, list) { + return { + ...state, + tipInfo: { + ...state.tipInfo, + list, + }, + } + }, + [TYPES.setVisibleTipList](state, visible) { + return { + ...state, + tipInfo: { + ...state.tipInfo, + visible, + }, + } + }, +} + +export default (state = initialState, action) => + mutations[action.type] + ? mutations[action.type](state, action.payload) + : state diff --git a/src/store/modules/songList/action.js b/src/store/modules/songList/action.js new file mode 100644 index 0000000..eefd15f --- /dev/null +++ b/src/store/modules/songList/action.js @@ -0,0 +1,217 @@ +import music from '@/utils/music' + +const cache = new Map() + +const LIST_LOAD_LIMIT = 30 + +export const TYPES = { + setTags: null, + setList: null, + clearList: null, + setListDetail: null, + setVisibleListDetail: null, + setSelectListInfo: null, + setListLoading: null, + setListDetailLoading: null, + setListEnd: null, + setListDetailEnd: null, +} + +for (const key of Object.keys(TYPES)) { + TYPES[key] = `list__${key}` +} + +export const getTags = () => (dispatch, getState) => { + const state = getState() + let source = state.common.setting.songList.source + if (state.songList.tags[source]) return Promise.resolve() + return music[source].songList.getTags().then(result => dispatch(setTags({ tags: result, source }))) +} +export const getList = ({ page = 1, isRefresh = false }) => (dispatch, getState) => { + const allState = getState() + const rootState = allState.common + let source = rootState.setting.songList.source + let tabId = rootState.setting.songList.tagInfo.id + let sortId = rootState.setting.songList.sortId + + let listKey = `slist__${source}__${sortId}__${tabId}` + let pageKey = `slist__${source}__${sortId}__${tabId}__${page}` + + if (isRefresh && cache.has(listKey)) cache.delete(listKey) + if (!cache.has(listKey)) cache.set(listKey, new Map()) + + const listCache = cache.get(listKey) + if (listCache.has(pageKey)) return Promise.resolve(listCache.get(pageKey)).then(result => dispatch(setList({ result, pageKey, listKey, page }))) + + dispatch(setListEnd(false)) + dispatch(setListLoading(true)) + return music[source].songList.getList(sortId, tabId, page).then(result => { + dispatch(setList({ result, pageKey, listKey, page })) + listCache.set(pageKey, result) + }).finally(() => { + const state = getState().songList + if (state.list.pageKey != pageKey) return + dispatch(setListLoading(false)) + }) +} + +const getListDetailLimit = ({ source, id, page }) => { + const listKey = `sdetail__${source}__${id}` + const prevPageKey = `sdetail__${source}__${id}__${page - 1}` + const tempListKey = `sdetail__${source}__${id}__temp` + + const listCache = cache.get(listKey) + let sourcePage = 0 + if (listCache.has(prevPageKey)) { + sourcePage = listCache.get(prevPageKey).sourcePage + } + return music[source].songList.getListDetail(id, sourcePage + 1).then(result => { + let p = page + if (listCache.has(tempListKey)) { + const list = listCache.get(tempListKey) + listCache.delete(tempListKey) + listCache.set(`sdetail__${source}__${id}__${p}`, { + data: { + ...result, + list: [...list, ...result.list.splice(0, LIST_LOAD_LIMIT - list.length)], + page: p, + limit: LIST_LOAD_LIMIT, + }, + sourcePage, + }) + p++ + } + sourcePage++ + do { + if (result.list.length < LIST_LOAD_LIMIT && sourcePage < Math.ceil(result.total / result.limit)) { + listCache.set(tempListKey, result.list.splice(0, LIST_LOAD_LIMIT)) + break + } + listCache.set(`sdetail__${source}__${id}__${p}`, { + data: { + ...result, + list: result.list.splice(0, LIST_LOAD_LIMIT), + page: p, + limit: LIST_LOAD_LIMIT, + }, + sourcePage, + }) + p++ + } while (result.list.length > 0) + return listCache.get(`sdetail__${source}__${id}__${page}`).data + }) +} + +export const getListDetail = ({ id, page, isRefresh = false }) => (dispatch, getState) => { + const allState = getState() + const rootState = allState.common + let source = rootState.setting.songList.source + let listKey = `sdetail__${source}__${id}` + let pageKey = `sdetail__${source}__${id}__${page}` + + if (isRefresh && cache.has(listKey)) cache.delete(listKey) + if (!cache.has(listKey)) cache.set(listKey, new Map()) + + const listCache = cache.get(listKey) + if (listCache.has(pageKey)) { + return Promise.resolve(listCache.get(pageKey).data).then(result => dispatch(setListDetail({ result, listKey, pageKey, source, id, page }))) + } + + dispatch(setListDetailEnd(false)) + dispatch(setListDetailLoading(true)) + return getListDetailLimit({ source, id, page }).then(result => { + dispatch(setListDetail({ result, listKey, pageKey, source, id, page })) + // listCache.set(pageKey, result) + }).finally(() => { + const state = getState().songList + if (state.listDetail.pageKey != pageKey) return + dispatch(setListDetailLoading(false)) + }) +} + +export const getListDetailAll = id => (dispatch, getState) => { + const allState = getState() + const rootState = allState.common + let source = rootState.setting.songList.source + let listKey = `sdetail__${source}__${id}` + const listCache = cache.get(listKey) + const loadData = (id, page) => { + let pageKey = `sdetail__${source}__${id}__${page}` + return listCache.has(pageKey) + ? Promise.resolve(listCache.get(pageKey).data) + : getListDetailLimit({ source, id, page }).then(result => { + // listCache.set(pageKey, result) + return result + }) + } + return loadData(id, 1).then(result => { + if (result.total <= result.limit) return result.list + + let maxPage = Math.ceil(result.total / result.limit) + const loadDetail = (loadPage = 0) => { + return ++loadPage == maxPage + ? loadData(id, loadPage).then(result => result.list) + : loadData(id, loadPage).then(result1 => loadDetail(loadPage).then(result2 => [...result1.list, ...result2])) + } + return loadDetail().then(result2 => [...result.list, ...result2]) + }) +} + +export const setVisibleListDetail = isShow => { + return { + type: TYPES.setVisibleListDetail, + payload: isShow, + } +} +export const setSelectListInfo = info => { + return { + type: TYPES.setSelectListInfo, + payload: info, + } +} +export const setTags = ({ tags, source }) => { + return { + type: TYPES.setTags, + payload: { tags, source }, + } +} +export const setList = ({ result, pageKey, listKey, page }) => { + return { + type: TYPES.setList, + payload: { result, pageKey, listKey, page }, + } +} +export const clearList = () => { + return { type: TYPES.clearList } +} +export const setListLoading = isLoading => { + return { + type: TYPES.setListLoading, + payload: isLoading, + } +} +export const setListDetailLoading = isLoading => { + return { + type: TYPES.setListDetailLoading, + payload: isLoading, + } +} +export const setListEnd = isEnd => { + return { + type: TYPES.setListEnd, + payload: isEnd, + } +} +export const setListDetailEnd = isEnd => { + return { + type: TYPES.setListDetailEnd, + payload: isEnd, + } +} + +export const setListDetail = ({ result, pageKey, listKey, source, id, page }) => { + return { + type: TYPES.setListDetail, + payload: { result, pageKey, listKey, source, id, page }, + } +} diff --git a/src/store/modules/songList/getter.js b/src/store/modules/songList/getter.js new file mode 100644 index 0000000..3d57ea0 --- /dev/null +++ b/src/store/modules/songList/getter.js @@ -0,0 +1,31 @@ +import { createSelector } from 'reselect' + + +// sourceInfo(state, getters, rootState, { sourceNames }) { +// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList } +// }, +// tags: state => state.tags, +// isVisibleListDetail: state => state.isVisibleListDetail, + +export const rawSources = state => state.songList.sources + +export const sortList = state => state.songList.sortList + +export const tags = state => state.songList.tags + +export const isVisibleListDetail = state => state.songList.isVisibleListDetail +export const selectListInfo = state => state.songList.selectListInfo +export const listData = state => state.songList.list +export const listDetailData = state => state.songList.listDetail + +export const listInfo = state => state.songList.list +export const listDetailInfo = state => state.songList.listDetail + +export const songListSource = state => state.common.setting.songList.source +export const songListSortId = state => state.common.setting.songList.sortId +export const songListTagInfo = state => state.common.setting.songList.tagInfo + +export const sources = createSelector([rawSources], sources => { + return sources.map(source => ({ label: source.name, id: source.id })) +}) + diff --git a/src/store/modules/songList/index.js b/src/store/modules/songList/index.js new file mode 100644 index 0000000..f9cf685 --- /dev/null +++ b/src/store/modules/songList/index.js @@ -0,0 +1,5 @@ +import * as action from './action' +import * as getter from './getter' + +export { action, getter } +export { default as reducer } from './reducer' diff --git a/src/store/modules/songList/reducer.js b/src/store/modules/songList/reducer.js new file mode 100644 index 0000000..3923e0e --- /dev/null +++ b/src/store/modules/songList/reducer.js @@ -0,0 +1,190 @@ +import { TYPES } from './action' +import music from '@/utils/music' +const sortList = {} +const sources = [] +for (const source of music.sources) { + const songList = music[source.id].songList + if (!songList) continue + sortList[source.id] = songList.sortList + sources.push(source) +} +// state +const initialState = { + sources, + sortList, + tags: {}, + list: { + list: [], + total: 0, + page: 1, + limit: 30, + listKey: null, + pageKey: null, + isLoading: false, + isEnd: false, + }, + listDetail: { + list: [], + desc: null, + total: 0, + page: 1, + limit: 30, + info: {}, + listKey: null, + pageKey: null, + isLoading: false, + isEnd: false, + }, + selectListInfo: {}, + isVisibleListDetail: false, +} + +sources.forEach(source => { + initialState.tags[source.id] = null +}) + +const mutations = { + [TYPES.setTags](state, { tags, source }) { + return { + ...state, + tags: { ...state.tags, [source]: tags }, + } + }, + [TYPES.clearList](state) { + return { + ...state, + list: { + ...state.list, + list: [], + total: 0, + page: 1, + pageKey: null, + listKey: null, + isLoading: false, + isEnd: false, + }, + } + }, + [TYPES.setList](state, { result, pageKey, listKey, page }) { + if (pageKey == state.list.pageKey && state.list.list.length) return state + return { + ...state, + list: { + ...state.list, + list: listKey == state.list.listKey && page != 1 ? [...state.list.list, ...result.list] : result.list, + total: result.total, + limit: result.limit, + page, + pageKey, + listKey, + isEnd: page >= Math.ceil(result.total / result.limit), + }, + } + }, + [TYPES.setListDetail](state, { result, pageKey, listKey, source, id, page }) { + const listIds = new Set() + let list = listKey == state.listDetail.listKey && page != 1 ? [...state.listDetail.list, ...result.list] : result.list + list = list.filter(item => { + if (listIds.has(item.songmid)) return false + listIds.add(item.songmid) + return true + }) + return { + ...state, + listDetail: { + ...state.listDetail, + list, + id, + source, + total: result.total, + limit: result.limit, + page, + pageKey, + listKey, + isEnd: page >= Math.ceil(result.total / result.limit), + info: result.info || { + name: state.selectListInfo.name, + img: state.selectListInfo.img, + desc: state.selectListInfo.desc, + author: state.selectListInfo.author, + play_count: state.selectListInfo.play_count, + }, + }, + } + }, + [TYPES.setVisibleListDetail](state, bool) { + const newState = { + ...state, + isVisibleListDetail: bool, + } + if (!bool) newState.listDetail = { ...newState.listDetail, list: [] } + return newState + }, + [TYPES.setSelectListInfo](state, info) { + return { + ...state, + selectListInfo: info, + } + }, + [TYPES.clearListDetail](state) { + return { + ...state, + listDetail: { + ...state.listDetail, + id: null, + source: null, + list: [], + desc: null, + total: 0, + page: 1, + limit: 30, + pageKey: null, + listKey: null, + isLoading: false, + isEnd: false, + info: {}, + }, + } + }, + [TYPES.setListLoading](state, isLoading) { + return { + ...state, + list: { + ...state.list, + isLoading, + }, + } + }, + [TYPES.setListDetailLoading](state, isLoading) { + return { + ...state, + listDetail: { + ...state.listDetail, + isLoading, + }, + } + }, + [TYPES.setListEnd](state, isEnd) { + return { + ...state, + list: { + ...state.list, + isEnd, + }, + } + }, + [TYPES.setListDetailEnd](state, isEnd) { + return { + ...state, + listDetail: { + ...state.listDetail, + isEnd, + }, + } + }, +} + +export default (state = initialState, action) => mutations[action.type] + ? mutations[action.type](state, action.payload) + : state + diff --git a/src/store/modules/top/action.js b/src/store/modules/top/action.js new file mode 100644 index 0000000..03b516b --- /dev/null +++ b/src/store/modules/top/action.js @@ -0,0 +1,158 @@ +import music from '@/utils/music' + +const cache = new Map() +const LIST_LOAD_LIMIT = 30 + +export const TYPES = { + setBoardsList: null, + setList: null, + clearList: null, + setListLoading: null, + setListEnd: null, +} + +for (const key of Object.keys(TYPES)) { + TYPES[key] = `top__${key}` +} + +export const getBoardsList = () => (dispatch, getState) => { + const state = getState() + let source = state.common.setting.leaderboard.source + // let tabId = rootState.setting.leaderboard.tabId + // let key = `${source}${tabId}${page}` + // if (state.list.length && state.key == key) return true + // commit('clearList') + if (state.top.boards[source].length) return Promise.resolve() + return music[source].leaderboard.getBoards().then(result => dispatch(setBoardsList({ boards: result, source }))) +} + +const getListLimit = ({ source, tabId, bangId, page }) => { + const listKey = `${source}__${tabId}` + const prevPageKey = `${source}__${tabId}__${page - 1}` + const tempListKey = `${source}__${tabId}__temp` + + const listCache = cache.get(listKey) + let sourcePage = 0 + if (listCache.has(prevPageKey)) { + sourcePage = listCache.get(prevPageKey).sourcePage + } + return music[source].leaderboard.getList(bangId, sourcePage + 1).then(result => { + let p = page + if (listCache.has(tempListKey)) { + const list = listCache.get(tempListKey) + listCache.delete(tempListKey) + listCache.set(`${source}__${tabId}__${p}`, { + data: { + ...result, + list: [...list, ...result.list.splice(0, LIST_LOAD_LIMIT - list.length)], + page: p, + limit: LIST_LOAD_LIMIT, + }, + sourcePage, + }) + p++ + } + sourcePage++ + do { + if (result.list.length < LIST_LOAD_LIMIT && sourcePage < Math.ceil(result.total / result.limit)) { + listCache.set(tempListKey, result.list.splice(0, LIST_LOAD_LIMIT)) + break + } + listCache.set(`${source}__${tabId}__${p}`, { + data: { + ...result, + list: result.list.splice(0, LIST_LOAD_LIMIT), + page: p, + limit: LIST_LOAD_LIMIT, + }, + sourcePage, + }) + p++ + } while (result.list.length > 0) + return listCache.get(`${source}__${tabId}__${page}`).data + }) +} + +export const getList = ({ page, isRefresh = false }) => (dispatch, getState) => { + const state = getState() + let tabId = state.common.setting.leaderboard.tabId + if (tabId == null) return Promise.resolve() + // console.log(tabId) + const [source, bangId] = tabId.split('__') + const listKey = `${source}__${tabId}` + const pageKey = `${source}__${tabId}__${page}` + + if (isRefresh && cache.has(listKey)) cache.delete(listKey) + if (!cache.has(listKey)) cache.set(listKey, new Map()) + + const listCache = cache.get(listKey) + if (listCache.has(pageKey)) { + return Promise.resolve(listCache.get(pageKey).data).then(result => dispatch(setList({ result, listKey, pageKey, page }))) + } + + dispatch(setListEnd(false)) + dispatch(setListLoading(true)) + return getListLimit({ source, tabId, bangId, page }).then(result => { + dispatch(setList({ result, listKey, pageKey, page })) + // listCache.set(pageKey, result) + }).finally(() => { + const state = getState().top + if (state.listInfo.pageKey != pageKey) return + dispatch(setListLoading(false)) + }) +} + +export const getListAll = tabId => (dispatch, getState) => { + // console.log(tabId) + const [source, bangId] = tabId.split('__') + const listKey = `${source}__${tabId}` + const listCache = cache.get(listKey) + const loadData = (bangId, page) => { + const pageKey = `${source}__${tabId}__${page}` + return listCache.has(pageKey) + ? Promise.resolve(listCache.get(pageKey)) + : music[source].leaderboard.getList(bangId, page).then(result => { + listCache.set(pageKey, result) + return result + }) + } + return loadData(bangId, 1).then(result => { + if (result.total <= result.limit) return result.list + + let maxPage = Math.ceil(result.total / result.limit) + const loadDetail = (loadPage = 1) => { + return loadPage == maxPage + ? loadData(bangId, ++loadPage).then(result => result.list) + : loadData(bangId, ++loadPage).then(result1 => loadDetail(loadPage).then(result2 => [...result1.list, ...result2])) + } + return loadDetail().then(result2 => [...result.list, ...result2]) + }) +} + +export const setBoardsList = ({ boards, source }) => { + return { + type: TYPES.setBoardsList, + payload: { boards, source }, + } +} +export const setList = ({ result, pageKey, listKey, page }) => { + return { + type: TYPES.setList, + payload: { result, pageKey, listKey, page }, + } +} +export const clearList = () => { + return { type: TYPES.clearList } +} +export const setListLoading = isLoading => { + return { + type: TYPES.setListLoading, + payload: isLoading, + } +} +export const setListEnd = isEnd => { + return { + type: TYPES.setListEnd, + payload: isEnd, + } +} diff --git a/src/store/modules/top/getter.js b/src/store/modules/top/getter.js new file mode 100644 index 0000000..2b83c43 --- /dev/null +++ b/src/store/modules/top/getter.js @@ -0,0 +1,24 @@ +import { createSelector } from 'reselect' + + +// sourceInfo(state, getters, rootState, { sourceNames }) { +// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList } +// }, +// tags: state => state.tags, +// isVisibleListDetail: state => state.isVisibleListDetail, + +export const rawSources = state => state.top.sources + +export const boards = state => state.top.boards + +export const listInfo = state => state.top.listInfo +export const isEnd = state => state.top.isEnd +export const isLoading = state => state.top.isLoading + +export const sourceId = state => state.common.setting.leaderboard.source +export const tabId = state => state.common.setting.leaderboard.tabId + +export const sources = createSelector([rawSources], sources => { + return sources.map(source => ({ label: source.name, id: source.id })) +}) + diff --git a/src/store/modules/top/index.js b/src/store/modules/top/index.js new file mode 100644 index 0000000..f9cf685 --- /dev/null +++ b/src/store/modules/top/index.js @@ -0,0 +1,5 @@ +import * as action from './action' +import * as getter from './getter' + +export { action, getter } +export { default as reducer } from './reducer' diff --git a/src/store/modules/top/reducer.js b/src/store/modules/top/reducer.js new file mode 100644 index 0000000..ce66489 --- /dev/null +++ b/src/store/modules/top/reducer.js @@ -0,0 +1,82 @@ +import { TYPES } from './action' +import music from '@/utils/music' +const sourceList = {} +const sources = [] +for (const source of music.sources) { + const leaderboard = music[source.id].leaderboard + if (!leaderboard || !leaderboard.getBoards) continue + sourceList[source.id] = [] + sources.push(source) +} + +// state +const initialState = { + sources, + boards: sourceList, + listInfo: { + list: [], + total: 0, + page: 1, + limit: 30, + listKey: null, + pageKey: null, + }, + isLoading: false, + isEnd: false, +} + +const mutations = { + [TYPES.setBoardsList](state, { boards, source }) { + return { + ...state, + boards: { ...state.boards, [source]: boards.list }, + } + }, + [TYPES.clearList](state) { + return { + ...state, + listInfo: { + ...state.listInfo, + list: [], + total: 0, + page: 1, + pageKey: null, + listKey: null, + }, + isLoading: false, + isEnd: false, + } + }, + [TYPES.setList](state, { result, pageKey, listKey, page }) { + return { + ...state, + listInfo: { + ...state.listInfo, + list: listKey == state.listInfo.listKey && page != 1 ? [...state.listInfo.list, ...result.list] : result.list, + total: result.total, + limit: result.limit, + page, + pageKey, + listKey, + }, + isEnd: page >= Math.ceil(result.total / result.limit), + } + }, + [TYPES.setListLoading](state, isLoading) { + return { + ...state, + isLoading, + } + }, + [TYPES.setListEnd](state, isEnd) { + return { + ...state, + isEnd, + } + }, +} + +export default (state = initialState, action) => mutations[action.type] + ? mutations[action.type](state, action.payload) + : state + diff --git a/src/store/reducer.js b/src/store/reducer.js new file mode 100644 index 0000000..0110c35 --- /dev/null +++ b/src/store/reducer.js @@ -0,0 +1,27 @@ +// import { persistCombineReducers } from 'redux-persist' +// import AsyncStorage from '@react-native-async-storage/async-storage' +import { combineReducers } from 'redux' + +import * as modules from './modules' + +// const config = { +// key: 'LIFTED_REDUX_STORE', +// storage: AsyncStorage, +// } + +const reducers = {} + + +for (const [moduleName, { reducer }] of Object.entries(modules)) { + reducers[moduleName] = reducer +} + +const combinedReducers = combineReducers(reducers) + +// const appReducer = persistCombineReducers(config, reducers) + +export { + reducers, + combinedReducers, +} +// export default (state, action) => appReducer(state, action) diff --git a/src/store/store.js b/src/store/store.js new file mode 100644 index 0000000..5b2995c --- /dev/null +++ b/src/store/store.js @@ -0,0 +1,48 @@ +import { createStore, applyMiddleware } from 'redux' +import thunkMiddleware from 'redux-thunk' +import { initSubscriber } from './subscriber' +// import { persistStore, persistReducer } from 'redux-persist' +// import AsyncStorage from '@react-native-async-storage/async-storage' +// import { createSelector } from 'reselect' + +import { combinedReducers } from './reducer' + +// const persistConfig = { +// key: 'root', +// storage: AsyncStorage, +// } + +// const persistedReducer = persistReducer(persistConfig, reducer) + +const middlewares = [thunkMiddleware] + +// let debuggWrapper = data => data + + +if (process.env.NODE_ENV === 'development') { + const { createLogger } = require('redux-logger') + // const { composeWithDevTools } = require('remote-redux-devtools') + middlewares.push(createLogger({ + collapsed: true, + })) + // debuggWrapper = composeWithDevTools({ realtime: true, port: 8097 }) +} + + +const initializeStore = () => { + const store = createStore(combinedReducers, applyMiddleware(...middlewares)) + initSubscriber(store) + // const persistor = persistStore(store) + return store + // return { store, persistor } +} + +// const store = createStore(reducer, applyMiddleware(...middlewares)) +// initSubscriber(store) + +let store + +export default () => { + if (!store) store = initializeStore() + return store +} diff --git a/src/store/subscriber.js b/src/store/subscriber.js new file mode 100644 index 0000000..230756f --- /dev/null +++ b/src/store/subscriber.js @@ -0,0 +1,7 @@ +import initSubscriber, { subscribe } from 'redux-subscriber' + +export { + initSubscriber, + subscribe, +} + diff --git a/src/store/useDispatch.js b/src/store/useDispatch.js new file mode 100644 index 0000000..31e14df --- /dev/null +++ b/src/store/useDispatch.js @@ -0,0 +1,24 @@ +import { useCallback } from 'react' +import { useDispatch } from 'react-redux' +import * as modules from './modules' + +const defaultAction = () => {} +export default (moduleName, name) => { + const dispatch = useDispatch() + + // console.log(selector) + // console.log(moduleName, key) + + return useCallback((...params) => { + const actions = modules[moduleName].action + let action + if (actions && actions[name]) action = actions[name] + else { + console.warn('action not found:', moduleName, name) + action = defaultAction + } + return dispatch(action(...params)) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) +} + diff --git a/src/store/useGetter.js b/src/store/useGetter.js new file mode 100644 index 0000000..e3a5250 --- /dev/null +++ b/src/store/useGetter.js @@ -0,0 +1,23 @@ +import { useMemo, useCallback } from 'react' +import { useSelector } from 'react-redux' +import * as modules from './modules' + +// console.log(modules) +const defaultGetter = state => state + +const useGetter = (moduleName, key, props) => { + const getter = useMemo(() => { + const getters = modules[moduleName].getter + if (getters && getters[key]) return getters[key] + console.warn('getter not found:', moduleName, key) + return defaultGetter + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + const selecteor = useCallback(state => getter(state, props), [props]) + + // console.log(selector) + // console.log(moduleName, key) + return useSelector(selecteor) +} + +export default useGetter diff --git a/src/theme/Colors.js b/src/theme/Colors.js new file mode 100644 index 0000000..f26d30f --- /dev/null +++ b/src/theme/Colors.js @@ -0,0 +1,122 @@ +/** + * Material Colors following material design guidelines for + * miscellaneous colors + */ + +export const MaterialColors = { + red: { + 100: '#ffcdd2', + 200: '#ef9a9a', + 300: '#e57373', + 400: '#ef5350', + 500: '#f44336', + 600: '#e53935', + 700: '#d32f2f', + 800: '#c62828', + 900: '#b71c1c', + }, + purple: { + 100: '#e1bee7', + 200: '#ce93d8', + 300: '#ba68c8', + 400: '#ab47bc', + 500: '#9c27b0', + 600: '#8e24aa', + 700: '#7b1fa2', + 800: '#6a1b9a', + 900: '#4a148c', + }, + blue: { + 100: '#bbdefb', + 200: '#90caf9', + 300: '#64b5f6', + 400: '#42a5f5', + 500: '#2196f3', + 600: '#1e88e5', + 700: '#1976d2', + 800: '#1565c0', + 900: '#0d47a1', + }, + green: { + 100: '#c8e6c9', + 200: '#a5d6a7', + 300: '#81c784', + 400: '#66bb6a', + 500: '#4caf50', + 600: '#43a047', + 700: '#388e3c', + 800: '#2e7d32', + 900: '#1b5e20', + }, + yellow: { + 100: '#fff9c4', + 200: '#fff59d', + 300: '#fff176', + 400: '#ffee58', + 500: '#ffeb3b', + 600: '#fdd835', + 700: '#fbc02d', + 800: '#f9a825', + 900: '#f57f17', + }, + orange: { + 100: '#ffe0b2', + 200: '#ffcc80', + 300: '#ffb74d', + 400: '#ffa726', + 500: '#ff9800', + 600: '#fb8c00', + 700: '#f57c00', + 800: '#ef6c00', + 900: '#e65100', + }, + brown: { + 100: '#d7ccc8', + 200: '#bcaaa4', + 300: '#a1887f', + 400: '#8d6e63', + 500: '#795548', + 600: '#6d4c41', + 700: '#5d4037', + 800: '#4e342e', + 900: '#3e2723', + }, + grey: { + 100: '#f5f5f5', + 200: '#eeeeee', + 300: '#e0e0e0', + 400: '#bdbdbd', + 500: '#9e9e9e', + 600: '#757575', + 700: '#616161', + 800: '#424242', + 900: '#212121', + }, +} + +/** + * App Colors: + * This contains all the color config for the application + */ + +export const AppColors = { + primary: '#fff', + + normal: '#333', + normal10: '#4c4c4c', + normal20: '#666', + normal30: '#808080', + normal40: '#999', + + secondary: '#4eb17d', + secondary10: '#73bf97', + secondary20: '#95d0b2', + secondary30: '#b9dfcb', + secondary40: '#dcefe5', + + borderColor: '#e6e6e6', + borderColor2: '#ebebeb', + borderColor3: '#f0f0f0', + borderColor4: '#f5f5f5', + borderColor5: '#fafafa', +} diff --git a/src/theme/Typography.js b/src/theme/Typography.js new file mode 100644 index 0000000..65049ac --- /dev/null +++ b/src/theme/Typography.js @@ -0,0 +1,50 @@ +/** + * Typography: + * This contains all the typography config for the application + * #Note: color and font size are defaulted as they can be overridden + * as required. + */ + +export const FontWeights = { + Bold: { + fontFamily: 'SFProDisplay-Bold', + color: '#000', + }, + Regular: { + fontFamily: 'SFProDisplay-Regular', + color: '#000', + }, + Light: { + fontFamily: 'SFProDisplay-Light', + color: '#000', + }, +} + +export const FontSizes = { + Heading: { + fontSize: 32, + }, + SubHeading: { + fontSize: 24, + }, + Label: { + fontSize: 20, + }, + Body: { + fontSize: 16, + }, + Caption: { + fontSize: 14, + }, +} + +export const BorderWidths = { + normal: 0.4, + normal2: 1, + normal3: 1.4, + normal4: 2, +} + +export const BorderRadius = { + normal: 4, +} diff --git a/src/theme/index.js b/src/theme/index.js new file mode 100644 index 0000000..ece92ba --- /dev/null +++ b/src/theme/index.js @@ -0,0 +1,18 @@ +import { AppColors, MaterialColors } from './Colors' +import * as Themes from './themes' +import { + FontWeights, + FontSizes, + BorderWidths, + BorderRadius, +} from './Typography' + +export { + AppColors, + MaterialColors, + FontWeights, + FontSizes, + BorderWidths, + BorderRadius, + Themes, +} diff --git a/src/theme/themes/blue.js b/src/theme/themes/blue.js new file mode 100644 index 0000000..261854c --- /dev/null +++ b/src/theme/themes/blue.js @@ -0,0 +1,39 @@ +export default { + id: 'blue', + colors: { + primary: '#fff', + + normal: '#333', + normal10: '#4c4c4c', + normal20: '#666', + normal30: '#808080', + normal35: '#8c8c8c', + normal40: '#999', + normal50: '#b2b2b2', + normal60: '#ccc', + normal70: '#e6e6e6', + normal75: '#f2f2f2', + + secondary_5: '#258bd0', + secondary: '#3498db', + secondary10: '#5eaee3', + secondary20: '#89c4eb', + secondary30: '#b5daf2', + secondary40: '#d2ebf9', + secondary45: '#e8f5fc', + + tertiary_5: '#41a581', + tertiary: '#48b78f', + tertiary10: '#5cbf9b', + tertiary20: '#6dc5a5', + tertiary30: '#7fccb0', + tertiary40: '#92d3bb', + tertiary45: '#a4dac6', + + borderColor: '#e6e6e6', + borderColor2: '#ebebeb', + borderColor3: '#f0f0f0', + borderColor4: '#f5f5f5', + borderColor5: '#fafafa', + }, +} diff --git a/src/theme/themes/green.js b/src/theme/themes/green.js new file mode 100644 index 0000000..6fb57e8 --- /dev/null +++ b/src/theme/themes/green.js @@ -0,0 +1,39 @@ +export default { + id: 'green', + colors: { + primary: '#fff', + + normal: '#333', + normal10: '#4c4c4c', + normal20: '#666', + normal30: '#808080', + normal35: '#8c8c8c', + normal40: '#999', + normal50: '#b2b2b2', + normal60: '#ccc', + normal70: '#e6e6e6', + normal75: '#f2f2f2', + + secondary_5: '#46a071', + secondary: '#4eb17d', + secondary10: '#73bf97', + secondary20: '#95d0b2', + secondary30: '#b9dfcb', + secondary40: '#dcefe5', + secondary45: '#edf7f2', + + tertiary_5: '#5497b5', + tertiary: '#66a2bd', + tertiary10: '#77adc5', + tertiary20: '#89b8cd', + tertiary30: '#9ac3d5', + tertiary40: '#accedd', + tertiary45: '#bed9e4', + + borderColor: '#e6e6e6', + borderColor2: '#ebebeb', + borderColor3: '#f0f0f0', + borderColor4: '#f5f5f5', + borderColor5: '#fafafa', + }, +} diff --git a/src/theme/themes/index.js b/src/theme/themes/index.js new file mode 100644 index 0000000..da9e088 --- /dev/null +++ b/src/theme/themes/index.js @@ -0,0 +1,3 @@ +export { default as green } from './green' +export { default as blue } from './blue' +export { default as red } from './red' diff --git a/src/theme/themes/red.js b/src/theme/themes/red.js new file mode 100644 index 0000000..dd24094 --- /dev/null +++ b/src/theme/themes/red.js @@ -0,0 +1,39 @@ +export default { + id: 'red', + colors: { + primary: '#fff', + + normal: '#333', + normal10: '#4c4c4c', + normal20: '#666', + normal30: '#808080', + normal35: '#8c8c8c', + normal40: '#999', + normal50: '#b2b2b2', + normal60: '#ccc', + normal70: '#e6e6e6', + normal75: '#f2f2f2', + + secondary_5: '#d2322d', + secondary: '#d64541', + secondary10: '#df6f6c', + secondary20: '#e89896', + secondary30: '#f1c1c0', + secondary40: '#f5d6d6', + secondary45: '#faeaea', + + tertiary_5: '#d29e2d', + tertiary: '#d7a842', + tertiary10: '#dbb257', + tertiary20: '#dfbb6b', + tertiary30: '#e4c581', + tertiary40: '#e9cf96', + tertiary45: '#edd8ab', + + borderColor: '#e6e6e6', + borderColor2: '#ebebeb', + borderColor3: '#f0f0f0', + borderColor4: '#f5f5f5', + borderColor5: '#fafafa', + }, +} diff --git a/src/utils/cache.js b/src/utils/cache.js new file mode 100644 index 0000000..088e140 --- /dev/null +++ b/src/utils/cache.js @@ -0,0 +1,6 @@ +import { NativeModules } from 'react-native' + +const { CacheModule } = NativeModules + +export const getAppCacheSize = () => CacheModule.getAppCacheSize().then(size => parseInt(size)) +export const clearAppCache = CacheModule.clearAppCache diff --git a/src/utils/common.js b/src/utils/common.js new file mode 100644 index 0000000..d271aea --- /dev/null +++ b/src/utils/common.js @@ -0,0 +1,44 @@ +import { PermissionsAndroid } from 'react-native' + + +export const checkStoragePermissions = () => PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE) + +export const requestStoragePermission = async() => { + const isGranted = await checkStoragePermissions() + if (isGranted) return isGranted + + try { + const granted = await PermissionsAndroid.requestMultiple( + [ + PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, + PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE, + ], + // { + // title: '存储读写权限申请', + // message: + // '洛雪音乐助手需要使用存储读写权限才能下载歌曲.', + // buttonNeutral: '一会再问我', + // buttonNegative: '取消', + // buttonPositive: '确定', + // }, + ) + // console.log(granted) + // console.log(Object.values(granted).every(r => r === PermissionsAndroid.RESULTS.GRANTED)) + // console.log(PermissionsAndroid.RESULTS) + const granteds = Object.values(granted) + return granteds.every(r => r === PermissionsAndroid.RESULTS.GRANTED) + ? true + : granteds.includes(PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN) + ? null + : false + // if (granted === PermissionsAndroid.RESULTS.GRANTED) { + // console.log('You can use the storage') + // } else { + // console.log('Storage permission denied') + // } + } catch (err) { + console.warn(err) + return err.message + } +} + diff --git a/src/utils/env.js b/src/utils/env.js new file mode 100644 index 0000000..553f01e --- /dev/null +++ b/src/utils/env.js @@ -0,0 +1,5 @@ +const isDev = process.env.NODE_ENV === 'development' + +export const debug = isDev && true +export const debugRequest = isDev && false +export const debugDownload = isDev && false diff --git a/src/utils/fs.js b/src/utils/fs.js new file mode 100644 index 0000000..3d0d6a2 --- /dev/null +++ b/src/utils/fs.js @@ -0,0 +1,53 @@ +import RNFS from 'react-native-fs' + +export const externalDirectoryPath = RNFS.ExternalDirectoryPath + +export const temporaryDirectoryPath = RNFS.TemporaryDirectoryPath +export const externalStorageDirectoryPath = RNFS.ExternalStorageDirectoryPath + +export const unlink = path => RNFS.unlink(path) + +export const readDir = path => RNFS.readDir(path) + +export const mkdir = path => RNFS.mkdir(path) + +export const stat = path => RNFS.stat(path) + +export const readFile = (path, encoding) => RNFS.readFile(path, encoding) + +export const copyFile = (fromPath, toPath) => RNFS.copyFile(fromPath, toPath) + +export const moveFile = (fromPath, toPath) => RNFS.moveFile(fromPath, toPath) + +export const existsFile = path => RNFS.exists(path) + +export const writeFile = (path, data, encoding = 'utf8') => RNFS.writeFile(path, data, encoding) + +export const appendFile = (path, data, encoding = 'utf8') => RNFS.appendFile(path, data, encoding) + +export const downloadFile = (url, path, options = {}) => { + if (!options.headers) { + options.headers = { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 10; Pixel 3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Mobile Safari/537.36', + } + } + return RNFS.downloadFile({ + fromUrl: url, // URL to download file from + toFile: path, // Local filesystem path to save the file to + ...options, + // headers: options.headers, // An object of headers to be passed to the server + // // background?: boolean; // Continue the download in the background after the app terminates (iOS only) + // // discretionary?: boolean; // Allow the OS to control the timing and speed of the download to improve perceived performance (iOS only) + // // cacheable?: boolean; // Whether the download can be stored in the shared NSURLCache (iOS only, defaults to true) + // progressInterval: options.progressInterval, + // progressDivider: options.progressDivider, + // begin: (res: DownloadBeginCallbackResult) => void; + // progress?: (res: DownloadProgressCallbackResult) => void; + // // resumable?: () => void; // only supported on iOS yet + // connectionTimeout?: number // only supported on Android yet + // readTimeout?: number // supported on Android and iOS + // // backgroundTimeout?: number // Maximum time (in milliseconds) to download an entire resource (iOS only, useful for timing out background downloads) + }) +} + +export const stopDownload = jobId => RNFS.stopDownload(jobId) diff --git a/src/utils/gzip.js b/src/utils/gzip.js new file mode 100644 index 0000000..72e9b0a --- /dev/null +++ b/src/utils/gzip.js @@ -0,0 +1,12 @@ +import { NativeModules } from 'react-native' + +const { GzipModule } = NativeModules + +export const gzip = (sourceFilePath, targetFilePath) => { + console.log(sourceFilePath, targetFilePath) + return GzipModule.gzip(sourceFilePath, targetFilePath, true) +} + +export const ungzip = (sourceFilePath, targetFilePath) => { + return GzipModule.unGzip(sourceFilePath, targetFilePath, true) +} diff --git a/src/utils/hooks/index.js b/src/utils/hooks/index.js new file mode 100644 index 0000000..3be31a0 --- /dev/null +++ b/src/utils/hooks/index.js @@ -0,0 +1,6 @@ +export { default as useLayout } from './useLayout' +export { default as useKeyboard } from './useKeyboard' +export { default as useDimensions } from './useDimensions' + +export { default as usePlayTime } from './usePlayTime' +export { default as useAssertApiSupport } from './useAssertApiSupport' diff --git a/src/utils/hooks/useAssertApiSupport.js b/src/utils/hooks/useAssertApiSupport.js new file mode 100644 index 0000000..8a63a4d --- /dev/null +++ b/src/utils/hooks/useAssertApiSupport.js @@ -0,0 +1,7 @@ +import { useGetter } from '@/store' + +export default source => { + const supportQualitys = useGetter('common', 'supportQualitys') + + return Boolean(supportQualitys[source]) +} diff --git a/src/utils/hooks/useDimensions.js b/src/utils/hooks/useDimensions.js new file mode 100644 index 0000000..b548aa2 --- /dev/null +++ b/src/utils/hooks/useDimensions.js @@ -0,0 +1,21 @@ +import { useEffect, useState } from 'react' +import { Dimensions } from 'react-native' + +export default () => { + const [dimensions, setDimensions] = useState({ + window: Dimensions.get('window'), + screen: Dimensions.get('screen'), + }) + + useEffect(() => { + const onChange = ({ window, screen }) => { + setDimensions({ window, screen }) + } + + Dimensions.addEventListener('change', onChange) + + return () => Dimensions.removeEventListener('change', onChange) + }, []) + + return dimensions +} diff --git a/src/utils/hooks/useKeyboard.js b/src/utils/hooks/useKeyboard.js new file mode 100644 index 0000000..adb2edf --- /dev/null +++ b/src/utils/hooks/useKeyboard.js @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react' +import { Keyboard } from 'react-native' + +export default () => { + const [shown, setShown] = useState(false) + const [keyboardHeight, setKeyboardHeight] = useState(0) + + const handleKeyboardDidShow = e => { + setShown(true) + setKeyboardHeight(e.endCoordinates.height) + } + + const handleKeyboardDidHide = () => { + setShown(false) + setKeyboardHeight(0) + } + + useEffect(() => { + Keyboard.addListener('keyboardDidShow', handleKeyboardDidShow) + Keyboard.addListener('keyboardDidHide', handleKeyboardDidHide) + + return () => { + Keyboard.removeListener('keyboardDidShow', handleKeyboardDidShow) + Keyboard.removeListener('keyboardDidHide', handleKeyboardDidHide) + } + }, []) + + return { + keyboardShown: shown, + keyboardHeight, + } +} diff --git a/src/utils/hooks/useLayout.js b/src/utils/hooks/useLayout.js new file mode 100644 index 0000000..85c93f7 --- /dev/null +++ b/src/utils/hooks/useLayout.js @@ -0,0 +1,16 @@ +import { useState, useCallback } from 'react' + +export default () => { + const [layout, setLayout] = useState({ + x: 0, + y: 0, + width: 0, + height: 0, + }) + const onLayout = useCallback((e) => setLayout(e.nativeEvent.layout), []) + + return { + onLayout, + ...layout, + } +} diff --git a/src/utils/hooks/usePlayTime.js b/src/utils/hooks/usePlayTime.js new file mode 100644 index 0000000..2ac20fb --- /dev/null +++ b/src/utils/hooks/usePlayTime.js @@ -0,0 +1,19 @@ +// import { useMemo } from 'react' +import { useTrackPlayerProgress } from '@/plugins/player/hook' +import { formatPlayTime2 } from '@/utils' +// import { useGetter } from '@/store' +// import { STATE_PLAYING, STATE_BUFFERING } from 'react-native-track-player' + +export default () => { + const { position, bufferedPosition, duration } = useTrackPlayerProgress(250) + // const isGettingUrl = useGetter('player', 'isGettingUrl') + + return { + curTimeStr: formatPlayTime2(position), + maxTimeStr: formatPlayTime2(duration), + time: position, + duration, + bufferedProgress: duration ? bufferedPosition / duration * 100 : 100, + progress: duration ? position / duration * 100 : 0, + } +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..acd2f45 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,127 @@ + + +/** + * 获取两个数之间的随机整数,大于等于min,小于max + * @param {*} min + * @param {*} max + */ +export const getRandom = (min, max) => Math.floor(Math.random() * (max - min)) + min + + +export const sizeFormate = size => { + // https://gist.github.com/thomseddon/3511330 + if (!size) return '0 B' + const units = ['B', 'KB', 'MB', 'GB', 'TB'] + const number = Math.floor(Math.log(size) / Math.log(1024)) + return `${(size / Math.pow(1024, Math.floor(number))).toFixed(2)} ${units[number]}` +} + +export const formatPlayTime = time => { + const m = parseInt(time / 60) + const s = parseInt(time % 60) + return m === 0 && s === 0 ? '--/--' : (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s) +} + +export const formatPlayTime2 = time => { + const m = parseInt(time / 60) + const s = parseInt(time % 60) + return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s) +} + +export const b64DecodeUnicode = str => { + // Going backwards: from bytestream, to percent-encoding, to original string. + return decodeURIComponent(window.atob(str).split('').map(function(c) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + }).join('')) +} + +const encodeNames = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'", + ''': "'", +} +export const decodeName = (str = '') => str.replace(/(?:&|<|>|"|'|')/gm, s => encodeNames[s]) + +// https://stackoverflow.com/a/53387532 +export const compareVer = (currentVer, targetVer) => { + // treat non-numerical characters as lower version + // replacing them with a negative number based on charcode of each character + const fix = s => `.${s.toLowerCase().charCodeAt(0) - 2147483647}.` + + currentVer = ('' + currentVer).replace(/[^0-9.]/g, fix).split('.') + targetVer = ('' + targetVer).replace(/[^0-9.]/g, fix).split('.') + const c = Math.max(currentVer.length, targetVer.length) + for (let i = 0; i < c; i++) { + // convert to integer the most efficient way + currentVer[i] = ~~currentVer[i] + targetVer[i] = ~~targetVer[i] + if (currentVer[i] > targetVer[i]) return 1 + else if (currentVer[i] < targetVer[i]) return -1 + } + return 0 +} + +export const isObject = item => item && typeof item === 'object' && !Array.isArray(item) + +/** + * 对象深度合并 + * @param {} target 要合并源对象 + * @param {} source 要合并目标对象 + */ +export const objectDeepMerge = (target, source, mergedObj) => { + if (!mergedObj) { + mergedObj = new Set() + mergedObj.add(target) + } + const base = {} + Object.keys(source).forEach(item => { + if (isObject(source[item])) { + if (mergedObj.has(source[item])) return + if (!isObject(target[item])) target[item] = {} + mergedObj.add(source[item]) + objectDeepMerge(target[item], source[item], mergedObj) + return + } + base[item] = source[item] + }) + Object.assign(target, base) +} + +/** + * 生成节流函数 + * @param {*} fn + * @param {*} delay + */ +export const throttle = (fn, delay = 100) => { + let timer = null + let _args = null + return function(...args) { + _args = args + if (timer) return + timer = setTimeout(() => { + timer = null + fn.apply(this, _args) + }, delay) + } +} + +/** + * 生成防抖函数 + * @param {*} fn + * @param {*} delay + */ +export const debounce = (fn, delay = 100) => { + let timer = null + let _args = null + return function(...args) { + _args = args + if (timer) clearTimeout(timer) + timer = setTimeout(() => { + timer = null + fn.apply(this, _args) + }, delay) + } +} diff --git a/src/utils/log.js b/src/utils/log.js new file mode 100644 index 0000000..5732e87 --- /dev/null +++ b/src/utils/log.js @@ -0,0 +1,58 @@ +import { requestStoragePermission } from '@/utils/common' +import { externalDirectoryPath, existsFile, writeFile, appendFile } from '@/utils/fs' + +if (process.env.NODE_ENV !== 'development') { + const logPath = externalDirectoryPath + '/debug.log' + + let tempLog = [] + + const log = window.console.log + const error = window.console.error + const warn = window.console.warn + + const writeLog = msg => appendFile(logPath, '\n' + msg) + + window.console.log = (...msgs) => { + log(...msgs) + let msg = msgs.map(m => typeof m == 'object' ? JSON.stringify(m) : m).join(' ') + if (msg.startsWith('%c')) return + let time = new Date().toLocaleString() + if (tempLog) { + tempLog.push({ type: 'LOG', time, text: msg }) + } else writeLog(`${time} LOG ${msg}`) + } + window.console.error = (...msgs) => { + error(...msgs) + let msg = msgs.map(m => typeof m == 'object' ? JSON.stringify(m) : m).join(' ') + let time = new Date().toLocaleString() + if (tempLog) { + tempLog.push({ type: 'ERROR', time, text: msg }) + } else writeLog(`${time} ERROR ${msg}`) + } + window.console.warn = (...msgs) => { + warn(...msgs) + let msg = msgs.map(m => typeof m == 'object' ? JSON.stringify(m) : m).join(' ') + let time = new Date().toLocaleString() + if (tempLog) { + tempLog.push({ type: 'WARN', time, text: msg }) + } else writeLog(`${time} WARN ${msg}`) + } + + const init = async() => { + try { + let result = await requestStoragePermission() + if (!result) return + let isExists = await existsFile(logPath) + console.log(logPath, isExists) + if (!isExists) await writeFile(logPath, '') + writeLog(tempLog.map(m => `${m.time} ${m.type} ${m.text}`).join('\n')) + tempLog = null + } catch (err) { + console.error(err) + } + } + + + init() +} + diff --git a/src/utils/message.js b/src/utils/message.js new file mode 100644 index 0000000..fb5accd --- /dev/null +++ b/src/utils/message.js @@ -0,0 +1,8 @@ +export const requestMsg = { + fail: '请求异常😮,可以多试几次,若还是不行就换一首吧。。。', + unachievable: '哦No😱...接口无法访问了!', + timeout: '请求超时', + // unachievable: '哦No😱...接口无法访问了!已帮你切换到临时接口,重试下看能不能播放吧~', + notConnectNetwork: '无法连接到服务器', + cancelRequest: '取消http请求', +} diff --git a/src/utils/music/api-source-info.js b/src/utils/music/api-source-info.js new file mode 100644 index 0000000..af6ea01 --- /dev/null +++ b/src/utils/music/api-source-info.js @@ -0,0 +1,26 @@ +// Support qualitys: 128k 320k flac wav + +module.exports = [ + { + id: 'test', + name: '测试接口', + disabled: false, + supportQualitys: { + kw: ['128k'], + kg: ['128k'], + tx: ['128k'], + wy: ['128k'], + mg: ['128k'], + // xm: ['128k'], + // bd: ['128k'], + }, + }, + { + id: 'temp', + name: '临时接口', + disabled: false, + supportQualitys: { + kw: ['128k'], + }, + }, +] diff --git a/src/utils/music/api-source.js b/src/utils/music/api-source.js new file mode 100644 index 0000000..51664ae --- /dev/null +++ b/src/utils/music/api-source.js @@ -0,0 +1,41 @@ +import apiSourceInfo from './api-source-info' + +import temp_api_kw from './kw/api-temp' +import test_api_kg from './kg/api-test' +import test_api_kw from './kw/api-test' +import test_api_tx from './tx/api-test' +import test_api_wy from './wy/api-test' +import test_api_mg from './mg/api-test' + +const apiList = { + temp_api_kw, + // test_api_bd: require('./bd/api-test'), + test_api_kg, + test_api_kw, + test_api_tx, + test_api_wy, + test_api_mg, + // test_api_tx: require('./tx/api-test'), + // test_api_wy: require('./wy/api-test'), + // test_api_xm: require('./xm/api-test'), +} +const supportQuality = {} + +for (const api of apiSourceInfo) { + supportQuality[api.id] = api.supportQualitys + // for (const source of Object.keys(api.supportQualitys)) { + // const path = `./${source}/api-${api.id}` + // console.log(path) + // apiList[`${api.id}_api_${source}`] = path + // } +} + +const getAPI = source => apiList[`${global.globalObj.apiSource}_api_${source}`] + +const apis = source => { + const api = getAPI(source) + if (api) return api + throw new Error('Api is not found') +} + +export { apis, supportQuality } diff --git a/src/utils/music/bd/api-test.js b/src/utils/music/bd/api-test.js new file mode 100644 index 0000000..36e9bfc --- /dev/null +++ b/src/utils/music/bd/api-test.js @@ -0,0 +1,20 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_test = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/bd/${songInfo.songmid}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, +} + +export default api_test diff --git a/src/utils/music/bd/hotSearch.js b/src/utils/music/bd/hotSearch.js new file mode 100644 index 0000000..5a9cbf2 --- /dev/null +++ b/src/utils/music/bd/hotSearch.js @@ -0,0 +1,23 @@ +import { httpFetch } from '../../request' + +export default { + _requestObj: null, + async getList(retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('http://musicapi.qianqian.com/v1/restserver/ting?from=android&version=7.0.2.0&channel=ppzs&operator=0&method=baidu.ting.search.hot', { + method: 'get', + headers: { + 'User-Agent': 'android_7.0.2.0;baiduyinyue', + }, + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.error_code !== 22000) throw new Error('获取热搜词失败') + // console.log(body, statusCode) + return { source: 'bd', list: this.filterList(body.result) } + }, + filterList(rawList) { + return rawList.map(item => item.word) + }, +} diff --git a/src/utils/music/bd/index.js b/src/utils/music/bd/index.js new file mode 100644 index 0000000..de780c9 --- /dev/null +++ b/src/utils/music/bd/index.js @@ -0,0 +1,41 @@ +import leaderboard from './leaderboard' +import { apis } from '../api-source' +import musicInfo from './musicInfo' +import songList from './songList' +import { httpFetch } from '../../request' +import musicSearch from './musicSearch' +import hotSearch from './hotSearch' + +const bd = { + leaderboard, + songList, + musicSearch, + hotSearch, + getMusicUrl(songInfo, type) { + return apis('bd').getMusicUrl(songInfo, type) + }, + getPic(songInfo) { + const requestObj = this.getMusicInfo(songInfo) + requestObj.promise = requestObj.promise.then(info => info.pic_premium) + return requestObj + }, + getLyric(songInfo) { + const requestObj = this.getMusicInfo(songInfo) + requestObj.promise = requestObj.promise.then(info => httpFetch(info.lrclink).promise.then(resp => ({ lyric: resp.body, tlyric: '' }))) + return requestObj + }, + // getLyric(songInfo) { + // return apis('bd').getLyric(songInfo) + // }, + // getPic(songInfo) { + // return apis('bd').getPic(songInfo) + // }, + getMusicInfo(songInfo) { + return musicInfo.getMusicInfo(songInfo.songmid) + }, + getMusicDetailPageUrl(songInfo) { + return `http://music.taihe.com/song/${songInfo.songmid}` + }, +} + +export default bd diff --git a/src/utils/music/bd/leaderboard.js b/src/utils/music/bd/leaderboard.js new file mode 100644 index 0000000..af7c257 --- /dev/null +++ b/src/utils/music/bd/leaderboard.js @@ -0,0 +1,155 @@ +import { httpFetch } from '../../request' +// import { formatPlayTime } from '../../index' +// import jshtmlencode from 'js-htmlencode' + +const boardList = [ + // { id: 'bd__601', name: '歌单榜', bangid: '601' }, + { id: 'bd__2', name: '热歌榜', bangid: '2' }, + { id: 'bd__20', name: '华语金曲榜', bangid: '20' }, + { id: 'bd__25', name: '网络歌曲榜', bangid: '25' }, + { id: 'bd__1', name: '新歌榜', bangid: '1' }, + { id: 'bd__21', name: '欧美金曲榜', bangid: '21' }, + { id: 'bd__200', name: '原创音乐榜', bangid: '200' }, + { id: 'bd__22', name: '经典老歌榜', bangid: '22' }, + { id: 'bd__24', name: '影视金曲榜', bangid: '24' }, + { id: 'bd__23', name: '情歌对唱榜', bangid: '23' }, + { id: 'bd__11', name: '摇滚榜', bangid: '11' }, + { id: 'bd__105', name: '好童星榜', bangid: '105' }, + { id: 'bd__106', name: '雅克•藏羌彝原创音乐榜', bangid: '106' }, +] + +export default { + limit: 20, + list: [ + { + id: 'bdrgb', + name: '热歌榜', + bangid: '2', + }, + { + id: 'bdxgb', + name: '新歌榜', + bangid: '1', + }, + { + id: 'bdycb', + name: '原创榜', + bangid: '200', + }, + { + id: 'bdhyjqb', + name: '华语榜', + bangid: '20', + }, + { + id: 'bdomjqb', + name: '欧美榜', + bangid: '21', + }, + { + id: 'bdwugqb', + name: '网络榜', + bangid: '25', + }, + { + id: 'bdjdlgb', + name: '老歌榜', + bangid: '22', + }, + { + id: 'bdysjqb', + name: '影视金曲榜', + bangid: '24', + }, + { + id: 'bdqgdcb', + name: '情歌对唱榜', + bangid: '23', + }, + { + id: 'bdygb', + name: '摇滚榜', + bangid: '11', + }, + ], + getUrl(id, p) { + return `http://musicmini.qianqian.com/2018/static/bangdan/bangdanList_${id}_${p}.html` + }, + regExps: { + item: /data-song="({.+?})"/g, + info: /{total[\s:]+"(\d+)", size[\s:]+"(\d+)", page[\s:]+"(\d+)"}/, + }, + requestObj: null, + getData(url) { + if (this.requestObj) this.requestObj.cancelHttp() + this.requestObj = httpFetch(url) + return this.requestObj.promise + }, + filterData(rawList) { + // console.log(rawList) + return rawList.map(item => { + const types = [] + const _types = {} + let size = null + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + if (item.biaoshi) { + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + // types.reverse() + + return { + singer: item.song_artist.replace(',', '、'), + name: item.song_title, + albumName: item.album_title, + albumId: item.album_id, + source: 'bd', + interval: '', + songmid: item.song_id, + img: null, + lrc: null, + types, + _types, + typeUrl: {}, + } + }) + }, + parseData(rawData) { + // return rawData.map(item => JSON.parse(item.replace(this.regExps.item, '$1').replace(/"/g, '"').replace(/\\\//g, '/').replace(/(@s_1,w_)\d+(,h_)\d+/, '$1500$2500'))) + return rawData.map(item => JSON.parse(item.replace(this.regExps.item, '$1').replace(/"/g, '"').replace(/\\\//g, '/'))) + }, + async getBoards(retryNum = 0) { + this.list = boardList + return { + list: boardList, + source: 'bd', + } + }, + getList(bangid, page, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + return this.getData(this.getUrl(bangid, page)).then(({ body }) => { + let result = body.match(this.regExps.item) + if (!result) return this.getList(bangid, page, retryNum) + let info = body.match(this.regExps.info) + if (!info) return this.getList(bangid, page, retryNum) + const list = this.filterData(this.parseData(result)) + this.limit = parseInt(info[2]) + return { + total: parseInt(info[1]), + list, + limit: this.limit, + page: parseInt(info[3]), + source: 'bd', + } + }) + }, +} diff --git a/src/utils/music/bd/musicInfo.js b/src/utils/music/bd/musicInfo.js new file mode 100644 index 0000000..7c6c0b0 --- /dev/null +++ b/src/utils/music/bd/musicInfo.js @@ -0,0 +1,20 @@ +import { httpFetch } from '../../request' + +export default { + cache: {}, + getMusicInfo(songmid) { + if (this.cache[songmid]) { + return { promise: Promise.resolve(this.cache[songmid]) } + } + const requestObj = httpFetch(`https://musicapi.qianqian.com/v1/restserver/ting?method=baidu.ting.song.getSongLink&format=json&from=bmpc&version=1.0.0&version_d=11.1.6.0&songid=${songmid}&type=1&res=1&s_protocol=1&aac=2&project=tpass`) + requestObj.promise = requestObj.promise.then(({ body }) => { + // console.log(body) + if (body.error_code == 22000) { + this.cache[songmid] = body.result.songinfo + return body.result.songinfo + } + return Promise.reject(new Error('获取音乐信息失败')) + }) + return requestObj + }, +} diff --git a/src/utils/music/bd/musicSearch.js b/src/utils/music/bd/musicSearch.js new file mode 100644 index 0000000..c7574b8 --- /dev/null +++ b/src/utils/music/bd/musicSearch.js @@ -0,0 +1,90 @@ +// import '../../polyfill/array.find' +// import jshtmlencode from 'js-htmlencode' +import { httpFetch } from '../../request' +import { formatPlayTime } from '../../index' +// import { debug } from '../../utils/env' +// import { formatSinger } from './util' + +let searchRequest +export default { + limit: 30, + total: 0, + page: 0, + allPage: 1, + musicSearch(str, page, limit) { + if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp() + searchRequest = httpFetch(`http://tingapi.ting.baidu.com/v1/restserver/ting?from=android&version=5.6.5.6&method=baidu.ting.search.merge&format=json&query=${encodeURIComponent(str)}&page_no=${page}&page_size=${limit}&type=0&data_source=0&use_cluster=1`) + return searchRequest.promise.then(({ body }) => body) + }, + handleResult(rawData) { + let ids = new Set() + const list = [] + if (!rawData) return list + rawData.forEach(item => { + if (ids.has(item.song_id)) return + ids.add(item.song_id) + const types = [] + const _types = {} + let size = null + let itemTypes = item.all_rate.split(',') + if (itemTypes.includes('128')) { + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + if (itemTypes.includes('320')) { + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + if (itemTypes.includes('flac')) { + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + // types.reverse() + + list.push({ + singer: item.author.replace(',', '、'), + name: item.title, + albumName: item.album_title, + albumId: item.album_id, + source: 'bd', + interval: formatPlayTime(parseInt(item.file_duration)), + songmid: item.song_id, + img: null, + lrc: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + search(str, page = 1, { limit } = {}, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + if (limit == null) limit = this.limit + + return this.musicSearch(str, page, limit).then(result => { + if (!result || result.error_code !== 22000) return this.search(str, page, { limit }, retryNum) + let list = this.handleResult(result.result.song_info.song_list) + + if (list == null) return this.search(str, page, { limit }, retryNum) + + this.total = result.result.song_info.total + this.page = page + this.allPage = Math.ceil(this.total / limit) + + return Promise.resolve({ + list, + allPage: this.allPage, + limit: limit, + total: this.total, + source: 'bd', + }) + }) + }, +} diff --git a/src/utils/music/bd/songList.js b/src/utils/music/bd/songList.js new file mode 100644 index 0000000..ad7e2ab --- /dev/null +++ b/src/utils/music/bd/songList.js @@ -0,0 +1,266 @@ +import { httpFetch } from '../../request' +import { formatPlayTime, toMD5 } from '../../index' +import CryptoJS from 'crypto-js' + +export default { + _requestObj_tags: null, + _requestObj_list: null, + _requestObj_listRecommend: null, + _requestObj_listDetail: null, + limit_list: 30, + limit_song: 10000, + successCode: 22000, + sortList: [ + { + name: '最热', + tid: 'hot', + id: '1', + }, + { + name: '最新', + tid: 'new', + id: '0', + }, + ], + regExps: { + // http://music.taihe.com/songlist/566347741 + listDetailLink: /^.+\/songlist\/(\d+)(?:\?.*|&.*$|#.*$|$)/, + }, + aesPassEncod(jsonData) { + let timestamp = Math.floor(Date.now() / 1000) + let privateKey = toMD5('baidu_taihe_music_secret_key' + timestamp).substr(8, 16) + let key = CryptoJS.enc.Utf8.parse(privateKey) + let iv = CryptoJS.enc.Utf8.parse(privateKey) + let arrData = [] + let strData = '' + for (let key in jsonData) arrData.push(key) + arrData.sort() + for (let i = 0; i < arrData.length; i++) { + let key = arrData[i] + strData += + (i === 0 ? '' : '&') + key + '=' + encodeURIComponent(jsonData[key]) + } + let JsonFormatter = { + stringify(cipherParams) { + let jsonObj = { + ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64), + } + if (cipherParams.iv) { + jsonObj.iv = cipherParams.iv.toString() + } + if (cipherParams.salt) { + jsonObj.s = cipherParams.salt.toString() + } + return jsonObj + }, + parse(jsonStr) { + let jsonObj = JSON.parse(jsonStr) + let cipherParams = CryptoJS.lib.CipherParams.create({ + ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct), + }) + if (jsonObj.iv) { + cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv) + } + if (jsonObj.s) { + cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s) + } + return cipherParams + }, + } + let encrypted = CryptoJS.AES.encrypt(strData, key, { + iv: iv, + blockSize: 16, + mode: CryptoJS.mode.CBC, + format: JsonFormatter, + }) + let ciphertext = encrypted.toString().ct + let sign = toMD5('baidu_taihe_music' + ciphertext + timestamp) + let jsonRet = { + timestamp: timestamp, + param: ciphertext, + sign: sign, + } + return jsonRet + }, + createUrl(param, method) { + let data = this.aesPassEncod(param) + return `http://musicmini.qianqian.com/v1/restserver/ting?method=${method}&time=${Date.now()}×tamp=${data.timestamp}¶m=${data.param}&sign=${data.sign}` + }, + getTagsUrl() { + return this.createUrl({ + from: 'qianqianmini', + type: 'diy', + version: '10.1.8', + }, 'baidu.ting.ugcdiy.getChannels') + }, + getListUrl(sortType, tagName, page) { + return this.createUrl({ + channelname: tagName || '全部', + from: 'qianqianmini', + offset: (page - 1) * this.limit_list, + order_type: sortType, + size: this.limit_list, + version: '10.1.8', + }, 'baidu.ting.ugcdiy.getChanneldiy') + }, + getListDetailUrl(list_id, page) { + return this.createUrl({ + list_id, + offset: (page - 1) * this.limit_song, + size: this.limit_song, + withcount: '1', + withsong: '1', + }, 'baidu.ting.ugcdiy.getBaseInfo') + }, + + // 获取标签 + getTags(tryNum = 0) { + if (this._requestObj_tags) this._requestObj_tags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_tags = httpFetch(this.getTagsUrl()) + return this._requestObj_tags.promise.then(({ body }) => { + if (body.error_code !== this.successCode) return this.getTags(++tryNum) + return { + hotTag: this.filterInfoHotTag(body.result.hot), + tags: this.filterTagInfo(body.result.tags), + source: 'bd', + } + }) + }, + filterInfoHotTag(rawList) { + return rawList.map(item => ({ + name: item, + id: item, + source: 'bd', + })) + }, + filterTagInfo(rawList) { + return rawList.map(type => ({ + name: type.first, + list: type.second.map(item => ({ + parent_id: type.first, + parent_name: type.first, + id: item, + name: item, + source: 'bd', + })), + })) + }, + + // 获取列表数据 + getList(sortId, tagId, page, tryNum = 0) { + if (this._requestObj_list) this._requestObj_list.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_list = httpFetch(this.getListUrl(sortId, tagId, page)) + return this._requestObj_list.promise.then(({ body }) => { + if (body.error_code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum) + return { + list: this.filterList(body.diyInfo), + total: body.nums, + page, + limit: this.limit_list, + source: 'bd', + } + }) + }, + + + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + filterList(rawData) { + return rawData.map(item => ({ + play_count: this.formatPlayCount(item.listen_num), + id: item.list_id, + author: item.username, + name: item.title, + // time: item.publish_time, + img: item.list_pic_large || item.list_pic, + grade: item.grade, + desc: item.desc || item.tag, + source: 'bd', + })) + }, + + // 获取歌曲列表内的音乐 + getListDetail(id, page, tryNum = 0) { + if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + + if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1') + + this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id, page)) + return this._requestObj_listDetail.promise.then(({ body }) => { + if (body.error_code !== this.successCode) return this.getListDetail(id, page, ++tryNum) + let listData = this.filterData(body.result.songlist) + return { + list: listData, + page, + limit: this.limit_song, + total: body.result.song_num, + source: 'bd', + info: { + name: body.result.info.list_title, + img: body.result.info.list_pic, + desc: body.result.info.list_desc, + author: body.result.info.userinfo.username, + play_count: this.formatPlayCount(body.result.listen_num), + }, + } + }) + }, + filterData(rawList) { + // console.log(rawList) + return rawList.map(item => { + const types = [] + const _types = {} + let size = null + let itemTypes = item.all_rate.split(',') + if (itemTypes.includes('128')) { + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + if (itemTypes.includes('320')) { + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + if (itemTypes.includes('flac')) { + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + // types.reverse() + + return { + singer: item.author.replace(',', '、'), + name: item.title, + albumName: item.album_title, + albumId: item.album_id, + source: 'bd', + interval: formatPlayTime(parseInt(item.file_duration)), + songmid: item.song_id, + img: item.pic_s500, + lrc: null, + types, + _types, + typeUrl: {}, + } + }) + }, + +} + +// getList +// getTags +// getListDetail diff --git a/src/utils/music/index.js b/src/utils/music/index.js new file mode 100644 index 0000000..2162643 --- /dev/null +++ b/src/utils/music/index.js @@ -0,0 +1,137 @@ +import kw from './kw' +import kg from './kg' +import tx from './tx' +import wy from './wy' +import mg from './mg' +// import bd from './bd' +import xm from './xm' +import { supportQuality } from './api-source' + + +const sources = { + sources: [ + { + name: '酷我音乐', + id: 'kw', + }, + { + name: '酷狗音乐', + id: 'kg', + }, + { + name: 'QQ音乐', + id: 'tx', + }, + { + name: '网易音乐', + id: 'wy', + }, + { + name: '咪咕音乐', + id: 'mg', + }, + // { + // name: '百度音乐', + // id: 'bd', + // }, + ], + kw, + kg, + tx, + wy, + mg, + // bd, + xm, +} +export default { + ...sources, + supportQuality, +} + +export const init = () => { + const tasks = [] + for (let source of sources.sources) { + let sm = sources[source.id] + sm && sm.init && tasks.push(sm.init()) + } + return Promise.all(tasks) +} + +export const findMusic = async(musicInfo) => { + const tasks = [] + const sortSingle = singer => singer.includes('、') ? singer.split('、').sort((a, b) => a.charCodeAt(0) - b.charCodeAt(0)).join('、') : singer + const sortMusic = (arr, callback) => { + const tempResult = [] + for (let i = arr.length - 1; i > -1; i--) { + const item = arr[i] + if (callback(item)) { + delete item.sortedSinger + tempResult.push(item) + arr.splice(i, 1) + } + } + tempResult.reverse() + return tempResult + } + const trimStr = str => typeof str == 'string' ? str.trim() : str + const sortedSinger = String(sortSingle(musicInfo.singer)).toLowerCase() + const musicName = trimStr(musicInfo.name) + const lowerCaseName = String(musicName).toLowerCase() + const lowerCaseAlbumName = String(musicInfo.albumName).toLowerCase() + for (const source of sources.sources) { + if (!sources[source.id].musicSearch || source.id === musicInfo.source || source.id === 'xm') continue + + tasks.push(sources[source.id].musicSearch.search(`${musicName} ${musicInfo.singer || ''}`.trim(), 1, { limit: 10 }).then(res => { + for (const item of res.list) { + item.sortedSinger = String(sortSingle(item.singer)).toLowerCase() + item.name = trimStr(item.name) + item.lowerCaseName = String(item.name).toLowerCase() + item.lowerCaseAlbumName = String(item.albumName).toLowerCase() + // console.log(lowerCaseName, item.lowerCaseName) + if ( + ( + item.sortedSinger === sortedSinger && item.lowerCaseName === lowerCaseName + ) || + ( + item.interval === musicInfo.interval && item.lowerCaseName === lowerCaseName && + (item.sortedSinger.includes(sortedSinger) || sortedSinger.includes(item.sortedSinger)) + ) || + ( + item.lowerCaseName === lowerCaseName && item.lowerCaseAlbumName === lowerCaseAlbumName && + item.interval === musicInfo.interval + ) + ) { + return item + } + } + for (const item of res.list) { + item.sortedSinger = String(sortSingle(item.singer)).toLowerCase() + item.name = trimStr(item.name) + item.lowerCaseName = String(item.name).toLowerCase() + item.lowerCaseAlbumName = String(item.albumName).toLowerCase() + // console.log(lowerCaseName, item.lowerCaseName) + if ( + item.sortedSinger === sortedSinger && item.interval === musicInfo.interval + ) { + return item + } + } + return null + }).catch(_ => null)) + } + const result = (await Promise.all(tasks)).filter(s => s) + const newResult = [] + if (result.length) { + newResult.push(...sortMusic(result, item => item.sortedSinger === sortedSinger && item.lowerCaseName === lowerCaseName && item.interval === musicInfo.interval)) + newResult.push(...sortMusic(result, item => item.lowerCaseName === lowerCaseName && item.sortedSinger === sortedSinger && item.lowerCaseAlbumName === lowerCaseAlbumName)) + newResult.push(...sortMusic(result, item => item.sortedSinger === sortedSinger && item.lowerCaseName === lowerCaseName)) + newResult.push(...sortMusic(result, item => item.sortedSinger === sortedSinger && item.interval === musicInfo.interval)) + for (const item of result) { + delete item.sortedSinger + delete item.lowerCaseName + } + newResult.push(...result) + } + // console.log(newResult) + return newResult +} diff --git a/src/utils/music/kg/api-test.js b/src/utils/music/kg/api-test.js new file mode 100644 index 0000000..0d96fd9 --- /dev/null +++ b/src/utils/music/kg/api-test.js @@ -0,0 +1,44 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_test = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/kg/${songInfo._types[type].hash}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, + getPic(songInfo) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/pic/kg/${songInfo.hash}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, + getLyric(songInfo) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/lrc/kg/${songInfo.hash}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, +} + +export default api_test diff --git a/src/utils/music/kg/comment.js b/src/utils/music/kg/comment.js new file mode 100644 index 0000000..cffd7aa --- /dev/null +++ b/src/utils/music/kg/comment.js @@ -0,0 +1,79 @@ +import { httpFetch } from '../../request' +import { decodeName, dateFormat2 } from '../../' + +export default { + _requestObj: null, + _requestObj2: null, + async getComment({ hash }, page = 1, limit = 20) { + if (this._requestObj) this._requestObj.cancelHttp() + + const _requestObj = httpFetch(`http://comment.service.kugou.com/index.php?r=commentsv2/getCommentWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&extdata=${hash}&p=${page}&pagesize=${limit}&ver=1.01&clientver=8373&appid=1001&kugouid=687373022`, { + headers: { + 'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi', + }, + }) + const { body, statusCode } = await _requestObj.promise + // console.log(body) + if (statusCode != 200 || body.err_code !== 0) throw new Error('获取评论失败') + return { source: 'kg', comments: this.filterComment(body.list || []), total: body.count, page, limit, maxPage: Math.ceil(body.count / limit) || 1 } + }, + async getHotComment({ hash, songmid }, page = 1, limit = 100) { + // console.log(songmid) + if (this._requestObj2) this._requestObj2.cancelHttp() + + const _requestObj2 = httpFetch(`http://comment.service.kugou.com/index.php?r=commentsv2/getCommentWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&extdata=${hash}&p=${page}&pagesize=${limit}&ver=1.01&clientver=8373&appid=1001&kugouid=687373022`, { + headers: { + 'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi', + }, + }) + const { body, statusCode } = await _requestObj2.promise + // console.log(body) + if (statusCode != 200 || body.err_code !== 0) throw new Error('获取热门评论失败') + return { source: 'kg', comments: this.filterComment(body.weightList || []) } + }, + async getReplyComment({ songmid, audioId }, replyId, page = 1, limit = 100) { + if (this._requestObj2) this._requestObj2.cancelHttp() + + songmid = songmid.length == 32 // 修复歌曲ID存储变更导致图片获取失败的问题 + ? audioId.split('_')[0] + : songmid + + const _requestObj2 = httpFetch(`http://comment.service.kugou.com/index.php?r=commentsv2/getReplyWithLike&code=fc4be23b4e972707f36b8a828a93ba8a&p=${page}&pagesize=${limit}&ver=1.01&clientver=8373&kugouid=687373022&appid=1001&childrenid=${songmid}&tid=${replyId}`, { + headers: { + 'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi', + }, + }) + const { body, statusCode } = await _requestObj2.promise + // console.log(body) + if (statusCode != 200 || body.err_code !== 0) throw new Error('获取回复评论失败') + return { source: 'kg', comments: this.filterComment(body.list || []) } + }, + filterComment(rawList) { + return rawList.map(item => { + let data = { + id: item.id, + text: decodeName(item.content || '').split('\n'), + time: item.addtime, + timeStr: dateFormat2(new Date(item.addtime).getTime()), + userName: item.user_name, + avatar: item.user_pic, + userId: item.user_id, + likedCount: item.like.likenum, + replyNum: item.reply_num, + reply: [], + } + + return item.pcontent ? { + id: item.id, + text: decodeName(item.pcontent).split('\n'), + time: null, + userName: item.puser, + avatar: null, + userId: item.puser_id, + likedCount: null, + replyNum: null, + reply: [data], + } : data + }) + }, +} diff --git a/src/utils/music/kg/hotSearch.js b/src/utils/music/kg/hotSearch.js new file mode 100644 index 0000000..4e0e244 --- /dev/null +++ b/src/utils/music/kg/hotSearch.js @@ -0,0 +1,33 @@ +import { httpFetch } from '../../request' +import { decodeName } from '../..' + +export default { + _requestObj: null, + async getList(retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('http://gateway.kugou.com/api/v3/search/hot_tab?signature=ee44edb9d7155821412d220bcaf509dd&appid=1005&clientver=10026&plat=0', { + method: 'get', + headers: { + dfid: '1ssiv93oVqMp27cirf2CvoF1', + mid: '156798703528610303473757548878786007104', + clienttime: 1584257267, + 'x-router': 'msearch.kugou.com', + 'user-agent': 'Android9-AndroidPhone-10020-130-0-searchrecommendprotocol-wifi', + 'kg-rc': 1, + }, + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.errcode !== 0) throw new Error('获取热搜词失败') + // console.log(body, statusCode) + return { source: 'kg', list: this.filterList(body.data.list) } + }, + filterList(rawList) { + const list = [] + rawList.forEach(item => { + item.keywords.map(k => list.push(decodeName(k.keyword))) + }) + return list + }, +} diff --git a/src/utils/music/kg/index.js b/src/utils/music/kg/index.js new file mode 100644 index 0000000..4d4ac3d --- /dev/null +++ b/src/utils/music/kg/index.js @@ -0,0 +1,36 @@ +import leaderboard from './leaderboard' +import { apis } from '../api-source' +import songList from './songList' +import musicSearch from './musicSearch' +import pic from './pic' +import lyric from './lyric' +import hotSearch from './hotSearch' +import comment from './comment' + +const kg = { + leaderboard, + songList, + musicSearch, + hotSearch, + comment, + getMusicUrl(songInfo, type) { + return apis('kg').getMusicUrl(songInfo, type) + }, + getLyric(songInfo) { + return lyric.getLyric(songInfo) + }, + // getLyric(songInfo) { + // return apis('kg').getLyric(songInfo) + // }, + getPic(songInfo) { + return pic.getPic(songInfo) + }, + getMusicDetailPageUrl(songInfo) { + return `https://www.kugou.com/song/#hash=${songInfo.hash}&album_id=${songInfo.albumId}` + }, + // getPic(songInfo) { + // return apis('kg').getPic(songInfo) + // }, +} + +export default kg diff --git a/src/utils/music/kg/leaderboard.js b/src/utils/music/kg/leaderboard.js new file mode 100644 index 0000000..7a6c3fb --- /dev/null +++ b/src/utils/music/kg/leaderboard.js @@ -0,0 +1,210 @@ +import { httpGet, cancelHttp, httpFetch } from '../../request' +import { decodeName, formatPlayTime, sizeFormate } from '../../index' + +let boardList = [{ id: 'kg__8888', name: '酷狗TOP500', bangid: '8888' }, { id: 'kg__6666', name: '酷狗飙升榜', bangid: '6666' }, { id: 'kg__37361', name: '酷狗雷达榜', bangid: '37361' }, { id: 'kg__23784', name: '网络红歌榜', bangid: '23784' }, { id: 'kg__24971', name: 'DJ热歌榜', bangid: '24971' }, { id: 'kg__35811', name: '会员专享热歌榜', bangid: '35811' }, { id: 'kg__31308', name: '华语新歌榜', bangid: '31308' }, { id: 'kg__31310', name: '欧美新歌榜', bangid: '31310' }, { id: 'kg__31311', name: '韩国新歌榜', bangid: '31311' }, { id: 'kg__31312', name: '日本新歌榜', bangid: '31312' }, { id: 'kg__31313', name: '粤语新歌榜', bangid: '31313' }, { id: 'kg__33162', name: 'ACG新歌榜', bangid: '33162' }, { id: 'kg__21101', name: '酷狗分享榜', bangid: '21101' }, { id: 'kg__30972', name: '腾讯音乐人原创榜', bangid: '30972' }, { id: 'kg__22603', name: '5sing音乐榜', bangid: '22603' }, { id: 'kg__33160', name: '电音热歌榜', bangid: '33160' }, { id: 'kg__21335', name: '繁星音乐榜', bangid: '21335' }, { id: 'kg__33161', name: '古风新歌榜', bangid: '33161' }, { id: 'kg__33163', name: '影视金曲榜', bangid: '33163' }, { id: 'kg__33166', name: '欧美金曲榜', bangid: '33166' }, { id: 'kg__33165', name: '粤语金曲榜', bangid: '33165' }, { id: 'kg__36107', name: '小语种热歌榜', bangid: '36107' }, { id: 'kg__4681', name: '美国BillBoard榜', bangid: '4681' }, { id: 'kg__4680', name: '英国单曲榜', bangid: '4680' }, { id: 'kg__4673', name: '日本公信榜', bangid: '4673' }, { id: 'kg__38623', name: '韩国Melon音乐榜', bangid: '38623' }, { id: 'kg__42807', name: 'joox本地热歌榜', bangid: '42807' }, { id: 'kg__42808', name: '台湾KKBOX风云榜', bangid: '42808' }] + +export default { + list: [ + { + id: 'kgtop500', + name: '酷狗TOP500', + bangid: '8888', + }, + { + id: 'kgwlhgb', + name: '网络榜', + bangid: '23784', + }, + { + id: 'kgbsb', + name: '飙升榜', + bangid: '6666', + }, + { + id: 'kgfxb', + name: '分享榜', + bangid: '21101', + }, + { + id: 'kgcyyb', + name: '纯音乐榜', + bangid: '33164', + }, + { + id: 'kggfjqb', + name: '古风榜', + bangid: '33161', + }, + { + id: 'kgyyjqb', + name: '粤语榜', + bangid: '33165', + }, + { + id: 'kgomjqb', + name: '欧美榜', + bangid: '33166', + }, + { + id: 'kgdyrgb', + name: '电音榜', + bangid: '33160', + }, + { + id: 'kgjdrgb', + name: 'DJ热歌榜', + bangid: '24971', + }, + { + id: 'kghyxgb', + name: '华语新歌榜', + bangid: '31308', + }, + ], + getUrl(p, id) { + return `http://www2.kugou.kugou.com/yueku/v9/rank/home/${p}-${id}.html` + }, + regExps: { + total: /total: '(\d+)',/, + page: /page: '(\d+)',/, + limit: /pagesize: '(\d+)',/, + listData: /global\.features = (\[.+\]);/, + }, + _requestBoardsObj: null, + _requestObj: null, + _cancelPromiseCancelFn: null, + getBoardsData() { + if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp() + this._requestBoardsObj = httpFetch('http://mobilecdnbj.kugou.com/api/v3/rank/list?version=9108&plat=0&showtype=2&parentid=0&apiver=6&area_code=1&withsong=1') + return this._requestBoardsObj.promise + }, + getData(url) { + if (this._requestObj != null) { + cancelHttp(this._requestObj) + this._cancelPromiseCancelFn(new Error('取消http请求')) + } + return new Promise((resolve, reject) => { + this._cancelPromiseCancelFn = reject + this._requestObj = httpGet(url, (err, resp, body) => { + this._requestObj = null + this._cancelPromiseCancelFn = null + if (err) { + console.log(err) + reject(err) + } + resolve(body) + }) + }) + }, + filterData(rawList) { + // console.log(rawList) + return rawList.map(item => { + const types = [] + const _types = {} + if (item.filesize !== 0) { + let size = sizeFormate(item.filesize) + types.push({ type: '128k', size, hash: item.hash }) + _types['128k'] = { + size, + hash: item.hash, + } + } + if (item.filesize_320 !== 0) { + let size = sizeFormate(item.filesize_320) + types.push({ type: '320k', size, hash: item.hash_320 }) + _types['320k'] = { + size, + hash: item.hash_320, + } + } + if (item.filesize_ape !== 0) { + let size = sizeFormate(item.filesize_ape) + types.push({ type: 'ape', size, hash: item.hash_ape }) + _types.ape = { + size, + hash: item.hash_ape, + } + } + if (item.filesize_flac !== 0) { + let size = sizeFormate(item.filesize_flac) + types.push({ type: 'flac', size, hash: item.hash_flac }) + _types.flac = { + size, + hash: item.hash_flac, + } + } + return { + singer: decodeName(item.singername), + name: decodeName(item.songname), + albumName: decodeName(item.album_name), + albumId: item.album_id, + songmid: item.audio_id, + source: 'kg', + interval: formatPlayTime(item.duration / 1000), + img: null, + lrc: null, + hash: item.HASH, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + + filterBoardsData(rawList) { + // console.log(rawList) + let list = [] + for (const board of rawList) { + if (board.isvol != 1) continue + list.push({ + id: 'kg__' + board.rankid, + name: board.rankname, + bangid: String(board.rankid), + }) + } + return list + }, + async getBoards(retryNum = 0) { + // if (++retryNum > 3) return Promise.reject(new Error('try max num')) + // let response + // try { + // response = await this.getBoardsData() + // } catch (error) { + // return this.getBoards(retryNum) + // } + // // console.log(response.body) + // if (response.statusCode !== 200 || response.body.errcode !== 0) return this.getBoards(retryNum) + // const list = this.filterBoardsData(response.body.data.info) + // // console.log(list) + // this.list = list + // return { + // list, + // source: 'kg', + // } + this.list = boardList + return { + list: boardList, + source: 'kg', + } + }, + getList(bangid, page) { + return this.getData(this.getUrl(page, bangid)).then(html => { + let total = html.match(this.regExps.total) + if (total) total = parseInt(RegExp.$1) + page = html.match(this.regExps.page) + if (page) page = parseInt(RegExp.$1) + let limit = html.match(this.regExps.limit) + if (limit) limit = parseInt(RegExp.$1) + let listData = html.match(this.regExps.listData) + if (listData) listData = this.filterData(JSON.parse(RegExp.$1)) + return { + total, + list: listData, + limit, + page, + source: 'kg', + } + }) + }, +} diff --git a/src/utils/music/kg/lyric.js b/src/utils/music/kg/lyric.js new file mode 100644 index 0000000..2467ae3 --- /dev/null +++ b/src/utils/music/kg/lyric.js @@ -0,0 +1,138 @@ +import { httpFetch } from '../../request' +import { decodeLyric } from './util' +import { decodeName } from '../..' + +const headExp = /^.*\[id:\$\w+\]\n/ + +const parseLyric = str => { + str = str.replace(/\r/g, '') + if (headExp.test(str)) str = str.replace(headExp, '') + let trans = str.match(/\[language:([\w=\\/+]+)\]/) + let lyric + let tlyric + if (trans) { + str = str.replace(/\[language:[\w=\\/+]+\]\n/, '') + let json = JSON.parse(Buffer.from(trans[1], 'base64').toString()) + for (const item of json.content) { + if (item.type == 1) { + tlyric = item.lyricContent + break + } + } + } + let i = 0 + let lxlyric = str.replace(/\[((\d+),\d+)\].*/g, str => { + let result = str.match(/\[((\d+),\d+)\].*/) + let time = parseInt(result[2]) + let ms = time % 1000 + time /= 1000 + let m = parseInt(time / 60).toString().padStart(2, '0') + time %= 60 + let s = parseInt(time).toString().padStart(2, '0') + time = `${m}:${s}.${ms}` + if (tlyric) tlyric[i] = `[${time}]${tlyric[i++][0]}` + return str.replace(result[1], time) + }) + tlyric = tlyric ? tlyric.join('\n') : '' + lxlyric = lxlyric.replace(/<(\d+,\d+),\d+>/g, '<$1>') + lxlyric = decodeName(lxlyric) + lyric = lxlyric.replace(/<\d+,\d+>/g, '') + tlyric = decodeName(tlyric) + return { + lyric, + tlyric, + lxlyric, + } +} + +export default { + getIntv(interval) { + let intvArr = interval.split(':') + let intv = 0 + let unit = 1 + while (intvArr.length) { + intv += (intvArr.pop()) * unit + unit *= 60 + } + return parseInt(intv) + }, + // getLyric(songInfo, tryNum = 0) { + // let requestObj = httpFetch(`http://m.kugou.com/app/i/krc.php?cmd=100&keyword=${encodeURIComponent(songInfo.name)}&hash=${songInfo.hash}&timelength=${songInfo._interval || this.getIntv(songInfo.interval)}&d=0.38664927426725626`, { + // headers: { + // 'KG-RC': 1, + // 'KG-THash': 'expand_search_manager.cpp:852736169:451', + // 'User-Agent': 'KuGou2012-9020-ExpandSearchManager', + // }, + // }) + // requestObj.promise = requestObj.promise.then(({ body, statusCode }) => { + // if (statusCode !== 200) { + // if (tryNum > 5) return Promise.reject('歌词获取失败') + // let tryRequestObj = this.getLyric(songInfo, ++tryNum) + // requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + // return tryRequestObj.promise + // } + // return { + // lyric: body, + // tlyric: '', + // } + // }) + // return requestObj + // }, + searchLyric(name, hash, time, tryNum = 0) { + let requestObj = httpFetch(`http://lyrics.kugou.com/search?ver=1&man=yes&client=pc&keyword=${encodeURIComponent(name)}&hash=${hash}&timelength=${time}`, { + headers: { + 'KG-RC': 1, + 'KG-THash': 'expand_search_manager.cpp:852736169:451', + 'User-Agent': 'KuGou2012-9020-ExpandSearchManager', + }, + }) + requestObj.promise = requestObj.promise.then(({ body, statusCode }) => { + if (statusCode !== 200) { + if (tryNum > 5) return Promise.reject('歌词获取失败') + let tryRequestObj = this.searchLyric(name, hash, time, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + if (body.candidates.length) { + let info = body.candidates[0] + return { id: info.id, accessKey: info.accesskey } + } + return null + }) + return requestObj + }, + getLyricDownload(id, accessKey, tryNum = 0) { + let requestObj = httpFetch(`http://lyrics.kugou.com/download?ver=1&client=pc&id=${id}&accesskey=${accessKey}&fmt=krc&charset=utf8`, { + headers: { + 'KG-RC': 1, + 'KG-THash': 'expand_search_manager.cpp:852736169:451', + 'User-Agent': 'KuGou2012-9020-ExpandSearchManager', + }, + }) + requestObj.promise = requestObj.promise.then(({ body, statusCode }) => { + if (statusCode !== 200) { + if (tryNum > 5) return Promise.reject('歌词获取失败') + let tryRequestObj = this.getLyric(id, accessKey, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + + return decodeLyric(body.content).then(result => parseLyric(result)) + }) + return requestObj + }, + getLyric(songInfo, tryNum = 0) { + let requestObj = this.searchLyric(songInfo.name, songInfo.hash, songInfo._interval || this.getIntv(songInfo.interval)) + + requestObj.promise = requestObj.promise.then(result => { + if (!result) return { lyric: null, tlyric: null, lxlyric: null } + + let requestObj2 = this.getLyricDownload(result.id, result.accessKey) + + requestObj.cancelHttp = requestObj2.cancelHttp.bind(requestObj2) + + return requestObj2.promise + }) + return requestObj + }, +} diff --git a/src/utils/music/kg/musicSearch.js b/src/utils/music/kg/musicSearch.js new file mode 100644 index 0000000..1fcd6da --- /dev/null +++ b/src/utils/music/kg/musicSearch.js @@ -0,0 +1,105 @@ +// import '../../polyfill/array.find' +// import jshtmlencode from 'js-htmlencode' +import { httpFetch } from '../../request' +import { decodeName, formatPlayTime, sizeFormate } from '../../index' +// import { debug } from '../../utils/env' +// import { formatSinger } from './util' + +let searchRequest +export default { + limit: 30, + total: 0, + page: 0, + allPage: 1, + musicSearch(str, page, limit) { + if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp() + searchRequest = httpFetch(`http://ioscdn.kugou.com/api/v3/search/song?keyword=${encodeURIComponent(str)}&page=${page}&pagesize=${limit}&showtype=10&plat=2&version=7910&tag=1&correct=1&privilege=1&sver=5`) + return searchRequest.promise.then(({ body }) => body) + }, + filterData(rawData) { + const types = [] + const _types = {} + if (rawData.filesize !== 0) { + let size = sizeFormate(rawData.filesize) + types.push({ type: '128k', size, hash: rawData.hash }) + _types['128k'] = { + size, + hash: rawData.hash, + } + } + if (rawData['320filesize'] !== 0) { + let size = sizeFormate(rawData['320filesize']) + types.push({ type: '320k', size, hash: rawData['320hash'] }) + _types['320k'] = { + size, + hash: rawData['320hash'], + } + } + if (rawData.sqfilesize !== 0) { + let size = sizeFormate(rawData.sqfilesize) + types.push({ type: 'flac', size, hash: rawData.sqhash }) + _types.flac = { + size, + hash: rawData.sqhash, + } + } + return { + singer: decodeName(rawData.singername), + name: decodeName(rawData.songname), + albumName: decodeName(rawData.album_name), + albumId: rawData.album_id, + songmid: rawData.audio_id, + source: 'kg', + interval: formatPlayTime(rawData.duration), + _interval: rawData.duration, + img: null, + lrc: null, + otherSource: null, + hash: rawData.hash, + types, + _types, + typeUrl: {}, + } + }, + handleResult(rawData) { + // console.log(rawData) + let ids = new Set() + const list = [] + rawData.forEach(item => { + const key = item.audio_id + if (ids.has(key)) return + ids.add(key) + list.push(this.filterData(item)) + for (const childItem of item.group) { + const key = item.audio_id + if (ids.has(key)) return + ids.add(key) + list.push(this.filterData(childItem)) + } + }) + return list + }, + search(str, page = 1, { limit } = {}, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + if (limit == null) limit = this.limit + // http://newlyric.kuwo.cn/newlyric.lrc?62355680 + return this.musicSearch(str, page, limit).then(result => { + if (!result || result.errcode !== 0) return this.search(str, page, { limit }, retryNum) + let list = this.handleResult(result.data.info) + + if (list == null) return this.search(str, page, { limit }, retryNum) + + this.total = result.data.total + this.page = page + this.allPage = Math.ceil(this.total / limit) + + return Promise.resolve({ + list, + allPage: this.allPage, + limit, + total: this.total, + source: 'kg', + }) + }) + }, +} diff --git a/src/utils/music/kg/pic.js b/src/utils/music/kg/pic.js new file mode 100644 index 0000000..04bceb6 --- /dev/null +++ b/src/utils/music/kg/pic.js @@ -0,0 +1,50 @@ +import { httpFetch } from '../../request' + +export default { + getPic(songInfo) { + const requestObj = httpFetch( + 'http://media.store.kugou.com/v1/get_res_privilege', + { + method: 'POST', + headers: { + 'KG-RC': 1, + 'KG-THash': 'expand_search_manager.cpp:852736169:451', + 'User-Agent': 'KuGou2012-9020-ExpandSearchManager', + }, + body: { + appid: 1001, + area_code: '1', + behavior: 'play', + clientver: '9020', + need_hash_offset: 1, + relate: 1, + resource: [ + { + album_audio_id: + songInfo.songmid.length == 32 // 修复歌曲ID存储变更导致图片获取失败的问题 + ? songInfo.audioId.split('_')[0] + : songInfo.songmid, + album_id: songInfo.albumId, + hash: songInfo.hash, + id: 0, + name: `${songInfo.singer} - ${songInfo.name}.mp3`, + type: 'audio', + }, + ], + token: '', + userid: 2626431536, + vip: 1, + }, + }, + ) + requestObj.promise = requestObj.promise.then(({ body }) => { + console.log(body) + if (body.error_code !== 0) return Promise.reject('图片获取失败') + let info = body.data[0].info + const img = info.imgsize ? info.image.replace('{size}', info.imgsize[0]) : info.image + if (!img) return Promise.reject('Pic get failed') + return img + }) + return requestObj + }, +} diff --git a/src/utils/music/kg/songList.js b/src/utils/music/kg/songList.js new file mode 100644 index 0000000..4332550 --- /dev/null +++ b/src/utils/music/kg/songList.js @@ -0,0 +1,590 @@ +import { httpFetch } from '../../request' +import { decodeName, formatPlayTime, sizeFormate } from '../../index' +import { toMD5 } from '../utils' + +export default { + _requestObj_tags: null, + _requestObj_listInfo: null, + _requestObj_list: null, + _requestObj_listRecommend: null, + _requestObj_listDetail: null, + listDetailLimit: 10000, + currentTagInfo: { + id: undefined, + info: undefined, + }, + sortList: [ + { + name: '推荐', + tid: 'recommend', + id: '5', + }, + { + name: '最热', + tid: 'hot', + id: '6', + }, + { + name: '最新', + tid: 'new', + id: '7', + }, + { + name: '热藏', + tid: 'hot_collect', + id: '3', + }, + { + name: '飙升', + tid: 'rise', + id: '8', + }, + ], + regExps: { + listData: /global\.data = (\[.+\]);/, + listInfo: /global = {[\s\S]+?name: "(.+)"[\s\S]+?pic: "(.+)"[\s\S]+?};/, + // https://www.kugou.com/yy/special/single/1067062.html + listDetailLink: /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/, + }, + getInfoUrl(tagId) { + return tagId + ? `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&cdn=cdn&t=5&c=${tagId}` + : 'http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_smarty=1&' + }, + getSongListUrl(sortId, tagId, page) { + if (tagId == null) tagId = '' + return `http://www2.kugou.kugou.com/yueku/v9/special/getSpecial?is_ajax=1&cdn=cdn&t=${sortId}&c=${tagId}&p=${page}` + }, + getSongListDetailUrl(id) { + return `http://www2.kugou.kugou.com/yueku/v9/special/single/${id}-5-9999.html` + }, + + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + filterInfoHotTag(rawData) { + const result = [] + if (rawData.status !== 1) return result + for (const key of Object.keys(rawData.data)) { + let tag = rawData.data[key] + result.push({ + id: tag.special_id, + name: tag.special_name, + source: 'kg', + }) + } + return result + }, + filterTagInfo(rawData) { + const result = [] + for (const name of Object.keys(rawData)) { + result.push({ + name, + list: rawData[name].data.map(tag => ({ + parent_id: tag.parent_id, + parent_name: tag.pname, + id: tag.id, + name: tag.name, + source: 'kg', + })), + }) + } + return result + }, + + getSongList(sortId, tagId, page, tryNum = 0) { + if (this._requestObj_list) this._requestObj_list.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_list = httpFetch( + this.getSongListUrl(sortId, tagId, page), + ) + return this._requestObj_list.promise.then(({ body }) => { + if (!body || body.status !== 1) return this.getSongList(sortId, tagId, page, ++tryNum) + return this.filterList(body.special_db) + }) + }, + getSongListRecommend(tryNum = 0) { + if (this._requestObj_listRecommend) this._requestObj_listRecommend.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_listRecommend = httpFetch( + 'http://everydayrec.service.kugou.com/guess_special_recommend', + { + method: 'post', + headers: { + 'User-Agent': 'KuGou2012-8275-web_browser_event_handler', + }, + body: { + appid: 1001, + clienttime: 1566798337219, + clientver: 8275, + key: 'f1f93580115bb106680d2375f8032d96', + mid: '21511157a05844bd085308bc76ef3343', + platform: 'pc', + userid: '262643156', + return_min: 6, + return_max: 15, + }, + }, + ) + return this._requestObj_listRecommend.promise.then(({ body }) => { + if (body.status !== 1) return this.getSongListRecommend(++tryNum) + return this.filterList(body.data.special_list) + }) + }, + filterList(rawData) { + return rawData.map(item => ({ + play_count: item.total_play_count || this.formatPlayCount(item.play_count), + id: 'id_' + item.specialid, + author: item.nickname, + name: item.specialname, + time: item.publish_time || item.publishtime, + img: item.img || item.imgurl, + grade: item.grade, + desc: item.intro, + source: 'kg', + })) + }, + + async createHttp(url, options, retryNum = 0) { + if (retryNum > 2) throw new Error('try max num') + let result + try { + result = await httpFetch(url, options).promise + } catch (err) { + console.log(err) + return this.createHttp(url, options, ++retryNum) + } + // console.log(result.statusCode, result.body) + if (result.statusCode !== 200 || + ( + (result.body.error_code !== undefined + ? result.body.error_code + : result.body.errcode !== undefined + ? result.body.errcode + : result.body.err_code + ) !== 0) + ) return this.createHttp(url, options, ++retryNum) + return result.body.data || result.body.info + }, + + createTask(hashs) { + let data = { + appid: 1001, + clienttime: 639437935, + clientver: 9020, + fields: + 'album_info,author_name,audio_info,ori_audio_name', + is_publish: '1', + key: '0475af1457cd3363c7b45b871e94428a', + mid: '21511157a05844bd085308bc76ef3342', + show_privilege: 1, + } + let list = hashs + let tasks = [] + while (list.length) { + tasks.push(Object.assign({ data: list.slice(0, 20) }, data)) + if (list.length < 20) break + list = list.slice(20) + } + let url = 'http://kmr.service.kugou.com/v2/album_audio/audio' + return tasks.map(task => this.createHttp(url, { + method: 'POST', + body: task, + headers: { + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', + }, + }).then(data => data.map(s => s[0]))) + }, + + async getUserListDetailByCode(id) { + const songInfo = await this.createHttp('http://t.kugou.com/command/', { + method: 'POST', + headers: { + 'KG-RC': 1, + 'KG-THash': 'network_super_call.cpp:3676261689:379', + 'User-Agent': '', + }, + body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: id }, + }) + // console.log(songInfo) + let songList + let info = songInfo.info + if (info.userid != null) { + songList = await this.createHttp('http://www2.kugou.kugou.com/apps/kucodeAndShare/app/', { + method: 'POST', + headers: { + 'KG-RC': 1, + 'KG-THash': 'network_super_call.cpp:3676261689:379', + 'User-Agent': '', + }, + body: { appid: 1001, clientver: 9020, mid: '21511157a05844bd085308bc76ef3343', clienttime: 640612895, key: '36164c4015e704673c588ee202b9ecb8', data: { id: info.id, type: 3, userid: info.userid, collect_type: 0, page: 1, pagesize: info.count } }, + }) + // console.log(songList) + } + let result = await Promise.all(this.createTask((songList || songInfo.list).map(item => ({ hash: item.hash })))).then(([...datas]) => datas.flat()) + return { + list: this.filterData2(result) || [], + page: 1, + limit: info.count, + total: info.count, + source: 'kg', + info: { + name: info.name, + img: (info.img_size && info.img_size.replace('{size}', 240)) || info.img, + // desc: body.result.info.list_desc, + author: info.username, + // play_count: this.formatPlayCount(info.count), + }, + } + }, + + async getUserListDetail3(chain, page) { + const songInfo = await this.createHttp(`http://m.kugou.com/schain/transfer?pagesize=${this.listDetailLimit}&chain=${chain}&su=1&page=${page}&n=0.7928855356604456`, { + headers: { + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', + }, + }) + if (!songInfo.list) { + if (songInfo.global_collection_id) return this.getUserListDetail2(songInfo.global_collection_id) + else throw new Error('fail') + } + let result = await Promise.all(this.createTask(songInfo.list.map(item => ({ hash: item.hash })))).then(([...datas]) => datas.flat()) + // console.log(info, songInfo) + return { + list: this.filterData2(result) || [], + page: 1, + limit: this.listDetailLimit, + total: songInfo.count, + source: 'kg', + info: { + name: songInfo.info.name, + img: songInfo.info.img, + // desc: body.result.info.list_desc, + author: songInfo.info.username, + // play_count: this.formatPlayCount(info.count), + }, + } + }, + + async getUserListDetail2(global_collection_id) { + let id = global_collection_id + if (id.length > 1000) throw new Error('get list error') + let info = await this.createHttp('https://mobiles.kugou.com/api/v5/special/info_v2?appid=1058&specialid=0&global_specialid=' + id + '&format=jsonp&srcappid=2919&clientver=20000&clienttime=1586163242519&mid=1586163242519&uuid=1586163242519&dfid=-&signature=' + toMD5('NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtappid=1058clienttime=1586163242519clientver=20000dfid=-format=jsonpglobal_specialid=' + id + 'mid=1586163242519specialid=0srcappid=2919uuid=1586163242519NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'), { + headers: { + mid: '1586163242519', + Referer: 'https://m3ws.kugou.com/share/index.php', + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', + dfid: '-', + clienttime: '1586163242519', + }, + }) + let songInfo = await this.createHttp('https://mobiles.kugou.com/api/v5/special/song_v2?appid=1058&global_specialid=' + id + '&specialid=0&plat=0&version=8000&pagesize=' + info.songcount + '&srcappid=2919&clientver=20000&clienttime=1586163263991&mid=1586163263991&uuid=1586163263991&dfid=-&signature=' + toMD5('NVPh5oo715z5DIWAeQlhMDsWXXQV4hwtappid=1058clienttime=1586163263991clientver=20000dfid=-global_specialid=' + id + 'mid=1586163263991pagesize=' + info.songcount + 'plat=0specialid=0srcappid=2919uuid=1586163263991version=8000NVPh5oo715z5DIWAeQlhMDsWXXQV4hwt'), { + headers: { + mid: '1586163263991', + Referer: 'https://m3ws.kugou.com/share/index.php', + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', + dfid: '-', + clienttime: '1586163263991', + }, + }) + let result = await Promise.all(this.createTask(songInfo.info.map(item => ({ hash: item.hash })))).then(([...datas]) => datas.flat()) + // console.log(info, songInfo) + return { + list: this.filterData2(result) || [], + page: 1, + limit: songInfo.total, + total: songInfo.total, + source: 'kg', + info: { + name: info.specialname, + img: info.imgurl && info.imgurl.replace('{size}', 240), + // desc: body.result.info.list_desc, + author: info.nickname, + // play_count: this.formatPlayCount(info.count), + }, + } + }, + + async getUserListDetail(link, page, retryNum = 0) { + if (retryNum > 3) return Promise.reject(new Error('link try max num')) + if (link.includes('#')) link = link.replace(/#.*$/, '') + if (link.includes('global_collection_id')) return this.getUserListDetail2(link.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1')) + if (link.includes('chain=')) return this.getUserListDetail3(link.replace(/^.*?chain=(\w+)(?:&.*$|#.*$|$)/, '$1'), page) + if (link.includes('.html')) { + if (link.includes('zlist.html')) { + link = link.replace(/^(.*)zlist\.html/, 'https://m3ws.kugou.com/zlist/list') + if (link.includes('pagesize')) { + link = link.replace('pagesize=30', 'pagesize=' + this.listDetailLimit).replace('page=1', 'page=' + page) + } else { + link += `&pagesize=${this.listDetailLimit}&page=${page}` + } + } else if (!link.includes('song.html')) return this.getUserListDetail3(link.replace(/.+\/(\w+).html(?:\?.*|&.*$|#.*$|$)/, '$1'), page) + } + if (this._requestObj_listDetailLink) this._requestObj_listDetailLink.cancelHttp() + + this._requestObj_listDetailLink = httpFetch(link, { + headers: { + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1', + Referer: link, + }, + }) + const { headers: { location }, statusCode, body } = await this._requestObj_listDetailLink.promise + // console.log(body, location) + if (statusCode > 400) return this.getUserListDetail(link, page, ++retryNum) + if (location) { + if (location.includes('global_collection_id')) return this.getUserListDetail2(location.replace(/^.*?global_collection_id=(\w+)(?:&.*$|#.*$|$)/, '$1')) + if (location.includes('chain=')) return this.getUserListDetail3(location.replace(/^.*?chain=(\w+)(?:&.*$|#.*$|$)/, '$1'), page) + + // console.log('location', location) + if (location.includes('.html')) { + if (location.includes('zlist.html')) { + let link = location.replace(/^(.*)zlist\.html/, 'https://m3ws.kugou.com/zlist/list') + if (link.includes('pagesize')) { + link = link.replace('pagesize=30', 'pagesize=' + this.listDetailLimit).replace('page=1', 'page=' + page) + } else { + link += `&pagesize=${this.listDetailLimit}&page=${page}` + } + return this.getUserListDetail(link, page, ++retryNum) + } else return this.getUserListDetail3(location.replace(/.+\/(\w+).html(?:\?.*|&.*$|#.*$|$)/, '$1'), page) + } + return this.getUserListDetail(link, page, ++retryNum) + } + if (typeof body == 'string') return this.getUserListDetail2(body.replace(/^[\s\S]+?"global_collection_id":"(\w+)"[\s\S]+?$/, '$1')) + if (body.errcode !== 0) return this.getUserListDetail(link, page, ++retryNum) + let listInfo = body.info['0'] + let result = body.list.info.map(item => ({ hash: item.hash })) + result = await Promise.all(this.createTask(result)).then(([...datas]) => datas.flat()) + return { + list: this.filterData2(result) || [], + page, + limit: this.listDetailLimit, + total: listInfo.count, + source: 'kg', + info: { + name: listInfo.name, + img: listInfo.pic && listInfo.pic.replace('{size}', 240), + // desc: body.result.info.list_desc, + author: listInfo.list_create_username, + // play_count: this.formatPlayCount(listInfo.count), + }, + } + }, + + getListDetail(id, page, tryNum = 0) { // 获取歌曲列表内的音乐 + if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + + id = id.toString() + if (id.includes('special/single/')) { + id = id.replace(this.regExps.listDetailLink, '$1') + } else if (/https?:/.test(id)) { + return this.getUserListDetail(id.replace(/^.*http/, 'http'), page) + } else if (/^\d+$/.test(id)) { + return this.getUserListDetailByCode(id) + } else if (id.startsWith('id_')) { + id = id.replace('id_', '') + } + + // if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1') + + this._requestObj_listDetail = httpFetch(this.getSongListDetailUrl(id)) + return this._requestObj_listDetail.promise.then(({ body }) => { + let listData = body.match(this.regExps.listData) + let listInfo = body.match(this.regExps.listInfo) + if (!listData) return this.getListDetail(id, page, ++tryNum) + listData = this.filterData(JSON.parse(listData[1])) + let name + let pic + if (listInfo) { + name = listInfo[1] + pic = listInfo[2] + } + return { + list: listData, + page: 1, + limit: 10000, + total: listData.length, + source: 'kg', + info: { + name, + img: pic, + // desc: body.result.info.list_desc, + // author: body.result.info.userinfo.username, + // play_count: this.formatPlayCount(body.result.listen_num), + }, + } + }) + }, + filterData(rawList) { + // console.log(rawList) + return rawList.map(item => { + const types = [] + const _types = {} + if (item.filesize !== 0) { + let size = sizeFormate(item.filesize) + types.push({ type: '128k', size, hash: item.hash }) + _types['128k'] = { + size, + hash: item.hash, + } + } + if (item.filesize_320 !== 0) { + let size = sizeFormate(item.filesize_320) + types.push({ type: '320k', size, hash: item.hash_320 }) + _types['320k'] = { + size, + hash: item.hash_320, + } + } + if (item.filesize_ape !== 0) { + let size = sizeFormate(item.filesize_ape) + types.push({ type: 'ape', size, hash: item.hash_ape }) + _types.ape = { + size, + hash: item.hash_ape, + } + } + if (item.filesize_flac !== 0) { + let size = sizeFormate(item.filesize_flac) + types.push({ type: 'flac', size, hash: item.hash_flac }) + _types.flac = { + size, + hash: item.hash_flac, + } + } + return { + singer: decodeName(item.singername), + name: decodeName(item.songname), + albumName: decodeName(item.album_name), + albumId: item.album_id, + songmid: item.audio_id, + source: 'kg', + interval: formatPlayTime(item.duration / 1000), + img: null, + lrc: null, + hash: item.hash, + types, + _types, + typeUrl: {}, + } + }) + }, + + // hash list filter + filterData2(rawList) { + // console.log(rawList) + let ids = new Set() + let list = [] + rawList.forEach(item => { + if (!item) return + if (ids.has(item.audio_info.audio_id)) return + ids.add(item.audio_info.audio_id) + const types = [] + const _types = {} + if (item.audio_info.filesize !== '0') { + let size = sizeFormate(parseInt(item.audio_info.filesize)) + types.push({ type: '128k', size, hash: item.audio_info.hash }) + _types['128k'] = { + size, + hash: item.audio_info.hash, + } + } + if (item.audio_info.filesize_320 !== '0') { + let size = sizeFormate(parseInt(item.audio_info.filesize_320)) + types.push({ type: '320k', size, hash: item.audio_info.hash_320 }) + _types['320k'] = { + size, + hash: item.audio_info.hash_320, + } + } + if (item.audio_info.filesize_flac !== '0') { + let size = sizeFormate(parseInt(item.audio_info.filesize_flac)) + types.push({ type: 'flac', size, hash: item.audio_info.hash_flac }) + _types.flac = { + size, + hash: item.audio_info.hash_flac, + } + } + list.push({ + singer: decodeName(item.author_name), + name: decodeName(item.ori_audio_name), + albumName: decodeName(item.album_info.album_name), + albumId: item.album_info.album_id, + songmid: item.audio_info.audio_id, + source: 'kg', + interval: formatPlayTime(parseInt(item.audio_info.timelength) / 1000), + img: null, + lrc: null, + hash: item.audio_info.hash, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + + // 获取列表信息 + getListInfo(tagId, tryNum = 0) { + if (this._requestObj_listInfo) this._requestObj_listInfo.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_listInfo = httpFetch(this.getInfoUrl(tagId)) + return this._requestObj_listInfo.promise.then(({ body }) => { + if (body.status !== 1) return this.getListInfo(tagId, ++tryNum) + return { + limit: body.data.params.pagesize, + page: body.data.params.p, + total: body.data.params.total, + source: 'kg', + } + }) + }, + + // 获取列表数据 + getList(sortId, tagId, page) { + let tasks = [this.getSongList(sortId, tagId, page)] + tasks.push( + this.currentTagInfo.id === tagId + ? Promise.resolve(this.currentTagInfo.info) + : this.getListInfo(tagId).then(info => { + this.currentTagInfo.id = tagId + this.currentTagInfo.info = Object.assign({}, info) + return info + }), + ) + if (!tagId && page === 1 && sortId === this.sortList[0].id) tasks.push(this.getSongListRecommend()) // 如果是所有类别,则顺便获取推荐列表 + return Promise.all(tasks).then(([list, info, recommendList]) => { + if (recommendList) list.unshift(...recommendList) + return { + list, + ...info, + } + }) + }, + + // 获取标签 + getTags(tryNum = 0) { + if (this._requestObj_tags) this._requestObj_tags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_tags = httpFetch(this.getInfoUrl()) + return this._requestObj_tags.promise.then(({ body }) => { + if (body.status !== 1) return this.getTags(++tryNum) + return { + hotTag: this.filterInfoHotTag(body.data.hotTag), + tags: this.filterTagInfo(body.data.tagids), + source: 'kg', + } + }) + }, +} + +// getList +// getTags +// getListDetail diff --git a/src/utils/music/kg/util.js b/src/utils/music/kg/util.js new file mode 100644 index 0000000..bf2ec68 --- /dev/null +++ b/src/utils/music/kg/util.js @@ -0,0 +1,22 @@ +import pako from 'pako' +import { Buffer } from 'buffer' + +// https://github.com/lyswhut/lx-music-desktop/issues/296#issuecomment-683285784 +const enc_key = Buffer.from([0x40, 0x47, 0x61, 0x77, 0x5e, 0x32, 0x74, 0x47, 0x51, 0x36, 0x31, 0x2d, 0xce, 0xd2, 0x6e, 0x69], 'binary') +export const decodeLyric = str => new Promise((resolve, reject) => { + if (!str.length) return + const buf_str = Buffer.from(str, 'base64').slice(4) + for (let i = 0, len = buf_str.length; i < len; i++) { + buf_str[i] = buf_str[i] ^ enc_key[i % 16] + } + const result = pako.inflate(buf_str, { to: 'string' }) + resolve(result) + // (err, result) => { + // if (err) return reject(err) + // resolve(result.toString()) + // } +}) + +// s.content[0].lyricContent.forEach(([str]) => { +// console.log(str) +// }) diff --git a/src/utils/music/kw/album.js b/src/utils/music/kw/album.js new file mode 100644 index 0000000..63e254c --- /dev/null +++ b/src/utils/music/kw/album.js @@ -0,0 +1,101 @@ +import { httpFetch } from '../../request' +import { decodeName } from '../../index' +import { formatSinger, objStr2JSON } from './util' + +// let requestObj_list +let requestObj_listDetail +export default { + limit_list: 36, + limit_song: 1000, + filterListDetail(rawList, albumName, albumId) { + // console.log(rawList) + // console.log(rawList.length, rawList2.length) + return rawList.map((item, inedx) => { + let formats = item.formats.split('|') + let types = [] + let _types = {} + if (formats.includes('MP3128')) { + types.push({ type: '128k', size: null }) + _types['128k'] = { + size: null, + } + } + // if (formats.includes('MP3192')) { + // types.push({ type: '192k', size: null }) + // _types['192k'] = { + // size: null, + // } + // } + if (formats.includes('MP3H')) { + types.push({ type: '320k', size: null }) + _types['320k'] = { + size: null, + } + } + // if (formats.includes('AL')) { + // types.push({ type: 'ape', size: null }) + // _types.ape = { + // size: null, + // } + // } + if (formats.includes('ALFLAC')) { + types.push({ type: 'flac', size: null }) + _types.flac = { + size: null, + } + } + // types.reverse() + return { + singer: formatSinger(decodeName(item.artist)), + name: decodeName(item.name), + albumName, + albumId, + songmid: item.id, + source: 'kw', + interval: null, + img: item.pic, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + getAlbumListDetail(id, page, retryNum = 0) { + if (requestObj_listDetail) { + requestObj_listDetail.cancelHttp() + } + if (retryNum > 2) return Promise.reject(new Error('try max num')) + requestObj_listDetail = httpFetch(`http://search.kuwo.cn/r.s?pn=${page - 1}&rn=${this.limit_song}&stype=albuminfo&albumid=${id}&show_copyright_off=0&encoding=utf&vipver=MUSIC_9.1.0`) + return requestObj_listDetail.promise.then(({ statusCode, body }) => { + if (statusCode !== 200) return this.getAlbumListDetail(id, page, ++retryNum) + body = objStr2JSON(body) + // console.log(body) + if (!body.musiclist) return this.getAlbumListDetail(id, page, ++retryNum) + return { + list: this.filterListDetail(body.musiclist, body.name, body.albumid), + page, + limit: this.limit_song, + total: parseInt(body.songnum), + source: 'kw', + info: { + name: body.name, + img: body.img || body.hts_img, + desc: body.info, + author: body.artist, + // play_count: this.formatPlayCount(body.playnum), + }, + } + }) + }, +} diff --git a/src/utils/music/kw/api-temp.js b/src/utils/music/kw/api-temp.js new file mode 100644 index 0000000..7f67392 --- /dev/null +++ b/src/utils/music/kw/api-temp.js @@ -0,0 +1,19 @@ +import { httpFetch } from '../../request' +import { headers, timeout } from '../options' + +const api_temp = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://tm.tempmusic.tk/url/kw/${songInfo.songmid}/${type}`, { + method: 'get', + headers, + timeout, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg)) + }) + return requestObj + }, +} + +export default api_temp diff --git a/src/utils/music/kw/api-test.js b/src/utils/music/kw/api-test.js new file mode 100644 index 0000000..1308775 --- /dev/null +++ b/src/utils/music/kw/api-test.js @@ -0,0 +1,31 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_test = { + // getMusicUrl(songInfo, type) { + // const requestObj = httpFetch(`http://45.32.53.128:3002/m/kw/u/${songInfo.songmid}/${type}`, { + // method: 'get', + // headers, + // timeout, + // }) + // requestObj.promise = requestObj.promise.then(({ body }) => { + // return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(body.msg)) + // }) + // return requestObj + // }, + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/kw/${songInfo.songmid}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, +} + +export default api_test diff --git a/src/utils/music/kw/comment.js b/src/utils/music/kw/comment.js new file mode 100644 index 0000000..99f160b --- /dev/null +++ b/src/utils/music/kw/comment.js @@ -0,0 +1,61 @@ +import { httpFetch } from '../../request' +import { dateFormat2 } from '../../' + +export default { + _requestObj: null, + _requestObj2: null, + async getComment({ songmid }, page = 1, limit = 20) { + if (this._requestObj) this._requestObj.cancelHttp() + + const _requestObj = httpFetch(`http://comment.kuwo.cn/com.s?type=get_comment&uid=0&digest=15&sid=${songmid}&page=${page}&rows=${limit}&f=web&prod=MUSIC_8.7.7.0_BCS37&devid=28556413`, { + headers: { + 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9;)', + }, + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.result !== 'ok') throw new Error('获取评论失败') + // console.log(body) + return { source: 'kw', comments: this.filterComment(body.rows), total: body.total, page, limit, maxPage: Math.ceil(body.total / limit) || 1 } + }, + async getHotComment({ songmid }, page = 1, limit = 100) { + if (this._requestObj2) this._requestObj2.cancelHttp() + + const _requestObj2 = httpFetch(`http://comment.kuwo.cn/com.s?type=get_rec_comment&uid=0&digest=15&sid=${songmid}&page=${page}&rows=${limit}&f=web&prod=MUSIC_8.7.7.0_BCS37&devid=28556413`, { + headers: { + 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9;)', + }, + }) + const { body, statusCode } = await _requestObj2.promise + if (statusCode != 200 || body.result !== 'ok') throw new Error('获取热门评论失败') + // console.log(body) + return { source: 'kw', comments: this.filterComment(body.rows) } + }, + filterComment(rawList) { + if (!rawList) return [] + return rawList.map(item => { + let data = { + id: item.id, + text: item.msg.split('\n'), + time: item.time, + timeStr: dateFormat2(new Date(item.time).getTime()), + userName: decodeURIComponent(item.u_name), + avatar: item.u_pic, + userId: item.u_id, + likedCount: item.like_num, + reply: [], + } + return item.reply ? { + id: item.id, + rootId: item.reply.id, + text: item.reply.msg.split('\n'), + time: item.reply.time, + timeStr: dateFormat2(new Date(item.reply.time).getTime()), + userName: decodeURIComponent(item.reply.u_name), + avatar: item.reply.u_pic, + userId: item.reply.u_id, + likedCount: item.reply.like_num, + reply: [data], + } : data + }) + }, +} diff --git a/src/utils/music/kw/decodeLyric.js b/src/utils/music/kw/decodeLyric.js new file mode 100644 index 0000000..d36aa6f --- /dev/null +++ b/src/utils/music/kw/decodeLyric.js @@ -0,0 +1,40 @@ +const { inflate } = require('pako') +const iconv = require('iconv-lite') + +const handleInflate = data => new Promise((resolve, reject) => { + resolve(Buffer.from(inflate(data))) +}) + +const buf_key = Buffer.from('yeelion') +const buf_key_len = buf_key.length + +const decodeLyric = async(buf, isGetLyricx) => { + // const info = buf.slice(0, index).toString() + // if (!info.startsWith('tp=content')) return null + // const isLyric = info.includes('\r\nlrcx=0\r\n') + if (buf.toString('utf8', 0, 10) != 'tp=content') return '' + console.log(buf) + // const index = buf.indexOf('\r\n\r\n') + 4 + const lrcData = await handleInflate(buf.slice(buf.indexOf('\r\n\r\n') + 4)) + + if (!isGetLyricx) return iconv.decode(lrcData, 'gb18030') + + const buf_str = Buffer.from(lrcData.toString(), 'base64') + const buf_str_len = buf_str.length + const output = new Uint16Array(buf_str_len) + let i = 0 + while (i < buf_str_len) { + let j = 0 + while (j < buf_key_len && i < buf_str_len) { + output[i] = buf_str[i] ^ buf_key[j] + i++ + j++ + } + } + + return iconv.decode(Buffer.from(output), 'gb18030') +} +export default async({ lrcBase64, isGetLyricx }) => { + const lrc = await decodeLyric(Buffer.from(lrcBase64, 'base64'), isGetLyricx) + return Buffer.from(lrc).toString('base64') +} diff --git a/src/utils/music/kw/hotSearch.js b/src/utils/music/kw/hotSearch.js new file mode 100644 index 0000000..7f3fd7a --- /dev/null +++ b/src/utils/music/kw/hotSearch.js @@ -0,0 +1,22 @@ +import { httpFetch } from '../../request' + +export default { + _requestObj: null, + async getList(retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('http://hotword.kuwo.cn/hotword.s?prod=kwplayer_ar_9.3.0.1&corp=kuwo&newver=2&vipver=9.3.0.1&source=kwplayer_ar_9.3.0.1_40.apk&p2p=1¬race=0&uid=0&plat=kwplayer_ar&rformat=json&encoding=utf8&tabid=1', { + headers: { + 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9;)', + }, + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.status !== 'ok') throw new Error('获取热搜词失败') + // console.log(body, statusCode) + return { source: 'kw', list: this.filterList(body.tagvalue) } + }, + filterList(rawList) { + return rawList.map(item => item.key) + }, +} diff --git a/src/utils/music/kw/index.js b/src/utils/music/kw/index.js new file mode 100644 index 0000000..d8c4dc2 --- /dev/null +++ b/src/utils/music/kw/index.js @@ -0,0 +1,113 @@ +import { httpGet, cancelHttp } from '../../request' +import tempSearch from './tempSearch' +import musicSearch from './musicSearch' +import { formatSinger, getToken } from './util' +import leaderboard from './leaderboard' +import lyric from './lyric' +import pic from './pic' +import { apis } from '../api-source' +import songList from './songList' +import hotSearch from './hotSearch' +import comment from './comment' + +const kw = { + _musicInfoRequestObj: null, + _musicInfoPromiseCancelFn: null, + _musicPicRequestObj: null, + _musicPicPromiseCancelFn: null, + // context: null, + + + // init(context) { + // if (this.isInited) return + // this.isInited = true + // this.context = context + + // // this.musicSearch.search('我又想你了').then(res => { + // // console.log(res) + // // }) + + // // this.getMusicUrl('62355680', '320k').then(url => { + // // console.log(url) + // // }) + // }, + + tempSearch, + musicSearch, + leaderboard, + songList, + hotSearch, + comment, + getLyric(songInfo, isGetLyricx) { + // let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer + return lyric.getLyric(songInfo.songmid, isGetLyricx) + }, + handleMusicInfo(songInfo) { + return this.getMusicInfo(songInfo).then(info => { + // console.log(JSON.stringify(info)) + songInfo.name = info.name + songInfo.singer = formatSinger(info.artist) + songInfo.img = info.pic + songInfo.albumName = info.album + return songInfo + // return Object.assign({}, songInfo, { + // name: info.name, + // singer: formatSinger(info.artist), + // img: info.pic, + // albumName: info.album, + // }) + }) + }, + + getMusicUrl(songInfo, type) { + return apis('kw').getMusicUrl(songInfo, type) + }, + + getMusicInfo(songInfo) { + if (this._musicInfoRequestObj != null) { + cancelHttp(this._musicInfoRequestObj) + this._musicInfoPromiseCancelFn(new Error('取消http请求')) + } + return new Promise((resolve, reject) => { + this._musicInfoPromiseCancelFn = reject + this._musicInfoRequestObj = httpGet(`http://www.kuwo.cn/api/www/music/musicInfo?mid=${songInfo.songmid}`, (err, resp, body) => { + this._musicInfoRequestObj = null + this._musicInfoPromiseCancelFn = null + if (err) { + console.log(err) + reject(err) + } + body.code === 200 ? resolve(body.data) : reject(new Error(body.msg)) + }) + }) + }, + + getMusicUrls(musicInfo, cb) { + let tasks = [] + let songId = musicInfo.songmid + musicInfo.types.forEach(type => { + tasks.push(kw.getMusicUrl(songId, type.type).promise) + }) + Promise.all(tasks).then(urlInfo => { + let typeUrl = {} + urlInfo.forEach(info => { + typeUrl[info.type] = info.url + }) + cb(typeUrl) + }) + }, + + getPic(songInfo) { + return pic.getPic(songInfo) + }, + + getMusicDetailPageUrl(songInfo) { + return `http://www.kuwo.cn/play_detail/${songInfo.songmid}` + }, + + init() { + return getToken() + }, +} + +export default kw diff --git a/src/utils/music/kw/leaderboard.js b/src/utils/music/kw/leaderboard.js new file mode 100644 index 0000000..a54b42a --- /dev/null +++ b/src/utils/music/kw/leaderboard.js @@ -0,0 +1,208 @@ +import { httpGet, cancelHttp, httpFetch } from '../../request' +import { formatPlayTime, decodeName } from '../../index' +import { formatSinger } from './util' + +const boardList = [{ id: 'kw__93', name: '酷我飙升榜', bangid: '93' }, { id: 'kw__17', name: '酷我新歌榜', bangid: '17' }, { id: 'kw__16', name: '酷我热歌榜', bangid: '16' }, { id: 'kw__158', name: '抖音热歌榜', bangid: '158' }, { id: 'kw__284', name: '酷我热评榜', bangid: '284' }, { id: 'kw__290', name: 'ACG新歌榜', bangid: '290' }, { id: 'kw__286', name: '台湾KKBOX榜', bangid: '286' }, { id: 'kw__279', name: '春日浅唱榜', bangid: '279' }, { id: 'kw__281', name: '巴士随身听榜', bangid: '281' }, { id: 'kw__255', name: 'KTV点唱榜', bangid: '255' }, { id: 'kw__280', name: '家务进行曲榜', bangid: '280' }, { id: 'kw__282', name: '熬夜修仙榜', bangid: '282' }, { id: 'kw__283', name: '枕边轻音乐榜', bangid: '283' }, { id: 'kw__278', name: '古风音乐榜', bangid: '278' }, { id: 'kw__264', name: 'Vlog音乐榜', bangid: '264' }, { id: 'kw__242', name: '酷我电音榜', bangid: '242' }, { id: 'kw__187', name: '流行趋势榜', bangid: '187' }, { id: 'kw__204', name: '现场音乐榜', bangid: '204' }, { id: 'kw__186', name: 'ACG神曲榜', bangid: '186' }, { id: 'kw__185', name: '最强翻唱榜', bangid: '185' }, { id: 'kw__26', name: '经典怀旧榜', bangid: '26' }, { id: 'kw__104', name: '酷我华语榜', bangid: '104' }, { id: 'kw__182', name: '酷我粤语榜', bangid: '182' }, { id: 'kw__22', name: '酷我欧美榜', bangid: '22' }, { id: 'kw__184', name: '酷我韩语榜', bangid: '184' }, { id: 'kw__183', name: '酷我日语榜', bangid: '183' }, { id: 'kw__145', name: '会员畅听榜', bangid: '145' }, { id: 'kw__153', name: '网红新歌榜', bangid: '153' }, { id: 'kw__64', name: '影视金曲榜', bangid: '64' }, { id: 'kw__176', name: 'DJ嗨歌榜', bangid: '176' }, { id: 'kw__106', name: '酷我真声音', bangid: '106' }, { id: 'kw__12', name: 'Billboard榜', bangid: '12' }, { id: 'kw__49', name: 'iTunes音乐榜', bangid: '49' }, { id: 'kw__180', name: 'beatport电音榜', bangid: '180' }, { id: 'kw__13', name: '英国UK榜', bangid: '13' }, { id: 'kw__164', name: '百大DJ榜', bangid: '164' }, { id: 'kw__246', name: 'YouTube音乐排行榜', bangid: '246' }, { id: 'kw__265', name: '韩国Genie榜', bangid: '265' }, { id: 'kw__14', name: '韩国M-net榜', bangid: '14' }, { id: 'kw__8', name: '香港电台榜', bangid: '8' }, { id: 'kw__15', name: '日本公信榜', bangid: '15' }, { id: 'kw__151', name: '腾讯音乐人原创榜', bangid: '151' }] + +export default { + list: [ + { + id: 'kwbiaosb', + name: '飙升榜', + bangid: 93, + }, + { + id: 'kwregb', + name: '热歌榜', + bangid: 16, + }, + { + id: 'kwhuiyb', + name: '会员榜', + bangid: 145, + }, + { + id: 'kwdouyb', + name: '抖音榜', + bangid: 158, + }, + { + id: 'kwqsb', + name: '趋势榜', + bangid: 187, + }, + { + id: 'kwhuaijb', + name: '怀旧榜', + bangid: 26, + }, + { + id: 'kwhuayb', + name: '华语榜', + bangid: 104, + }, + { + id: 'kwyueyb', + name: '粤语榜', + bangid: 182, + }, + { + id: 'kwoumb', + name: '欧美榜', + bangid: 22, + }, + { + id: 'kwhanyb', + name: '韩语榜', + bangid: 184, + }, + { + id: 'kwriyb', + name: '日语榜', + bangid: 183, + }, + ], + getUrl: (p, l, id) => `http://kbangserver.kuwo.cn/ksong.s?from=pc&fmt=json&pn=${p - 1}&rn=${l}&type=bang&data=content&id=${id}&show_copyright_off=0&pcmp4=1&isbang=1`, + regExps: { + + }, + limit: 100, + _requestBoardsObj: null, + + _cancelRequestObj: null, + _cancelPromiseCancelFn: null, + getBoardsData() { + if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp() + this._requestBoardsObj = httpFetch('http://qukudata.kuwo.cn/q.k?op=query&cont=tree&node=2&pn=0&rn=1000&fmt=json&level=2') + return this._requestBoardsObj.promise + }, + getData(url) { + if (this._cancelRequestObj != null) { + cancelHttp(this._cancelRequestObj) + this._cancelPromiseCancelFn(new Error('取消http请求')) + } + return new Promise((resolve, reject) => { + this._cancelPromiseCancelFn = reject + this._cancelRequestObj = httpGet(url, (err, resp) => { + this._cancelRequestObj = null + this._cancelPromiseCancelFn = null + if (err) { + console.log(err) + reject(err) + } + resolve(resp) + }) + }) + }, + filterData(rawList) { + // console.log(rawList) + // console.log(rawList.length, rawList2.length) + return rawList.map((item, inedx) => { + let formats = item.formats.split('|') + let types = [] + let _types = {} + if (formats.includes('MP3128')) { + types.push({ type: '128k', size: null }) + _types['128k'] = { + size: null, + } + } + // if (formats.includes('MP3192')) { + // types.push({ type: '192k', size: null }) + // _types['192k'] = { + // size: null, + // } + // } + if (formats.includes('MP3H')) { + types.push({ type: '320k', size: null }) + _types['320k'] = { + size: null, + } + } + // if (formats.includes('AL')) { + // types.push({ type: 'ape', size: null }) + // _types.ape = { + // size: null, + // } + // } + if (formats.includes('ALFLAC')) { + types.push({ type: 'flac', size: null }) + _types.flac = { + size: null, + } + } + // types.reverse() + return { + singer: formatSinger(decodeName(item.artist)), + name: decodeName(item.name), + albumName: decodeName(item.album), + albumId: item.albumid, + songmid: item.id, + source: 'kw', + interval: formatPlayTime(parseInt(item.song_duration)), + img: item.pic, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + + filterBoardsData(rawList) { + // console.log(rawList) + let list = [] + for (const board of rawList) { + if (board.source != '1') continue + list.push({ + id: 'kw__' + board.sourceid, + name: board.name, + bangid: String(board.sourceid), + }) + } + return list + }, + async getBoards(retryNum = 0) { + // if (++retryNum > 3) return Promise.reject(new Error('try max num')) + // let response + // try { + // response = await this.getBoardsData() + // } catch (error) { + // return this.getBoards(retryNum) + // } + // console.log(response.body) + // if (response.statusCode !== 200 || !response.body.child) return this.getBoards(retryNum) + // const list = this.filterBoardsData(response.body.child) + // // console.log(list) + // console.log(JSON.stringify(list)) + // this.list = list + // return { + // list, + // source: 'kw', + // } + this.list = boardList + return { + list: boardList, + source: 'kw', + } + }, + + getList(id, page, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + return this.getData(this.getUrl(page, this.limit, id)).then(({ statusCode, body }) => { + // console.log(body) + if (statusCode !== 200 || !body.musiclist) return this.getList(id, page, retryNum) + // console.log(data1.musiclist, data2.data) + let total = parseInt(body.num) + let list = this.filterData(body.musiclist) + return { + total, + list, + limit: this.limit, + page, + source: 'kw', + } + }) + }, +} diff --git a/src/utils/music/kw/lyric.js b/src/utils/music/kw/lyric.js new file mode 100644 index 0000000..8c424f1 --- /dev/null +++ b/src/utils/music/kw/lyric.js @@ -0,0 +1,20 @@ +import { httpFetch } from '../../request' + +export default { + formatTime(time) { + const m = parseInt(time / 60) + const s = (time % 60).toFixed(2) + return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s) + }, + transformLrc({ songinfo, lrclist }) { + return `[ti:${songinfo.songName}]\n[ar:${songinfo.artist}]\n[al:${songinfo.album}]\n[by:]\n[offset:0]\n${lrclist ? lrclist.map(l => `[${this.formatTime(l.time)}]${l.lineLyric}\n`).join('') : '暂无歌词'}` + }, + getLyric(songId) { + const requestObj = httpFetch(`http://m.kuwo.cn/newh5/singles/songinfoandlrc?musicId=${songId}`) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.status != 200) return Promise.reject(new Error('请求失败')) + return { lyric: this.transformLrc(body.data), tlyric: '', lxlyric: null } + }) + return requestObj + }, +} diff --git a/src/utils/music/kw/musicSearch.js b/src/utils/music/kw/musicSearch.js new file mode 100644 index 0000000..8931d33 --- /dev/null +++ b/src/utils/music/kw/musicSearch.js @@ -0,0 +1,150 @@ +// import '../../polyfill/array.find' +// import jshtmlencode from 'js-htmlencode' +import { httpGet, cancelHttp } from '../../request' +import { formatPlayTime, decodeName } from '../../index' +// import { debug } from '../../utils/env' +import { formatSinger } from './util' + +export default { + regExps: { + mInfo: /bitrate:(\d+),format:(\w+),size:([\w.]+)/, + }, + _musicSearchRequestObj: null, + _musicSearchPromiseCancelFn: null, + limit: 30, + total: 0, + page: 0, + allPage: 1, + // cancelFn: null, + musicSearch(str, page, limit) { + if (this._musicSearchRequestObj != null) { + cancelHttp(this._musicSearchRequestObj) + this._musicSearchPromiseCancelFn(new Error('取消http请求')) + } + return new Promise((resolve, reject) => { + this._musicSearchPromiseCancelFn = reject + this._musicSearchRequestObj = httpGet(`http://search.kuwo.cn/r.s?client=kt&all=${encodeURIComponent(str)}&pn=${page - 1}&rn=${limit}&uid=794762570&ver=kwplayer_ar_9.2.2.1&vipver=1&show_copyright_off=1&newver=1&ft=music&cluster=0&strategy=2012&encoding=utf8&rformat=json&vermerge=1&mobi=1&issubtitle=1`, (err, resp, body) => { + this._musicSearchRequestObj = null + this._musicSearchPromiseCancelFn = null + if (err) { + console.log(err) + reject(err) + } + resolve(body) + }) + }) + }, + // getImg(songId) { + // return httpGet(`http://player.kuwo.cn/webmusic/sj/dtflagdate?flag=6&rid=MUSIC_${songId}`) + // }, + // getLrc(songId) { + // return httpGet(`http://mobile.kuwo.cn/mpage/html5/songinfoandlrc?mid=${songId}&flag=0`) + // }, + handleResult(rawData) { + const result = [] + if (!rawData) return result + for (let i = 0; i < rawData.length; i++) { + const info = rawData[i] + let songId = info.MUSICRID.replace('MUSIC_', '') + // const format = (info.FORMATS || info.formats).split('|') + + if (!info.MINFO) { + console.log('mInfo is undefined') + return null + } + + const types = [] + const _types = {} + + let infoArr = info.MINFO.split(';') + infoArr.forEach(info => { + info = info.match(this.regExps.mInfo) + if (info) { + switch (info[2]) { + case 'flac': + types.push({ type: 'flac', size: info[3] }) + _types.flac = { + size: info[3].toLocaleUpperCase(), + } + break + // case 'ape': + // types.push({ type: 'ape', size: info[3] }) + // _types.ape = { + // size: info[3].toLocaleUpperCase(), + // } + // break + case 'mp3': + switch (info[1]) { + case '320': + types.push({ type: '320k', size: info[3] }) + _types['320k'] = { + size: info[3].toLocaleUpperCase(), + } + break + case '192': + // types.push({ type: '192k', size: info[3] }) + // _types['192k'] = { + // size: info[3].toLocaleUpperCase(), + // } + // break + case '128': + types.push({ type: '128k', size: info[3] }) + _types['128k'] = { + size: info[3].toLocaleUpperCase(), + } + break + } + break + } + } + }) + types.reverse() + + let interval = parseInt(info.DURATION) + + result.push({ + name: decodeName(info.SONGNAME), + singer: formatSinger(decodeName(info.ARTIST)), + source: 'kw', + // img = (info.album.name === '' || info.album.name === '空') + // ? `http://player.kuwo.cn/webmusic/sj/dtflagdate?flag=6&rid=MUSIC_160911.jpg` + // : `https://y.gtimg.cn/music/photo_new/T002R500x500M000${info.album.mid}.jpg` + songmid: songId, + albumId: decodeName(info.ALBUMID || ''), + interval: Number.isNaN(interval) ? 0 : formatPlayTime(interval), + albumName: info.ALBUM ? decodeName(info.ALBUM) : '', + lrc: null, + img: null, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + } + return result + }, + search(str, page = 1, { limit } = {}, retryNum = 0) { + if (retryNum > 2) return Promise.reject(new Error('try max num')) + if (limit == null) limit = this.limit + // http://newlyric.kuwo.cn/newlyric.lrc?62355680 + return this.musicSearch(str, page, limit).then(result => { + // console.log(result) + if (!result || (result.TOTAL !== '0' && result.SHOW === '0')) return this.search(str, page, { limit }, ++retryNum) + let list = this.handleResult(result.abslist) + + if (list == null) return this.search(str, page, { limit }) + + this.total = parseInt(result.TOTAL) + this.page = page + this.allPage = Math.ceil(this.total / limit) + + return Promise.resolve({ + list, + allPage: this.allPage, + total: this.total, + limit, + source: 'kw', + }) + }) + }, +} diff --git a/src/utils/music/kw/pic.js b/src/utils/music/kw/pic.js new file mode 100644 index 0000000..7263a51 --- /dev/null +++ b/src/utils/music/kw/pic.js @@ -0,0 +1,9 @@ +import { httpFetch } from '../../request' + +export default { + getPic({ songmid }) { + const requestObj = httpFetch(`http://artistpicserver.kuwo.cn/pic.web?corp=kuwo&type=rid_pic&pictype=500&size=500&rid=${songmid}`) + requestObj.promise = requestObj.promise.then(({ body }) => /^http/.test(body) ? body : null) + return requestObj + }, +} diff --git a/src/utils/music/kw/songList.js b/src/utils/music/kw/songList.js new file mode 100644 index 0000000..3a9b5fa --- /dev/null +++ b/src/utils/music/kw/songList.js @@ -0,0 +1,316 @@ +import { httpFetch } from '../../request' +import { formatPlayTime, decodeName } from '../../index' +import { formatSinger } from './util' +import album from './album' + +export default { + _requestObj_tags: null, + _requestObj_hotTags: null, + _requestObj_list: null, + _requestObj_listDetail: null, + limit_list: 36, + limit_song: 10000, + successCode: 200, + sortList: [ + { + name: '最新', + tid: 'new', + id: 'new', + }, + { + name: '最热', + tid: 'hot', + id: 'hot', + }, + ], + regExps: { + mInfo: /bitrate:(\d+),format:(\w+),size:([\w.]+)/, + // http://www.kuwo.cn/playlist_detail/2886046289 + // https://m.kuwo.cn/h5app/playlist/2736267853?t=qqfriend + listDetailLink: /^.+\/playlist(?:_detail)?\/(\d+)(?:\?.*|&.*$|#.*$|$)/, + }, + tagsUrl: 'http://wapi.kuwo.cn/api/pc/classify/playlist/getTagList?cmd=rcm_keyword_playlist&user=0&prod=kwplayer_pc_9.0.5.0&vipver=9.0.5.0&source=kwplayer_pc_9.0.5.0&loginUid=0&loginSid=0&appUid=76039576', + hotTagUrl: 'http://wapi.kuwo.cn/api/pc/classify/playlist/getRcmTagList?loginUid=0&loginSid=0&appUid=76039576', + getListUrl({ sortId, id, type, page }) { + if (!id) return `http://wapi.kuwo.cn/api/pc/classify/playlist/getRcmPlayList?loginUid=0&loginSid=0&appUid=76039576&&pn=${page}&rn=${this.limit_list}&order=${sortId}` + switch (type) { + case '10000': return `http://wapi.kuwo.cn/api/pc/classify/playlist/getTagPlayList?loginUid=0&loginSid=0&appUid=76039576&pn=${page}&id=${id}&rn=${this.limit_list}` + case '43': return `http://mobileinterfaces.kuwo.cn/er.s?type=get_pc_qz_data&f=web&id=${id}&prod=pc` + } + // http://wapi.kuwo.cn/api/pc/classify/playlist/getTagPlayList?loginUid=0&loginSid=0&appUid=76039576&id=173&pn=1&rn=100 + }, + getListDetailUrl(id, page) { + // http://nplserver.kuwo.cn/pl.svc?op=getlistinfo&pid=2858093057&pn=0&rn=100&encode=utf8&keyset=pl2012&identity=kuwo&pcmp4=1&vipver=MUSIC_9.0.5.0_W1&newver=1 + return `http://nplserver.kuwo.cn/pl.svc?op=getlistinfo&pid=${id}&pn=${page - 1}&rn=${this.limit_song}&encode=utf8&keyset=pl2012&identity=kuwo&pcmp4=1&vipver=MUSIC_9.0.5.0_W1&newver=1` + // http://mobileinterfaces.kuwo.cn/er.s?type=get_pc_qz_data&f=web&id=140&prod=pc + }, + + // http://nplserver.kuwo.cn/pl.svc?op=getlistinfo&pid=2849349915&pn=0&rn=100&encode=utf8&keyset=pl2012&identity=kuwo&pcmp4=1&vipver=MUSIC_9.0.5.0_W1&newver=1 + // 获取标签 + getTag(tryNum = 0) { + if (this._requestObj_tags) this._requestObj_tags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_tags = httpFetch(this.tagsUrl) + return this._requestObj_tags.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.getTag(++tryNum) + return this.filterTagInfo(body.data) + }) + }, + // 获取标签 + getHotTag(tryNum = 0) { + if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_hotTags = httpFetch(this.hotTagUrl) + return this._requestObj_hotTags.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.getHotTag(++tryNum) + return this.filterInfoHotTag(body.data[0].data) + }) + }, + filterInfoHotTag(rawList) { + return rawList.map(item => ({ + id: `${item.id}-${item.digest}`, + name: item.name, + source: 'kw', + })) + }, + filterTagInfo(rawList) { + return rawList.map(type => ({ + name: type.name, + list: type.data.map(item => ({ + parent_id: type.id, + parent_name: type.name, + id: `${item.id}-${item.digest}`, + name: item.name, + source: 'kw', + })), + })) + }, + + // 获取列表数据 + getList(sortId, tagId, page, tryNum = 0) { + if (this._requestObj_list) this._requestObj_list.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + let id + let type + if (tagId) { + let arr = tagId.split('-') + id = arr[0] + type = arr[1] + } else { + id = null + } + this._requestObj_list = httpFetch(this.getListUrl({ sortId, id, type, page })) + return this._requestObj_list.promise.then(({ body }) => { + if (!id || type == '10000') { + if (body.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum) + return { + list: this.filterList(body.data.data), + total: body.data.total, + page: body.data.pn, + limit: body.data.rn, + source: 'kw', + } + } else if (!body.length) { + return this.getList(sortId, id, type, page, ++tryNum) + } + return { + list: this.filterList2(body), + total: 1000, + page, + limit: 1000, + source: 'kw', + } + }) + }, + + + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + filterList(rawData) { + return rawData.map(item => ({ + play_count: this.formatPlayCount(item.listencnt), + id: `digest-${item.digest}__${item.id}`, + author: item.uname, + name: item.name, + // time: item.publish_time, + img: item.img, + grade: item.favorcnt / 10, + desc: item.desc, + source: 'kw', + })) + }, + filterList2(rawData) { + // console.log(rawData) + const list = [] + rawData.forEach(item => { + if (!item.label) return + list.push(...item.list.map(item => ({ + play_count: item.play_count && this.formatPlayCount(item.listencnt), + id: `digest-${item.digest}__${item.id}`, + author: item.uname, + name: item.name, + // time: item.publish_time, + img: item.img, + grade: item.favorcnt && item.favorcnt / 10, + desc: item.desc, + source: 'kw', + }))) + }) + return list + }, + + getListDetailDigest8(id, page, tryNum = 0) { + if (this._requestObj_listDetail) { + this._requestObj_listDetail.cancelHttp() + } + if (tryNum > 2) return Promise.reject(new Error('try max num')) + + this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id, page)) + return this._requestObj_listDetail.promise.then(({ body }) => { + if (body.result !== 'ok') return this.getListDetail(id, page, ++tryNum) + return { + list: this.filterListDetail(body.musiclist), + page, + limit: body.rn, + total: body.total, + source: 'kw', + info: { + name: body.title, + img: body.pic, + desc: body.info, + author: body.uname, + play_count: this.formatPlayCount(body.playnum), + }, + } + }) + }, + getListDetailDigest5Info(id, tryNum = 0) { + if (this._requestObj_listDetail) { + this._requestObj_listDetail.cancelHttp() + } + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_listDetail = httpFetch(`http://qukudata.kuwo.cn/q.k?op=query&cont=ninfo&node=${id}&pn=0&rn=1&fmt=json&src=mbox&level=2`) + return this._requestObj_listDetail.promise.then(({ statusCode, body }) => { + if (statusCode != 200 || !body.child) return this.getListDetail(id, ++tryNum) + // console.log(body) + return body.child.length ? body.child[0].sourceid : null + }) + }, + getListDetailDigest5Music(id, page, tryNum = 0) { + if (this._requestObj_listDetail) { + this._requestObj_listDetail.cancelHttp() + } + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_listDetail = httpFetch(`http://nplserver.kuwo.cn/pl.svc?op=getlistinfo&pid=${id}&pn=${page - 1}}&rn=${this.limit_song}&encode=utf-8&keyset=pl2012&identity=kuwo&pcmp4=1`) + return this._requestObj_listDetail.promise.then(({ body }) => { + // console.log(body) + if (body.result !== 'ok') return this.getListDetail(id, page, ++tryNum) + return { + list: this.filterListDetail(body.musiclist), + page, + limit: body.rn, + total: body.total, + source: 'kw', + info: { + name: body.title, + img: body.pic, + desc: body.info, + author: body.uname, + play_count: this.formatPlayCount(body.playnum), + }, + } + }) + }, + async getListDetailDigest5(id, page) { + const detailId = await this.getListDetailDigest5Info(id) + return this.getListDetailDigest5Music(detailId, page) + }, + + // 获取歌曲列表内的音乐 + getListDetail(id, page) { + // console.log(id) + if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1') + else if (/^digest-/.test(id)) { + let [digest, _id] = id.split('__') + digest = digest.replace('digest-', '') + id = _id + switch (digest) { + case '8': + break + case '13': return album.getAlbumListDetail(id, page) + case '5': + default: return this.getListDetailDigest5(id, page) + } + } + return this.getListDetailDigest8(id, page) + }, + filterListDetail(rawData) { + // console.log(rawData) + return rawData.map(item => { + let infoArr = item.MINFO.split(';') + let types = [] + let _types = {} + for (let info of infoArr) { + info = info.match(this.regExps.mInfo) + if (info) { + switch (info[2]) { + case 'flac': + types.push({ type: 'flac', size: info[3] }) + _types.flac = { + size: info[3].toLocaleUpperCase(), + } + break + case 'mp3': + switch (info[1]) { + case '320': + types.push({ type: '320k', size: info[3] }) + _types['320k'] = { + size: info[3].toLocaleUpperCase(), + } + break + case '192': + case '128': + types.push({ type: '128k', size: info[3] }) + _types['128k'] = { + size: info[3].toLocaleUpperCase(), + } + break + } + break + } + } + } + types.reverse() + + return { + singer: formatSinger(decodeName(item.artist)), + name: decodeName(item.name), + albumName: decodeName(item.album), + albumId: item.albumid, + songmid: item.id, + source: 'kw', + interval: formatPlayTime(parseInt(item.duration)), + img: null, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + getTags() { + return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag, source: 'kw' })) + }, +} + +// getList +// getTags +// getListDetail diff --git a/src/utils/music/kw/tempSearch.js b/src/utils/music/kw/tempSearch.js new file mode 100644 index 0000000..f1f958f --- /dev/null +++ b/src/utils/music/kw/tempSearch.js @@ -0,0 +1,32 @@ +// import { httpFetch } from '../../request' +import { decodeName } from '../../index' +import { tokenRequest } from './util' + + +export default { + regExps: { + relWord: /RELWORD=(.+)/, + }, + requestObj: null, + async tempSearch(str) { + this.cancelTempSearch() + this.requestObj = await tokenRequest(`http://www.kuwo.cn/api/www/search/searchKey?key=${encodeURIComponent(str)}`) + return this.requestObj.promise.then(({ body }) => { + // console.log(body) + if (body.code !== 200) return Promise.reject(new Error('请求失败')) + return body + }) + }, + handleResult(rawData) { + return rawData.map(info => { + let matchResult = info.match(this.regExps.relWord) + return matchResult ? decodeName(matchResult[1]) : '' + }) + }, + cancelTempSearch() { + if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp() + }, + async search(str) { + return this.tempSearch(str).then(result => this.handleResult(result.data)) + }, +} diff --git a/src/utils/music/kw/util.js b/src/utils/music/kw/util.js new file mode 100644 index 0000000..4df9da0 --- /dev/null +++ b/src/utils/music/kw/util.js @@ -0,0 +1,76 @@ +// import BackgroundTimer from 'react-native-background-timer' +import { httpGet, httpFetch } from '../../request' +export { default as decodeLyric } from './decodeLyric' + +const kw_token = { + token: null, + isGetingToken: false, +} + +const translationMap = { + "{'": '{"', + "'}\n": '"}', + "'}": '"}', + "':'": '":"', + "','": '","', + "':{'": '":{"', + "':['": '":["', + "'}],'": '"}],"', + "':[{'": '":[{"', + "'},'": '"},"', + "'},{'": '"},{"', + "':[],'": '":[],"', + "':{},'": '":{},"', +} + +export const objStr2JSON = str => { + return JSON.parse(str.replace(/(^{'|'}\n$|'}$|':'|','|':\[{'|'}\],'|':{'|'},'|'},{'|':\['|':\[\],'|':{},')/g, s => translationMap[s])) +} + +export const formatSinger = rawData => rawData.replace(/&/g, '、') + +export const matchToken = headers => { + try { + return headers['set-cookie'].match(/kw_token=(\w+)/)[1] + } catch (err) { + return null + } +} + +const wait = time => new Promise(resolve => setTimeout(() => resolve(), time)) + + +export const getToken = (retryNum = 0) => new Promise((resolve, reject) => { + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + if (kw_token.isGetingToken) return wait(1000).then(() => getToken(retryNum).then(token => resolve(token))) + if (kw_token.token) return resolve(kw_token.token) + kw_token.isGetingToken = true + httpGet('http://www.kuwo.cn/', (err, resp) => { + kw_token.isGetingToken = false + if (err) return getToken(++retryNum) + if (resp.statusCode != 200) return reject(new Error('获取失败')) + const token = kw_token.token = matchToken(resp.headers) + resolve(token) + }) +}) + +export const tokenRequest = async(url, options = {}) => { + let token = kw_token.token + if (!token) token = await getToken() + if (!options.headers) { + options.headers = { + Referer: 'http://www.kuwo.cn/', + csrf: token, + cookie: 'kw_token=' + token, + } + } + const requestObj = httpFetch(url, options) + requestObj.promise = requestObj.promise.then(resp => { + if (resp.statusCode == 200) { + kw_token.token = matchToken(resp.headers) + } + return resp + }) + return requestObj +} diff --git a/src/utils/music/mg/album.js b/src/utils/music/mg/album.js new file mode 100644 index 0000000..625fc3a --- /dev/null +++ b/src/utils/music/mg/album.js @@ -0,0 +1,30 @@ +import { httpFetch } from '../../request' + +export default { + getAlbum(songInfo, tryNum = 0) { + let requestObj = httpFetch(`http://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/queryAlbumSong?albumId=${songInfo.albumId}&pageNo=1`, { + headers: { + sign: '46DB65104950B98FE451AD41047CC6C4', + timestamp: 1603451430776, + appId: 'yyapp2', + mode: 'android', + ua: 'Android_migu', + version: '6.9.4', + osVersion: 'android 7.0', + 'User-Agent': 'okhttp/3.9.1', + channel: '0146832', + }, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.code !== '000000') { + if (tryNum > 5) return Promise.reject('获取专辑失败') + let tryRequestObj = this.getAlbum(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + console.log(body) + return body.songList + }) + return requestObj + }, +} diff --git a/src/utils/music/mg/api-test.js b/src/utils/music/mg/api-test.js new file mode 100644 index 0000000..a64b6b2 --- /dev/null +++ b/src/utils/music/mg/api-test.js @@ -0,0 +1,20 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_test = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/mg/${songInfo.copyrightId}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, +} + +export default api_test diff --git a/src/utils/music/mg/comment.js b/src/utils/music/mg/comment.js new file mode 100644 index 0000000..a6c8a13 --- /dev/null +++ b/src/utils/music/mg/comment.js @@ -0,0 +1,95 @@ +import { httpFetch } from '../../request' +import album from './album' +import { dateFormat2 } from '../../' + +export default { + _requestObj: null, + _requestObj2: null, + _requestObj3: null, + async getSongId(musicInfo) { + if (this._requestObj3) this._requestObj3.cancelHttp() + this.requestObj3 = album.getAlbum(musicInfo) + const list = await this.requestObj3.promise + const copyrightId = musicInfo.copyrightId + let info = list.find(s => s.copyrightId == copyrightId) + const songmid = musicInfo.songmid + if (!info) info = list.find(s => s.songId == songmid) + return info ? info.songId : null + }, + async getComment(musicInfo, page = 1, limit = 20) { + if (this._requestObj) this._requestObj.cancelHttp() + if (!musicInfo.songId) { + let id = await this.getSongId(musicInfo) + if (!id) throw new Error('获取评论失败') + musicInfo.songId = id + } + + const _requestObj = httpFetch(`https://music.migu.cn/v3/api/comment/listComments?targetId=${musicInfo.songId}&pageSize=${limit}&pageNo=${page}`, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4195.1 Safari/537.36', + Referer: 'https://music.migu.cn', + }, + }) + const { body, statusCode } = await _requestObj.promise + // console.log(body) + if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取评论失败') + return { source: 'mg', comments: this.filterComment(body.data.items), total: body.data.itemTotal, page, limit, maxPage: Math.ceil(body.data.itemTotal / limit) || 1 } + }, + async getHotComment(musicInfo, page = 1, limit = 100) { + if (this._requestObj2) this._requestObj2.cancelHttp() + + if (!musicInfo.songId) { + let id = await this.getSongId(musicInfo) + if (!id) throw new Error('获取评论失败') + musicInfo.songId = id + } + + const _requestObj2 = httpFetch(`https://music.migu.cn/v3/api/comment/listTopComments?targetId=${musicInfo.songId}&pageSize=${limit}&pageNo=${page}`, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4195.1 Safari/537.36', + Referer: 'https://music.migu.cn', + }, + }) + const { body, statusCode } = await _requestObj2.promise + // console.log(body) + if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取热门评论失败') + return { source: 'mg', comments: this.filterComment(body.data.items) } + }, + async getReplyComment(musicInfo, replyId, page = 1, limit = 100) { + if (this._requestObj2) this._requestObj2.cancelHttp() + + const _requestObj2 = httpFetch(`https://music.migu.cn/v3/api/comment/listCommentsById?commentId=${replyId}&pageSize=${limit}&pageNo=${page}`, { + headers: { + 'User-Agent': 'Android712-AndroidPhone-8983-18-0-COMMENT-wifi', + }, + }) + const { body, statusCode } = await _requestObj2.promise + // console.log(body) + if (statusCode != 200 || body.returnCode !== '000000') throw new Error('获取回复评论失败') + return { source: 'mg', comments: this.filterComment(body.data.items) } + }, + filterComment(rawList) { + return rawList.map(item => ({ + id: item.commentId, + text: item.body.split('\n'), + time: item.createTime, + timeStr: dateFormat2(new Date(item.createTime).getTime()), + userName: item.author.name, + avatar: item.author.avatar, + userId: item.author.id, + likedCount: item.praiseCount, + replyNum: item.replyTotal, + reply: item.replyCommentList.map(c => ({ + id: c.commentId, + text: c.body.split('\n'), + time: c.createTime, + timeStr: dateFormat2(new Date(c.createTime).getTime()), + userName: c.author.name, + avatar: c.author.avatar, + userId: c.author.id, + likedCount: c.praiseCount, + replyNum: c.replyTotal, + })), + })) + }, +} diff --git a/src/utils/music/mg/hotSearch.js b/src/utils/music/mg/hotSearch.js new file mode 100644 index 0000000..7069184 --- /dev/null +++ b/src/utils/music/mg/hotSearch.js @@ -0,0 +1,18 @@ +import { httpFetch } from '../../request' + +export default { + _requestObj: null, + async getList(retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('http://jadeite.migu.cn:7090/music_search/v2/search/hotword') + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.code !== '000000') throw new Error('获取热搜词失败') + // console.log(body, statusCode) + return { source: 'mg', list: this.filterList(body.data) } + }, + filterList(rawList) { + return rawList.map(item => item.word) + }, +} diff --git a/src/utils/music/mg/index.js b/src/utils/music/mg/index.js new file mode 100644 index 0000000..d6fede7 --- /dev/null +++ b/src/utils/music/mg/index.js @@ -0,0 +1,30 @@ +import { apis } from '../api-source' +import leaderboard from './leaderboard2' +import songList from './songList' +import musicSearch from './musicSearch' +import pic from './pic' +import lyric from './lyric' +import hotSearch from './hotSearch' +import comment from './comment' + +const mg = { + songList, + musicSearch, + leaderboard, + hotSearch, + comment, + getMusicUrl(songInfo, type) { + return apis('mg').getMusicUrl(songInfo, type) + }, + getLyric(songInfo) { + return lyric.getLyric(songInfo) + }, + getPic(songInfo) { + return pic.getPic(songInfo) + }, + getMusicDetailPageUrl(songInfo) { + return `http://music.migu.cn/v3/music/song/${songInfo.copyrightId}` + }, +} + +export default mg diff --git a/src/utils/music/mg/leaderboard.js b/src/utils/music/mg/leaderboard.js new file mode 100644 index 0000000..0d1cbef --- /dev/null +++ b/src/utils/music/mg/leaderboard.js @@ -0,0 +1,212 @@ +import { httpFetch } from '../../request' +import { sizeFormate } from '../../index' +// import jshtmlencode from 'js-htmlencode' + +const boardList = [{ id: 'mg__27553319', name: '咪咕尖叫新歌榜', bangid: '27553319' }, { id: 'mg__27186466', name: '咪咕尖叫热歌榜', bangid: '27186466' }, { id: 'mg__27553408', name: '咪咕尖叫原创榜', bangid: '27553408' }, { id: 'mg__23189800', name: '咪咕港台榜', bangid: '23189800' }, { id: 'mg__23189399', name: '咪咕内地榜', bangid: '23189399' }, { id: 'mg__19190036', name: '咪咕欧美榜', bangid: '19190036' }, { id: 'mg__23189813', name: '咪咕日韩榜', bangid: '23189813' }, { id: 'mg__23190126', name: '咪咕彩铃榜', bangid: '23190126' }, { id: 'mg__15140045', name: '咪咕KTV榜', bangid: '15140045' }, { id: 'mg__15140034', name: '咪咕网络榜', bangid: '15140034' }, { id: 'mg__23217754', name: 'MV榜', bangid: '23217754' }, { id: 'mg__23218151', name: '新专辑榜', bangid: '23218151' }, { id: 'mg__21958042', name: 'iTunes榜', bangid: '21958042' }, { id: 'mg__21975570', name: 'billboard榜', bangid: '21975570' }, { id: 'mg__22272815', name: '台湾Hito中文榜', bangid: '22272815' }, { id: 'mg__22272904', name: '中国TOP排行榜', bangid: '22272904' }, { id: 'mg__22272943', name: '韩国Melon榜', bangid: '22272943' }, { id: 'mg__22273437', name: '英国UK榜', bangid: '22273437' }] + +export default { + limit: 200, + list: [ + { + id: 'mgyyb', + name: '音乐榜', + bangid: '27553319', + }, + { + id: 'mgysb', + name: '影视榜', + bangid: '23603721', + }, + { + id: 'mghybnd', + name: '华语内地榜', + bangid: '23603926', + }, + { + id: 'mghyjqbgt', + name: '华语港台榜', + bangid: '23603954', + }, + { + id: 'mgomb', + name: '欧美榜', + bangid: '23603974', + }, + { + id: 'mgrhb', + name: '日韩榜', + bangid: '23603982', + }, + { + id: 'mgwlb', + name: '网络榜', + bangid: '23604058', + }, + { + id: 'mgclb', + name: '彩铃榜', + bangid: '23604023', + }, + { + id: 'mgktvb', + name: 'KTV榜', + bangid: '23604040', + }, + { + id: 'mgrcb', + name: '原创榜', + bangid: '23604032', + }, + ], + getUrl(id, page) { + return `https://app.c.nf.migu.cn/MIGUM3.0/v1.0/template/rank-detail/release?columnId=${id}` + // return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}` + }, + successCode: '000000', + requestBoardsObj: null, + requestObj: null, + getBoardsData() { + if (this.requestBoardsObj) this._requestBoardsObj.cancelHttp() + this.requestBoardsObj = httpFetch('https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/indexrank.do?templateVersion=8', { + headers: { + sign: 'c3b7ae985e2206e97f1b2de8f88691e2', + timestamp: 1578225871982, + appId: 'yyapp2', + mode: 'android', + ua: 'Android_migu', + version: '6.9.4', + osVersion: 'android 7.0', + 'User-Agent': 'okhttp/3.9.1', + }, + }) + return this.requestBoardsObj.promise + }, + getData(url) { + if (this.requestObj) this.requestObj.cancelHttp() + this.requestObj = httpFetch(url) + return this.requestObj.promise + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + filterData(rawData) { + // console.log(JSON.stringify(rawData)) + // console.log(rawData) + let ids = new Set() + const list = [] + rawData.forEach(item => { + if (ids.has(item.copyrightId)) return + ids.add(item.copyrightId) + + const types = [] + const _types = {} + item.rateFormats && item.rateFormats.forEach(type => { + let size + switch (type.formatType) { + case 'PQ': + size = sizeFormate(type.size) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + break + case 'HQ': + size = sizeFormate(type.size) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + break + case 'SQ': + size = sizeFormate(type.size) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + break + } + }) + + list.push({ + singer: this.getSinger(item.artists), + name: item.songName, + albumName: item.album, + albumId: item.albumId, + songmid: item.copyrightId, + songId: item.songId, + copyrightId: item.copyrightId, + source: 'mg', + interval: null, + img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null, + lrc: null, + lrcUrl: item.lrcUrl, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + filterBoardsData(rawList) { + // console.log(rawList) + let list = [] + for (const board of rawList) { + if (board.template != 'group1') continue + for (const item of board.itemList) { + if ((item.template != 'row1' && item.template != 'grid1' && !item.actionUrl) || !item.actionUrl.includes('rank-info')) continue + + let data = item.displayLogId.param + list.push({ + id: 'mg__' + data.rankId, + name: data.rankName, + bangid: String(data.rankId), + }) + } + } + return list + }, + async getBoards(retryNum = 0) { + // if (++retryNum > 3) return Promise.reject(new Error('try max num')) + // let response + // try { + // response = await this.getBoardsData() + // } catch (error) { + // return this.getBoards(retryNum) + // } + // // console.log(response.body.data.contentItemList) + // if (response.statusCode !== 200 || response.body.code !== this.successCode) return this.getBoards(retryNum) + // const list = this.filterBoardsData(response.body.data.contentItemList) + // // console.log(list) + // // console.log(JSON.stringify(list)) + // this.list = list + // return { + // list, + // source: 'mg', + // } + this.list = boardList + return { + list: boardList, + source: 'mg', + } + }, + getList(bangid, page, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + return this.getData(this.getUrl(bangid, page)).then(({ statusCode, body }) => { + console.log(body) + if (statusCode !== 200 || body.code !== this.successCode) return this.getList(bangid, page, retryNum) + const list = this.filterData(body.data.columnInfo.dataList) + return { + total: list.length, + list, + limit: this.limit, + page, + source: 'mg', + } + }) + }, +} diff --git a/src/utils/music/mg/leaderboard2.js b/src/utils/music/mg/leaderboard2.js new file mode 100644 index 0000000..bf77f4c --- /dev/null +++ b/src/utils/music/mg/leaderboard2.js @@ -0,0 +1,174 @@ +import { httpFetch } from '../../request' +import { formatPlayTime } from '../../index' +// import { sizeFormate } from '../../index' +// import jshtmlencode from 'js-htmlencode' + +// const boardList = [{ id: 'mg__27553319', name: '咪咕尖叫新歌榜', bangid: '27553319' }, { id: 'mg__27186466', name: '咪咕尖叫热歌榜', bangid: '27186466' }, { id: 'mg__27553408', name: '咪咕尖叫原创榜', bangid: '27553408' }, { id: 'mg__23189800', name: '咪咕港台榜', bangid: '23189800' }, { id: 'mg__23189399', name: '咪咕内地榜', bangid: '23189399' }, { id: 'mg__19190036', name: '咪咕欧美榜', bangid: '19190036' }, { id: 'mg__23189813', name: '咪咕日韩榜', bangid: '23189813' }, { id: 'mg__23190126', name: '咪咕彩铃榜', bangid: '23190126' }, { id: 'mg__15140045', name: '咪咕KTV榜', bangid: '15140045' }, { id: 'mg__15140034', name: '咪咕网络榜', bangid: '15140034' }, { id: 'mg__23217754', name: 'MV榜', bangid: '23217754' }, { id: 'mg__23218151', name: '新专辑榜', bangid: '23218151' }, { id: 'mg__21958042', name: 'iTunes榜', bangid: '21958042' }, { id: 'mg__21975570', name: 'billboard榜', bangid: '21975570' }, { id: 'mg__22272815', name: '台湾Hito中文榜', bangid: '22272815' }, { id: 'mg__22272904', name: '中国TOP排行榜', bangid: '22272904' }, { id: 'mg__22272943', name: '韩国Melon榜', bangid: '22272943' }, { id: 'mg__22273437', name: '英国UK榜', bangid: '22273437' }] +const boardList = [ + { id: 'mg__jianjiao_newsong', bangid: 'jianjiao_newsong', name: '尖叫新歌榜' }, + { id: 'mg__jianjiao_hotsong', bangid: 'jianjiao_hotsong', name: '尖叫热歌榜' }, + { id: 'mg__jianjiao_original', bangid: 'jianjiao_original', name: '尖叫原创榜' }, + { id: 'mg__migumusic', bangid: 'migumusic', name: '音乐榜' }, + { id: 'mg__movies', bangid: 'movies', name: '影视榜' }, + { id: 'mg__mainland', bangid: 'mainland', name: '内地榜' }, + { id: 'mg__hktw', bangid: 'hktw', name: '港台榜' }, + { id: 'mg__eur_usa', bangid: 'eur_usa', name: '欧美榜' }, + { id: 'mg__jpn_kor', bangid: 'jpn_kor', name: '日韩榜' }, + { id: 'mg__coloring', bangid: 'coloring', name: '彩铃榜' }, + { id: 'mg__ktv', bangid: 'ktv', name: 'KTV榜' }, + { id: 'mg__network', bangid: 'network', name: '网络榜' }, + { id: 'mg__newalbum', bangid: 'newalbum', name: '新专辑榜' }, + { id: 'mg__mv', bangid: 'mv', name: 'MV榜' }, + { id: 'mg__itunes', bangid: 'itunes', name: '美国iTunes榜' }, + { id: 'mg__billboard', bangid: 'billboard', name: '美国billboard榜' }, + { id: 'mg__hito', bangid: 'hito', name: 'Hito中文榜' }, + { id: 'mg__mnet', bangid: 'mnet', name: '韩国Melon榜' }, + { id: 'mg__uk', bangid: 'uk', name: '英国UK榜' }, +] + +export default { + limit: 10000, + getUrl(id, page) { + return `https://music.migu.cn/v3/music/top/${id}` + // return `http://m.music.migu.cn/migu/remoting/cms_list_tag?nid=${id}&pageSize=${this.limit}&pageNo=${page - 1}` + }, + successCode: '000000', + requestBoardsObj: null, + requestObj: null, + regExps: { + listData: /var listData = (\{.+\})<\/script>/, + }, + getData(url) { + if (this.requestObj) this.requestObj.cancelHttp() + this.requestObj = httpFetch(url) + return this.requestObj.promise + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + getIntv(interval) { + let intvArr = interval.split(':') + let intv = 0 + let unit = 1 + while (intvArr.length) { + intv += (intvArr.pop()) * unit + unit *= 60 + } + return parseInt(intv) + }, + formateIntv() { + + }, + filterData(rawData) { + // console.log(JSON.stringify(rawData)) + // console.log(rawData) + let ids = new Set() + const list = [] + rawData.forEach(item => { + if (ids.has(item.copyrightId)) return + ids.add(item.copyrightId) + + const types = [] + const _types = {} + + const size = null + types.push({ type: '128k', size }) + _types['128k'] = { size } + + if (item.hq) { + const size = null + types.push({ type: '320k', size }) + _types['320k'] = { size } + } + if (item.sq) { + const size = null + types.push({ type: 'flac', size }) + _types.flac = { size } + } + + list.push({ + singer: this.getSinger(item.singers), + name: item.name, + albumName: item.album.albumName, + albumId: item.album.albumId, + songmid: item.copyrightId, + songId: item.id, + copyrightId: item.copyrightId, + source: 'mg', + interval: item.duration ? formatPlayTime(this.getIntv(item.duration)) : null, + img: item.mediumPic ? `https:${item.mediumPic}` : null, + lrc: null, + // lrcUrl: item.lrcUrl, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + filterBoardsData(rawList) { + // console.log(rawList) + let list = [] + for (const board of rawList) { + if (board.template != 'group1') continue + for (const item of board.itemList) { + if ((item.template != 'row1' && item.template != 'grid1' && !item.actionUrl) || !item.actionUrl.includes('rank-info')) continue + + let data = item.displayLogId.param + list.push({ + id: 'mg__' + data.rankId, + name: data.rankName, + bangid: String(data.rankId), + }) + } + } + return list + }, + async getBoards(retryNum = 0) { + // if (++retryNum > 3) return Promise.reject(new Error('try max num')) + // let response + // try { + // response = await this.getBoardsData() + // } catch (error) { + // return this.getBoards(retryNum) + // } + // // console.log(response.body.data.contentItemList) + // if (response.statusCode !== 200 || response.body.code !== this.successCode) return this.getBoards(retryNum) + // const list = this.filterBoardsData(response.body.data.contentItemList) + // // console.log(list) + // // console.log(JSON.stringify(list)) + // this.list = list + // return { + // list, + // source: 'mg', + // } + this.list = boardList + return { + list: boardList, + source: 'mg', + } + }, + getList(bangid, page, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + return this.getData(this.getUrl(bangid, page)).then(({ statusCode, body }) => { + if (statusCode !== 200) return this.getList(bangid, page, retryNum) + let listData = body.match(this.regExps.listData) + if (!listData) return this.getList(bangid, page, retryNum) + const datas = JSON.parse(RegExp.$1) + // console.log(datas) + listData = this.filterData(datas.songs.items) + return { + total: datas.songs.itemTotal, + list: this.filterData(datas.songs.items), + limit: this.limit, + page, + source: 'mg', + } + }) + }, +} diff --git a/src/utils/music/mg/lyric.js b/src/utils/music/mg/lyric.js new file mode 100644 index 0000000..cd6a49e --- /dev/null +++ b/src/utils/music/mg/lyric.js @@ -0,0 +1,42 @@ +import { httpFetch } from '../../request' + +export default { + getLyric(songInfo, tryNum = 0) { + // console.log(songInfo.copyrightId) + if (songInfo.lrcUrl) { + let requestObj = httpFetch(songInfo.lrcUrl) + requestObj.promise = requestObj.promise.then(({ body, statusCode }) => { + if (statusCode !== 200) { + if (tryNum > 5) return Promise.reject('歌词获取失败') + let tryRequestObj = this.getLyric(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + return { + lyric: body, + tlyric: '', + } + }) + return requestObj + } else { + let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getLyric?copyrightId=${songInfo.copyrightId}`, { + headers: { + Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu', + }, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.returnCode !== '000000') { + if (tryNum > 5) return Promise.reject('歌词获取失败') + let tryRequestObj = this.getLyric(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + return { + lyric: body.lyric, + tlyric: '', + } + }) + return requestObj + } + }, +} diff --git a/src/utils/music/mg/musicSearch.js b/src/utils/music/mg/musicSearch.js new file mode 100644 index 0000000..183a3d5 --- /dev/null +++ b/src/utils/music/mg/musicSearch.js @@ -0,0 +1,125 @@ +// import '../../polyfill/array.find' +// import jshtmlencode from 'js-htmlencode' +import { httpFetch } from '../../request' +import { sizeFormate } from '../../index' +// import { debug } from '../../utils/env' +// import { formatSinger } from './util' + +let searchRequest +export default { + limit: 30, + total: 0, + page: 0, + allPage: 1, + musicSearch(str, page, limit) { + if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp() + searchRequest = httpFetch(`http://jadeite.migu.cn:7090/music_search/v2/search/searchAll?sid=4f87090d01c84984a11976b828e2b02c18946be88a6b4c47bcdc92fbd40762db&isCorrect=1&isCopyright=1&searchSwitch=%7B%22song%22%3A1%2C%22album%22%3A0%2C%22singer%22%3A0%2C%22tagSong%22%3A1%2C%22mvSong%22%3A0%2C%22bestShow%22%3A1%2C%22songlist%22%3A0%2C%22lyricSong%22%3A0%7D&pageSize=${limit}&text=${encodeURIComponent(str)}&pageNo=${page}&sort=0`, { + headers: { + sign: 'c3b7ae985e2206e97f1b2de8f88691e2', + timestamp: 1578225871982, + appId: 'yyapp2', + mode: 'android', + ua: 'Android_migu', + version: '6.9.4', + osVersion: 'android 7.0', + 'User-Agent': 'okhttp/3.9.1', + }, + }) + // searchRequest = httpFetch(`https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/search_all.do?isCopyright=1&isCorrect=1&pageNo=${page}&pageSize=${limit}&searchSwitch={%22song%22:1,%22album%22:0,%22singer%22:0,%22tagSong%22:0,%22mvSong%22:0,%22songlist%22:0,%22bestShow%22:0}&sort=0&text=${encodeURIComponent(str)}`) + return searchRequest.promise.then(({ body }) => body) + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + handleResult(rawData) { + // console.log(rawData) + let ids = new Set() + const list = [] + rawData.forEach(item => { + if (ids.has(item.id)) return + ids.add(item.id) + const types = [] + const _types = {} + item.rateFormats && item.rateFormats.forEach(type => { + let size + switch (type.formatType) { + case 'PQ': + size = sizeFormate(type.size) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + break + case 'HQ': + size = sizeFormate(type.size) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + break + case 'SQ': + size = sizeFormate(type.size) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + break + } + }) + + const albumNInfo = item.albums && item.albums.length ? { + id: item.albums[0].id, + name: item.albums[0].name, + } : {} + + list.push({ + singer: this.getSinger(item.singers), + name: item.name, + albumName: albumNInfo.name, + albumId: albumNInfo.id, + songmid: item.id, + songId: item.songId, + copyrightId: item.copyrightId, + source: 'mg', + interval: null, + img: item.imgItems && item.imgItems.length ? item.imgItems[0].img : null, + lrc: null, + lrcUrl: item.lyricUrl, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + search(str, page = 1, { limit } = {}, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + if (limit == null) limit = this.limit + // http://newlyric.kuwo.cn/newlyric.lrc?62355680 + return this.musicSearch(str, page, limit).then(result => { + // console.log(result) + if (!result || result.code !== '000000') return Promise.reject(new Error(result ? result.info : '搜索失败')) + const songResultData = result.songResultData || { resultList: [], totalCount: 0 } + + let list = this.handleResult(songResultData.resultList.flat()) + if (list == null) return this.search(str, page, { limit }, retryNum) + + this.total = parseInt(songResultData.totalCount) + this.page = page + this.allPage = Math.ceil(this.total / limit) + + return Promise.resolve({ + list, + allPage: this.allPage, + limit, + total: this.total, + source: 'mg', + }) + }) + }, +} diff --git a/src/utils/music/mg/pic.js b/src/utils/music/mg/pic.js new file mode 100644 index 0000000..46a4046 --- /dev/null +++ b/src/utils/music/mg/pic.js @@ -0,0 +1,21 @@ +import { httpFetch } from '../../request' + +export default { + getPic(songInfo, tryNum = 0) { + let requestObj = httpFetch(`http://music.migu.cn/v3/api/music/audioPlayer/getSongPic?songId=${songInfo.songmid}`, { + headers: { + Referer: 'http://music.migu.cn/v3/music/player/audio?from=migu', + }, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.returnCode !== '000000') { + if (tryNum > 5) return Promise.reject('图片获取失败') + let tryRequestObj = this.getPic(songInfo, ++tryNum) + requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) + return tryRequestObj.promise + } + return body.largePic || body.mediumPic || body.smallPic + }) + return requestObj + }, +} diff --git a/src/utils/music/mg/songList.js b/src/utils/music/mg/songList.js new file mode 100644 index 0000000..ea9faa0 --- /dev/null +++ b/src/utils/music/mg/songList.js @@ -0,0 +1,307 @@ +import { httpFetch } from '../../request' +import { sizeFormate } from '../../index' + +const tagData = { code: '000000', info: 'SUCCESS', columnInfo: { columnTitle: '分类', columnId: '15244430', columnPid: '15031270', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 6, columnStatus: 1, columnCreateTime: '2016-11-10 10:53:05.077', columntype: 2011, contents: [{ contentId: '18464615', relationType: 2011, objectInfo: { columnTitle: '热门', columnId: '18464615', columnPid: '15244430', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 8, columnStatus: 1, columnCreateTime: '2017-02-20 16:09:13.400', columntype: 2011, contents: [{ contentId: '1000001672', relationType: 4034, objectInfo: { tagId: '1000001672', tagName: '流行', resourceType: '2034' }, relationSort: 9 }, { contentId: '1003449727', relationType: 4034, objectInfo: { tagId: '1003449727', tagName: '厂牌', resourceType: '2034' }, relationSort: 8 }, { contentId: '1000001795', relationType: 4034, objectInfo: { tagId: '1000001795', tagName: '伤感', resourceType: '2034' }, relationSort: 7 }, { contentId: '1001076080', relationType: 4034, objectInfo: { tagId: '1001076080', tagName: '电影', resourceType: '2034' }, relationSort: 6 }, { contentId: '1000001675', relationType: 4034, objectInfo: { tagId: '1000001675', tagName: '中国风', resourceType: '2034' }, relationSort: 5 }, { contentId: '1000001635', relationType: 4034, objectInfo: { tagId: '1000001635', tagName: '经典老歌', resourceType: '2034' }, relationSort: 4 }, { contentId: '1000001831', relationType: 4034, objectInfo: { tagId: '1000001831', tagName: '翻唱', resourceType: '2034' }, relationSort: 3 }, { contentId: '1000001762', relationType: 4034, objectInfo: { tagId: '1000001762', tagName: '国语', resourceType: '2034' }, relationSort: 1 }], dataVersion: '1620410266029', customizedPicUrls: [] }, relationSort: 6 }, { contentId: '15244503', relationType: 2011, objectInfo: { columnTitle: '主题', columnId: '15244503', columnPid: '15244430', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 23, columnStatus: 1, columnCreateTime: '2016-11-10 10:54:10.261', columntype: 2011, contents: [{ contentId: '1003449727', relationType: 4034, objectInfo: { tagId: '1003449727', tagName: '厂牌', resourceType: '2034' }, relationSort: 29 }, { contentId: '1001076080', relationType: 4034, objectInfo: { tagId: '1001076080', tagName: '电影', resourceType: '2034' }, relationSort: 28 }, { contentId: '1001076078', relationType: 4034, objectInfo: { tagId: '1001076078', tagName: '电视剧', resourceType: '2034' }, relationSort: 27 }, { contentId: '1001076083', relationType: 4034, objectInfo: { tagId: '1001076083', tagName: '综艺', resourceType: '2034' }, relationSort: 26 }, { contentId: '1000001827', relationType: 4034, objectInfo: { tagId: '1000001827', tagName: 'KTV', resourceType: '2034' }, relationSort: 23 }, { contentId: '1000001698', relationType: 4034, objectInfo: { tagId: '1000001698', tagName: '爱情', resourceType: '2034' }, relationSort: 22 }, { contentId: '1000001635', relationType: 4034, objectInfo: { tagId: '1000001635', tagName: '经典老歌', resourceType: '2034' }, relationSort: 21 }, { contentId: '1001076096', relationType: 4034, objectInfo: { tagId: '1001076096', tagName: '网络热歌', resourceType: '2034' }, relationSort: 20 }, { contentId: '1000001780', relationType: 4034, objectInfo: { tagId: '1000001780', tagName: '儿童歌曲', resourceType: '2034' }, relationSort: 19 }, { contentId: '1000587702', relationType: 4034, objectInfo: { tagId: '1000587702', tagName: '广场舞', resourceType: '2034' }, relationSort: 18 }, { contentId: '1000587717', relationType: 4034, objectInfo: { tagId: '1000587717', tagName: '70后', resourceType: '2034' }, relationSort: 17 }, { contentId: '1000587718', relationType: 4034, objectInfo: { tagId: '1000587718', tagName: '80后', resourceType: '2034' }, relationSort: 16 }, { contentId: '1000587726', relationType: 4034, objectInfo: { tagId: '1000587726', tagName: '90后', resourceType: '2034' }, relationSort: 15 }, { contentId: '1000001670', relationType: 4034, objectInfo: { tagId: '1000001670', tagName: '红歌', resourceType: '2034' }, relationSort: 14 }, { contentId: '1000587698', relationType: 4034, objectInfo: { tagId: '1000587698', tagName: '游戏', resourceType: '2034' }, relationSort: 13 }, { contentId: '1000587706', relationType: 4034, objectInfo: { tagId: '1000587706', tagName: '动漫', resourceType: '2034' }, relationSort: 12 }, { contentId: '1000001675', relationType: 4034, objectInfo: { tagId: '1000001675', tagName: '中国风', resourceType: '2034' }, relationSort: 11 }, { contentId: '1000587712', relationType: 4034, objectInfo: { tagId: '1000587712', tagName: '青春校园', resourceType: '2034' }, relationSort: 10 }, { contentId: '1000587673', relationType: 4034, objectInfo: { tagId: '1000587673', tagName: '小清新', resourceType: '2034' }, relationSort: 9 }, { contentId: '1000093902', relationType: 4034, objectInfo: { tagId: '1000093902', tagName: 'DJ舞曲', resourceType: '2034' }, relationSort: 7 }, { contentId: '1000093963', relationType: 4034, objectInfo: { tagId: '1000093963', tagName: '广告', resourceType: '2034' }, relationSort: 6 }, { contentId: '1000001831', relationType: 4034, objectInfo: { tagId: '1000001831', tagName: '翻唱', resourceType: '2034' }, relationSort: 2 }, { contentId: '1003449726', relationType: 4034, objectInfo: { tagId: '1003449726', tagName: '读书', resourceType: '2034' }, relationSort: 1 }], dataVersion: '1620410266055', customizedPicUrls: [] }, relationSort: 5 }, { contentId: '15244509', relationType: 2011, objectInfo: { columnTitle: '风格', columnId: '15244509', columnPid: '15244430', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 12, columnStatus: 1, columnCreateTime: '2016-11-10 10:54:57.257', columntype: 2011, contents: [{ contentId: '1000001672', relationType: 4034, objectInfo: { tagId: '1000001672', tagName: '流行', resourceType: '2034' }, relationSort: 14 }, { contentId: '1000001808', relationType: 4034, objectInfo: { tagId: '1000001808', tagName: 'R&B', resourceType: '2034' }, relationSort: 13 }, { contentId: '1000001809', relationType: 4034, objectInfo: { tagId: '1000001809', tagName: '嘻哈', resourceType: '2034' }, relationSort: 12 }, { contentId: '1000001674', relationType: 4034, objectInfo: { tagId: '1000001674', tagName: '摇滚', resourceType: '2034' }, relationSort: 11 }, { contentId: '1000001682', relationType: 4034, objectInfo: { tagId: '1000001682', tagName: '电子', resourceType: '2034' }, relationSort: 10 }, { contentId: '1000001852', relationType: 4034, objectInfo: { tagId: '1000001852', tagName: '电子舞曲', resourceType: '2034' }, relationSort: 9 }, { contentId: '1000001681', relationType: 4034, objectInfo: { tagId: '1000001681', tagName: '爵士', resourceType: '2034' }, relationSort: 6 }, { contentId: '1000001683', relationType: 4034, objectInfo: { tagId: '1000001683', tagName: '乡村', resourceType: '2034' }, relationSort: 5 }, { contentId: '1000001851', relationType: 4034, objectInfo: { tagId: '1000001851', tagName: '蓝调', resourceType: '2034' }, relationSort: 4 }, { contentId: '1000001775', relationType: 4034, objectInfo: { tagId: '1000001775', tagName: '民谣', resourceType: '2034' }, relationSort: 3 }, { contentId: '1000001807', relationType: 4034, objectInfo: { tagId: '1000001807', tagName: '纯音乐', resourceType: '2034' }, relationSort: 2 }, { contentId: '1000001783', relationType: 4034, objectInfo: { tagId: '1000001783', tagName: '古典', resourceType: '2034' }, relationSort: 1 }], dataVersion: '1620410266033', customizedPicUrls: [] }, relationSort: 4 }, { contentId: '18464665', relationType: 2011, objectInfo: { columnTitle: '语种', columnId: '18464665', columnPid: '15244430', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 6, columnStatus: 1, columnCreateTime: '2017-02-20 16:07:16.566', columntype: 2011, contents: [{ contentId: '1000001762', relationType: 4034, objectInfo: { tagId: '1000001762', tagName: '国语', resourceType: '2034' }, relationSort: 6 }, { contentId: '1000001763', relationType: 4034, objectInfo: { tagId: '1000001763', tagName: '粤语', resourceType: '2034' }, relationSort: 5 }, { contentId: '1000001766', relationType: 4034, objectInfo: { tagId: '1000001766', tagName: '英语', resourceType: '2034' }, relationSort: 4 }, { contentId: '1000001599', relationType: 4034, objectInfo: { tagId: '1000001599', tagName: '韩语', resourceType: '2034' }, relationSort: 3 }, { contentId: '1000001767', relationType: 4034, objectInfo: { tagId: '1000001767', tagName: '日语', resourceType: '2034' }, relationSort: 2 }, { contentId: '1003449724', relationType: 4034, objectInfo: { tagId: '1003449724', tagName: '小语种', resourceType: '2034' }, relationSort: 1 }], dataVersion: '1620410266036', customizedPicUrls: [] }, relationSort: 3 }, { contentId: '18464583', relationType: 2011, objectInfo: { columnTitle: '心情', columnId: '18464583', columnPid: '15244430', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 13, columnStatus: 1, columnCreateTime: '2017-02-20 15:59:03.412', columntype: 2011, contents: [{ contentId: '1000587677', relationType: 4034, objectInfo: { tagId: '1000587677', tagName: '幸福', resourceType: '2034' }, relationSort: 15 }, { contentId: '1000587710', relationType: 4034, objectInfo: { tagId: '1000587710', tagName: '治愈', resourceType: '2034' }, relationSort: 14 }, { contentId: '1000001703', relationType: 4034, objectInfo: { tagId: '1000001703', tagName: '思念', resourceType: '2034' }, relationSort: 13 }, { contentId: '1000587667', relationType: 4034, objectInfo: { tagId: '1000587667', tagName: '期待', resourceType: '2034' }, relationSort: 12 }, { contentId: '1000001700', relationType: 4034, objectInfo: { tagId: '1000001700', tagName: '励志', resourceType: '2034' }, relationSort: 11 }, { contentId: '1000001694', relationType: 4034, objectInfo: { tagId: '1000001694', tagName: '欢快', resourceType: '2034' }, relationSort: 10 }, { contentId: '1002600588', relationType: 4034, objectInfo: { tagId: '1002600588', tagName: '叛逆', resourceType: '2034' }, relationSort: 9 }, { contentId: '1002600585', relationType: 4034, objectInfo: { tagId: '1002600585', tagName: '宣泄', resourceType: '2034' }, relationSort: 8 }, { contentId: '1000001696', relationType: 4034, objectInfo: { tagId: '1000001696', tagName: '怀旧', resourceType: '2034' }, relationSort: 7 }, { contentId: '1000587679', relationType: 4034, objectInfo: { tagId: '1000587679', tagName: '减压', resourceType: '2034' }, relationSort: 6 }, { contentId: '1000001699', relationType: 4034, objectInfo: { tagId: '1000001699', tagName: '寂寞', resourceType: '2034' }, relationSort: 5 }, { contentId: '1002600579', relationType: 4034, objectInfo: { tagId: '1002600579', tagName: '忧郁', resourceType: '2034' }, relationSort: 4 }, { contentId: '1000001795', relationType: 4034, objectInfo: { tagId: '1000001795', tagName: '伤感', resourceType: '2034' }, relationSort: 3 }], dataVersion: '1620410266187', customizedPicUrls: [] }, relationSort: 2 }, { contentId: '18464638', relationType: 2011, objectInfo: { columnTitle: '场景', columnId: '18464638', columnPid: '15244430', opNumItem: { playNum: 0, playNumDesc: '0', keepNum: 0, keepNumDesc: '0', commentNum: 0, commentNumDesc: '0', shareNum: 0, shareNumDesc: '0', orderNumByWeek: 0, orderNumByWeekDesc: '0', orderNumByTotal: 0, orderNumByTotalDesc: '0', thumbNum: 0, thumbNumDesc: '0', followNum: 0, followNumDesc: '0', subscribeNum: 0, subscribeNumDesc: '0', livePlayNum: 0, livePlayNumDesc: '0', popularNum: 0, popularNumDesc: '0', bookingNum: 0, bookingNumDesc: '0' }, contentsCount: 13, columnStatus: 1, columnCreateTime: '2017-02-20 16:02:59.711', columntype: 2011, contents: [{ contentId: '1000587689', relationType: 4034, objectInfo: { tagId: '1000587689', tagName: '清晨', resourceType: '2034' }, relationSort: 21 }, { contentId: '1000587690', relationType: 4034, objectInfo: { tagId: '1000587690', tagName: '夜晚', resourceType: '2034' }, relationSort: 20 }, { contentId: '1000587688', relationType: 4034, objectInfo: { tagId: '1000587688', tagName: '睡前安眠', resourceType: '2034' }, relationSort: 19 }, { contentId: '1003449726', relationType: 4034, objectInfo: { tagId: '1003449726', tagName: '读书', resourceType: '2034' }, relationSort: 18 }, { contentId: '1003449723', relationType: 4034, objectInfo: { tagId: '1003449723', tagName: '下午·茶', resourceType: '2034' }, relationSort: 16 }, { contentId: '1000093923', relationType: 4034, objectInfo: { tagId: '1000093923', tagName: '驾车', resourceType: '2034' }, relationSort: 15 }, { contentId: '1003449615', relationType: 4034, objectInfo: { tagId: '1003449615', tagName: '运动', resourceType: '2034' }, relationSort: 13 }, { contentId: '1000587694', relationType: 4034, objectInfo: { tagId: '1000587694', tagName: '散步', resourceType: '2034' }, relationSort: 12 }, { contentId: '1000001749', relationType: 4034, objectInfo: { tagId: '1000001749', tagName: '旅行', resourceType: '2034' }, relationSort: 11 }, { contentId: '1000587686', relationType: 4034, objectInfo: { tagId: '1000587686', tagName: '夜店', resourceType: '2034' }, relationSort: 10 }, { contentId: '1002600606', relationType: 4034, objectInfo: { tagId: '1002600606', tagName: '派对', resourceType: '2034' }, relationSort: 9 }, { contentId: '1000001634', relationType: 4034, objectInfo: { tagId: '1000001634', tagName: '咖啡馆', resourceType: '2034' }, relationSort: 3 }, { contentId: '1000587692', relationType: 4034, objectInfo: { tagId: '1000587692', tagName: '瑜伽', resourceType: '2034' }, relationSort: 1 }], dataVersion: '1620846028994', customizedPicUrls: [] }, relationSort: 1 }], dataVersion: '1620846028941', customizedPicUrls: [] } } + +export default { + _requestObj_tags: null, + _requestObj_list: null, + _requestObj_listDetail: null, + _requestObj_listDetailInfo: null, + limit_list: 10, + limit_song: 10000, + successCode: '000000', + cachedDetailInfo: {}, + sortList: [ + { + name: '推荐', + id: '15127315', + tid: 'recommend', + // id: '1', + }, + { + name: '最新', + id: '15127272', + tid: 'new', + // id: '2', + }, + ], + regExps: { + list: /<li><div class="thumb">.+?<\/li>/g, + listInfo: /.+data-original="(.+?)".*data-id="(\d+)".*<div class="song-list-name"><a\s.*?>(.+?)<\/a>.+<i class="iconfont cf-bofangliang"><\/i>(.+?)<\/div>/, + + // https://music.migu.cn/v3/music/playlist/161044573?page=1 + listDetailLink: /^.+\/playlist\/(\d+)(?:\?.*|&.*$|#.*$|$)/, + }, + tagsUrl: 'https://app.c.nf.migu.cn/MIGUM2.0/v1.0/content/indexTagPage.do?needAll=0', + getSongListUrl(sortId, tagId, page) { + // if (tagId == null) { + // return sortId == 'recommend' + // ? `https://music.migu.cn/v3/music/playlist?page=${page}&from=migu` + // : `https://music.migu.cn/v3/music/playlist?sort=${sortId}&page=${page}&from=migu` + // } + // return `https://music.migu.cn/v3/music/playlist?tagId=${tagId}&page=${page}&from=migu` + if (tagId == null) { + // return `https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=1` + // return `https://c.musicapp.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=${this.limit_list}&start=${page}&templateVersion=5&type=${sortId}` + // https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?count=50&start=2&templateVersion=5&type=1 + return `https://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&columnId=${sortId}&startIndex=${(page - 1) * 10}` + } + // return `https://app.c.nf.migu.cn/MIGUM2.0/v2.0/content/getMusicData.do?area=2&count=${this.limit_list}&start=${page}&tags=${tagId}&templateVersion=5&type=3` + return `https://m.music.migu.cn/migu/remoting/playlist_bycolumnid_tag?playListType=2&type=1&tagId=${tagId}&startIndex=${(page - 1) * 10}` + }, + getSongListDetailUrl(id, page) { + return `https://app.c.nf.migu.cn/MIGUM2.0/v1.0/user/queryMusicListSongs.do?musicListId=${id}&pageNo=${page}&pageSize=${this.limit_song}` + }, + defaultHeaders: { + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1', + Referer: 'https://m.music.migu.cn/', + // language: 'Chinese', + // ua: 'Android_migu', + // mode: 'android', + // version: '6.8.5', + }, + + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + + getListDetailList(id, page, tryNum = 0) { + if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + // https://h5.nf.migu.cn/app/v4/p/share/playlist/index.html?id=184187437&channel=0146921 + + if (/playlist\/index\.html\?/.test(id)) { + id = id.replace(/.*(?:\?|&)id=(\d+)(?:&.*|$)/, '$1') + } else if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1') + + this._requestObj_listDetail = httpFetch(this.getSongListDetailUrl(id, page), { headers: this.defaultHeaders }) + return this._requestObj_listDetail.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum) + // console.log(JSON.stringify(body)) + // console.log(body) + return { + list: this.filterListDetail(body.list), + page, + limit: this.limit_song, + total: body.totalCount, + source: 'mg', + } + }) + }, + + getListDetailInfo(id, tryNum = 0) { + if (this._requestObj_listDetailInfo) this._requestObj_listDetailInfo.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + + if (this.cachedDetailInfo[id]) return Promise.resolve(this.cachedDetailInfo[id]) + this._requestObj_listDetailInfo = httpFetch(`https://c.musicapp.migu.cn/MIGUM3.0/resource/playlist/v2.0?playlistId=${id}`, { + headers: this.defaultHeaders, + }) + return this._requestObj_listDetailInfo.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.getListDetail(id, ++tryNum) + // console.log(JSON.stringify(body)) + // console.log(body) + const cachedDetailInfo = this.cachedDetailInfo[id] = { + name: body.data.title, + img: body.data.imgItem.img, + desc: body.data.summary, + author: body.data.ownerName, + play_count: this.formatPlayCount(body.data.opNumItem.playNum), + } + return cachedDetailInfo + }) + }, + + getListDetail(id, page) { // 获取歌曲列表内的音乐 + // https://h5.nf.migu.cn/app/v4/p/share/playlist/index.html?id=184187437&channel=0146921 + if (/playlist\/index\.html\?/.test(id)) { + id = id.replace(/.*(?:\?|&)id=(\d+)(?:&.*|$)/, '$1') + } else if ((/[?&:/]/.test(id))) id = id.replace(this.regExps.listDetailLink, '$1') + + return Promise.all([ + this.getListDetailList(id, page), + this.getListDetailInfo(id), + ]).then(([listData, info]) => { + listData.info = info + return listData + }) + }, + filterListDetail(rawList) { + // console.log(rawList) + let ids = new Set() + const list = [] + rawList.forEach(item => { + if (ids.has(item.songId)) return + ids.add(item.songId) + const types = [] + const _types = {} + item.rateFormats && item.rateFormats.forEach(type => { + let size + switch (type.formatType) { + case 'PQ': + size = sizeFormate(type.size) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + break + case 'HQ': + size = sizeFormate(type.size) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + break + case 'SQ': + size = sizeFormate(type.size) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + break + } + }) + + + list.push({ + singer: item.singer, + name: item.songName, + albumName: item.album, + albumId: item.albumId, + songmid: item.copyrightId, + copyrightId: item.copyrightId, + songId: item.songId, + source: 'mg', + interval: null, + img: item.albumImgs && item.albumImgs.length ? item.albumImgs[0].img : null, + lrc: null, + lrcUrl: item.lrcUrl, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + + // 获取列表数据 + getList(sortId, tagId, page, tryNum = 0) { + if (this._requestObj_list) this._requestObj_list.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_list = httpFetch(this.getSongListUrl(sortId, tagId, page), { + headers: this.defaultHeaders, + // headers: { + // sign: 'c3b7ae985e2206e97f1b2de8f88691e2', + // timestamp: 1578225871982, + // appId: 'yyapp2', + // mode: 'android', + // ua: 'Android_migu', + // version: '6.9.4', + // osVersion: 'android 7.0', + // 'User-Agent': 'okhttp/3.9.1', + // }, + }) + // return this._requestObj_list.promise.then(({ statusCode, body }) => { + // if (statusCode !== 200) return this.getList(sortId, tagId, page) + // let list = body.replace(/[\r\n]/g, '').match(this.regExps.list) + // if (!list) return Promise.reject('获取列表失败') + // return list.map(item => { + // let info = item.match(this.regExps.listInfo) + // return { + // play_count: info[4], + // id: info[2], + // author: '', + // name: info[3], + // time: '', + // img: info[1], + // grade: 0, + // desc: '', + // source: 'mg', + // } + // }) + // }) + return this._requestObj_list.promise.then(({ body }) => { + // console.log(body) + if (body.retCode !== '100000' || body.retMsg.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum) + return { + list: this.filterList(body.retMsg.playlist), + total: parseInt(body.retMsg.countSize), + page, + limit: this.limit_list, + source: 'mg', + } + }) + // return this._requestObj_list.promise.then(({ body }) => { + // if (body.retCode !== '100000') return this.getList(sortId, tagId, page, ++tryNum) + // // if (body.code !== '000000') return this.getList(sortId, tagId, page, ++tryNum) + // console.log(body) + // // return { + // // list: this.filterList(body.data.contentItemList[0].itemList), + // // total: parseInt(body.retMsg.countSize), + // // page, + // // limit: this.limit_list, + // // source: 'mg', + // // } + // }) + }, + filterList(rawData) { + return rawData.map(item => ({ + play_count: this.formatPlayCount(item.playCount), + id: item.playListId, + author: item.createName, + name: item.playListName, + time: item.createTime, + img: item.image, + grade: item.grade, + desc: item.summary, + source: 'mg', + })) + }, + + // 获取标签 + getTag(tryNum = 0) { + // if (this._requestObj_tags) this._requestObj_tags.cancelHttp() + // if (tryNum > 2) return Promise.reject(new Error('try max num')) + // this._requestObj_tags = httpFetch(this.tagsUrl, { headers: this.defaultHeaders }) + // return this._requestObj_tags.promise.then(({ body }) => { + // if (body.code !== this.successCode) return this.getTag(++tryNum) + // return this.filterTagInfo(body.columnInfo.contents) + // }) + return Promise.resolve(this.filterTagInfo(tagData.columnInfo.contents)) + }, + filterTagInfo(rawList) { + return { + hotTag: rawList[0].objectInfo.contents.map(item => ({ + id: item.objectInfo.tagId, + name: item.objectInfo.tagName, + source: 'mg', + })), + tags: rawList.slice(1).map(({ objectInfo }) => ({ + name: objectInfo.columnTitle, + list: objectInfo.contents.map(item => ({ + parent_id: objectInfo.columnId, + parent_name: objectInfo.columnTitle, + id: item.objectInfo.tagId, + name: item.objectInfo.tagName, + source: 'mg', + })), + })), + source: 'mg', + } + }, + getTags() { + return this.getTag() + }, +} + +// getList +// getTags +// getListDetail diff --git a/src/utils/music/options.js b/src/utils/music/options.js new file mode 100644 index 0000000..5f05969 --- /dev/null +++ b/src/utils/music/options.js @@ -0,0 +1,9 @@ +export const bHh = '624868746c' + +export const headers = { + 'User-Agent': 'lx-music mobile request', + [bHh]: [bHh], +} + + +export const timeout = 15000 diff --git a/src/utils/music/tx/api-test.js b/src/utils/music/tx/api-test.js new file mode 100644 index 0000000..4fb4ea8 --- /dev/null +++ b/src/utils/music/tx/api-test.js @@ -0,0 +1,25 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_messoer = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/tx/${songInfo.songmid}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, + getPic(songInfo) { + return { + promise: Promise.resolve(`https://y.gtimg.cn/music/photo_new/T002R500x500M000${songInfo.albumId}.jpg`), + } + }, +} + +export default api_messoer diff --git a/src/utils/music/tx/comment.js b/src/utils/music/tx/comment.js new file mode 100644 index 0000000..1367df3 --- /dev/null +++ b/src/utils/music/tx/comment.js @@ -0,0 +1,187 @@ +import { httpFetch } from '../../request' +import { dateFormat2 } from '../../' + +const emojis = { + e400846: '😘', + e400874: '😴', + e400825: '😃', + e400847: '😙', + e400835: '😍', + e400873: '😳', + e400836: '😎', + e400867: '😭', + e400832: '😊', + e400837: '😏', + e400875: '😫', + e400831: '😉', + e400855: '😡', + e400823: '😄', + e400862: '😨', + e400844: '😖', + e400841: '😓', + e400830: '😈', + e400828: '😆', + e400833: '😋', + e400822: '😀', + e400843: '😕', + e400829: '😇', + e400824: '😂', + e400834: '😌', + e400877: '😷', + e400132: '🍉', + e400181: '🍺', + e401067: '☕️', + e400186: '🥧', + e400343: '🐷', + e400116: '🌹', + e400126: '🍃', + e400613: '💋', + e401236: '❤️', + e400622: '💔', + e400637: '💣', + e400643: '💩', + e400773: '🔪', + e400102: '🌛', + e401328: '🌞', + e400420: '👏', + e400914: '🙌', + e400408: '👍', + e400414: '👎', + e401121: '✋', + e400396: '👋', + e400384: '👉', + e401115: '✊', + e400402: '👌', + e400905: '🙈', + e400906: '🙉', + e400907: '🙊', + e400562: '👻', + e400932: '🙏', + e400644: '💪', + e400611: '💉', + e400185: '🎁', + e400655: '💰', + e400325: '🐥', + e400612: '💊', + e400198: '🎉', + e401685: '⚡️', + e400631: '💝', + e400768: '🔥', + e400432: '👑', +} + +export default { + _requestObj: null, + _requestObj2: null, + async getComment({ songId }, page = 1, limit = 20) { + if (this._requestObj) this._requestObj.cancelHttp() + + const _requestObj = httpFetch('http://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', { + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)', + }, + form: { + uin: '0', + format: 'json', + cid: '205360772', + reqtype: '2', + biztype: '1', + topid: songId, + cmd: '8', + needmusiccrit: '1', + pagenum: page - 1, + pagesize: limit, + }, + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.code !== 0) throw new Error('获取评论失败') + // console.log(body, statusCode) + const comment = body.comment + return { + source: 'tx', + comments: this.filterComment(comment.commentlist), + total: comment.commenttotal, + page, + limit, + maxPage: Math.ceil(comment.commenttotal / limit) || 1, + } + }, + async getHotComment({ songId }, page = 1, limit = 100) { + if (this._requestObj2) this._requestObj2.cancelHttp() + + const _requestObj2 = httpFetch('http://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg', { + headers: { + 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)', + }, + form: { + uin: '0', + format: 'json', + cid: '205360772', + reqtype: '2', + biztype: '1', + topid: songId, + cmd: '9', + needmusiccrit: '1', + pagenum: page - 1, + pagesize: limit, + }, + }) + const { body, statusCode } = await _requestObj2.promise + if (statusCode != 200 || body.code !== 0) throw new Error('获取热门评论失败') + // console.log(body, statusCode) + const comment = body.comment + return { + source: 'tx', + comments: this.filterComment(comment.commentlist), + total: comment.commenttotal, + } + }, + replaceEmoji(msg) { + let rxp = /^\[em\](e\d+)\[\/em\]$/ + let result = msg.match(/\[em\]e\d+\[\/em\]/g) + if (!result) return msg + result = Array.from(new Set(result)) + for (let item of result) { + let code = item.replace(rxp, '$1') + msg = msg.replace(new RegExp(item.replace('[em]', '\\[em\\]').replace('[/em]', '\\[\\/em\\]'), 'g'), emojis[code] || '') + } + return msg + }, + filterComment(rawList) { + return rawList.map(item => { + let time = item.rootcommentid ? parseInt(item.rootcommentid.substring(item.rootcommentid.lastIndexOf('_') + 1) + '000') : null + if (item.middlecommentcontent) { + let firstItem = item.middlecommentcontent[0] + firstItem.avatarurl = item.avatarurl + firstItem.praisenum = item.praisenum + item.avatarurl = null + item.praisenum = null + item.middlecommentcontent.reverse() + } + return { + id: item.subcommentid, + rootId: item.rootcommentid, + text: item.rootcommentcontent ? this.replaceEmoji(item.rootcommentcontent).replace(/\\n/g, '\n').split('\n') : [], + time, + timeStr: time ? dateFormat2(time) : null, + userName: item.rootcommentnick ? item.rootcommentnick.substring(1) : '', + avatar: item.avatarurl, + userId: item.encrypt_rootcommentuin, + likedCount: item.praisenum, + reply: item.middlecommentcontent ? item.middlecommentcontent.map(c => { + let index = c.subcommentid.lastIndexOf('_') + return { + id: c.subcommentid, + text: this.replaceEmoji(c.subcommentcontent).replace(/\\n/g, '\n').split('\n'), + time: parseInt(c.subcommentid.substring(index + 1) + '000'), + timeStr: dateFormat2(parseInt(c.subcommentid.substring(index + 1) + '000')), + userName: c.replynick.substring(1), + avatar: c.avatarurl, + userId: c.encrypt_replyuin, + likedCount: c.praisenum, + } + }) : [], + } + }) + }, +} diff --git a/src/utils/music/tx/hotSearch.js b/src/utils/music/tx/hotSearch.js new file mode 100644 index 0000000..f1451e2 --- /dev/null +++ b/src/utils/music/tx/hotSearch.js @@ -0,0 +1,23 @@ +import { httpFetch } from '../../request' + +export default { + _requestObj: null, + async getList(retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('https://c.y.qq.com/splcloud/fcgi-bin/gethotkey.fcg', { + method: 'get', + headers: { + Referer: 'https://y.qq.com/portal/player.html', + }, + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.code !== 0) throw new Error('获取热搜词失败') + // console.log(body) + return { source: 'tx', list: this.filterList(body.data.hotkey) } + }, + filterList(rawList) { + return rawList.map(item => item.k) + }, +} diff --git a/src/utils/music/tx/index.js b/src/utils/music/tx/index.js new file mode 100644 index 0000000..6c1bd56 --- /dev/null +++ b/src/utils/music/tx/index.js @@ -0,0 +1,31 @@ +import leaderboard from './leaderboard' +import lyric from './lyric' +import songList from './songList' +import musicSearch from './musicSearch' +import { apis } from '../api-source' +import hotSearch from './hotSearch' +import comment from './comment' + +const tx = { + leaderboard, + songList, + musicSearch, + hotSearch, + comment, + + getMusicUrl(songInfo, type) { + return apis('tx').getMusicUrl(songInfo, type) + }, + getLyric(songInfo) { + // let singer = songInfo.singer.indexOf('、') > -1 ? songInfo.singer.split('、')[0] : songInfo.singer + return lyric.getLyric(songInfo.songmid) + }, + getPic(songInfo) { + return apis('tx').getPic(songInfo) + }, + getMusicDetailPageUrl(songInfo) { + return `https://y.qq.com/n/yqq/song/${songInfo.songmid}.html` + }, +} + +export default tx diff --git a/src/utils/music/tx/leaderboard.js b/src/utils/music/tx/leaderboard.js new file mode 100644 index 0000000..d798fdc --- /dev/null +++ b/src/utils/music/tx/leaderboard.js @@ -0,0 +1,255 @@ +import { httpGet, cancelHttp, httpFetch } from '../../request' +import { formatPlayTime, sizeFormate } from '../../index' + +let boardList = [{ id: 'tx__4', name: '流行指数榜', bangid: '4' }, { id: 'tx__26', name: '热歌榜', bangid: '26' }, { id: 'tx__27', name: '新歌榜', bangid: '27' }, { id: 'tx__62', name: '飙升榜', bangid: '62' }, { id: 'tx__58', name: '说唱榜', bangid: '58' }, { id: 'tx__57', name: '电音榜', bangid: '57' }, { id: 'tx__28', name: '网络歌曲榜', bangid: '28' }, { id: 'tx__5', name: '内地榜', bangid: '5' }, { id: 'tx__3', name: '欧美榜', bangid: '3' }, { id: 'tx__59', name: '香港地区榜', bangid: '59' }, { id: 'tx__16', name: '韩国榜', bangid: '16' }, { id: 'tx__60', name: '抖音排行榜', bangid: '60' }, { id: 'tx__29', name: '影视金曲榜', bangid: '29' }, { id: 'tx__17', name: '日本榜', bangid: '17' }, { id: 'tx__52', name: '腾讯音乐人原创榜', bangid: '52' }, { id: 'tx__36', name: 'K歌金曲榜', bangid: '36' }, { id: 'tx__61', name: '台湾地区榜', bangid: '61' }, { id: 'tx__63', name: 'DJ舞曲榜', bangid: '63' }, { id: 'tx__64', name: '综艺新歌榜', bangid: '64' }, { id: 'tx__65', name: '国风热歌榜', bangid: '65' }, { id: 'tx__66', name: 'ACG新歌榜', bangid: '66' }, { id: 'tx__67', name: '听歌识曲榜', bangid: '67' }, { id: 'tx__70', name: '达人音乐榜', bangid: '70' }] + +export default { + limit: 300, + list: [ + { + id: 'txlxzsb', + name: '流行榜', + bangid: 4, + }, + { + id: 'txrgb', + name: '热歌榜', + bangid: 26, + }, + { + id: 'txwlhgb', + name: '网络榜', + bangid: 28, + }, + { + id: 'txdyb', + name: '抖音榜', + bangid: 60, + }, + { + id: 'txndb', + name: '内地榜', + bangid: 5, + }, + { + id: 'txxgb', + name: '香港榜', + bangid: 59, + }, + { + id: 'txtwb', + name: '台湾榜', + bangid: 61, + }, + { + id: 'txoumb', + name: '欧美榜', + bangid: 3, + }, + { + id: 'txhgb', + name: '韩国榜', + bangid: 16, + }, + { + id: 'txrbb', + name: '日本榜', + bangid: 17, + }, + { + id: 'txtybb', + name: 'YouTube榜', + bangid: 128, + }, + ], + getUrl(id, period, limit) { + return `https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&inCharset=utf8&outCharset=utf-8&platform=yqq.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({ + comm: { + cv: 1602, + ct: 20, + }, + toplist: { + module: 'musicToplist.ToplistInfoServer', + method: 'GetDetail', + param: { + topid: id, + num: limit, + period, + }, + }, + }))}` + }, + regExps: { + periodList: /<i class="play_cover__btn c_tx_link js_icon_play" data-listkey=".+?" data-listname=".+?" data-tid=".+?" data-date=".+?" .+?<\/i>/g, + period: /data-listname="(.+?)" data-tid=".*?\/(.+?)" data-date="(.+?)" .+?<\/i>/, + }, + periods: {}, + periodUrl: 'https://c.y.qq.com/node/pc/wk_v15/top.html', + _requestBoardsObj: null, + _cancelRequestObj: null, + _cancelPromiseCancelFn: null, + getBoardsData() { + if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp() + this._requestBoardsObj = httpFetch('https://c.y.qq.com/v8/fcg-bin/fcg_myqq_toplist.fcg?g_tk=1928093487&inCharset=utf-8&outCharset=utf-8¬ice=0&format=json&uin=0&needNewCode=1&platform=h5') + return this._requestBoardsObj.promise + }, + getData(url) { + if (this._cancelRequestObj != null) { + cancelHttp(this._cancelRequestObj) + this._cancelPromiseCancelFn(new Error('取消http请求')) + } + return new Promise((resolve, reject) => { + this._cancelPromiseCancelFn = reject + this._cancelRequestObj = httpGet(url, (err, resp, body) => { + this._cancelRequestObj = null + this._cancelPromiseCancelFn = null + if (err) { + console.log(err) + reject(err) + } + resolve(body) + }) + }) + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + filterData(rawList) { + // console.log(rawList) + return rawList.map(item => { + let types = [] + let _types = {} + if (item.file.size_128mp3 !== 0) { + let size = sizeFormate(item.file.size_128mp3) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + if (item.file.size_320mp3 !== 0) { + let size = sizeFormate(item.file.size_320mp3) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + if (item.file.size_ape !== 0) { + let size = sizeFormate(item.file.size_ape) + types.push({ type: 'ape', size }) + _types.ape = { + size, + } + } + if (item.file.size_flac !== 0) { + let size = sizeFormate(item.file.size_flac) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + // types.reverse() + return { + singer: this.getSinger(item.singer), + name: item.title, + albumName: item.album.title, + albumId: item.album.mid, + source: 'tx', + interval: formatPlayTime(item.interval), + songId: item.id, + albumMid: item.album.mid, + strMediaMid: item.file.media_mid, + songmid: item.mid, + img: (item.album.name === '' || item.album.name === '空') + ? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg` + : `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.album.mid}.jpg`, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + getPeriods(bangid) { + return this.getData(this.periodUrl).then(html => { + let result = html.match(this.regExps.periodList) + if (!result) return Promise.reject() + result.forEach(item => { + let result = item.match(this.regExps.period) + if (!result) return + this.periods[result[2]] = { + name: result[1], + bangid: result[2], + period: result[3], + } + }) + const info = this.periods[bangid] + return info && info.period + }) + }, + filterBoardsData(rawList) { + // console.log(rawList) + let list = [] + for (const board of rawList) { + // 排除 MV榜 + if (board.id == 201) continue + + if (board.topTitle.startsWith('巅峰榜·')) { + board.topTitle = board.topTitle.substring(4, board.topTitle.length) + } + if (!board.topTitle.endsWith('榜')) board.topTitle += '榜' + list.push({ + id: 'tx__' + board.id, + name: board.topTitle, + bangid: String(board.id), + }) + } + return list + }, + async getBoards(retryNum = 0) { + // if (++retryNum > 3) return Promise.reject(new Error('try max num')) + // let response + // try { + // response = await this.getBoardsData() + // } catch (error) { + // return this.getBoards(retryNum) + // } + // // console.log(response.body) + // if (response.statusCode !== 200 || response.body.code !== 0) return this.getBoards(retryNum) + // const list = this.filterBoardsData(response.body.data.topList) + // // console.log(list) + // this.list = list + // return { + // list, + // source: 'tx', + // } + this.list = boardList + return { + list: boardList, + source: 'tx', + } + }, + getList(bangid, page, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + bangid = parseInt(bangid) + let info = this.periods[bangid] + let p = info ? Promise.resolve(info.period) : this.getPeriods(bangid) + return p.then(period => { + return this.getData(this.getUrl(bangid, period, this.limit)).then(data => { + // console.log(data) + if (data.code !== 0) return this.getList(bangid, page, retryNum) + return { + total: data.toplist.data.songInfoList.length, + list: this.filterData(data.toplist.data.songInfoList), + limit: this.limit, + page: 1, + source: 'tx', + } + }) + }) + }, +} diff --git a/src/utils/music/tx/lyric.js b/src/utils/music/tx/lyric.js new file mode 100644 index 0000000..a371a6e --- /dev/null +++ b/src/utils/music/tx/lyric.js @@ -0,0 +1,23 @@ +import { httpFetch } from '../../request' +import { b64DecodeUnicode, decodeName } from '../../index' + +export default { + regexps: { + matchLrc: /.+"lyric":"([\w=+/]*)".+/, + }, + getLyric(songmid) { + const requestObj = httpFetch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&platform=yqq`, { + headers: { + Referer: 'https://y.qq.com/portal/player.html', + }, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.code != 0) return Promise.reject(new Error('获取歌词失败')) + return { + lyric: decodeName(b64DecodeUnicode(body.lyric)), + tlyric: decodeName(b64DecodeUnicode(body.trans)), + } + }) + return requestObj + }, +} diff --git a/src/utils/music/tx/musicSearch.js b/src/utils/music/tx/musicSearch.js new file mode 100644 index 0000000..db63854 --- /dev/null +++ b/src/utils/music/tx/musicSearch.js @@ -0,0 +1,107 @@ +// import '../../polyfill/array.find' +// import jshtmlencode from 'js-htmlencode' +import { httpFetch } from '../../request' +import { formatPlayTime, sizeFormate } from '../../index' +// import { debug } from '../../utils/env' +// import { formatSinger } from './util' + +let searchRequest +export default { + limit: 30, + total: 0, + page: 0, + allPage: 1, + successCode: 0, + musicSearch(str, page, limit, retryNum = 0) { + if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp() + if (retryNum > 5) return Promise.reject(new Error('搜索失败')) + searchRequest = httpFetch(`https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=sizer.yqq.song_next&searchid=49252838123499591&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=${page}&n=${limit}&w=${encodeURIComponent(str)}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0`) + // searchRequest = httpFetch(`http://ioscdn.kugou.com/api/v3/search/song?keyword=${encodeURIComponent(str)}&page=${page}&pagesize=${this.limit}&showtype=10&plat=2&version=7910&tag=1&correct=1&privilege=1&sver=5`) + return searchRequest.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.musicSearch(str, page, limit, ++retryNum) + return body.data + }) + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + handleResult(rawList) { + // console.log(rawData) + return rawList.map(item => { + let types = [] + let _types = {} + if (item.file.size_128mp3 !== 0) { + let size = sizeFormate(item.file.size_128mp3) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + if (item.file.size_320mp3 !== 0) { + let size = sizeFormate(item.file.size_320mp3) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + if (item.file.size_ape !== 0) { + let size = sizeFormate(item.file.size_ape) + types.push({ type: 'ape', size }) + _types.ape = { + size, + } + } + if (item.file.size_flac !== 0) { + let size = sizeFormate(item.file.size_flac) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + // types.reverse() + return { + singer: this.getSinger(item.singer), + name: item.title, + albumName: item.album.title, + albumId: item.album.mid, + source: 'tx', + interval: formatPlayTime(item.interval), + songId: item.id, + albumMid: item.album.mid, + strMediaMid: item.file.strMediaMid, + songmid: item.mid, + img: (item.album.name === '' || item.album.name === '空') + ? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg` + : `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.album.mid}.jpg`, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + search(str, page = 1, { limit } = {}) { + if (limit == null) limit = this.limit + // http://newlyric.kuwo.cn/newlyric.lrc?62355680 + return this.musicSearch(str, page, limit).then(({ song }) => { + let list = this.handleResult(song.list) + + this.total = song.totalnum + this.page = page + this.allPage = Math.ceil(this.total / limit) + + return Promise.resolve({ + list, + allPage: this.allPage, + limit, + total: this.total, + source: 'tx', + }) + }) + }, +} diff --git a/src/utils/music/tx/songList.js b/src/utils/music/tx/songList.js new file mode 100644 index 0000000..f366c04 --- /dev/null +++ b/src/utils/music/tx/songList.js @@ -0,0 +1,302 @@ +import { httpFetch } from '../../request' +import { formatPlayTime, sizeFormate } from '../../index' +import jshtmlencode from 'js-htmlencode' + +export default { + _requestObj_tags: null, + _requestObj_hotTags: null, + _requestObj_list: null, + _requestObj_listDetail: null, + _requestObj_listDetailLink: null, + limit_list: 36, + limit_song: 100000, + successCode: 0, + sortList: [ + { + name: '最热', + tid: 'hot', + id: 5, + }, + { + name: '最新', + tid: 'new', + id: 2, + }, + ], + regExps: { + hotTagHtml: /class="c_bg_link js_tag_item" data-id="\w+">.+?<\/a>/g, + hotTag: /data-id="(\w+)">(.+?)<\/a>/, + + // https://y.qq.com/n/yqq/playlist/7217720898.html + // https://i.y.qq.com/n2/m/share/details/taoge.html?platform=11&appshare=android_qq&appversion=9050006&id=7217720898&ADTAG=qfshare + listDetailLink1: /^.+(?:\?|&)id=(\d+)(?:&.*$|#.*$|$)/, + listDetailLink2: /^.+\/(\d+)\.html(?:\?.*|&.*$|#.*$|$)/, + }, + tagsUrl: 'https://u.y.qq.com/cgi-bin/musicu.fcg?loginUin=0&hostUin=0&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=wk_v15.json&needNewCode=0&data=%7B%22tags%22%3A%7B%22method%22%3A%22get_all_categories%22%2C%22param%22%3A%7B%22qq%22%3A%22%22%7D%2C%22module%22%3A%22playlist.PlaylistAllCategoriesServer%22%7D%7D', + hotTagUrl: 'https://c.y.qq.com/node/pc/wk_v15/category_playlist.html', + getListUrl(sortId, id, page) { + return id + ? `https://u.y.qq.com/cgi-bin/musicu.fcg?loginUin=0&hostUin=0&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=wk_v15.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({ + comm: { cv: 1602, ct: 20 }, + playlist: { + method: 'get_category_content', + param: { + titleid: id, + caller: '0', + category_id: id, + size: this.limit_list, + page: page - 1, + use_page: 1, + }, + module: 'playlist.PlayListCategoryServer', + }, + }))}` + : `https://u.y.qq.com/cgi-bin/musicu.fcg?loginUin=0&hostUin=0&format=json&inCharset=utf-8&outCharset=utf-8¬ice=0&platform=wk_v15.json&needNewCode=0&data=${encodeURIComponent(JSON.stringify({ + comm: { cv: 1602, ct: 20 }, + playlist: { + method: 'get_playlist_by_tag', + param: { id: 10000000, sin: this.limit_list * (page - 1), size: this.limit_list, order: sortId, cur_page: page }, + module: 'playlist.PlayListPlazaServer', + }, + }))}` + }, + getListDetailUrl(id) { + return `https://c.y.qq.com/qzone/fcg-bin/fcg_ucc_getcdinfo_byids_cp.fcg?type=1&json=1&utf8=1&onlysong=0&new_format=1&disstid=${id}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0` + }, + + // http://nplserver.kuwo.cn/pl.svc?op=getlistinfo&pid=2849349915&pn=0&rn=100&encode=utf8&keyset=pl2012&identity=kuwo&pcmp4=1&vipver=MUSIC_9.0.5.0_W1&newver=1 + // 获取标签 + getTag(tryNum = 0) { + if (this._requestObj_tags) this._requestObj_tags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_tags = httpFetch(this.tagsUrl) + return this._requestObj_tags.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.getTag(++tryNum) + return this.filterTagInfo(body.tags.data.v_group) + }) + }, + // 获取标签 + getHotTag(tryNum = 0) { + if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_hotTags = httpFetch(this.hotTagUrl) + return this._requestObj_hotTags.promise.then(({ statusCode, body }) => { + if (statusCode !== 200) return this.getHotTag(++tryNum) + return this.filterInfoHotTag(body) + }) + }, + filterInfoHotTag(html) { + let hotTag = html.match(this.regExps.hotTagHtml) + const hotTags = [] + if (!hotTag) return hotTags + + hotTag.forEach(tagHtml => { + let result = tagHtml.match(this.regExps.hotTag) + if (!result) return + hotTags.push({ + id: parseInt(result[1]), + name: result[2], + source: 'tx', + }) + }) + return hotTags + }, + filterTagInfo(rawList) { + return rawList.map(type => ({ + name: type.group_name, + list: type.v_item.map(item => ({ + parent_id: type.group_id, + parent_name: type.group_name, + id: item.id, + name: item.name, + source: 'tx', + })), + })) + }, + + // 获取列表数据 + getList(sortId, tagId, page, tryNum = 0) { + if (this._requestObj_list) this._requestObj_list.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_list = httpFetch( + this.getListUrl(sortId, tagId, page), + ) + return this._requestObj_list.promise.then(({ body }) => { + if (body.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum) + return tagId ? this.filterList2(body.playlist.data, page) : this.filterList(body.playlist.data, page) + }) + }, + + + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + filterList(data, page) { + return { + list: data.v_playlist.map(item => ({ + play_count: this.formatPlayCount(item.access_num), + id: item.tid, + author: item.creator_info.nick, + name: item.title, + // time: item.publish_time, + img: item.cover_url_medium, + // grade: item.favorcnt / 10, + desc: item.desc, + source: 'tx', + })), + total: data.total, + page, + limit: this.limit_list, + source: 'tx', + } + }, + filterList2({ content }, page) { + // console.log(content.v_item) + return { + list: content.v_item.map(({ basic }) => ({ + play_count: this.formatPlayCount(basic.play_cnt), + id: basic.tid, + author: basic.creator.nick, + name: basic.title, + // time: basic.publish_time, + img: basic.cover.medium_url || basic.cover.default_url, + // grade: basic.favorcnt / 10, + desc: jshtmlencode.htmlDecode(basic.desc).replace(/<br>/g, '\n'), + source: 'tx', + })), + total: content.total_cnt, + page, + limit: this.limit_list, + source: 'tx', + } + }, + + async handleParseId(link, retryNum = 0) { + if (this._requestObj_listDetailLink) this._requestObj_listDetailLink.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('link try max num')) + + this._requestObj_listDetailLink = httpFetch(link) + const { headers: { location }, statusCode } = await this._requestObj_listDetailLink.promise + // console.log(headers) + if (statusCode > 400) return this.handleParseId(link, ++retryNum) + return location == null ? link : location + }, + + // 获取歌曲列表内的音乐 + async getListDetail(id, tryNum = 0) { + if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + + if ((/[?&:/]/.test(id))) { + let regx = /\/\/i\.y\.qq\.com/.test(id) ? this.regExps.listDetailLink1 : this.regExps.listDetailLink2 + if (!regx.test(id)) { + id = await this.handleParseId(id) + regx = this.regExps.listDetailLink1 + console.log(id) + } + id = id.replace(regx, '$1') + // console.log(id) + } + + this._requestObj_listDetail = httpFetch(this.getListDetailUrl(id), { + headers: { + Origin: 'https://y.qq.com', + Referer: `https://y.qq.com/n/yqq/playsquare/${id}.html`, + }, + }) + const { body } = await this._requestObj_listDetail.promise + + if (body.code !== this.successCode) return this.getListDetail(id, ++tryNum) + const cdlist = body.cdlist[0] + return { + list: this.filterListDetail(cdlist.songlist), + page: 1, + limit: cdlist.songlist.length + 1, + total: cdlist.songlist.length, + source: 'tx', + info: { + name: cdlist.dissname, + img: cdlist.logo, + desc: jshtmlencode.htmlDecode(cdlist.desc).replace(/<br>/g, '\n'), + author: cdlist.nickname, + play_count: this.formatPlayCount(cdlist.visitnum), + }, + } + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + filterListDetail(rawList) { + // console.log(rawList) + return rawList.map(item => { + let types = [] + let _types = {} + if (item.file.size_128mp3 !== 0) { + let size = sizeFormate(item.file.size_128mp3) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + if (item.file.size_320mp3 !== 0) { + let size = sizeFormate(item.file.size_320mp3) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + if (item.file.size_ape !== 0) { + let size = sizeFormate(item.file.size_ape) + types.push({ type: 'ape', size }) + _types.ape = { + size, + } + } + if (item.file.size_flac !== 0) { + let size = sizeFormate(item.file.size_flac) + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + } + // types.reverse() + return { + singer: this.getSinger(item.singer), + name: item.title, + albumName: item.album.title, + albumId: item.album.mid, + source: 'tx', + interval: formatPlayTime(item.interval), + songId: item.id, + albumMid: item.album.mid, + strMediaMid: item.file.media_mid, + songmid: item.mid, + img: (item.album.name === '' || item.album.name === '空') + ? `https://y.gtimg.cn/music/photo_new/T001R500x500M000${item.singer[0].mid}.jpg` + : `https://y.gtimg.cn/music/photo_new/T002R500x500M000${item.album.mid}.jpg`, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + } + }) + }, + getTags() { + return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag, source: 'tx' })) + }, +} + +// getList +// getTags +// getListDetail diff --git a/src/utils/music/tx/tipSearch.js b/src/utils/music/tx/tipSearch.js new file mode 100644 index 0000000..23f397e --- /dev/null +++ b/src/utils/music/tx/tipSearch.js @@ -0,0 +1,30 @@ +import { httpFetch } from '../../request' + + +export default { + regExps: { + relWord: /RELWORD=(.+)/, + }, + requestObj: null, + tempSearch(str) { + this.cancelTempSearch() + this.requestObj = httpFetch(`https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?is_xml=0&format=json&key=${encodeURIComponent(str)}&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0`, { + headers: { + Referer: 'https://y.qq.com/portal/player.html', + }, + }) + return this.requestObj.promise.then(({ statusCode, body }) => { + if (statusCode != 200 || body.code != 0) return Promise.reject(new Error('请求失败')) + return body.data + }) + }, + handleResult(rawData) { + return rawData.map(info => `${info.name} - ${info.singer}`) + }, + cancelTempSearch() { + if (this.requestObj && this.requestObj.cancelHttp) this.requestObj.cancelHttp() + }, + async search(str) { + return this.tempSearch(str).then(result => this.handleResult(result.song.itemlist)) + }, +} diff --git a/src/utils/music/utils.js b/src/utils/music/utils.js new file mode 100644 index 0000000..b7ba8e5 --- /dev/null +++ b/src/utils/music/utils.js @@ -0,0 +1,21 @@ +// import crypto from 'crypto' + +/** + * 获取音乐音质 + * @param {*} info + * @param {*} type + */ + +const types = ['flac', 'wav', 'ape', '320k', '192k', '128k'] +export const getMusicType = (info, type) => { + const list = global.globalObj.qualityList[info.source] + if (!list) return '128k' + if (!list.includes(type)) type = list[list.length - 1] + const rangeType = types.slice(types.indexOf(type)) + for (const type of rangeType) { + if (info._types[type]) return type + } + return '128k' +} + +// export const toMD5 = str => crypto.createHash('md5').update(str).digest('hex') diff --git a/src/utils/music/wy/api-test.js b/src/utils/music/wy/api-test.js new file mode 100644 index 0000000..42a3b49 --- /dev/null +++ b/src/utils/music/wy/api-test.js @@ -0,0 +1,44 @@ +import { httpFetch } from '../../request' +import { requestMsg } from '../../message' +import { headers, timeout } from '../options' + +const api_test = { + getMusicUrl(songInfo, type) { + const requestObj = httpFetch(`http://ts.tempmusic.tk/url/wy/${songInfo.songmid}/${type}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve({ type, url: body.data }) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, +/* getPic(songInfo) { + const requestObj = httpFetch(`http://localhost:3100/pic/wy/${songInfo.songmid}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, + getLyric(songInfo) { + const requestObj = httpFetch(`http://localhost:3100/lrc/wy/${songInfo.songmid}`, { + method: 'get', + timeout, + headers, + family: 4, + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + return body.code === 0 ? Promise.resolve(body.data) : Promise.reject(new Error(requestMsg.fail)) + }) + return requestObj + }, */ +} + +export default api_test diff --git a/src/utils/music/wy/comment.js b/src/utils/music/wy/comment.js new file mode 100644 index 0000000..0847a44 --- /dev/null +++ b/src/utils/music/wy/comment.js @@ -0,0 +1,138 @@ +import { httpFetch } from '../../request' +import { weapi } from './utils/crypto' +import { dateFormat2 } from '../../' + +let cursorTools = { + cache: {}, + getCursor(id, page, limit) { + let cacheData = this.cache[id] + if (!cacheData) cacheData = this.cache[id] = {} + let orderType + let cursor + let offset + if (page == 1) { + cacheData.page = 1 + cursor = cacheData.cursor = cacheData.prevCursor = Date.now() + orderType = 1 + offset = 0 + } else if (cacheData.page) { + cursor = cacheData.cursor + if (page > cacheData.page) { + orderType = 1 + offset = (page - cacheData.page - 1) * limit + } else if (page < cacheData.page) { + orderType = 0 + offset = (cacheData.page - page - 1) * limit + } else { + cursor = cacheData.cursor = cacheData.prevCursor + offset = cacheData.offset + orderType = cacheData.orderType + } + } + return { + orderType, + cursor, + offset, + } + }, + setCursor(id, cursor, orderType, offset, page) { + let cacheData = this.cache[id] + if (!cacheData) cacheData = this.cache[id] = {} + cacheData.prevCursor = cacheData.cursor + cacheData.cursor = cursor + cacheData.orderType = orderType + cacheData.offset = offset + cacheData.page = page + }, +} + +export default { + _requestObj: null, + _requestObj2: null, + async getComment({ songmid }, page = 1, limit = 20) { + if (this._requestObj) this._requestObj.cancelHttp() + + const id = 'R_SO_4_' + songmid + + const cursorInfo = cursorTools.getCursor(songmid, page, limit) + + const _requestObj = httpFetch('https://music.163.com/weapi/comment/resource/comments/get', { + method: 'post', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + origin: 'https://music.163.com', + Refere: 'http://music.163.com/', + }, + form: weapi({ + cursor: cursorInfo.cursor, + offset: cursorInfo.offset, + orderType: cursorInfo.orderType, + pageNo: page, + pageSize: limit, + rid: id, + threadId: id, + }), + }) + const { body, statusCode } = await _requestObj.promise + // console.log(body) + if (statusCode != 200 || body.code !== 200) throw new Error('获取评论失败') + cursorTools.setCursor(songmid, body.data.cursor, cursorInfo.orderType, cursorInfo.offset, page) + return { source: 'wy', comments: this.filterComment(body.data.comments), total: body.data.totalCount, page, limit, maxPage: Math.ceil(body.data.totalCount / limit) || 1 } + }, + async getHotComment({ songmid }, page = 1, limit = 100) { + if (this._requestObj2) this._requestObj2.cancelHttp() + + const id = 'R_SO_4_' + songmid + + const _requestObj2 = httpFetch('https://music.163.com/weapi/comment/resource/comments/get', { + method: 'post', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + origin: 'https://music.163.com', + Refere: 'http://music.163.com/', + }, + form: weapi({ + cursor: Date.now().toString(), + offset: 0, + orderType: 1, + pageNo: page, + pageSize: limit, + rid: id, + threadId: id, + }), + }) + const { body, statusCode } = await _requestObj2.promise + if (statusCode != 200 || body.code !== 200) throw new Error('获取热门评论失败') + // console.log(body) + return { source: 'wy', comments: this.filterComment(body.data.hotComments) } + }, + filterComment(rawList) { + return rawList.map(item => { + let data = { + id: item.commentId, + text: item.content ? item.content.split('\n') : '', + time: item.time ? item.time : '', + timeStr: item.time ? dateFormat2(item.time) : '', + userName: item.user.nickname, + avatar: item.user.avatarUrl, + userId: item.user.userId, + likedCount: item.likedCount, + reply: [], + } + + let replyData = item.beReplied && item.beReplied[0] + return replyData ? { + id: item.commentId, + rootId: replyData.beRepliedCommentId, + text: replyData.content ? replyData.content.split('\n') : '', + time: item.time, + timeStr: null, + userName: replyData.user.nickname, + avatar: replyData.user.avatarUrl, + userId: replyData.user.userId, + likedCount: null, + reply: [data], + } : data + }) + }, +} diff --git a/src/utils/music/wy/hotSearch.js b/src/utils/music/wy/hotSearch.js new file mode 100644 index 0000000..5ee4ffa --- /dev/null +++ b/src/utils/music/wy/hotSearch.js @@ -0,0 +1,26 @@ +import { httpFetch } from '../../request' +import { weapi } from './utils/crypto' + +export default { + _requestObj: null, + async getList(retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('https://music.163.com/weapi/search/hot', { + method: 'post', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + origin: 'https://music.163.com', + }, + form: weapi({ type: 1111 }), + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.code !== 200) throw new Error('获取热搜词失败') + // console.log(body) + return { source: 'wy', list: this.filterList(body.result.hots) } + }, + filterList(rawList) { + return rawList.map(item => item.first) + }, +} diff --git a/src/utils/music/wy/index.js b/src/utils/music/wy/index.js new file mode 100644 index 0000000..7312243 --- /dev/null +++ b/src/utils/music/wy/index.js @@ -0,0 +1,32 @@ +import leaderboard from './leaderboard' +import { apis } from '../api-source' +import getLyric from './lyric' +import getMusicInfo from './musicInfo' +import musicSearch from './musicSearch' +import songList from './songList' +import hotSearch from './hotSearch' +import comment from './comment' + +const wy = { + leaderboard, + musicSearch, + songList, + hotSearch, + comment, + getMusicUrl(songInfo, type) { + return apis('wy').getMusicUrl(songInfo, type) + }, + getLyric(songInfo) { + return getLyric(songInfo.songmid) + }, + getPic(songInfo) { + const requestObj = getMusicInfo(songInfo.songmid) + requestObj.promise = requestObj.promise.then(info => info.al.picUrl) + return requestObj + }, + getMusicDetailPageUrl(songInfo) { + return `https://music.163.com/#/song?id=${songInfo.songmid}` + }, +} + +export default wy diff --git a/src/utils/music/wy/leaderboard.js b/src/utils/music/wy/leaderboard.js new file mode 100644 index 0000000..dd6aa60 --- /dev/null +++ b/src/utils/music/wy/leaderboard.js @@ -0,0 +1,202 @@ +import { weapi } from './utils/crypto' +import { httpFetch } from '../../request' +import musicDetailApi from './musicDetail' + +const topList = [ + { id: 'wy__19723756', bangid: '19723756', name: '云音乐飙升榜' }, + { id: 'wy__3778678', bangid: '3778678', name: '云音乐热歌榜' }, + { id: 'wy__3779629', bangid: '3779629', name: '云音乐新歌榜' }, + { id: 'wy__2884035', bangid: '2884035', name: '云音乐原创榜' }, + { id: 'wy__2250011882', bangid: '2250011882', name: '抖音排行榜' }, + { id: 'wy__1978921795', bangid: '1978921795', name: '云音乐电音榜' }, + { id: 'wy__4395559', bangid: '4395559', name: '华语金曲榜' }, + { id: 'wy__71384707', bangid: '71384707', name: '云音乐古典音乐榜' }, + { id: 'wy__10520166', bangid: '10520166', name: '云音乐国电榜' }, + { id: 'wy__2006508653', bangid: '2006508653', name: '电竞音乐榜' }, + { id: 'wy__991319590', bangid: '991319590', name: '云音乐说唱榜' }, + { id: 'wy__180106', bangid: '180106', name: 'UK排行榜周榜' }, + { id: 'wy__60198', bangid: '60198', name: '美国Billboard周榜' }, + { id: 'wy__21845217', bangid: '21845217', name: 'KTV嗨榜' }, + { id: 'wy__11641012', bangid: '11641012', name: 'iTunes榜' }, + { id: 'wy__120001', bangid: '120001', name: 'Hit FM Top榜' }, + { id: 'wy__60131', bangid: '60131', name: '日本Oricon周榜' }, + { id: 'wy__3733003', bangid: '3733003', name: '韩国Melon排行榜周榜' }, + { id: 'wy__60255', bangid: '60255', name: '韩国Mnet排行榜周榜' }, + { id: 'wy__46772709', bangid: '46772709', name: '韩国Melon原声周榜' }, + { id: 'wy__64016', bangid: '64016', name: '中国TOP排行榜(内地榜)' }, + { id: 'wy__112504', bangid: '112504', name: '中国TOP排行榜(港台榜)' }, + { id: 'wy__3112516681', bangid: '3112516681', name: '中国新乡村音乐排行榜' }, + { id: 'wy__10169002', bangid: '10169002', name: '香港电台中文歌曲龙虎榜' }, + { id: 'wy__27135204', bangid: '27135204', name: '法国 NRJ EuroHot 30周榜' }, + { id: 'wy__1899724', bangid: '1899724', name: '中国嘻哈榜' }, + { id: 'wy__112463', bangid: '112463', name: '台湾Hito排行榜' }, + { id: 'wy__3812895', bangid: '3812895', name: 'Beatport全球电子舞曲榜' }, + { id: 'wy__2617766278', bangid: '2617766278', name: '新声榜' }, + { id: 'wy__745956260', bangid: '745956260', name: '云音乐韩语榜' }, + { id: 'wy__2847251561', bangid: '2847251561', name: '说唱TOP榜' }, + { id: 'wy__2023401535', bangid: '2023401535', name: '英国Q杂志中文版周榜' }, + { id: 'wy__2809513713', bangid: '2809513713', name: '云音乐欧美热歌榜' }, + { id: 'wy__2809577409', bangid: '2809577409', name: '云音乐欧美新歌榜' }, + { id: 'wy__71385702', bangid: '71385702', name: '云音乐ACG音乐榜' }, + { id: 'wy__3001835560', bangid: '3001835560', name: '云音乐ACG动画榜' }, + { id: 'wy__3001795926', bangid: '3001795926', name: '云音乐ACG游戏榜' }, + { id: 'wy__3001890046', bangid: '3001890046', name: '云音乐ACG VOCALOID榜' }, +] + +export default { + limit: 100000, + list: [ + { + id: 'wybsb', + name: '飙升榜', + bangid: '19723756', + }, + { + id: 'wyrgb', + name: '热歌榜', + bangid: '3778678', + }, + { + id: 'wyxgb', + name: '新歌榜', + bangid: '3779629', + }, + { + id: 'wyycb', + name: '原创榜', + bangid: '2884035', + }, + { + id: 'wygdb', + name: '古典榜', + bangid: '71384707', + }, + { + id: 'wydouyb', + name: '抖音榜', + bangid: '2250011882', + }, + { + id: 'wyhyb', + name: '韩语榜', + bangid: '745956260', + }, + { + id: 'wydianyb', + name: '电音榜', + bangid: '1978921795', + }, + { + id: 'wydjb', + name: '电竞榜', + bangid: '2006508653', + }, + { + id: 'wyktvbb', + name: 'KTV唛榜', + bangid: '21845217', + }, + ], + getUrl(id) { + return `https://music.163.com/discover/toplist?id=${id}` + }, + regExps: { + list: /<textarea id="song-list-pre-data" style="display:none;">(.+?)<\/textarea>/, + }, + _requestBoardsObj: null, + _requestBoardsDetailObj: null, + getBoardsData() { + if (this._requestBoardsObj) this._requestBoardsObj.cancelHttp() + this._requestBoardsObj = httpFetch('https://music.163.com/weapi/toplist', { + method: 'post', + form: weapi({}), + }) + return this._requestBoardsObj.promise + }, + getData(id) { + if (this._requestBoardsDetailObj) this._requestBoardsDetailObj.cancelHttp() + this._requestBoardsDetailObj = httpFetch('https://music.163.com/weapi/v3/playlist/detail', { + method: 'post', + form: weapi({ + id, + n: 100000, + p: 1, + }), + }) + return this._requestBoardsDetailObj.promise + }, + + filterBoardsData(rawList) { + // console.log(rawList) + let list = [] + for (const board of rawList) { + // 排除 MV榜 + // if (board.id == 201) continue + list.push({ + id: 'wy__' + board.id, + name: board.name, + bangid: String(board.id), + }) + } + return list + }, + async getBoards(retryNum = 0) { + // if (++retryNum > 3) return Promise.reject(new Error('try max num')) + // let response + // try { + // response = await this.getBoardsData() + // } catch (error) { + // return this.getBoards(retryNum) + // } + // console.log(response.body) + // if (response.statusCode !== 200 || response.body.code !== 200) return this.getBoards(retryNum) + // const list = this.filterBoardsData(response.body.list) + // console.log(list) + // console.log(JSON.stringify(list)) + // this.list = list + // return { + // list, + // source: 'wy', + // } + this.list = topList + return { + list: topList, + source: 'wy', + } + }, + async getList(bangid, page, retryNum = 0) { + if (++retryNum > 6) return Promise.reject(new Error('try max num')) + // console.log(bangid) + let resp + try { + resp = await this.getData(bangid) + } catch (err) { + if (err.message == 'try max num') { + throw err + } else { + return this.getList(bangid, page, retryNum) + } + } + if (resp.statusCode !== 200 || resp.body.code !== 200) return this.getList(bangid, page, retryNum) + // console.log(resp.body) + let musicDetail + try { + musicDetail = await musicDetailApi.getList(resp.body.playlist.trackIds.map(trackId => trackId.id)) + } catch (err) { + console.log(err) + if (err.message == 'try max num') { + throw err + } else { + return this.getList(bangid, page, retryNum) + } + } + // console.log(musicDetail) + return { + total: musicDetail.list.length, + list: musicDetail.list, + limit: this.limit, + page, + source: 'wy', + } + }, +} diff --git a/src/utils/music/wy/lyric.js b/src/utils/music/wy/lyric.js new file mode 100644 index 0000000..301a2bb --- /dev/null +++ b/src/utils/music/wy/lyric.js @@ -0,0 +1,62 @@ +import { httpFetch } from '../../request' +import { linuxapi } from './utils/crypto' +// import { decodeName } from '../..' + +// const parseLyric = (str, lrc) => { +// if (!str) return '' + +// str = str.replace(/\r/g, '') + +// let lxlyric = str.replace(/\[((\d+),\d+)\].*/g, str => { +// let result = str.match(/\[((\d+),\d+)\].*/) +// let time = parseInt(result[2]) +// let ms = time % 1000 +// time /= 1000 +// let m = parseInt(time / 60).toString().padStart(2, '0') +// time %= 60 +// let s = parseInt(time).toString().padStart(2, '0') +// time = `${m}:${s}.${ms}` +// str = str.replace(result[1], time) + +// let startTime = 0 +// str = str.replace(/\(0,1\) /g, ' ').replace(/\(\d+,\d+\)/g, time => { +// const [start, end] = time.replace(/^\((\d+,\d+)\)$/, '$1').split(',') + +// time = `<${parseInt(startTime + parseInt(start))},${end}>` +// startTime = parseInt(startTime + parseInt(end)) +// return time +// }) + +// return str +// }) + +// lxlyric = decodeName(lxlyric) +// return lxlyric.trim() +// } + +export default songmid => { + const requestObj = httpFetch('https://music.163.com/api/linux/forward', { + method: 'post', + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + form: linuxapi({ + method: 'POST', + url: 'https://music.163.com/api/song/lyric', + params: { + id: songmid, + lv: -1, + kv: -1, + tv: -1, + }, + }), + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + if (body.code !== 200) return Promise.reject('获取歌词失败') + return { + lyric: body.lrc.lyric, + tlyric: body.tlyric.lyric, + // lxlyric: parseLyric(body.klyric.lyric), + } + }) + return requestObj +} + diff --git a/src/utils/music/wy/musicDetail.js b/src/utils/music/wy/musicDetail.js new file mode 100644 index 0000000..a53d99b --- /dev/null +++ b/src/utils/music/wy/musicDetail.js @@ -0,0 +1,91 @@ +import { httpFetch } from '../../request' +import { weapi } from './utils/crypto' +import { formatPlayTime, sizeFormate } from '../..' +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/song_detail.js + +export default { + _requestObj: null, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + filterList({ songs, privileges }) { + // console.log(tracks, privileges) + const list = [] + songs.forEach((item, index) => { + const types = [] + const _types = {} + let size + let privilege = privileges[index] + if (privilege.id !== item.id) privilege = privileges.find(p => p.id === item.id) + if (!privilege) return + + switch (privilege.maxbr) { + case 999000: + size = null + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + case 320000: + if (item.h) { + size = sizeFormate(item.h.size) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + case 128000: + if (item.l) { + size = sizeFormate(item.l.size) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + } + + types.reverse() + + list.push({ + singer: this.getSinger(item.ar), + name: item.name, + albumName: item.al.name, + albumId: item.al.id, + source: 'wy', + interval: formatPlayTime(item.dt / 1000), + songmid: item.id, + img: item.al.picUrl, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + async getList(ids = [], retryNum = 0) { + if (this._requestObj) this._requestObj.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('try max num')) + + const _requestObj = httpFetch('https://music.163.com/weapi/v3/song/detail', { + method: 'post', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + origin: 'https://music.163.com', + }, + form: weapi({ + c: '[' + ids.map(id => ('{"id":' + id + '}')).join(',') + ']', + ids: '[' + ids.join(',') + ']', + }), + }) + const { body, statusCode } = await _requestObj.promise + if (statusCode != 200 || body.code !== 200) throw new Error('获取歌曲详情失败') + // console.log(body) + return { source: 'wy', list: this.filterList(body) } + }, +} diff --git a/src/utils/music/wy/musicInfo.js b/src/utils/music/wy/musicInfo.js new file mode 100644 index 0000000..88a5da5 --- /dev/null +++ b/src/utils/music/wy/musicInfo.js @@ -0,0 +1,25 @@ +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/song_detail.js +import { httpFetch } from '../../request' +import { weapi } from './utils/crypto' + +export default songmid => { + const requestObj = httpFetch('https://music.163.com/weapi/v3/song/detail', { + method: 'post', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + Referer: 'https://music.163.com/song?id=' + songmid, + origin: 'https://music.163.com', + }, + form: weapi({ + c: `[{"id":${songmid}}]`, + ids: `[${songmid}]`, + }), + }) + requestObj.promise = requestObj.promise.then(({ body }) => { + // console.log(body) + if (body.code !== 200 || !body.songs.length) return Promise.reject('获取歌曲信息失败') + return body.songs[0] + }) + return requestObj +} + diff --git a/src/utils/music/wy/musicSearch.js b/src/utils/music/wy/musicSearch.js new file mode 100644 index 0000000..4fdf855 --- /dev/null +++ b/src/utils/music/wy/musicSearch.js @@ -0,0 +1,128 @@ +import { httpFetch } from '../../request' +import { weapi } from './utils/crypto' +// import { sizeFormate, formatPlayTime } from '../../index' +import musicDetailApi from './musicDetail' + +let searchRequest +export default { + limit: 30, + total: 0, + page: 0, + allPage: 1, + musicSearch(str, page, limit) { + if (searchRequest && searchRequest.cancelHttp) searchRequest.cancelHttp() + searchRequest = httpFetch('https://music.163.com/weapi/search/get', { + method: 'post', + headers: { + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + origin: 'https://music.163.com', + }, + form: weapi({ + s: str, + type: 1, // 1: 单曲, 10: 专辑, 100: 歌手, 1000: 歌单, 1002: 用户, 1004: MV, 1006: 歌词, 1009: 电台, 1014: 视频 + limit, + offset: limit * (page - 1), + }), + }) + return searchRequest.promise.then(({ body }) => + body && body.code === 200 + ? musicDetailApi.getList(body.result.songs.map(s => s.id)).then(({ list }) => { + this.total = body.result.songCount || 0 + this.page = page + this.allPage = Math.ceil(this.total / limit) + return { + code: 200, + data: { + list, + allPage: this.allPage, + limit, + total: this.total, + source: 'wy', + }, + } + }) + : body) + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + /* handleResult(rawList) { + // console.log(rawList) + if (!rawList) return [] + return rawList.map(item => { + const types = [] + const _types = {} + let size + switch (item.privilege.maxbr) { + case 999000: + size = null + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + case 320000: + if (item.h) { + size = sizeFormate(item.h.size) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + case 192000: + case 128000: + if (item.l) { + size = sizeFormate(item.l.size) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + } + + types.reverse() + + return { + singer: this.getSinger(item.ar), + name: item.name, + albumName: item.al.name, + albumId: item.al.id, + source: 'wy', + interval: formatPlayTime(item.dt / 1000), + songmid: item.id, + img: item.al.picUrl, + lrc: null, + types, + _types, + typeUrl: {}, + } + }) + }, */ + search(str, page = 1, { limit } = {}, retryNum = 0) { + if (++retryNum > 3) return Promise.reject(new Error('try max num')) + if (limit == null) limit = this.limit + return this.musicSearch(str, page, limit).then(result => { + // console.log(result) + if (!result || result.code !== 200) return this.search(str, page, { limit }, retryNum) + // let list = this.handleResult(result.result.songs || []) + + // if (list == null) return this.search(str, page, { limit }, retryNum) + + // this.total = result.result.songCount || 0 + // this.page = page + // this.allPage = Math.ceil(this.total / this.limit) + + // return Promise.resolve({ + // list, + // allPage: this.allPage, + // limit: this.limit, + // total: this.total, + // source: 'wy', + // }) + return result.data + }) + }, +} diff --git a/src/utils/music/wy/songList.js b/src/utils/music/wy/songList.js new file mode 100644 index 0000000..be0aab3 --- /dev/null +++ b/src/utils/music/wy/songList.js @@ -0,0 +1,282 @@ +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/playlist_catlist.js +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/playlist_hot.js +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/top_playlist.js +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/module/playlist_detail.js + +import { weapi, linuxapi } from './utils/crypto' +import { httpFetch } from '../../request' +import { formatPlayTime, sizeFormate } from '../../index' +import musicDetailApi from './musicDetail' + +export default { + _requestObj_tags: null, + _requestObj_hotTags: null, + _requestObj_list: null, + _requestObj_listDetail: null, + _requestObj_listDetailLink: null, + limit_list: 30, + limit_song: 100000, + successCode: 200, + sortList: [ + { + name: '最热', + tid: 'hot', + id: 'hot', + }, + { + name: '最新', + tid: 'new', + id: 'new', + }, + ], + regExps: { + listDetailLink: /^.+(?:\?|&)id=(\d+)(?:&.*$|#.*$|$)/, + }, + /** + * 格式化播放数量 + * @param {*} num + */ + formatPlayCount(num) { + if (num > 100000000) return parseInt(num / 10000000) / 10 + '亿' + if (num > 10000) return parseInt(num / 1000) / 10 + '万' + return num + }, + getSinger(singers) { + let arr = [] + singers.forEach(singer => { + arr.push(singer.name) + }) + return arr.join('、') + }, + + async handleParseId(link, retryNum = 0) { + if (this._requestObj_listDetailLink) this._requestObj_listDetailLink.cancelHttp() + if (retryNum > 2) return Promise.reject(new Error('link try max num')) + + this._requestObj_listDetailLink = httpFetch(link) + const { headers: { location }, statusCode } = await this._requestObj_listDetailLink.promise + // console.log(headers) + if (statusCode > 400) return this.handleParseId(link, ++retryNum) + return location == null ? link : location + }, + + async getListDetail(id, page, tryNum = 0) { // 获取歌曲列表内的音乐 + if (this._requestObj_listDetail) this._requestObj_listDetail.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + + if ((/[?&:/]/.test(id))) { + if (!this.regExps.listDetailLink.test(id)) id = await this.handleParseId(id) + // console.log(id) + id = id.replace(this.regExps.listDetailLink, '$1') + } + + this._requestObj_listDetail = httpFetch('https://music.163.com/api/linux/forward', { + method: 'post', + 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', + form: linuxapi({ + method: 'POST', + url: 'https://music.163.com/api/v3/playlist/detail', + params: { + id, + n: this.limit_song, + s: 8, + }, + }), + }) + const { statusCode, body } = await this._requestObj_listDetail.promise + if (statusCode !== 200 || body.code !== this.successCode) return this.getListDetail(id, page, ++tryNum) + let limit = 1000 + let rangeStart = (page - 1) * limit + // console.log(body) + let musicDetail + try { + musicDetail = await musicDetailApi.getList(body.playlist.trackIds.slice(rangeStart, limit * page).map(trackId => trackId.id)) + } catch (err) { + console.log(err) + if (err.message == 'try max num') { + throw err + } else { + return this.getListDetail(id, page, ++tryNum) + } + } + // console.log(musicDetail) + return { + list: musicDetail.list, + page, + limit, + total: body.playlist.trackIds.length, + source: 'wy', + info: { + play_count: this.formatPlayCount(body.playlist.playCount), + name: body.playlist.name, + img: body.playlist.coverImgUrl, + desc: body.playlist.description, + author: body.playlist.creator.nickname, + }, + } + }, + filterListDetail({ playlist: { tracks }, privileges }) { + // console.log(tracks, privileges) + const list = [] + tracks.forEach((item, index) => { + const types = [] + const _types = {} + let size + let privilege = privileges[index] + if (privilege.id !== item.id) privilege = privileges.find(p => p.id === item.id) + if (!privilege) return + + switch (privilege.maxbr) { + case 999000: + size = null + types.push({ type: 'flac', size }) + _types.flac = { + size, + } + case 320000: + if (item.h) { + size = sizeFormate(item.h.size) + types.push({ type: '320k', size }) + _types['320k'] = { + size, + } + } + case 128000: + if (item.l) { + size = sizeFormate(item.l.size) + types.push({ type: '128k', size }) + _types['128k'] = { + size, + } + } + } + + types.reverse() + + list.push({ + singer: this.getSinger(item.ar), + name: item.name, + albumName: item.al.name, + albumId: item.al.id, + source: 'wy', + interval: formatPlayTime(item.dt / 1000), + songmid: item.id, + img: item.al.picUrl, + lrc: null, + otherSource: null, + types, + _types, + typeUrl: {}, + }) + }) + return list + }, + + // 获取列表数据 + getList(sortId, tagId, page, tryNum = 0) { + if (tryNum > 2) return Promise.reject(new Error('try max num')) + if (this._requestObj_list) this._requestObj_list.cancelHttp() + this._requestObj_list = httpFetch('https://music.163.com/weapi/playlist/list', { + method: 'post', + form: weapi({ + cat: tagId || '全部', // 全部,华语,欧美,日语,韩语,粤语,小语种,流行,摇滚,民谣,电子,舞曲,说唱,轻音乐,爵士,乡村,R&B/Soul,古典,民族,英伦,金属,朋克,蓝调,雷鬼,世界音乐,拉丁,另类/独立,New Age,古风,后摇,Bossa Nova,清晨,夜晚,学习,工作,午休,下午茶,地铁,驾车,运动,旅行,散步,酒吧,怀旧,清新,浪漫,性感,伤感,治愈,放松,孤独,感动,兴奋,快乐,安静,思念,影视原声,ACG,儿童,校园,游戏,70后,80后,90后,网络歌曲,KTV,经典,翻唱,吉他,钢琴,器乐,榜单,00后 + order: sortId, // hot,new + limit: this.limit_list, + offset: this.limit_list * (page - 1), + total: true, + }), + }) + return this._requestObj_list.promise.then(({ body }) => { + // console.log(JSON.stringify(body)) + if (body.code !== this.successCode) return this.getList(sortId, tagId, page, ++tryNum) + return { + list: this.filterList(body.playlists), + total: parseInt(body.total), + page, + limit: this.limit_list, + source: 'wy', + } + }) + }, + filterList(rawData) { + return rawData.map(item => ({ + play_count: this.formatPlayCount(item.playCount), + id: item.id, + author: item.creator.nickname, + name: item.name, + time: item.createTime, + img: item.coverImgUrl, + grade: item.grade, + desc: item.description, + source: 'wy', + })) + }, + + // 获取标签 + getTag(tryNum = 0) { + if (this._requestObj_tags) this._requestObj_tags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_tags = httpFetch('https://music.163.com/weapi/playlist/catalogue', { + method: 'post', + form: weapi({}), + }) + return this._requestObj_tags.promise.then(({ body }) => { + // console.log(JSON.stringify(body)) + if (body.code !== this.successCode) return this.getTag(++tryNum) + return this.filterTagInfo(body) + }) + }, + filterTagInfo({ sub, categories }) { + const subList = {} + for (const item of sub) { + if (!subList[item.category]) subList[item.category] = [] + subList[item.category].push({ + parent_id: categories[item.category], + parent_name: categories[item.category], + id: item.name, + name: item.name, + source: 'wy', + }) + } + + const list = [] + for (const key of Object.keys(categories)) { + list.push({ + name: categories[key], + list: subList[key], + source: 'wy', + }) + } + return list + }, + + // 获取热门标签 + getHotTag(tryNum = 0) { + if (this._requestObj_hotTags) this._requestObj_hotTags.cancelHttp() + if (tryNum > 2) return Promise.reject(new Error('try max num')) + this._requestObj_hotTags = httpFetch('https://music.163.com/weapi/playlist/hottags', { + method: 'post', + form: weapi({}), + }) + return this._requestObj_hotTags.promise.then(({ body }) => { + // console.log(JSON.stringify(body)) + if (body.code !== this.successCode) return this.getTag(++tryNum) + return this.filterHotTagInfo(body.tags) + }) + }, + filterHotTagInfo(rawList) { + return rawList.map(item => ({ + id: item.playlistTag.name, + name: item.playlistTag.name, + source: 'wy', + })) + }, + + getTags() { + return Promise.all([this.getTag(), this.getHotTag()]).then(([tags, hotTag]) => ({ tags, hotTag, source: 'wy' })) + }, +} + +// getList +// getTags +// getListDetail diff --git a/src/utils/music/wy/utils/crypto.js b/src/utils/music/wy/utils/crypto.js new file mode 100644 index 0000000..e39aad1 --- /dev/null +++ b/src/utils/music/wy/utils/crypto.js @@ -0,0 +1,33 @@ +// https://github.com/Binaryify/NeteaseCloudMusicApi/blob/master/util/crypto.js +import { createCipheriv, publicEncrypt, randomBytes } from 'crypto' +const iv = Buffer.from('0102030405060708') +const presetKey = Buffer.from('0CoJUm6Qyw8W8jud') +const linuxapiKey = Buffer.from('rFgB&h#%2?^eDg:Q') +const base62 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' +const publicKey = '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6sXqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9SdB1Ua44oncaTWz7OBGLbCiK45wIDAQAB\n-----END PUBLIC KEY-----' + +const aesEncrypt = (buffer, mode, key, iv) => { + const cipher = createCipheriv('aes-128-' + mode, key, iv) + return Buffer.concat([cipher.update(buffer), cipher.final()]) +} + +const rsaEncrypt = (buffer, key) => { + buffer = Buffer.concat([Buffer.alloc(128 - buffer.length), buffer]) + return publicEncrypt({ key: key, padding: 3 }, buffer) +} + +export const weapi = object => { + const text = JSON.stringify(object) + const secretKey = randomBytes(16).map(n => (base62.charAt(n % 62).charCodeAt())) + return { + params: aesEncrypt(Buffer.from(aesEncrypt(Buffer.from(text), 'cbc', presetKey, iv).toString('base64')), 'cbc', secretKey, iv).toString('base64'), + encSecKey: rsaEncrypt(secretKey.reverse(), publicKey).toString('hex'), + } +} + +export const linuxapi = object => { + const text = JSON.stringify(object) + return { + eparams: aesEncrypt(Buffer.from(text), 'ecb', linuxapiKey, '').toString('hex').toUpperCase(), + } +} diff --git a/src/utils/music/xm.js b/src/utils/music/xm.js new file mode 100644 index 0000000..5142a0d --- /dev/null +++ b/src/utils/music/xm.js @@ -0,0 +1,57 @@ +// import { apis } from '../api-source' +// import leaderboard from './leaderboard' +// import songList from './songList' +// import musicSearch from './musicSearch' +// import pic from './pic' +// import lyric from './lyric' +// import hotSearch from './hotSearch' +// import comment from './comment' +// import musicInfo from './musicInfo' +// import { closeVerifyModal } from './util' + +const xm = { + // songList, + // musicSearch, + // leaderboard, + // hotSearch, + // closeVerifyModal, + comment: { + getComment() { + return Promise.reject(new Error('fail')) + }, + getHotComment() { + return Promise.reject(new Error('fail')) + }, + }, + getMusicUrl(songInfo, type) { + return { + promise: Promise.reject(new Error('fail')), + } + // return apis('xm').getMusicUrl(songInfo, type) + }, + getLyric(songInfo) { + return { + promise: Promise.reject(new Error('fail')), + } + // return lyric.getLyric(songInfo) + }, + getPic(songInfo) { + return { + promise: Promise.reject(new Error('fail')), + } + // return pic.getPic(songInfo) + }, + // getMusicDetailPageUrl(songInfo) { + // if (songInfo.songStringId) return `https://www.xiami.com/song/${songInfo.songStringId}` + + // musicInfo.getMusicInfo(songInfo).then(({ data }) => { + // songInfo.songStringId = data.songStringId + // }) + // return `https://www.xiami.com/song/${songInfo.songmid}` + // }, + // init() { + // getToken() + // }, +} + +export default xm diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..56cc0eb --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,194 @@ +// import needle from 'needle' +// import progress from 'request-progress' +import BackgroundTimer from 'react-native-background-timer' +import { debugRequest } from './env' +import { requestMsg } from './message' +import { bHh } from './music/options' +import { deflateRaw } from 'pako' + +const defaultHeaders = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36', +} +// var proxyUrl = "http://" + user + ":" + password + "@" + host + ":" + port; +// var proxiedRequest = request.defaults({'proxy': proxyUrl}); + + +/** + * 请求超时自动重试 + * @param {*} url + * @param {*} options + */ +export const httpFetch = (url, options = { method: 'get' }) => { + const requestObj = fetchData(url, options) + return { + promise: requestObj.request.catch(err => { + console.log('出错', err.message) + switch (err.message) { + case 'socket hang up': + return Promise.reject(new Error(requestMsg.unachievable)) + case 'Aborted': + return Promise.reject(new Error(requestMsg.timeout)) + case 'Network request failed': + return Promise.reject(new Error(requestMsg.notConnectNetwork)) + default: + return Promise.reject(err) + } + }), + cancelHttp() { + requestObj.abort() + }, + } +} + +/** + * http get 请求 + * @param {*} url 地址 + * @param {*} options 选项 + * @param {*} callback 回调 + * @return {Number} index 用于取消请求 + */ +export const httpGet = (url, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + const requestObj = fetchData(url, { ...options, method: 'get' }) + requestObj.request.then(resp => { + callback(null, resp, resp.body) + }).catch(err => { + debugRequest && console.log(JSON.stringify(err)) + callback(err, null, null) + }) + + return () => { + requestObj.abort() + } +} + +/* +const fetchWithTimeout = (resource, options) => { + const { timeout = 8000 } = options + + const controller = new global.AbortController() + const id = BackgroundTimer.setTimeout(() => controller.abort(), timeout) + + return { + request: global.fetch(resource, { + ...options, + signal: controller.signal, + }).then(response => { + BackgroundTimer.clearTimeout(id) + return response + }), + abort() { + controller.abort() + }, + } +} */ + + +const handleDeflateRaw = data => new Promise((resolve, reject) => { + resolve(Buffer.from(deflateRaw(data))) + // deflateRaw(data, (err, buf) => { + // if (err) return reject(err) + // resolve(buf) + // }) +}) + +const regx = /(?:\d\w)+/g + +const handleRequestData = async(url, { + method = 'get', + headers = {}, + format = 'json', + ...options +}) => { + // console.log(url, options) + headers = Object.assign({ + Accept: 'application/json', + }, headers) + options.cache = 'no-store' + if (method.toLocaleLowerCase() === 'post' && !headers['Content-Type']) { + if (options.form) { + headers['Content-Type'] = 'application/x-www-form-urlencoded' + const formBody = [] + for (let [key, value] of Object.entries(options.form)) { + let encodedKey = encodeURIComponent(key) + let encodedValue = encodeURIComponent(value) + formBody.push(`${encodedKey}=${encodedValue}`) + } + options.body = formBody.join('&') + delete options.form + } else if (options.formData) { + headers['Content-Type'] = 'multipart/form-data' + const formBody = [] + for (let [key, value] of Object.entries(options.form)) { + let encodedKey = encodeURIComponent(key) + let encodedValue = encodeURIComponent(value) + formBody.push(`${encodedKey}=${encodedValue}`) + } + options.body = options.formData + delete options.formData + } else { + headers['Content-Type'] = 'application/json' + } + } + if (headers['Content-Type'] === 'application/json' && options.body) { + options.body = JSON.stringify(options.body) + } + if (headers[bHh]) { + let s = Buffer.from(bHh, 'hex').toString() + s = s.replace(s.substr(-1), '') + s = Buffer.from(s, 'base64').toString() + const v = process.versions.app.split('-')[0].split('.').map(n => n.length < 3 ? n.padStart(3, '0') : n).join('') + const v2 = process.versions.app.split('-')[1] || '' + headers[s] = !s || `${(await handleDeflateRaw(Buffer.from(JSON.stringify(`${url}${v}`.match(regx), null, 1).concat(v)).toString('base64'))).toString('hex')}&${parseInt(v)}${v2}` + delete headers[bHh] + } + + return { + ...options, + method, + headers: Object.assign({}, defaultHeaders, headers), + } +} + +const fetchData = (url, { timeout = 15000, ...options }) => { + console.log('---start---', url) + + const controller = new global.AbortController() + const id = BackgroundTimer.setTimeout(() => controller.abort(), timeout) + + return { + request: handleRequestData(url, options).then(options => { + return global.fetch(url, { + ...options, + signal: controller.signal, + }).then(response => { + BackgroundTimer.clearTimeout(id) + return response + }).then(resp => resp.text().then(text => { + // console.log(options, headers, text) + return { + headers: resp.headers.map, + body: text, + statusCode: resp.status, + url: resp.url, + ok: resp.ok, + } + })).then(resp => { + try { + resp.body = JSON.parse(resp.body) + } catch (_) { + } + return resp + }).catch(err => { + // console.log(err, err.code, err.message) + return Promise.reject(err) + }) + }), + abort() { + controller.abort() + }, + } +} diff --git a/src/utils/tools.js b/src/utils/tools.js new file mode 100644 index 0000000..08d6b1a --- /dev/null +++ b/src/utils/tools.js @@ -0,0 +1,186 @@ +import { Platform, NativeModules, ToastAndroid, BackHandler, Linking } from 'react-native' +import { getData, setData, getAllKeys, removeData, removeDataMultiple, setDataMultiple, getDataMultiple } from '@/plugins/storage' +import { storageDataPrefix } from '@/config' +import { throttle } from './index' + +const playInfoStorageKey = storageDataPrefix.playInfo +const listPositionPrefix = storageDataPrefix.listPosition +const listPrefix = storageDataPrefix.list +const listSortPrefix = storageDataPrefix.listSort +const defaultListKey = listPrefix + 'default' +const loveListKey = listPrefix + 'love' + + +// https://stackoverflow.com/a/47349998 +let deviceLanguage = Platform.OS === 'ios' + ? NativeModules.SettingsManager.settings.AppleLocale || + NativeModules.SettingsManager.settings.AppleLanguages[0] // iOS 13 + : NativeModules.I18nManager.localeIdentifier +deviceLanguage = typeof deviceLanguage === 'string' ? deviceLanguage.substring(0, 5).toLocaleLowerCase() : '' + +const handleSaveListScrollPosition = throttle(data => { + setData(listPositionPrefix, data) +}, 1000) + +/** + * 显示toast + * @param {String} message 消息 + * @param {String} duration 时长,可用值:long、short + * @param {String} position 位置,可用值:top、center、bottom + */ +export const toast = (message, duration = 'short', position = 'bottom') => { + switch (duration) { + case 'long': + duration = ToastAndroid.LONG + break + case 'short': + default: + duration = ToastAndroid.SHORT + break + } + switch (position) { + case 'top': + position = ToastAndroid.TOP + break + case 'center': + position = ToastAndroid.CENTER + break + case 'bottom': + default: + position = ToastAndroid.BOTTOM + break + } + ToastAndroid.show(message, duration, position) +} + +export const openUrl = url => Linking.canOpenURL(url).then(() => Linking.openURL(url)) + +export const assertApiSupport = source => global.globalObj.qualityList[source] != undefined + +// const handleRemoveDataMultiple = async keys => { +// await removeDataMultiple(keys.splice(0, 500)) +// if (keys.length) return handleRemoveDataMultiple(keys) +// } + + +export const getAllListData = async() => { + let defaultList + let loveList + let userList = [] + let keys = await getAllKeys() + const listKeys = [] + for (const key of keys) { + if (key.startsWith(listPrefix)) { + listKeys.push(key) + } + } + const listData = await getDataMultiple(listKeys) + for (const { key, value } of listData) { + switch (key) { + case defaultListKey: + defaultList = value + break + case loveListKey: + loveList = value + break + default: + userList.push(value) + break + } + } + const listPositionData = await getData(listPositionPrefix) || {} + const listPosition = {} + for (const [key, value] of Object.entries(listPositionData)) { + listPosition[key] = value + } + const listSortData = await getData(listSortPrefix) || {} + return { + defaultList, + loveList, + userList, + listPosition, + listSort: listSortData, + } +} + +export const saveList = async listData => { + if (Array.isArray(listData)) { + await setDataMultiple(listData.map(list => ({ key: listPrefix + list.id, value: list }))) + } else { + await setData(listPrefix + listData.id, listData) + } +} +export const removeList = async listId => { + if (Array.isArray(listId)) { + await removeDataMultiple(listId.map(id => { + delete global.listScrollPosition[id] + delete global.listSort[id] + return listPrefix + id + })) + } else { + await removeData(listPrefix + listId) + } + await setData(listSortPrefix, global.listSort) + handleSaveListScrollPosition(global.listScrollPosition) +} + + +export const saveListAllSort = async listSort => { + global.listSort = listSort + await setData(listSortPrefix, listSort) +} +export const saveListSort = (listId, index) => { + global.listSort[listId] = index + setData(listSortPrefix, global.listSort) +} +export const removeListSort = async listIds => { + for (const id of listIds) { + delete global.listSort[id] + } + setData(listSortPrefix, global.listSort) +} + +export const getMusicUrl = (musicInfo, type) => getData(`${storageDataPrefix.musicUrl}${musicInfo.source}_${musicInfo.songmid}_${type}`).then(url => url || '') +export const saveMusicUrl = (musicInfo, type, url) => setData(`${storageDataPrefix.musicUrl}${musicInfo.source}_${musicInfo.songmid}_${type}`, url) +export const clearMusicUrl = async() => { + let keys = (await getAllKeys()).filter(key => key.startsWith(storageDataPrefix.musicUrl)) + await removeDataMultiple(keys) +} + +export const getLyric = musicInfo => getData(`${storageDataPrefix.lyric}${musicInfo.source}_${musicInfo.songmid}`).then(lrcInfo => lrcInfo || {}) +export const saveLyric = (musicInfo, { lyric, tlyric, lxlyric }) => setData(`${storageDataPrefix.lyric}${musicInfo.source}_${musicInfo.songmid}`, { lyric, tlyric, lxlyric }) +export const clearLyric = async() => { + let keys = (await getAllKeys()).filter(key => key.startsWith(storageDataPrefix.lyric)) + await removeDataMultiple(keys) +} + +export const clearMusicUrlAndLyric = async() => { + let keys = (await getAllKeys()).filter(key => key.startsWith(storageDataPrefix.musicUrl) || key.startsWith(storageDataPrefix.lyric)) + await removeDataMultiple(keys) +} + +export const savePlayInfo = throttle(n => { + setData(playInfoStorageKey, n) +}, 2000) +export const getPlayInfo = () => getData(playInfoStorageKey) + + +export const saveListScrollPosition = (listId, position) => { + global.listScrollPosition[listId] = position + handleSaveListScrollPosition(global.listScrollPosition) +} +export const getListScrollPosition = listId => { + return global.listScrollPosition[listId] || 0 +} +export const removeListScrollPosition = async listIds => { + for (const id of listIds) { + delete global.listScrollPosition[id] + } + handleSaveListScrollPosition(global.listScrollPosition) +} + +export const exitApp = BackHandler.exitApp + +export { + deviceLanguage, +} diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 0000000..cff09e2 --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,9 @@ +import { NativeModules } from 'react-native' + +const { UtilsModule } = NativeModules + +export const exitApp = UtilsModule.exitApp + +export const getSupportedAbis = UtilsModule.getSupportedAbis + +export const installApk = (filePath, fileProviderAuthority) => UtilsModule.installApk(filePath, fileProviderAuthority) diff --git a/src/utils/version.js b/src/utils/version.js new file mode 100644 index 0000000..0064959 --- /dev/null +++ b/src/utils/version.js @@ -0,0 +1,109 @@ +import { httpGet } from '@/utils/request' +import { author, name } from '../../package.json' +import { downloadFile, stopDownload, temporaryDirectoryPath } from '@/utils/fs' +import { getSupportedAbis, installApk } from '@/utils/utils' +import { APP_PROVIDER_NAME } from '@/config/constant' +import { toast } from './tools' + +const abis = [ + 'arm64-v8a', + 'armeabi-v7a', + 'x86_64', + 'x86', + 'universal', +] + +export const getVersionInfo = (retryNum = 0) => { + return new Promise((resolve, reject) => { + httpGet(`https://raw.githubusercontent.com/${author.name}/${name}/master/publish/version.json`, { + timeout: 15000, + }, (err, resp, body) => { + if (err || body.version == null) { + // toast(err.message) + return ++retryNum > 1 + ? getVersionInfo2().then(resolve).catch(reject) + : getVersionInfo(retryNum).then(resolve).catch(reject) + } + resolve(body) + }) + }) +} + +const getVersionInfo2 = (retryNum = 0) => { + return new Promise((resolve, reject) => { + httpGet('https://gitee.com/lyswhut/lx-music-mobile-versions/raw/master/version.json', { + timeout: 20000, + }, (err, resp, body) => { + if (err || body.version == null) { + return ++retryNum > 3 + ? getVersionInfo3().then(resolve).catch(reject) + : getVersionInfo2(retryNum).then(resolve).catch(reject) + } + resolve(body) + }) + }) +} + +const getVersionInfo3 = (retryNum = 0) => { + return new Promise((resolve, reject) => { + httpGet('https://cdn.stsky.cn/lx-music/mobile/version.json', { + timeout: 20000, + }, (err, resp, body) => { + if (err || body.version == null) { + return ++retryNum > 3 + ? resolve({ version: '0.0.0', desc: '', history: [] }) + : getVersionInfo3(retryNum).then(resolve).catch(reject) + } + resolve(body) + }) + }) +} + +const getTargetAbi = async() => { + const supportedAbis = await getSupportedAbis() + for (const abi of abis) { + if (supportedAbis.includes(abi)) return abi + } + return abis[abis.length - 1] +} +let downloadJobId = null +const noop = () => {} +let apkSavePath + +export const downloadNewVersion = async(version, onDownload = noop) => { + const abi = await getTargetAbi() + const url = `https://github.com/${author.name}/${name}/releases/download/v${version}/app-${abi}-release.apk` + let savePath = temporaryDirectoryPath + '/lx-music-mobile.apk' + + if (downloadJobId) await stopDownload(downloadJobId) + + const { jobId, promise } = downloadFile(url, savePath, { + progressInterval: 500, + connectionTimeout: 20000, + readTimeout: 30000, + begin({ statusCode, contentLength }) { + onDownload(contentLength, 0) + // switch (statusCode) { + // case 200: + // case 206: + // break + // default: + // onDownload(null, contentLength, 0) + // break + // } + }, + progress({ contentLength, bytesWritten }) { + onDownload(contentLength, bytesWritten) + }, + }) + downloadJobId = jobId + return promise.then(() => { + apkSavePath = savePath + return updateApp() + }) +} + +export const updateApp = async() => { + if (!apkSavePath) throw new Error('apk Save Path is null') + await installApk(apkSavePath, APP_PROVIDER_NAME) +} diff --git a/track-player.json b/track-player.json new file mode 100644 index 0000000..461108a --- /dev/null +++ b/track-player.json @@ -0,0 +1,5 @@ +{ + "dash": false, + "hls": false, + "smoothstreaming": false +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..50fabbd --- /dev/null +++ b/yarn.lock @@ -0,0 +1,9073 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.10.4.tgz?cache=0&sync_timestamp=1593522948158&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcode-frame%2Fdownload%2F%40babel%2Fcode-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha1-Fo2ho26Q2miujUnA8bSMfGJJITo= + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" + integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== + dependencies: + "@babel/highlight" "^7.12.13" + +"@babel/compat-data@^7.13.15": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4" + integrity sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA== + +"@babel/compat-data@^7.13.8": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.12.tgz#a8a5ccac19c200f9dd49624cac6e19d7be1236a1" + integrity sha512-3eJJ841uKxeV8dcN/2yGEUy+RfgQspPEgQat85umsE1rotuquQ2AbIub4S6j7c50a2d+4myc+zSlnXeIHrOnhQ== + +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.7.5": + version "7.11.6" + resolved "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.11.6.tgz?cache=0&sync_timestamp=1599146750684&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcore%2Fdownload%2F%40babel%2Fcore-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" + integrity sha1-OpRV3HOH/xusRXcGULwTugShVlE= + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.6" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.5" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.5" + "@babel/types" "^7.11.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.1.6": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.10.tgz#07de050bbd8193fcd8a3c27918c0890613a94559" + integrity sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.10" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.10" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/core@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.2.tgz#54e45334ffc0172048e5c93ded36461d3ad4c417" + integrity sha512-OgC1mON+l4U4B4wiohJlQNUU3H73mpTyYY3j/c8U9dr9UagGGSm+WFpzjy/YLdoyjiG++c1kIDgxCo/mLwQJeQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.14.2" + "@babel/helper-compilation-targets" "^7.13.16" + "@babel/helper-module-transforms" "^7.14.2" + "@babel/helpers" "^7.14.0" + "@babel/parser" "^7.14.2" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.14.2" + "@babel/types" "^7.14.2" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/generator@^7.11.5", "@babel/generator@^7.11.6", "@babel/generator@^7.5.0": + version "7.11.6" + resolved "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.11.6.tgz?cache=0&sync_timestamp=1599146753105&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fgenerator%2Fdownload%2F%40babel%2Fgenerator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" + integrity sha1-uGiQD4GxY7TUZOokVFxhy6xNxiA= + dependencies: + "@babel/types" "^7.11.5" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.13.0", "@babel/generator@^7.13.9": + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" + integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== + dependencies: + "@babel/types" "^7.13.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.14.0": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.1.tgz#1f99331babd65700183628da186f36f63d615c93" + integrity sha512-TMGhsXMXCP/O1WtQmZjpEYDhCYC9vFhayWZPJSZCGkPJgUqX0rF0wwtrYvnzVxIjcF80tkUertXVk5cwqi5cAQ== + dependencies: + "@babel/types" "^7.14.1" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.14.2.tgz#d5773e8b557d421fd6ce0d5efa5fd7fc22567c30" + integrity sha512-OnADYbKrffDVai5qcpkMxQ7caomHOoEwjkouqnN2QhydAjowFAZcsdecFIRUBdb+ZcruwYE4ythYmF1UBZU5xQ== + dependencies: + "@babel/types" "^7.14.2" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.10.4.tgz?cache=0&sync_timestamp=1593521294951&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-annotate-as-pure%2Fdownload%2F%40babel%2Fhelper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha1-W/DUlaP3V6w72ki1vzs7ownHK6M= + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-builder-binary-assignment-operator-visitor/download/@babel/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz?cache=0&sync_timestamp=1593522960718&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-builder-binary-assignment-operator-visitor%2Fdownload%2F%40babel%2Fhelper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha1-uwt18xv5jL+f8UPBrleLhydK4aM= + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.11.5" + resolved "https://registry.npm.taobao.org/@babel/helper-builder-react-jsx-experimental/download/@babel/helper-builder-react-jsx-experimental-7.11.5.tgz#4ea43dd63857b0a35cd1f1b161dc29b43414e79f" + integrity sha1-TqQ91jhXsKNc0fGxYdwptDQU558= + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.11.5" + +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-builder-react-jsx/download/@babel/helper-builder-react-jsx-7.10.4.tgz?cache=0&sync_timestamp=1593521449509&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-builder-react-jsx%2Fdownload%2F%40babel%2Fhelper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha1-gJXN2/+Fjm+pwyba7lSi8nMsHV0= + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-compilation-targets@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.10.tgz#1310a1678cb8427c07a753750da4f8ce442bdd0c" + integrity sha512-/Xju7Qg1GQO4mHZ/Kcs6Au7gfafgZnwm+a7sy/ow/tV1sHeraRUHbjdat8/UvDor4Tez+siGKDk6zIKtCPKVJA== + dependencies: + "@babel/compat-data" "^7.13.8" + "@babel/helper-validator-option" "^7.12.17" + browserslist "^4.14.5" + semver "^6.3.0" + +"@babel/helper-compilation-targets@^7.13.16": + version "7.13.16" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz#6e91dccf15e3f43e5556dffe32d860109887563c" + integrity sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA== + dependencies: + "@babel/compat-data" "^7.13.15" + "@babel/helper-validator-option" "^7.12.17" + browserslist "^4.14.5" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5": + version "7.10.5" + resolved "https://registry.npm.taobao.org/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha1-n2FEa6gOgkCwpchcb9rIRZ1vJZ0= + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-class-features-plugin@^7.13.0": + version "7.13.11" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.13.11.tgz#30d30a005bca2c953f5653fc25091a492177f4f6" + integrity sha512-ays0I7XYq9xbjCSvT+EvysLgfc3tOkwCULHjrnscGT3A9qD4sk3wXnJ3of0MAWsWGjdinFvajHU2smYuqXKMrw== + dependencies: + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/helper-replace-supers" "^7.13.0" + "@babel/helper-split-export-declaration" "^7.12.13" + +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.10.4.tgz?cache=0&sync_timestamp=1593522973297&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-create-regexp-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha1-/dYNiFJGWaC2lZwFeZJeQlcU87g= + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + regexpu-core "^4.7.0" + +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.npm.taobao.org/@babel/helper-define-map/download/@babel/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha1-tTwQ23imQIABUmkrEzkxR6y5uzA= + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.11.4" + resolved "https://registry.npm.taobao.org/@babel/helper-explode-assignable-expression/download/@babel/helper-explode-assignable-expression-7.11.4.tgz?cache=0&sync_timestamp=1597948364953&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-explode-assignable-expression%2Fdownload%2F%40babel%2Fhelper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" + integrity sha1-LY40cCUswXq6kX7eeAPUp6J2pBs= + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-function-name/download/@babel/helper-function-name-7.10.4.tgz?cache=0&sync_timestamp=1593522977138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-function-name%2Fdownload%2F%40babel%2Fhelper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha1-0tOyDFmtjEcRL6fSqUvAnV74Lxo= + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" + integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.13" + "@babel/template" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/helper-function-name@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz#397688b590760b6ef7725b5f0860c82427ebaac2" + integrity sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ== + dependencies: + "@babel/helper-get-function-arity" "^7.12.13" + "@babel/template" "^7.12.13" + "@babel/types" "^7.14.2" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.10.4.tgz?cache=0&sync_timestamp=1593521294451&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-get-function-arity%2Fdownload%2F%40babel%2Fhelper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha1-mMHL6g4jMvM/mkZhuM4VBbLBm6I= + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" + integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/helper-member-expression-to-functions/download/@babel/helper-member-expression-to-functions-7.11.0.tgz?cache=0&sync_timestamp=1596144430473&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-member-expression-to-functions%2Fdownload%2F%40babel%2Fhelper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha1-rmnIPYTugvS0L5bioJQQk1qPJt8= + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-member-expression-to-functions@^7.13.0", "@babel/helper-member-expression-to-functions@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" + integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-module-imports/download/@babel/helper-module-imports-7.10.4.tgz?cache=0&sync_timestamp=1593522965782&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-module-imports%2Fdownload%2F%40babel%2Fhelper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha1-TFxUvgS9MWcKc4J5fXW5+i5bViA= + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-module-imports@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" + integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha1-sW8lAinkchGr3YSzS2RzfCqy01k= + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + +"@babel/helper-module-transforms@^7.13.0": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.12.tgz#600e58350490828d82282631a1422268e982ba96" + integrity sha512-7zVQqMO3V+K4JOOj40kxiCrMf6xlQAkewBB0eu2b03OO/Q21ZutOzjpfD79A5gtE/2OWi1nv625MrDlGlkbknQ== + dependencies: + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.12.11" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.12" + +"@babel/helper-module-transforms@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz#ac1cc30ee47b945e3e0c4db12fa0c5389509dfe5" + integrity sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA== + dependencies: + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.14.0" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.14.2" + "@babel/types" "^7.14.2" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-optimise-call-expression/download/@babel/helper-optimise-call-expression-7.10.4.tgz?cache=0&sync_timestamp=1593521296446&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-optimise-call-expression%2Fdownload%2F%40babel%2Fhelper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha1-UNyWQT1ZT5lad5BZBbBYk813lnM= + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-optimise-call-expression@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" + integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-plugin-utils/download/@babel/helper-plugin-utils-7.10.4.tgz?cache=0&sync_timestamp=1593521082372&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-plugin-utils%2Fdownload%2F%40babel%2Fhelper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha1-L3WoMSadT2d95JmG3/WZJ1M883U= + +"@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" + integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== + +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.npm.taobao.org/@babel/helper-regex/download/@babel/helper-regex-7.10.5.tgz?cache=0&sync_timestamp=1594750677873&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-regex%2Fdownload%2F%40babel%2Fhelper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha1-Mt+7eYmQc8QVVXBToZvQVarlCuA= + dependencies: + lodash "^4.17.19" + +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-replace-supers/download/@babel/helper-replace-supers-7.10.4.tgz?cache=0&sync_timestamp=1593522959591&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-replace-supers%2Fdownload%2F%40babel%2Fhelper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha1-1YXNk4jqBuYDHkzUS2cTy+rZ5s8= + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.13.0", "@babel/helper-replace-supers@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" + integrity sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.13.12" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.12" + +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helper-simple-access/download/@babel/helper-simple-access-7.10.4.tgz?cache=0&sync_timestamp=1593522975802&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-simple-access%2Fdownload%2F%40babel%2Fhelper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha1-D1zNopRSd6KnotOoIeFTle3PNGE= + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-simple-access@^7.12.13", "@babel/helper-simple-access@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" + integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/helper-skip-transparent-expression-wrappers/download/@babel/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha1-7sFi8RLC9Y068K8SXju1dmUUZyk= + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/helper-split-export-declaration/download/@babel/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha1-+KSRJErPamdhWKxCBykRuoOtCZ8= + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" + integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-identifier@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" + integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== + +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/helpers/download/@babel/helpers-7.10.4.tgz?cache=0&sync_timestamp=1593522959913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelpers%2Fdownload%2F%40babel%2Fhelpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha1-Kr6w1yGv98Cpc3a54fb2XXpHUEQ= + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" + integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== + dependencies: + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" + +"@babel/helpers@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.14.0.tgz#ea9b6be9478a13d6f961dbb5f36bf75e2f3b8f62" + integrity sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg== + dependencies: + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.14.0" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" + integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.5", "@babel/parser@^7.7.0": + version "7.11.5" + resolved "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha1-x/9jA99xCA7HpPW4wAPFjxz1EDc= + +"@babel/parser@^7.1.6", "@babel/parser@^7.12.13", "@babel/parser@^7.13.0", "@babel/parser@^7.13.10": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.12.tgz#ba320059420774394d3b0c0233ba40e4250b81d1" + integrity sha512-4T7Pb244rxH24yR116LAuJ+adxXXnHhZaLJjegJVKSdoNCe4x1eDBaud5YIcQFcqzsaD5BHvJw5BQ0AZapdCRw== + +"@babel/parser@^7.14.0": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.1.tgz#1bd644b5db3f5797c4479d89ec1817fe02b84c47" + integrity sha512-muUGEKu8E/ftMTPlNp+mc6zL3E9zKWmF5sDHZ5MSsoTP9Wyz64AhEf9kD08xYJ7w6Hdcu8H550ircnPyWSIF0Q== + +"@babel/parser@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.2.tgz#0c1680aa44ad4605b16cbdcc5c341a61bde9c746" + integrity sha512-IoVDIHpsgE/fu7eXBeRWt8zLbDrSvD7H1gpomOkPpBoEN8KCruCqSDdqo8dddwQQrui30KSvQBaMUOJiuFu6QQ== + +"@babel/plugin-proposal-class-properties@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-class-properties/download/@babel/plugin-proposal-class-properties-7.10.4.tgz?cache=0&sync_timestamp=1593522963242&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-class-properties%2Fdownload%2F%40babel%2Fplugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha1-ozv2Mto5ClnHqMVwBF0RFc13iAc= + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-class-properties@^7.1.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz#146376000b94efd001e57a40a88a525afaab9f37" + integrity sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" + +"@babel/plugin-proposal-export-default-from@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-export-default-from/download/@babel/plugin-proposal-export-default-from-7.10.4.tgz#08f66eef0067cbf6a7bc036977dcdccecaf0c6c5" + integrity sha1-CPZu7wBny/anvANpd9zczsrwxsU= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-default-from" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz?cache=0&sync_timestamp=1593521087263&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator%2Fdownload%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha1-AqfpYfwy5tWy2wZJ4Bv4Dd7n4Eo= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.1.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz#3730a31dafd3c10d8ccd10648ed80a2ac5472ef3" + integrity sha512-iePlDPBn//UhxExyS9KyeYU7RM9WScAG+D3Hhno0PLJebAEpDZMocbDe64eqynhNAnwz/vZoL/q/QB2T1OH39A== + dependencies: + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha1-vYH5Wh90Z2DqQ7bC09YrEXkK0K8= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.10.4" + +"@babel/plugin-proposal-optional-catch-binding@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.10.4.tgz?cache=0&sync_timestamp=1593521089386&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-optional-catch-binding%2Fdownload%2F%40babel%2Fplugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha1-Mck4MJ0kp4pJ1o/av/qoY3WFVN0= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.0.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha1-3lhm0GRvav2quKVmOC/joiF1UHY= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.1.0": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.13.12.tgz#ba9feb601d422e0adea6760c2bd6bbb7bfec4866" + integrity sha512-fcEdKOkIB7Tf4IxrgEVeFC4zeJSTr78no9wTdBuZZbqF64kzllU0ybo2zrzm7gUQfxGhBgq4E39oRs8Zx/RMYQ== + dependencies: + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha1-qYP7Gusuw/btBCohD2QOkOeG/g0= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-bigint/download/@babel/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha1-TJpvZp9dDN8bkKFnHpoUa+UwDOo= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-class-properties/download/@babel/plugin-syntax-class-properties-7.10.4.tgz?cache=0&sync_timestamp=1593521086484&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-class-properties%2Fdownload%2F%40babel%2Fplugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha1-ZkTmoLqlWmH54yMfbJ7rbuRsEkw= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-dynamic-import@^7.0.0": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-default-from@^7.0.0", "@babel/plugin-syntax-export-default-from@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-export-default-from/download/@babel/plugin-syntax-export-default-from-7.10.4.tgz?cache=0&sync_timestamp=1593521154476&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-export-default-from%2Fdownload%2F%40babel%2Fplugin-syntax-export-default-from-7.10.4.tgz#e5494f95006355c10292a0ff1ce42a5746002ec8" + integrity sha1-5UlPlQBjVcECkqD/HOQqV0YALsg= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.10.4", "@babel/plugin-syntax-flow@^7.2.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-flow/download/@babel/plugin-syntax-flow-7.10.4.tgz#53351dd7ae01995e567d04ce42af1a6e0ba846a6" + integrity sha1-UzUd164BmV5WfQTOQq8abguoRqY= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-flow@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.12.13.tgz#5df9962503c0a9c918381c929d51d4d6949e7e86" + integrity sha512-J/RYxnlSLXZLVR7wTRsozxKT8qbsx1mNKJzXEEjQ0Kjx1ZACcyHgbanNWNCFtc36IzuWhYWPpvJFFoexoOWFmA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-import-meta/download/@babel/plugin-syntax-import-meta-7.10.4.tgz?cache=0&sync_timestamp=1593523664516&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-import-meta%2Fdownload%2F%40babel%2Fplugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha1-7mATSMNw+jNNIge+FYd3SWUh/VE= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-jsx/download/@babel/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha1-Oauq48v3EMQ3PYQpSE5rohNAFmw= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-logical-assignment-operators/download/@babel/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha1-ypHvRjA1MESLkGZSusLp/plB9pk= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.0.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-nullish-coalescing-operator/download/@babel/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha1-Fn7XA2iIYIH3S1w2xlqIwDtm0ak= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-numeric-separator/download/@babel/plugin-syntax-numeric-separator-7.10.4.tgz?cache=0&sync_timestamp=1593521788128&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-numeric-separator%2Fdownload%2F%40babel%2Fplugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha1-ubBws+M1cM2f0Hun+pHA3Te5r5c= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-catch-binding/download/@babel/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha1-YRGiZbz7Ag6579D9/X0mQCue1sE= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.0.0", "@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha1-T2nCq5UWfgGAzVM2YT+MV4j31Io= + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz#c5f0fa6e249f5b739727f923540cf7a806130178" + integrity sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-typescript@^7.10.4": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-typescript/download/@babel/plugin-syntax-typescript-7.10.4.tgz#2f55e770d3501e83af217d782cb7517d7bb34d25" + integrity sha1-L1XncNNQHoOvIX14LLdRfXuzTSU= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-typescript@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz#9dff111ca64154cef0f4dc52cf843d9f12ce4474" + integrity sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-transform-arrow-functions@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-arrow-functions/download/@babel/plugin-transform-arrow-functions-7.10.4.tgz?cache=0&sync_timestamp=1593521290488&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-arrow-functions%2Fdownload%2F%40babel%2Fplugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha1-4ilg135pfHT0HFAdRNc9v4pqZM0= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoped-functions/download/@babel/plugin-transform-block-scoped-functions-7.10.4.tgz?cache=0&sync_timestamp=1593522071341&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-block-scoped-functions%2Fdownload%2F%40babel%2Fplugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha1-GvpZV0T3XkOpGvc7DZmOz+Trwug= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-block-scoping@^7.0.0": + version "7.11.1" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" + integrity sha1-W37+mIUr741lLAsoFEzZOp5LUhU= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-classes@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.10.4.tgz?cache=0&sync_timestamp=1593522971188&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-classes%2Fdownload%2F%40babel%2Fplugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha1-QFE2rys+IYvEoZJiKLyRerGgrcc= + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-computed-properties/download/@babel/plugin-transform-computed-properties-7.10.4.tgz?cache=0&sync_timestamp=1593521290771&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-computed-properties%2Fdownload%2F%40babel%2Fplugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha1-ne2DqBboLe0o1S1LTsvdgQzfwOs= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-destructuring@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.10.4.tgz?cache=0&sync_timestamp=1593521291443&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-destructuring%2Fdownload%2F%40babel%2Fplugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha1-cN3Ss9G+qD0BUJ6bsl3bOnT8heU= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-exponentiation-operator@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-exponentiation-operator/download/@babel/plugin-transform-exponentiation-operator-7.10.4.tgz?cache=0&sync_timestamp=1593522967206&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-exponentiation-operator%2Fdownload%2F%40babel%2Fplugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha1-WuM4xX+M9AAb2zVgeuZrktZlry4= + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-flow-strip-types/download/@babel/plugin-transform-flow-strip-types-7.10.4.tgz?cache=0&sync_timestamp=1593521451679&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-flow-strip-types%2Fdownload%2F%40babel%2Fplugin-transform-flow-strip-types-7.10.4.tgz#c497957f09e86e3df7296271e9eb642876bf7788" + integrity sha1-xJeVfwnobj33KWJx6etkKHa/d4g= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-flow" "^7.10.4" + +"@babel/plugin-transform-flow-strip-types@^7.12.13": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.13.0.tgz#58177a48c209971e8234e99906cb6bd1122addd3" + integrity sha512-EXAGFMJgSX8gxWD7PZtW/P6M+z74jpx3wm/+9pn+c2dOawPpBkUX7BrfyPvo6ZpXbgRIEuwgwDb/MGlKvu2pOg== + dependencies: + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-flow" "^7.12.13" + +"@babel/plugin-transform-for-of@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-for-of/download/@babel/plugin-transform-for-of-7.10.4.tgz?cache=0&sync_timestamp=1593521291715&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-for-of%2Fdownload%2F%40babel%2Fplugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha1-wIiS6IGdOl2ykDGxFa9RHbv+uuk= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-function-name@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-function-name/download/@babel/plugin-transform-function-name-7.10.4.tgz?cache=0&sync_timestamp=1593522961117&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-function-name%2Fdownload%2F%40babel%2Fplugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha1-akZ4gOD8ljhRS6NpERgR3b4mRLc= + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-literals@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-literals/download/@babel/plugin-transform-literals-7.10.4.tgz?cache=0&sync_timestamp=1593521291903&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-literals%2Fdownload%2F%40babel%2Fplugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha1-n0K6CEEQChNfInEtDjkcRi9XHzw= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-member-expression-literals/download/@babel/plugin-transform-member-expression-literals-7.10.4.tgz?cache=0&sync_timestamp=1593521293070&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-member-expression-literals%2Fdownload%2F%40babel%2Fplugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha1-sexE/PGVr8uNssYs2OVRyIG6+Lc= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-modules-commonjs@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.10.4.tgz?cache=0&sync_timestamp=1593522963909&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-commonjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha1-ZmZ8Pu2h6/eJbUHx8WsXEFovvKA= + dependencies: + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.1.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.13.8.tgz#7b01ad7c2dcf2275b06fa1781e00d13d420b3e1b" + integrity sha512-9QiOx4MEGglfYZ4XOnU79OHr6vIWUakIj9b4mioN8eQIoEh+pf5p/zEB36JpDFWA12nNMiRf7bfoRvl9Rn79Bw== + dependencies: + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/helper-simple-access" "^7.12.13" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-object-assign@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-object-assign/download/@babel/plugin-transform-object-assign-7.10.4.tgz#f7c8f54ce8052ccd8b9da9b3358848423221c338" + integrity sha1-98j1TOgFLM2LnamzNYhIQjIhwzg= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-object-super@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-object-super/download/@babel/plugin-transform-object-super-7.10.4.tgz?cache=0&sync_timestamp=1593522965761&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-object-super%2Fdownload%2F%40babel%2Fplugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha1-1xRsTROUM+emUm+IjGZ+MUoJOJQ= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.10.5.tgz?cache=0&sync_timestamp=1594750687789&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-parameters%2Fdownload%2F%40babel%2Fplugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha1-WdM51Y0LGVBDX0BD504lEABeLEo= + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-property-literals@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-property-literals/download/@babel/plugin-transform-property-literals-7.10.4.tgz?cache=0&sync_timestamp=1593521293406&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-property-literals%2Fdownload%2F%40babel%2Fplugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha1-9v5UtlkDUimHhbg+3YFdIUxC48A= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-react-display-name/download/@babel/plugin-transform-react-display-name-7.10.4.tgz?cache=0&sync_timestamp=1593521445959&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-display-name%2Fdownload%2F%40babel%2Fplugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" + integrity sha1-tXlfTj4xQEGcNhG3oqODK5rvMo0= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-react-jsx-self@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-self/download/@babel/plugin-transform-react-jsx-self-7.10.4.tgz?cache=0&sync_timestamp=1593521448504&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx-self%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" + integrity sha1-zTAaX+2JiMGC7QudVem9bbC9k2k= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + +"@babel/plugin-transform-react-jsx-source@^7.0.0": + version "7.10.5" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx-source/download/@babel/plugin-transform-react-jsx-source-7.10.5.tgz?cache=0&sync_timestamp=1594749044885&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx-source%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" + integrity sha1-NPF3kRdSCnecBU8s3ZaAQ1uSIrQ= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-react-jsx/download/@babel/plugin-transform-react-jsx-7.10.4.tgz?cache=0&sync_timestamp=1593521453850&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-react-jsx%2Fdownload%2F%40babel%2Fplugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha1-ZzyfkTlIdkpEIWg7K+8pNpaP3fI= + dependencies: + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + +"@babel/plugin-transform-regenerator@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-regenerator/download/@babel/plugin-transform-regenerator-7.10.4.tgz?cache=0&sync_timestamp=1593521089707&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-regenerator%2Fdownload%2F%40babel%2Fplugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha1-IBXlnYOQdOdoON4hWdtCGWb9i2M= + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-runtime@^7.0.0": + version "7.11.5" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-runtime/download/@babel/plugin-transform-runtime-7.11.5.tgz#f108bc8e0cf33c37da031c097d1df470b3a293fc" + integrity sha1-8Qi8jgzzPDfaAxwJfR30cLOik/w= + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + resolve "^1.8.1" + semver "^5.5.1" + +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-shorthand-properties/download/@babel/plugin-transform-shorthand-properties-7.10.4.tgz?cache=0&sync_timestamp=1593521293679&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-shorthand-properties%2Fdownload%2F%40babel%2Fplugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha1-n9Jexc3VVbt/Rz5ebuHJce7eTdY= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.0.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-spread/download/@babel/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha1-+oTTAPXk9XdS/kGm0bPFVPE/F8w= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + +"@babel/plugin-transform-sticky-regex@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-sticky-regex/download/@babel/plugin-transform-sticky-regex-7.10.4.tgz?cache=0&sync_timestamp=1593521295131&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-sticky-regex%2Fdownload%2F%40babel%2Fplugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha1-jziJ7oZXWBEwop2cyR18c7fEoo0= + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.0.0": + version "7.10.5" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-template-literals/download/@babel/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha1-eLxdYmpmQtszEtnQ8AH152Of3ow= + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typescript@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.13.0.tgz#4a498e1f3600342d2a9e61f60131018f55774853" + integrity sha512-elQEwluzaU8R8dbVuW2Q2Y8Nznf7hnjM7+DSCd14Lo5fF63C9qNLbwZYbmZrtV9/ySpSUpkRpQXvJb6xyu4hCQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.13.0" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/plugin-syntax-typescript" "^7.12.13" + +"@babel/plugin-transform-typescript@^7.5.0": + version "7.11.0" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-typescript/download/@babel/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" + integrity sha1-K0h5Z2rzc0LrsnghbdCQrGfxOrs= + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.0.0": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/plugin-transform-unicode-regex/download/@babel/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha1-5W1x+SgvrG2wnIJ0IFVXbV5tgKg= + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-flow@^7.0.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.12.13.tgz#71ee7fe65a95b507ac12bcad65a4ced27d8dfc3e" + integrity sha512-gcEjiwcGHa3bo9idURBp5fmJPcyFPOszPQjztXrOjUE2wWVqc6fIVJPgWPIQksaQ5XZ2HWiRsf2s1fRGVjUtVw== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + "@babel/plugin-transform-flow-strip-types" "^7.12.13" + +"@babel/preset-typescript@^7.1.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.13.0.tgz#ab107e5f050609d806fbb039bec553b33462c60a" + integrity sha512-LXJwxrHy0N3f6gIJlYbLta1D9BDtHpQeqwzM0LIfjDlr6UE/D5Mc7W4iDiQzaE+ks0sTjT26ArcHWnJVt0QiHw== + dependencies: + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/helper-validator-option" "^7.12.17" + "@babel/plugin-transform-typescript" "^7.13.0" + +"@babel/register@^7.0.0": + version "7.11.5" + resolved "https://registry.npm.taobao.org/@babel/register/download/@babel/register-7.11.5.tgz#79becf89e0ddd0fba8b92bc279bc0f5d2d7ce2ea" + integrity sha1-eb7PieDd0PuouSvCebwPXS184uo= + dependencies: + find-cache-dir "^2.0.0" + lodash "^4.17.19" + make-dir "^2.1.0" + pirates "^4.0.0" + source-map-support "^0.5.16" + +"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.13.6": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" + integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" + integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.8.4": + version "7.11.2" + resolved "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.11.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha1-9UnBPHVMxAuHZEufqfCaapX+BzY= + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.9.2": + version "7.13.17" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.17.tgz#8966d1fc9593bf848602f0662d6b4d0069e3a7ec" + integrity sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.0.0", "@babel/template@^7.10.4", "@babel/template@^7.3.3": + version "7.10.4" + resolved "https://registry.npm.taobao.org/@babel/template/download/@babel/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha1-MlGZbEIA68cdGo/EBfupQPNrong= + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/template@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" + integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/parser" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.7.0": + version "7.11.5" + resolved "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" + integrity sha1-vnd7k7UY62127i4eodFD2qEeYcM= + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.5" + "@babel/types" "^7.11.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/traverse@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" + integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.0" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.13.0" + "@babel/types" "^7.13.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/traverse@^7.14.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.0.tgz#cea0dc8ae7e2b1dec65f512f39f3483e8cc95aef" + integrity sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.14.0" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.14.0" + "@babel/types" "^7.14.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.2.tgz#9201a8d912723a831c2679c7ebbf2fe1416d765b" + integrity sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.14.2" + "@babel/helper-function-name" "^7.14.2" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.14.2" + "@babel/types" "^7.14.2" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.7.0": + version "7.11.5" + resolved "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha1-2d5XfQElLXfGgAzuA57mT691Zi0= + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@babel/types@^7.12.1": + version "7.12.6" + resolved "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.12.6.tgz?cache=0&sync_timestamp=1604486339981&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" + integrity sha1-rg5V7xzOH7yIHNJvgjTrPmV+3JY= + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@babel/types@^7.12.13", "@babel/types@^7.13.0", "@babel/types@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.12.tgz#edbf99208ef48852acdff1c8a681a1e4ade580cd" + integrity sha512-K4nY2xFN4QMvQwkQ+zmBDp6ANMbVNw6BbxWmYA4qNjhR9W+Lj/8ky5MEY2Me5r+B2c6/v6F53oMndG+f9s3IiA== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@babel/types@^7.14.0", "@babel/types@^7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.1.tgz#095bd12f1c08ab63eff6e8f7745fa7c9cc15a9db" + integrity sha512-S13Qe85fzLs3gYRUnrpyeIrBJIMYv33qSTg1qoBwiG6nPKwUWAD9odSzWhEedpwOIzSEI6gbdQIWEMiCI42iBA== + dependencies: + "@babel/helper-validator-identifier" "^7.14.0" + to-fast-properties "^2.0.0" + +"@babel/types@^7.14.2": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.2.tgz#4208ae003107ef8a057ea8333e56eb64d2f6a2c3" + integrity sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw== + dependencies: + "@babel/helper-validator-identifier" "^7.14.0" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.npm.taobao.org/@bcoe/v8-coverage/download/@bcoe/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha1-daLotRy3WKdVPWgEpZMteqznXDk= + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.npm.taobao.org/@cnakazawa/watch/download/@cnakazawa/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha1-+GSuhQBND8q29QvpFBxNo2jRZWo= + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@electron/get@^1.0.1": + version "1.12.4" + resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.12.4.tgz#a5971113fc1bf8fa12a8789dc20152a7359f06ab" + integrity sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg== + dependencies: + debug "^4.1.1" + env-paths "^2.2.0" + fs-extra "^8.1.0" + got "^9.6.0" + progress "^2.0.3" + semver "^6.2.0" + sumchecker "^3.0.1" + optionalDependencies: + global-agent "^2.0.2" + global-tunnel-ng "^2.7.1" + +"@eslint/eslintrc@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.1.tgz#442763b88cecbe3ee0ec7ca6d6dd6168550cbf14" + integrity sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@hapi/hoek@^9.0.0": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.1.tgz#9daf5745156fd84b8e9889a2dc721f0c58e894aa" + integrity sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw== + +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.npm.taobao.org/@istanbuljs/load-nyc-config/download/@istanbuljs/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha1-/T2x1Z7PfPEh6AZQu4ZxL5tV7O0= + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.2" + resolved "https://registry.npm.taobao.org/@istanbuljs/schema/download/@istanbuljs/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" + integrity sha1-JlIL8Jq+SlZEzVQU43ElqJVCQd0= + +"@jest/console@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^26.6.2" + jest-util "^26.6.2" + slash "^3.0.0" + +"@jest/core@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/reporters" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^26.6.2" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-resolve-dependencies "^26.6.3" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + jest-watcher "^26.6.2" + micromatch "^4.0.2" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/create-cache-key-function@^26.5.0": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-26.6.2.tgz#04cf439207a4fd12418d8aee551cddc86f9ac5f5" + integrity sha512-LgEuqU1f/7WEIPYqwLPIvvHuc1sB6gMVbT6zWhin3txYUNYK/kGQrC1F2WR4gR34YlI9bBtViTm5z98RqVZAaw== + dependencies: + "@jest/types" "^26.6.2" + +"@jest/environment@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== + dependencies: + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + +"@jest/fake-timers@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== + dependencies: + "@jest/types" "^26.6.2" + "@sinonjs/fake-timers" "^6.0.1" + "@types/node" "*" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-util "^26.6.2" + +"@jest/globals@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/types" "^26.6.2" + expect "^26.6.2" + +"@jest/reporters@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.3" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^26.6.2" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^7.0.0" + optionalDependencies: + node-notifier "^8.0.0" + +"@jest/source-map@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== + dependencies: + "@jest/console" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== + dependencies: + "@jest/test-result" "^26.6.2" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.6.2" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-regex-util "^26.0.0" + jest-util "^26.6.2" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^26.5.2": + version "26.5.2" + resolved "https://registry.npm.taobao.org/@jest/types/download/@jest/types-26.5.2.tgz#44c24f30c8ee6c7f492ead9ec3f3c62a5289756d" + integrity sha1-RMJPMMjubH9JLq2ew/PGKlKJdW0= + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@react-native-async-storage/async-storage@^1.15.4": + version "1.15.4" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.15.4.tgz#cdba464ca3bb9f10ec538342cbf2520c06f453ab" + integrity sha512-pC0MS6UBuv/YiVAxtzi7CgUed8oCQNYMtGt0yb/I9fI/BWTiJK5cj4YtW2XtL95K5IuvPX/6uGWaouZ8KqXwdg== + dependencies: + deep-assign "^3.0.0" + +"@react-native-community/checkbox@^0.5.7": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@react-native-community/checkbox/-/checkbox-0.5.7.tgz#ac818de88736acc1a4539188f2d435cf5e845ae1" + integrity sha512-CiHBAMWy5fsFIHLd1pf8frlWrLT8DnCXUSxdlGKazHm7srQSReKH4R5absShjmYOHRo9raWEnKZO/cm7MUDHZg== + +"@react-native-community/cli-debugger-ui@^5.0.1-alpha.1": + version "5.0.1-alpha.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-5.0.1-alpha.1.tgz#09a856ccd2954cf16eea59b14dd26ae66720e4e6" + integrity sha512-o6msDywXU7q0dPKhCTo8IrpmJ+7o+kVghyHlrAndnb30p6vnm4pID5Yi7lHXGfs6bQXorKUWX8oD5xYwWkN8qw== + dependencies: + serve-static "^1.13.1" + +"@react-native-community/cli-hermes@^5.0.1-alpha.1": + version "5.0.1-alpha.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-5.0.1-alpha.1.tgz#3c3836d6e537baa7615618262f8da1686052667f" + integrity sha512-7FNhqeZCbON4vhzZpV8nx4gB3COJy2KGbVku376CnIAjMncxJhupqORWdMukP8jNuuvUZ1R0vj0L0+W/M5rY1w== + dependencies: + "@react-native-community/cli-platform-android" "^5.0.1-alpha.1" + "@react-native-community/cli-tools" "^5.0.1-alpha.1" + chalk "^3.0.0" + hermes-profile-transformer "^0.0.6" + ip "^1.1.5" + +"@react-native-community/cli-platform-android@^5.0.1-alpha.0", "@react-native-community/cli-platform-android@^5.0.1-alpha.1": + version "5.0.1-alpha.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-5.0.1-alpha.1.tgz#343ea5b469ac696268ecc1961ee44b91d1367cd1" + integrity sha512-Fx9Tm0Z9sl5CD/VS8XWIY1gTgf28MMnAvyx0oj7yO4IzWuOpJPyWxTJITc80GAK6tlyijORv5kriYpXnquxQLg== + dependencies: + "@react-native-community/cli-tools" "^5.0.1-alpha.1" + chalk "^3.0.0" + execa "^1.0.0" + fs-extra "^8.1.0" + glob "^7.1.3" + jetifier "^1.6.2" + lodash "^4.17.15" + logkitty "^0.7.1" + slash "^3.0.0" + xmldoc "^1.1.2" + +"@react-native-community/cli-platform-ios@^5.0.1-alpha.0": + version "5.0.1-alpha.2" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-5.0.1-alpha.2.tgz#58ab0641355cbe68a0d1737dde8c7d66eb0c0e39" + integrity sha512-W15A75j+4bx6qbcapFia1A0M+W3JAt7Bc4VgEYvxDDRI62EsSHk1k6ZBNxs/j0cDPSYF9ZXHlRI+CWi3r9bTbQ== + dependencies: + "@react-native-community/cli-tools" "^5.0.1-alpha.1" + chalk "^3.0.0" + glob "^7.1.3" + js-yaml "^3.13.1" + lodash "^4.17.15" + plist "^3.0.1" + xcode "^2.0.0" + +"@react-native-community/cli-server-api@^5.0.1-alpha.2": + version "5.0.1-alpha.2" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-5.0.1-alpha.2.tgz#a82557273bad99d188682169892aaa4b283ba149" + integrity sha512-qzjoLF51GmvUHQrcJZE+wD3bTmgnTNOnGBU6z4terKmPdt/EBBSUkdXc6ScWWRF6oWP+xpxLZ//tKic2v2f+ag== + dependencies: + "@react-native-community/cli-debugger-ui" "^5.0.1-alpha.1" + "@react-native-community/cli-tools" "^5.0.1-alpha.1" + compression "^1.7.1" + connect "^3.6.5" + errorhandler "^1.5.0" + nocache "^2.1.0" + pretty-format "^26.6.2" + serve-static "^1.13.1" + ws "^1.1.0" + +"@react-native-community/cli-tools@^5.0.1-alpha.1": + version "5.0.1-alpha.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-5.0.1-alpha.1.tgz#b8ceed3ee5f1c2c7d860518da3dd919dc5953870" + integrity sha512-TwQxtfEOxGf8n5+UYKVO5exm56TwEAsWjYcoWkUKcSsIBl6VwCR4s3qGB8Y63uLUN2wf9MKnzvsaX337GjMVTA== + dependencies: + chalk "^3.0.0" + lodash "^4.17.15" + mime "^2.4.1" + node-fetch "^2.6.0" + open "^6.2.0" + shell-quote "1.6.1" + +"@react-native-community/cli-types@^5.0.1-alpha.1": + version "5.0.1-alpha.1" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-5.0.1-alpha.1.tgz#e8cf69966cf4e0fb5dda9bc708a52980ed1f8896" + integrity sha512-RdsLU0Jf3HodFnAY+oxCJt3VlhaN4MxGhfISvjGzqdjq3kpzmxex3+7fi6QvS97Kd6G2cheOJAdgP5wcwxp3Ng== + dependencies: + ora "^3.4.0" + +"@react-native-community/cli@^5.0.1-alpha.0": + version "5.0.1-alpha.2" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-5.0.1-alpha.2.tgz#7e78378120fd4e264e4b577cbcf5e52b5beaa53b" + integrity sha512-PP22TVV2VyELXhAX4PcBisasssastSEx23XDklfPoCPIXD2QgGC7y39n/b5I9tOzKi2qYswCEAcDpwXYwevGOg== + dependencies: + "@react-native-community/cli-debugger-ui" "^5.0.1-alpha.1" + "@react-native-community/cli-hermes" "^5.0.1-alpha.1" + "@react-native-community/cli-server-api" "^5.0.1-alpha.2" + "@react-native-community/cli-tools" "^5.0.1-alpha.1" + "@react-native-community/cli-types" "^5.0.1-alpha.1" + appdirsjs "^1.2.4" + chalk "^3.0.0" + command-exists "^1.2.8" + commander "^2.19.0" + cosmiconfig "^5.1.0" + deepmerge "^3.2.0" + envinfo "^7.7.2" + execa "^1.0.0" + find-up "^4.1.0" + fs-extra "^8.1.0" + glob "^7.1.3" + graceful-fs "^4.1.3" + joi "^17.2.1" + leven "^3.1.0" + lodash "^4.17.15" + metro "^0.64.0" + metro-config "^0.64.0" + metro-core "^0.64.0" + metro-react-native-babel-transformer "^0.64.0" + metro-resolver "^0.64.0" + metro-runtime "^0.64.0" + minimist "^1.2.0" + mkdirp "^0.5.1" + node-stream-zip "^1.9.1" + ora "^3.4.0" + pretty-format "^26.6.2" + prompts "^2.4.0" + semver "^6.3.0" + serve-static "^1.13.1" + strip-ansi "^5.2.0" + sudo-prompt "^9.0.0" + wcwidth "^1.0.1" + +"@react-native/assets@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e" + integrity sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ== + +"@react-native/normalize-color@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-1.0.0.tgz#c52a99d4fe01049102d47dc45d40cbde4f720ab6" + integrity sha512-xUNRvNmCl3UGCPbbHvfyFMnpvLPoOjDCcp5bT9m2k+TF/ZBklEQwhPZlkrxRx2NhgFh1X3a5uL7mJ7ZR+8G7Qg== + +"@react-native/polyfills@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-1.0.0.tgz#05bb0031533598f9458cf65a502b8df0eecae780" + integrity sha512-0jbp4RxjYopTsIdLl+/Fy2TiwVYHy4mgeu07DG4b/LyM0OS/+lPP5c9sbnt/AMlnF6qz2JRZpPpGw1eMNS6A4w== + +"@sideway/address@^4.1.0": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.1.tgz#9e321e74310963fdf8eebfbee09c7bd69972de4d" + integrity sha512-+I5aaQr3m0OAmMr7RQ3fR9zx55sejEYR2BFJaxL+zT3VM2611X0SHvPWIbAUBZVTn/YzYKbV8gJ2oT/QELknfQ== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@sinonjs/commons@^1.7.0": + version "1.8.1" + resolved "https://registry.npm.taobao.org/@sinonjs/commons/download/@sinonjs/commons-1.8.1.tgz?cache=0&sync_timestamp=1594975770012&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40sinonjs%2Fcommons%2Fdownload%2F%40sinonjs%2Fcommons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" + integrity sha1-598A+YogMyT23HzGBsrZ1KirIhc= + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.npm.taobao.org/@sinonjs/fake-timers/download/@sinonjs/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha1-KTZ0/MsyYqx4LHqt/eyoaxDHXEA= + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": + version "7.1.10" + resolved "https://registry.npm.taobao.org/@types/babel__core/download/@types/babel__core-7.1.10.tgz?cache=0&sync_timestamp=1600981911385&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fbabel__core%2Fdownload%2F%40types%2Fbabel__core-7.1.10.tgz#ca58fc195dd9734e77e57c6f2df565623636ab40" + integrity sha1-ylj8GV3Zc0535XxvLfVlYjY2q0A= + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.2" + resolved "https://registry.npm.taobao.org/@types/babel__generator/download/@types/babel__generator-7.6.2.tgz?cache=0&sync_timestamp=1601076667357&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fbabel__generator%2Fdownload%2F%40types%2Fbabel__generator-7.6.2.tgz#f3d71178e187858f7c45e30380f8f1b7415a12d8" + integrity sha1-89cReOGHhY98ReMDgPjxt0FaEtg= + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.0.3" + resolved "https://registry.npm.taobao.org/@types/babel__template/download/@types/babel__template-7.0.3.tgz?cache=0&sync_timestamp=1600981915244&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fbabel__template%2Fdownload%2F%40types%2Fbabel__template-7.0.3.tgz#b8aaeba0a45caca7b56a5de9459872dde3727214" + integrity sha1-uKrroKRcrKe1al3pRZhy3eNychQ= + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.0.15" + resolved "https://registry.npm.taobao.org/@types/babel__traverse/download/@types/babel__traverse-7.0.15.tgz?cache=0&sync_timestamp=1601076667199&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fbabel__traverse%2Fdownload%2F%40types%2Fbabel__traverse-7.0.15.tgz#db9e4238931eb69ef8aab0ad6523d4d4caa39d03" + integrity sha1-255COJMetp74qrCtZSPU1MqjnQM= + dependencies: + "@babel/types" "^7.3.0" + +"@types/graceful-fs@^4.1.2": + version "4.1.3" + resolved "https://registry.npm.taobao.org/@types/graceful-fs/download/@types/graceful-fs-4.1.3.tgz?cache=0&sync_timestamp=1600472533872&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fgraceful-fs%2Fdownload%2F%40types%2Fgraceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f" + integrity sha1-A5rzX+Jr7DUAPo2G0u6cWGNUNI8= + dependencies: + "@types/node" "*" + +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.3" + resolved "https://registry.npm.taobao.org/@types/istanbul-lib-coverage/download/@types/istanbul-lib-coverage-2.0.3.tgz?cache=0&sync_timestamp=1596838937660&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fistanbul-lib-coverage%2Fdownload%2F%40types%2Fistanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha1-S6jdtyAiH0MuRDvV+RF/0iz9R2I= + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.npm.taobao.org/@types/istanbul-lib-report/download/@types/istanbul-lib-report-3.0.0.tgz?cache=0&sync_timestamp=1596838937561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fistanbul-lib-report%2Fdownload%2F%40types%2Fistanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha1-wUwk8Y6oGQwRjudWK3/5mjZVJoY= + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.npm.taobao.org/@types/istanbul-reports/download/@types/istanbul-reports-3.0.0.tgz?cache=0&sync_timestamp=1596838937739&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fistanbul-reports%2Fdownload%2F%40types%2Fistanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha1-UIsTqjRPpJdiNOdd3cw0klc32CE= + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.npm.taobao.org/@types/json5/download/@types/json5-0.0.29.tgz?cache=0&sync_timestamp=1596839392866&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fjson5%2Fdownload%2F%40types%2Fjson5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +"@types/node@*": + version "14.11.5" + resolved "https://registry.npm.taobao.org/@types/node/download/@types/node-14.11.5.tgz#fecad41c041cae7f2404ad4b2d0742fdb628b305" + integrity sha1-/srUHAQcrn8kBK1LLQdC/bYoswU= + +"@types/node@^12.0.12": + version "12.20.13" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.13.tgz#e743bae112bd779ac9650f907197dd2caa7f0364" + integrity sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A== + +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.npm.taobao.org/@types/normalize-package-data/download/@types/normalize-package-data-2.4.0.tgz?cache=0&sync_timestamp=1596839391651&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnormalize-package-data%2Fdownload%2F%40types%2Fnormalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4= + +"@types/prettier@^2.0.0": + version "2.1.1" + resolved "https://registry.npm.taobao.org/@types/prettier/download/@types/prettier-2.1.1.tgz?cache=0&sync_timestamp=1600119657716&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fprettier%2Fdownload%2F%40types%2Fprettier-2.1.1.tgz#be148756d5480a84cde100324c03a86ae5739fb5" + integrity sha1-vhSHVtVICoTN4QAyTAOoauVzn7U= + +"@types/prop-types@*": + version "15.7.3" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" + integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== + +"@types/react-redux@^7.1.16": + version "7.1.16" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21" + integrity sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + +"@types/react@*": + version "17.0.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79" + integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.1" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" + integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== + +"@types/stack-utils@^2.0.0": + version "2.0.0" + resolved "https://registry.npm.taobao.org/@types/stack-utils/download/@types/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" + integrity sha1-cDZkC04hzC8lmugmzoQ9J32tjP8= + +"@types/yargs-parser@*": + version "15.0.0" + resolved "https://registry.npm.taobao.org/@types/yargs-parser/download/@types/yargs-parser-15.0.0.tgz?cache=0&sync_timestamp=1596841192658&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs-parser%2Fdownload%2F%40types%2Fyargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" + integrity sha1-yz+fdBhp4gzOMw/765JxWQSDiC0= + +"@types/yargs@^15.0.0": + version "15.0.7" + resolved "https://registry.npm.taobao.org/@types/yargs/download/@types/yargs-15.0.7.tgz?cache=0&sync_timestamp=1600887248772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-15.0.7.tgz#dad50a7a234a35ef9460737a56024287a3de1d2b" + integrity sha1-2tUKeiNKNe+UYHN6VgJCh6PeHSs= + dependencies: + "@types/yargs-parser" "*" + +"@yarnpkg/lockfile@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +abab@^2.0.3: + version "2.0.5" + resolved "https://registry.npm.taobao.org/abab/download/abab-2.0.5.tgz?cache=0&sync_timestamp=1599849993777&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fabab%2Fdownload%2Fabab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha1-wLZ4+zLWD8EhnHhNaoJv44Wut5o= + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/abort-controller/download/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha1-6vVNU7YrrkE46AnKIlyEOabvs5I= + dependencies: + event-target-shim "^5.0.0" + +absolute-path@^0.0.0: + version "0.0.0" + resolved "https://registry.npm.taobao.org/absolute-path/download/absolute-path-0.0.0.tgz#a78762fbdadfb5297be99b15d35a785b2f095bf7" + integrity sha1-p4di+9rftSl76ZsV01p4Wy8JW/c= + +accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha1-UxvHJlF6OytB+FACHGzBXqq1B80= + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/acorn-globals/download/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha1-Rs3Tnw+P8IqHZhm1X1rIptx3C0U= + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.npm.taobao.org/acorn-walk/download/acorn-walk-7.2.0.tgz?cache=0&sync_timestamp=1597235855275&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn-walk%2Fdownload%2Facorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha1-DeiJpgEgOQmw++B7iTjcIdLpZ7w= + +acorn@^7.1.1, acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.npm.taobao.org/acorn/download/acorn-7.4.1.tgz?cache=0&sync_timestamp=1601885779818&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Facorn%2Fdownload%2Facorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo= + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^6.12.3: + version "6.12.5" + resolved "https://registry.npm.taobao.org/ajv/download/ajv-6.12.5.tgz?cache=0&sync_timestamp=1600886864349&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fajv%2Fdownload%2Fajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" + integrity sha1-GbDouuj0duW6ZmMAOHd1+xoApNo= + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^7.0.2: + version "7.2.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.2.3.tgz#ca78d1cf458d7d36d1c3fa0794dd143406db5772" + integrity sha512-idv5WZvKVXDqKralOImQgPM9v6WOdLNa0IY3B3doOjw/YxRGT8I+allIJ6kd7Uaj+SF1xZUSU+nPM5aDNBVtnw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +anser@^1.4.9: + version "1.4.10" + resolved "https://registry.npm.taobao.org/anser/download/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" + integrity sha1-vvo+3fKCaEvQO2Pc2jknrvjC41s= + +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= + dependencies: + string-width "^2.0.0" + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^4.2.1: + version "4.3.1" + resolved "https://registry.npm.taobao.org/ansi-escapes/download/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" + integrity sha1-pcR8xDGB8fOP/XB2g3cA05VSKmE= + dependencies: + type-fest "^0.11.0" + +ansi-fragments@^0.2.1: + version "0.2.1" + resolved "https://registry.npm.taobao.org/ansi-fragments/download/ansi-fragments-0.2.1.tgz#24409c56c4cc37817c3d7caa99d8969e2de5a05e" + integrity sha1-JECcVsTMN4F8PXyqmdiWni3loF4= + dependencies: + colorette "^1.0.7" + slice-ansi "^2.0.0" + strip-ansi "^5.0.0" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc= + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz?cache=0&sync_timestamp=1601839122515&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0= + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha1-vLJLTzeTTZqnrBe0ra+J58du8us= + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.3: + version "3.1.1" + resolved "https://registry.npm.taobao.org/anymatch/download/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha1-xV7PAhheJGklk5kxDBc84xIzsUI= + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +appdirsjs@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.4.tgz#3ab582acc9fdfaaa0c1f81b3a25422ad4d95f9d4" + integrity sha512-WO5StDORR6JF/xYnXk/Fm0yu+iULaV5ULKuUw0Tu+jbgiTlSquaWBCgbpnsHLMXldf+fM3Gxn5p7vjond7He6w== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/arr-diff/download/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha1-NgSLv/TntH4TZkQxbJlmnqWukfE= + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.npm.taobao.org/array-filter/download/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= + +array-includes@^3.1.1: + version "3.1.1" + resolved "https://registry.npm.taobao.org/array-includes/download/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha1-zdZ+aFK9+cEhVGB4ZzIlXtJFk0g= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + +array-includes@^3.1.2, array-includes@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" + integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.2" + get-intrinsic "^1.1.1" + is-string "^1.0.5" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.npm.taobao.org/array-map/download/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.npm.taobao.org/array-reduce/download/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +array.prototype.flat@^1.2.3: + version "1.2.3" + resolved "https://registry.npm.taobao.org/array.prototype.flat/download/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha1-DegrQmsDGNv9uUAInjiwQ9N/bHs= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +array.prototype.flatmap@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" + integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + function-bind "^1.1.1" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.npm.taobao.org/asap/download/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha1-jSR136tVO7M+d7VOWeiAu4ziMTY= + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/assign-symbols/download/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +ast-types@0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" + integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== + dependencies: + tslib "^2.0.1" + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/astral-regex/download/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k= + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^2.4.0: + version "2.6.3" + resolved "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8= + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz?cache=0&sync_timestamp=1589682812085&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws-sign2%2Fdownload%2Faws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.10.1" + resolved "https://registry.npm.taobao.org/aws4/download/aws4-1.10.1.tgz?cache=0&sync_timestamp=1597236947743&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faws4%2Fdownload%2Faws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" + integrity sha1-4eguTz6Zniz9YbFhKA0WoRH4ZCg= + +babel-core@^7.0.0-bridge.0: + version "7.0.0-bridge.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" + integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== + +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&sync_timestamp=1599054223324&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha1-aWjlaKkQt4+zd5zdi2rC9HmUMjI= + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== + dependencies: + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.npm.taobao.org/babel-plugin-dynamic-import-node/download/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha1-hP2hnJduxcbe/vV/lCez3vZuF6M= + dependencies: + object.assign "^4.1.0" + +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/babel-plugin-istanbul/download/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha1-4VnM3Jr5XgtXDHW0Vzt8NNZx12U= + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-module-resolver@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.1.0.tgz#22a4f32f7441727ec1fbf4967b863e1e3e9f33e2" + integrity sha512-MlX10UDheRr3lb3P0WcaIdtCSRlxdQsB1sBqL7W0raF070bGl1HQQq5K3T2vf2XAYie+ww+5AKC/WrkjRO2knA== + dependencies: + find-babel-config "^1.2.0" + glob "^7.1.6" + pkg-up "^3.1.0" + reselect "^4.0.0" + resolve "^1.13.1" + +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.npm.taobao.org/babel-plugin-syntax-trailing-function-commas/download/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha1-qiE8FDXiv/62/KhCKH71NK0F1c8= + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-fbjs@^3.3.0: + version "3.3.0" + resolved "https://registry.npm.taobao.org/babel-preset-fbjs/download/babel-preset-fbjs-3.3.0.tgz#a6024764ea86c8e06a22d794ca8b69534d263541" + integrity sha1-pgJHZOqGyOBqIteUyotpU00mNUE= + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== + dependencies: + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.npm.taobao.org/base-64/download/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha1-eAqZyE59YAJgNhURxId2E78k9rs= + +base64-js@^1.0.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base64-js@^1.1.2, base64-js@^1.2.3, base64-js@^1.3.1: + version "1.3.1" + resolved "https://registry.npm.taobao.org/base64-js/download/base64-js-1.3.1.tgz?cache=0&sync_timestamp=1599054234315&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbase64-js%2Fdownload%2Fbase64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha1-WOzoy3XdB+ce0IxzarxfrE2/jfE= + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.npm.taobao.org/base/download/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha1-e95c7RRbbVUakNuH+DxVi060io8= + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +big-integer@^1.6.44: + version "1.6.48" + resolved "https://registry.npm.taobao.org/big-integer/download/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" + integrity sha1-j9iL0WMsukocjD49cVnwi7lbS54= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +boolean@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.4.tgz#aa1df8749af41d7211b66b4eee584722ff428c27" + integrity sha512-5pyOr+w2LNN72F2mAq6J0ckHUfJYSgRKma7e/wlcMMhgOLV9OI0ERhERYXxUqo+dPyVxcbXKy9n+wg13+LpNnA== + +boxen@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^2.0.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^1.2.0" + widest-line "^2.0.0" + +bplist-creator@0.0.8: + version "0.0.8" + resolved "https://registry.npm.taobao.org/bplist-creator/download/bplist-creator-0.0.8.tgz#56b2a6e79e9aec3fc33bf831d09347d73794e79c" + integrity sha1-VrKm556a7D/DO/gx0JNH1zeU55w= + dependencies: + stream-buffers "~2.2.0" + +bplist-parser@0.2.0: + version "0.2.0" + resolved "https://registry.npm.taobao.org/bplist-parser/download/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha1-Q6nRg+W/nVRSAM6sPnEveeu+jQ4= + dependencies: + big-integer "^1.6.44" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.npm.taobao.org/braces/download/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha1-WXn9PxTNUxVl5fot8av/8d+u5yk= + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.npm.taobao.org/braces/download/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha1-NFThpGLujVmeI23zNs2epPiv4Qc= + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/browser-process-hrtime/download/browser-process-hrtime-1.0.0.tgz?cache=0&sync_timestamp=1589683598073&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrowser-process-hrtime%2Fdownload%2Fbrowser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha1-PJtLfXgsgSHlbxAQbYTA0P/JRiY= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^4.14.5: + version "4.16.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== + dependencies: + caniuse-lite "^1.0.30001181" + colorette "^1.2.1" + electron-to-chromium "^1.3.649" + escalade "^3.1.1" + node-releases "^1.1.70" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.npm.taobao.org/bser/download/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha1-5nh9og7OnQeZhTPP2d5vXDj0vAU= + dependencies: + node-int64 "^0.4.0" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha1-MnE7wCj3XAL9txDXx7zsHyxgcO8= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.9.1: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/bytes/download/bytes-3.0.0.tgz?cache=0&sync_timestamp=1589682741197&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbytes%2Fdownload%2Fbytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha1-Cn9GQWgxyLZi7jb+TnxZ129marI= + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/caller-callsite/download/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/caller-path/download/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/callsites/download/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz?cache=0&sync_timestamp=1589682790492&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA= + +camelcase@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/camelcase/download/camelcase-6.0.0.tgz?cache=0&sync_timestamp=1589682790492&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcamelcase%2Fdownload%2Fcamelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" + integrity sha1-Uln3ww414njxvcKk2RIws3ytmB4= + +caniuse-lite@^1.0.30001181: + version "1.0.30001204" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001204.tgz#256c85709a348ec4d175e847a3b515c66e79f2aa" + integrity sha512-JUdjWpcxfJ9IPamy2f5JaRDCaqJOxDzOSKtbdx4rH9VivMd1vIzoPumsJa9LoMIi4Fx2BV2KZOxWhNkBjaYivQ== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/capture-exit/download/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha1-+5U7+uvreB9iiYI52rtCbQilCaQ= + dependencies: + rsvp "^4.8.4" + +capture-stack-trace@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" + integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/chalk/download/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ= + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +changelog-parser@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/changelog-parser/-/changelog-parser-2.8.0.tgz#c14293e3e8fab797913c722de965480198650108" + integrity sha512-ZtSwN0hY7t+WpvaXqqXz98RHCNhWX9HsvCRAv1aBLlqJ7BpKtqdM6Nu6JOiUhRAWR7Gov0aN0fUnmflTz0WgZg== + dependencies: + line-reader "^0.2.4" + remove-markdown "^0.2.2" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/char-regex/download/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha1-10Q1giYhf5ge1Y9Hmx1rzClUXc8= + +ci-info@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/ci-info/download/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y= + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +cjs-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha1-+TNprouafOAv1B+q0MqDAzGQxGM= + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/cli-cursor/download/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^2.0.0: + version "2.4.0" + resolved "https://registry.npm.taobao.org/cli-spinners/download/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha1-xiVtsha4eM+6RyDnGc7Hz3JoXX8= + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/cliui/download/cliui-6.0.0.tgz?cache=0&sync_timestamp=1597608006561&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha1-UR1wLAxOQcoVbX0OlgIfI+EyJbE= + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npm.taobao.org/clone/download/clone-1.0.4.tgz?cache=0&sync_timestamp=1589682821772&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fclone%2Fdownload%2Fclone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz?cache=0&sync_timestamp=1589683669101&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fco%2Fdownload%2Fco-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/collect-v8-coverage/download/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha1-zCyOlPwYu9/+ZNZTRXDIpnOyf1k= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^1.0.7: + version "1.2.1" + resolved "https://registry.npm.taobao.org/colorette/download/colorette-1.2.1.tgz?cache=0&sync_timestamp=1593955763917&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcolorette%2Fdownload%2Fcolorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha1-TQuSEyXBT6+SYzCGpTbbbolWSxs= + +colorette@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha1-w9RaizT9cwYxoRCoolIGgrMdWn8= + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.npm.taobao.org/command-exists/download/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha1-xQclrzgIyKsCYP1gsB+/oluVT2k= + +commander@^2.19.0: + version "2.20.3" + resolved "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1598576116597&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha1-/UhehMA+tIgcIHIrpIA16FMa6zM= + +commander@~2.13.0: + version "2.13.0" + resolved "https://registry.npm.taobao.org/commander/download/commander-2.13.0.tgz?cache=0&sync_timestamp=1598576116597&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + integrity sha1-aWS8pnaF33wfFDDFhPB9dZeIW5w= + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/commondir/download/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A= + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.npm.taobao.org/compressible/download/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha1-r1PMprBw1MPAdQ+9dyhqbXzEb7o= + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.1: + version "1.7.4" + resolved "https://registry.npm.taobao.org/compression/download/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha1-lVI+/xcMpXwpoMpB5v4TH0Hlu48= + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@^1.1.11: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^3.0.0: + version "3.1.5" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.5.tgz#e9af331fadc14dabd544d3e7e76dc446a09a530f" + integrity sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA== + dependencies: + dot-prop "^4.2.1" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +connect@^3.6.5: + version "3.7.0" + resolved "https://registry.npm.taobao.org/connect/download/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha1-XUk0iRDKpeB6AYALAw0MNfIEhPg= + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +console-browserify@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.npm.taobao.org/contains-path/download/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js@^3.6.5: + version "3.12.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.1.tgz#6b5af4ff55616c08a44d386f1f510917ff204112" + integrity sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw== + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cosmiconfig@^5.0.5, cosmiconfig@^5.1.0: + version "5.2.1" + resolved "https://registry.npm.taobao.org/cosmiconfig/download/cosmiconfig-5.2.1.tgz?cache=0&sync_timestamp=1596310819353&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcosmiconfig%2Fdownload%2Fcosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha1-BA9yaAnFked6F8CjYmykW08Wixo= + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= + dependencies: + capture-stack-trace "^1.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q= + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.npm.taobao.org/cross-spawn/download/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha1-9zqFudXUHQRVUcF34ogtSshXKKY= + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= + +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.npm.taobao.org/cssom/download/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha1-WmbPk9LQtmHYC/akT7ZfXC5OChA= + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.npm.taobao.org/cssom/download/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha1-nxJ29bK0Y/IRTT8sdSUK+MGjb0o= + +cssstyle@^2.2.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/cssstyle/download/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha1-/2ZaDdvcMYZLCWR/NBY0Q9kLCFI= + dependencies: + cssom "~0.3.6" + +csstype@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" + integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g== + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz?cache=0&sync_timestamp=1601073454623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdashdash%2Fdownload%2Fdashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/data-urls/download/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha1-FWSFpyljqXD11YIar2Qr7yvy25s= + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + +dayjs@^1.8.15: + version "1.9.1" + resolved "https://registry.npm.taobao.org/dayjs/download/dayjs-1.9.1.tgz?cache=0&sync_timestamp=1601296698962&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdayjs%2Fdownload%2Fdayjs-1.9.1.tgz#201a755f7db5103ed6de63ba93a984141c754541" + integrity sha1-IBp1X321ED7W3mO6k6mEFBx1RUE= + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1600502894812&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8= + dependencies: + ms "2.0.0" + +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decimal.js@^10.2.0: + version "10.2.1" + resolved "https://registry.npm.taobao.org/decimal.js/download/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha1-I4rnsPDHk9PjzqQQEIs1osAUJqM= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-3.0.0.tgz#c8e4c4d401cba25550a2f0f486a2e75bc5f219a2" + integrity sha512-YX2i9XjJ7h5q/aQ/IM9PEwEnDqETAIYbggmdDB3HLTlSgo1CxPsj6pvhPG68rq6SVE0+p+6Ywsm5fTYNrYtBWw== + dependencies: + is-obj "^1.0.0" + +deep-diff@^0.3.5: + version "0.3.8" + resolved "https://registry.npm.taobao.org/deep-diff/download/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" + integrity sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ= + +deep-equal@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.npm.taobao.org/deep-is/download/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +deepmerge@^3.2.0: + version "3.3.0" + resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-3.3.0.tgz#d3c47fd6f3a93d517b14426b0628a17b0125f5f7" + integrity sha1-08R/1vOpPVF7FEJrBiihewEl9fc= + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha1-RNLqNnm49NT/ujPwPYZfwee/SVU= + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE= + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.npm.taobao.org/define-property/download/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/define-property/download/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.npm.taobao.org/define-property/download/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha1-1Flono1lS6d+AqgX+HENcCyxbp0= + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.npm.taobao.org/denodeify/download/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" + integrity sha1-OjYof1A05pnnV3kBBSwubJQlFjE= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/detect-newline/download/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha1-V29d/GOuGhkv8ZLYrTr2MImRtlE= + +detect-node@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.5.tgz#9d270aa7eaa5af0b72c4c9d9b814e7f4ce738b79" + integrity sha512-qi86tE6hRcFHy8jI1m2VG+LaPUR1LhqDa5G8tVjuUXmOrpuAgqsA1pN0+ldgr3aKUH+QLI9hCY/OcRYisERejw== + +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.npm.taobao.org/doctrine/download/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/doctrine/download/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha1-XNAfwQFiG0LEzX9dGmYkNxbT850= + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@^1.0.1: + version "1.1.0" + resolved "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58" + integrity sha1-X3yCjxv8RIh9wqMVq1xFaR1US1g= + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + entities "^2.0.0" + +domelementtype@^2.0.1: + version "2.0.2" + resolved "https://registry.npm.taobao.org/domelementtype/download/domelementtype-2.0.2.tgz?cache=0&sync_timestamp=1600028495728&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomelementtype%2Fdownload%2Fdomelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" + integrity sha1-87blSSAeRvWItZRj3XcYcTH+aXE= + +domelementtype@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" + integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/domexception/download/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha1-+0Su+6eT4VdLCvau0oAdBXUp8wQ= + dependencies: + webidl-conversions "^5.0.0" + +domhandler@^3.0.0: + version "3.3.0" + resolved "https://registry.npm.taobao.org/domhandler/download/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" + integrity sha1-bbfqRuRhfrFc+HXfaLK4UkzgA3o= + dependencies: + domelementtype "^2.0.1" + +domhandler@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e" + integrity sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA== + dependencies: + domelementtype "^2.1.0" + +domutils@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3" + integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.0.1" + domhandler "^4.0.0" + +dot-prop@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" + integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== + dependencies: + is-obj "^1.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz?cache=0&sync_timestamp=1589682745945&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecc-jsbn%2Fdownload%2Fecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.649: + version "1.3.697" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.697.tgz#4ba8af135d72d06534bd78f68d1be0dca3d2c590" + integrity sha512-VTAS+IWwGlfaL7VtfUMzFeV55PT/HglNFqQ6eW9E3PfjvPqhZfqJj+8dd9zrqrJYcouUfCgQw0OIse85Dz9V9Q== + +electron@^11.1.0: + version "11.4.6" + resolved "https://registry.yarnpkg.com/electron/-/electron-11.4.6.tgz#0a5e3aebca0bf576633a5adb8fb4295eb7221afc" + integrity sha512-WN7zUwaAmcB1lXyyaMxPsNWAFCpRMDltQb4zCjvoD5TBBoePcjd6UwyVUD93pSKJXjmWoae8PbZWrbZlXowcSg== + dependencies: + "@electron/get" "^1.0.1" + "@types/node" "^12.0.12" + extract-zip "^1.0.3" + +elliptic@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emittery@^0.7.1: + version "0.7.1" + resolved "https://registry.npm.taobao.org/emittery/download/emittery-0.7.1.tgz?cache=0&sync_timestamp=1593956086892&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Femittery%2Fdownload%2Femittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" + integrity sha1-wCN1qSekCUjANFzJAwcll/UnBFE= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@^1.0.2, encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha1-WuZKX0UFe682JuwU2gyl5LJDHrA= + dependencies: + once "^1.4.0" + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +entities@^2.0.0: + version "2.0.3" + resolved "https://registry.npm.taobao.org/entities/download/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha1-XEh+V0Krk8Fau12iJ1m4WQ7AO38= + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +envinfo@^7.7.2: + version "7.7.3" + resolved "https://registry.npm.taobao.org/envinfo/download/envinfo-7.7.3.tgz?cache=0&sync_timestamp=1598316397491&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenvinfo%2Fdownload%2Fenvinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc" + integrity sha1-Sy2GIuPnNmr7gJGyPtlVaeoCCMw= + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha1-tKxAZIEH/c3PriQvQovqihTU8b8= + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.6.tgz#5a99a707bd7a4c58a797902d48d82803ede6aad8" + integrity sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ== + dependencies: + stackframe "^1.1.1" + +errorhandler@^1.5.0: + version "1.5.1" + resolved "https://registry.npm.taobao.org/errorhandler/download/errorhandler-1.5.1.tgz#b9ba5d17cf90744cd1e851357a6e75bf806a9a91" + integrity sha1-ubpdF8+QdEzR6FE1em51v4BqmpE= + dependencies: + accepts "~1.3.7" + escape-html "~1.0.3" + +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: + version "1.17.7" + resolved "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.17.7.tgz?cache=0&sync_timestamp=1601502719982&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha1-pN5hsvZpifx0IWdsHLl4dXOs5Uw= + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-abstract@^1.18.0-next.0: + version "1.18.0-next.1" + resolved "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.18.0-next.1.tgz?cache=0&sync_timestamp=1601502719982&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha1-bjoKS9pxflAjqzuOkL7DYQjSLGg= + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: + version "1.18.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" + integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.2" + is-callable "^1.2.3" + is-negative-zero "^2.0.1" + is-regex "^1.1.2" + is-string "^1.0.5" + object-inspect "^1.9.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.npm.taobao.org/es-to-primitive/download/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha1-5VzUyc3BiLzvsDs2bHNjI/xciYo= + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-error@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha1-owME6Z2qMuI7L9IPUbq9B8/8o0Q= + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^1.14.1: + version "1.14.3" + resolved "https://registry.npm.taobao.org/escodegen/download/escodegen-1.14.3.tgz?cache=0&sync_timestamp=1596669832613&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescodegen%2Fdownload%2Fescodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha1-TnuB+6YVgdyXWC7XjKt/Do1j9QM= + dependencies: + esprima "^4.0.1" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-standard@^16.0.2: + version "16.0.2" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz#71e91727ac7a203782d0a5ca4d1c462d14e234f6" + integrity sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw== + +eslint-import-resolver-node@^0.3.4: + version "0.3.4" + resolved "https://registry.npm.taobao.org/eslint-import-resolver-node/download/eslint-import-resolver-node-0.3.4.tgz?cache=0&sync_timestamp=1592327223893&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-import-resolver-node%2Fdownload%2Feslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha1-hf+oGULCUBLYIxCW3fZ5wDBCxxc= + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.6.0: + version "2.6.0" + resolved "https://registry.npm.taobao.org/eslint-module-utils/download/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + integrity sha1-V569CU9Wr3eX0ZyYZsnJSGYpv6Y= + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.npm.taobao.org/eslint-plugin-es/download/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha1-dafN/czdwFiZNK7rOEF18iHFeJM= + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-html@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-6.1.2.tgz#fa26e4804428956c80e963b6499c192061c2daf3" + integrity sha512-bhBIRyZFqI4EoF12lGDHAmgfff8eLXx6R52/K3ESQhsxzCzIE6hdebS7Py651f7U3RBotqroUnC3L29bR7qJWQ== + dependencies: + htmlparser2 "^6.0.1" + +eslint-plugin-import@^2.22.1: + version "2.22.1" + resolved "https://registry.npm.taobao.org/eslint-plugin-import/download/eslint-plugin-import-2.22.1.tgz?cache=0&sync_timestamp=1601248464145&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-import%2Fdownload%2Feslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha1-CJbH5qDPRBCaLZe5WQPCu2iddwI= + dependencies: + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.4" + eslint-module-utils "^2.6.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.1" + read-pkg-up "^2.0.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.npm.taobao.org/eslint-plugin-node/download/eslint-plugin-node-11.1.0.tgz?cache=0&sync_timestamp=1589806431146&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-plugin-node%2Fdownload%2Feslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha1-yVVEQW7kraJnQKMEdO78VALcZx0= + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-promise@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz#fb2188fb734e4557993733b41aa1a688f46c6f24" + integrity sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng== + +eslint-plugin-react-hooks@^4.2.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/eslint-plugin-react-hooks/download/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" + integrity sha1-jCKcJo1GiVYzTJQ7tF/IYCgPVVY= + +eslint-plugin-react@^7.23.2: + version "7.23.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.23.2.tgz#2d2291b0f95c03728b55869f01102290e792d494" + integrity sha512-AfjgFQB+nYszudkxRkTFu0UR1zEQig0ArVMPloKhxwlwkzaw/fBiH0QWcBBhZONlXqQC51+nfqFrkn4EzHcGBw== + dependencies: + array-includes "^3.1.3" + array.prototype.flatmap "^1.2.4" + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.0.4" + object.entries "^1.1.3" + object.fromentries "^2.0.4" + object.values "^1.1.3" + prop-types "^15.7.2" + resolve "^2.0.0-next.3" + string.prototype.matchall "^4.0.4" + +eslint-plugin-standard@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-5.0.0.tgz#c43f6925d669f177db46f095ea30be95476b1ee4" + integrity sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/eslint-utils/download/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc= + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.npm.taobao.org/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz?cache=0&sync_timestamp=1597435068105&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Feslint-visitor-keys%2Fdownload%2Feslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha1-MOvR73wv3/AcOk8VEESvJfqwUj4= + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.26.0: + version "7.26.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.26.0.tgz#d416fdcdcb3236cd8f282065312813f8c13982f6" + integrity sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.4.1" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^13.6.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.21" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.npm.taobao.org/esprima/download/esprima-4.0.1.tgz?cache=0&sync_timestamp=1589682833047&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fesprima%2Fdownload%2Fesprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha1-E7BM2z5sXRnfkatph6hpVhmwqnE= + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1, estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.npm.taobao.org/estraverse/download/estraverse-4.3.0.tgz?cache=0&sync_timestamp=1596642998635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Festraverse%2Fdownload%2Festraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0= + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +event-target-shim@^5.0.0, event-target-shim@^5.0.1: + version "5.0.1" + resolved "https://registry.npm.taobao.org/event-target-shim/download/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha1-XU0+vflYPWOlMzzi3rdICrKwV4k= + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +exec-sh@^0.3.2: + version "0.3.4" + resolved "https://registry.npm.taobao.org/exec-sh/download/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" + integrity sha1-OgGM61JsxvbfK7UEsr/o46STTsU= + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg= + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^4.0.0: + version "4.0.3" + resolved "https://registry.npm.taobao.org/execa/download/execa-4.0.3.tgz#0a34dabbad6d66100bd6f2c576c8669403f317f2" + integrity sha1-CjTau61tZhAL1vLFdshmlAPzF/I= + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.npm.taobao.org/exit/download/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== + dependencies: + "@jest/types" "^26.6.2" + ansi-styles "^4.0.0" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz?cache=0&sync_timestamp=1589682707348&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fextend%2Fdownload%2Fextend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo= + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM= + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extract-zip@^1.0.3: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.npm.taobao.org/fb-watchman/download/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha1-/IT7OdJwnPP/bXQ3BhV7tXCKioU= + dependencies: + bser "2.1.1" + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/fill-range/download/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npm.taobao.org/fill-range/download/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha1-GRmmp8df44ssfHflGYU12prN2kA= + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.npm.taobao.org/finalhandler/download/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha1-t+fQAP/RGTjQ/bBTUG9uur6fWH0= + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-babel-config@^1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/find-babel-config/download/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2" + integrity sha1-qbezF+tbmGDNqdVHQKjIM3oig6I= + dependencies: + json5 "^0.5.1" + path-exists "^3.0.0" + +find-cache-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/find-cache-dir/download/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha1-jQ+UzRP+Q8bHwmGg2GEVypGMBfc= + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/find-up/download/find-up-2.1.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/find-up/download/find-up-3.0.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha1-SRafHXmTQwZG2mHsxa41XCHJe3M= + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npm.taobao.org/find-up/download/find-up-4.1.0.tgz?cache=0&sync_timestamp=1597169842138&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffind-up%2Fdownload%2Ffind-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha1-l6/n1s3AvFkoWEt8jXsW6KmqXRk= + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +findit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findit/-/findit-2.0.0.tgz#6509f0126af4c178551cfa99394e032e13a4d56e" + integrity sha1-ZQnwEmr0wXhVHPqZOU4DLhOk1W4= + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + +flow-parser@0.*: + version "0.147.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.147.0.tgz#747f67611e731c89927dd5d368bf7f616d1e51be" + integrity sha512-z+b/pgp2QLvsWJkzhKXU8yC5TmaNyXGRmHac3x0Swmn9uQESRXhNIJq9TPHKPPeWgFym33OLO+5BlIdy/tXRCQ== + +flow-parser@^0.121.0: + version "0.121.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f" + integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha1-3M5SwF9kTymManq5Nr1yTO/786Y= + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz?cache=0&sync_timestamp=1589682752100&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffresh%2Fdownload%2Ffresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-extra@^0.22.1: + version "0.22.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.22.1.tgz#5fd6f8049dc976ca19eb2355d658173cabcce056" + integrity sha1-X9b4BJ3JdsoZ6yNV1lgXPKvM4FY= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + rimraf "^2.2.8" + +fs-extra@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/fs-extra/download/fs-extra-1.0.0.tgz?cache=0&sync_timestamp=1591229972229&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" + integrity sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz?cache=0&sync_timestamp=1591229972229&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA= + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^2.1.2: + version "2.1.3" + resolved "https://registry.npm.taobao.org/fsevents/download/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha1-+3OHA66NL5/pAMM4Nt3r7ouX8j4= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha1-WPQ2H/mH5f9uHnohCCeqNx6qwmk= + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npm.taobao.org/get-caller-file/download/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha1-T5RBKoLbMvNuOwuXQfipf+sDH34= + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.npm.taobao.org/get-package-type/download/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha1-jeLYA8/0TfO8bEVuZmizbDkm4Ro= + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz?cache=0&sync_timestamp=1597056502934&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fget-stream%2Fdownload%2Fget-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha1-wbJVV189wh1Zv8ec09K0axw6VLU= + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0, get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.npm.taobao.org/get-stream/download/get-stream-5.2.0.tgz?cache=0&sync_timestamp=1597056502934&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fget-stream%2Fdownload%2Fget-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha1-SWaheV7lrOZecGxLe+txJX1uItM= + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz?cache=0&sync_timestamp=1589682745510&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgetpass%2Fdownload%2Fgetpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-parent@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-agent@^2.0.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/global-agent/-/global-agent-2.2.0.tgz#566331b0646e6bf79429a16877685c4a1fbf76dc" + integrity sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg== + dependencies: + boolean "^3.0.1" + core-js "^3.6.5" + es6-error "^4.1.1" + matcher "^3.0.0" + roarr "^2.15.3" + semver "^7.3.2" + serialize-error "^7.0.1" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= + dependencies: + ini "^1.3.4" + +global-tunnel-ng@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz#d03b5102dfde3a69914f5ee7d86761ca35d57d8f" + integrity sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg== + dependencies: + encodeurl "^1.0.2" + lodash "^4.17.10" + npm-conf "^1.1.3" + tunnel "^0.0.6" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +globals@^13.6.0: + version "13.7.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.7.0.tgz#aed3bcefd80ad3ec0f0be2cf0c895110c0591795" + integrity sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.2.tgz#2a235d34f4d8036219f7e34929b5de9e18166b8b" + integrity sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ== + dependencies: + define-properties "^1.1.3" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: + version "4.2.4" + resolved "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.2.4.tgz?cache=0&sync_timestamp=1589682809142&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fgraceful-fs%2Fdownload%2Fgraceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha1-Ila94U02MpWMRl68ltxGfKB6Kfs= + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.npm.taobao.org/growly/download/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.5.tgz?cache=0&sync_timestamp=1596082584903&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhar-validator%2Fdownload%2Fhar-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha1-HwgDufjLIMD6E4It8ezds2veHv0= + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-bigints@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.0, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/has-symbols/download/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha1-n1IUdYpEGWxAbZvXbOv4HsLdMeg= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hermes-engine@~0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/hermes-engine/-/hermes-engine-0.7.2.tgz#303cd99d23f68e708b223aec2d49d5872985388b" + integrity sha512-E2DkRaO97gwL98LPhgfkMqhHiNsrAjIfEk3wWYn2Y31xdkdWn0572H7RnVcGujMJVqZNJvtknxlpsUb8Wzc3KA== + +hermes-profile-transformer@^0.0.6: + version "0.0.6" + resolved "https://registry.npm.taobao.org/hermes-profile-transformer/download/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" + integrity sha1-vQ9ezO2oDdDdquRDRpqyb7OPwns= + dependencies: + source-map "^0.7.3" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoist-non-react-statics@3.x.x, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hosted-git-info@^2.1.4: + version "2.8.8" + resolved "https://registry.npm.taobao.org/hosted-git-info/download/hosted-git-info-2.8.8.tgz?cache=0&sync_timestamp=1594427993800&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhosted-git-info%2Fdownload%2Fhosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha1-dTm9S8Hg4KiVgVouAmJCCxKFhIg= + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/html-encoding-sniffer/download/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha1-QqbcT9M/ACgRduiyN1nKTk+hhfM= + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npm.taobao.org/html-escaper/download/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha1-39YAJ9o2o238viNiYsAKWCJoFFM= + +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + +htmlparser2@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.0.1.tgz#422521231ef6d42e56bd411da8ba40aa36e91446" + integrity sha512-GDKPd+vk4jvSuvCbyuzx/unmXkk090Azec7LovXP8as1Hn8q9p3hbjmDGbUqqhknw0ajwit6LiiWqfiTUPMK7w== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.4.4" + entities "^2.0.0" + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz?cache=0&sync_timestamp=1593407858306&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY= + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz?cache=0&sync_timestamp=1600868452638&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-signature%2Fdownload%2Fhttp-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/human-signals/download/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha1-xbHNFPUK6uCatsWf5jujOV/k36M= + +i18next@^20.2.2: + version "20.2.2" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-20.2.2.tgz#175644829dcf35546ba8c174583acfe449e4ef1a" + integrity sha512-uWCv9LzKpe+OwvnKKrb8CbJwgAhasQofD58cB0PQ6bTPXEl5PlItl5C4esmY8HtriLu9nrjc2Hi0IfYv3Fy8BQ== + dependencies: + "@babel/runtime" "^7.12.0" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs= + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.npm.taobao.org/ieee754/download/ieee754-1.2.1.tgz?cache=0&sync_timestamp=1603838208740&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fieee754%2Fdownload%2Fieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha1-jrehCmP/8l0VpXsAFYbRd9Gw01I= + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1: + version "5.1.8" + resolved "https://registry.npm.taobao.org/ignore/download/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha1-8VCotQo0KJsz4i9YiavU2AFvDlc= + +image-size@^0.6.0: + version "0.6.3" + resolved "https://registry.npm.taobao.org/image-size/download/image-size-0.6.3.tgz?cache=0&sync_timestamp=1599125294328&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimage-size%2Fdownload%2Fimage-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" + integrity sha1-5+XGW7U0vXzc7dbLUWYnKoX3X7I= + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/import-fresh/download/import-fresh-2.0.0.tgz?cache=0&sync_timestamp=1589682760620&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fimport-fresh%2Fdownload%2Fimport-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/import-local/download/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha1-qM/QQx0d5KIZlwPQA+PmI2T6bbY= + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.4, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY= + dependencies: + loose-envify "^1.0.0" + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/ip-regex/download/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= + +ip@^1.1.4, ip@^1.1.5: + version "1.1.5" + resolved "https://registry.npm.taobao.org/ip/download/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY= + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" + integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== + dependencies: + call-bind "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npm.taobao.org/is-arrayish/download/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2" + integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg== + +is-boolean-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.0.tgz#e2aaad3a3a8fca34c28f6eee135b156ed2587ff0" + integrity sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA== + dependencies: + call-bind "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha1-76ouqdqg16suoTqXsritUf776L4= + +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.npm.taobao.org/is-callable/download/is-callable-1.2.2.tgz?cache=0&sync_timestamp=1600719276620&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-callable%2Fdownload%2Fis-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha1-x8ZxXNItTdtI0+GZcCI6zquwgNk= + +is-callable@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" + integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== + +is-ci@^1.0.10: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== + dependencies: + ci-info "^1.5.0" + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-ci/download/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw= + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc= + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.npm.taobao.org/is-date-object/download/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha1-vac28s2P0G0yhE53Q7+nSUw7/X4= + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco= + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/is-descriptor/download/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw= + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.npm.taobao.org/is-directory/download/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-docker@^2.0.0: + version "2.1.1" + resolved "https://registry.npm.taobao.org/is-docker/download/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" + integrity sha1-QSWojkTkUNOE4JBH7eca3C0UQVY= + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ= + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/is-generator-fn/download/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha1-fRQK3DiarzARqPKipM+m+q3/sRg= + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-negative-zero/download/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= + +is-number-object@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npm.taobao.org/is-number/download/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss= + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= + dependencies: + path-is-inside "^1.0.1" + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc= + dependencies: + isobject "^3.0.1" + +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/is-potential-custom-element-name/download/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= + +is-regex@^1.0.4, is-regex@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" + integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== + dependencies: + call-bind "^1.0.2" + has-symbols "^1.0.1" + +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/is-regex/download/is-regex-1.1.1.tgz?cache=0&sync_timestamp=1596555640677&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-regex%2Fdownload%2Fis-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha1-xvmKrMVG9s7FRooHt7FTq1ZKV7k= + dependencies: + has-symbols "^1.0.1" + +is-retry-allowed@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/is-stream/download/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha1-venDJoDW+uBBKdasnZIc54FfeOM= + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.npm.taobao.org/is-string/download/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha1-QEk+0ZjvP/R3uMf5L2ROyCpc06Y= + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.3" + resolved "https://registry.npm.taobao.org/is-symbol/download/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha1-OOEBS55jKb4N6dJKQU/XRB7GGTc= + dependencies: + has-symbols "^1.0.1" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0= + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.npm.taobao.org/is-wsl/download/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/is-wsl/download/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha1-dKTHbnfKn9P5MvKQwX6jJs0VcnE= + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/istanbul-lib-coverage/download/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha1-9ZRKN8cLVQsCp4pcOyBVsoDOyOw= + +istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.npm.taobao.org/istanbul-lib-instrument/download/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha1-hzxv/4l0UBGCIndGlqPyiQLXfB0= + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/istanbul-lib-report/download/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha1-dRj+UupE3jcvRgp2tezan/tz2KY= + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/istanbul-lib-source-maps/download/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha1-dXQ85tlruG3H7kNSz2Nmoj8LGtk= + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/istanbul-reports/download/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha1-1ZMhDlAAaDdQywn8BkTktuJ/1Ts= + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== + dependencies: + "@jest/types" "^26.6.2" + execa "^4.0.0" + throat "^5.0.0" + +jest-cli@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== + dependencies: + "@jest/core" "^26.6.3" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + is-ci "^2.0.0" + jest-config "^26.6.3" + jest-util "^26.6.2" + jest-validate "^26.6.2" + prompts "^2.0.1" + yargs "^15.4.1" + +jest-config@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^26.6.3" + "@jest/types" "^26.6.2" + babel-jest "^26.6.3" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + jest-environment-jsdom "^26.6.2" + jest-environment-node "^26.6.2" + jest-get-type "^26.3.0" + jest-jasmine2 "^26.6.3" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + micromatch "^4.0.2" + pretty-format "^26.6.2" + +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.npm.taobao.org/jest-docblock/download/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha1-Pi+iCJn8koyxO9D/aL03EaNoibU= + dependencies: + detect-newline "^3.0.0" + +jest-each@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + jest-get-type "^26.3.0" + jest-util "^26.6.2" + pretty-format "^26.6.2" + +jest-environment-jsdom@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + jsdom "^16.4.0" + +jest-environment-node@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.npm.taobao.org/jest-get-type/download/jest-get-type-26.3.0.tgz?cache=0&sync_timestamp=1597057386449&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-get-type%2Fdownload%2Fjest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha1-6X3Dw/U8K0Bsp6+u1Ek7HQmRmeA= + +jest-haste-map@^26.5.2: + version "26.5.2" + resolved "https://registry.npm.taobao.org/jest-haste-map/download/jest-haste-map-26.5.2.tgz?cache=0&sync_timestamp=1601981782578&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-haste-map%2Fdownload%2Fjest-haste-map-26.5.2.tgz#a15008abfc502c18aa56e4919ed8c96304ceb23d" + integrity sha1-oVAIq/xQLBiqVuSRntjJYwTOsj0= + dependencies: + "@jest/types" "^26.5.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^26.0.0" + jest-serializer "^26.5.0" + jest-util "^26.5.2" + jest-worker "^26.5.0" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== + dependencies: + "@jest/types" "^26.6.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +jest-jasmine2@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^26.6.2" + is-generator-fn "^2.0.0" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" + throat "^5.0.0" + +jest-leak-detector@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== + dependencies: + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== + dependencies: + chalk "^4.0.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + pretty-format "^26.6.2" + slash "^3.0.0" + stack-utils "^2.0.2" + +jest-mock@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.npm.taobao.org/jest-pnp-resolver/download/jest-pnp-resolver-1.2.2.tgz?cache=0&sync_timestamp=1592991731398&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-pnp-resolver%2Fdownload%2Fjest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha1-twSsCuAoqJEIpNBAs/kZ393I4zw= + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.npm.taobao.org/jest-regex-util/download/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha1-0l5xhLNuOf1GbDvEG+CXHoIf7ig= + +jest-resolve-dependencies@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== + dependencies: + "@jest/types" "^26.6.2" + jest-regex-util "^26.0.0" + jest-snapshot "^26.6.2" + +jest-resolve@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + jest-pnp-resolver "^1.2.2" + jest-util "^26.6.2" + read-pkg-up "^7.0.1" + resolve "^1.18.1" + slash "^3.0.0" + +jest-runner@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.7.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-config "^26.6.3" + jest-docblock "^26.0.0" + jest-haste-map "^26.6.2" + jest-leak-detector "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + jest-runtime "^26.6.3" + jest-util "^26.6.2" + jest-worker "^26.6.2" + source-map-support "^0.5.6" + throat "^5.0.0" + +jest-runtime@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/globals" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + cjs-module-lexer "^0.6.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^15.4.1" + +jest-serializer@^26.5.0: + version "26.5.0" + resolved "https://registry.npm.taobao.org/jest-serializer/download/jest-serializer-26.5.0.tgz?cache=0&sync_timestamp=1601890225776&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-serializer%2Fdownload%2Fjest-serializer-26.5.0.tgz#f5425cc4c5f6b4b355f854b5f0f23ec6b962bc13" + integrity sha1-9UJcxMX2tLNV+FS18PI+xrlivBM= + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-snapshot@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.6.2" + graceful-fs "^4.2.4" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + jest-haste-map "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + natural-compare "^1.4.0" + pretty-format "^26.6.2" + semver "^7.3.2" + +jest-util@^26.5.2: + version "26.5.2" + resolved "https://registry.npm.taobao.org/jest-util/download/jest-util-26.5.2.tgz?cache=0&sync_timestamp=1601981780632&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-util%2Fdownload%2Fjest-util-26.5.2.tgz#8403f75677902cc52a1b2140f568e91f8ed4f4d7" + integrity sha1-hAP3VneQLMUqGyFA9WjpH47U9Nc= + dependencies: + "@jest/types" "^26.5.2" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + micromatch "^4.0.2" + +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + micromatch "^4.0.2" + +jest-validate@^26.5.2: + version "26.5.2" + resolved "https://registry.npm.taobao.org/jest-validate/download/jest-validate-26.5.2.tgz?cache=0&sync_timestamp=1601981782848&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-validate%2Fdownload%2Fjest-validate-26.5.2.tgz#7ea266700b64234cd1c0cee982490c5a80e9b0f0" + integrity sha1-fqJmcAtkI0zRwM7pgkkMWoDpsPA= + dependencies: + "@jest/types" "^26.5.2" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.3.0" + leven "^3.1.0" + pretty-format "^26.5.2" + +jest-validate@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== + dependencies: + "@jest/types" "^26.6.2" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.3.0" + leven "^3.1.0" + pretty-format "^26.6.2" + +jest-watcher@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== + dependencies: + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^26.6.2" + string-length "^4.0.1" + +jest-worker@^26.0.0, jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^26.5.0: + version "26.5.0" + resolved "https://registry.npm.taobao.org/jest-worker/download/jest-worker-26.5.0.tgz?cache=0&sync_timestamp=1601890130827&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-worker%2Fdownload%2Fjest-worker-26.5.0.tgz#87deee86dbbc5f98d9919e0dadf2c40e3152fa30" + integrity sha1-h97uhtu8X5jZkZ4NrfLEDjFS+jA= + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== + dependencies: + "@jest/core" "^26.6.3" + import-local "^3.0.2" + jest-cli "^26.6.3" + +jetifier@^1.6.2: + version "1.6.6" + resolved "https://registry.npm.taobao.org/jetifier/download/jetifier-1.6.6.tgz#fec8bff76121444c12dc38d2dad6767c421dab68" + integrity sha1-/si/92EhREwS3DjS2tZ2fEIdq2g= + +joi@^17.2.1: + version "17.4.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" + integrity sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + +js-htmlencode@^0.3.0: + version "0.3.0" + resolved "https://registry.npm.taobao.org/js-htmlencode/download/js-htmlencode-0.3.0.tgz#b1ce293df94e96f8a8a08b1f3368f977bd255731" + integrity sha1-sc4pPflOlviooIsfM2j5d70lVzE= + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz?cache=0&sync_timestamp=1589682745609&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsbn%2Fdownload%2Fjsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsc-android@^245459.0.0: + version "245459.0.0" + resolved "https://registry.npm.taobao.org/jsc-android/download/jsc-android-245459.0.0.tgz#e584258dd0b04c9159a27fb104cd5d491fd202c9" + integrity sha1-5YQljdCwTJFZon+xBM1dSR/SAsk= + +jscodeshift@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.11.0.tgz#4f95039408f3f06b0e39bb4d53bc3139f5330e2f" + integrity sha512-SdRK2C7jjs4k/kT2mwtO07KJN9RnjxtKn03d9JVj6c3j9WwaLcFYsICYDnLAzY0hp+wG2nxl+Cm2jWLiNVYb8g== + dependencies: + "@babel/core" "^7.1.6" + "@babel/parser" "^7.1.6" + "@babel/plugin-proposal-class-properties" "^7.1.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.1.0" + "@babel/plugin-proposal-optional-chaining" "^7.1.0" + "@babel/plugin-transform-modules-commonjs" "^7.1.0" + "@babel/preset-flow" "^7.0.0" + "@babel/preset-typescript" "^7.1.0" + "@babel/register" "^7.0.0" + babel-core "^7.0.0-bridge.0" + colors "^1.1.2" + flow-parser "0.*" + graceful-fs "^4.2.4" + micromatch "^3.1.10" + neo-async "^2.5.0" + node-dir "^0.1.17" + recast "^0.20.3" + temp "^0.8.1" + write-file-atomic "^2.3.0" + +jsdom@^16.4.0: + version "16.4.0" + resolved "https://registry.npm.taobao.org/jsdom/download/jsdom-16.4.0.tgz?cache=0&sync_timestamp=1596916084670&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsdom%2Fdownload%2Fjsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb" + integrity sha1-NgBb3i0Tb3Pu4agwxtReVUCO3ds= + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" + tough-cookie "^3.0.1" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + ws "^7.2.3" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.npm.taobao.org/json-parse-better-errors/download/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha1-u4Z8+zRQ5pEHwTHRxRS6s9yLyqk= + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npm.taobao.org/json-parse-even-better-errors/download/json-parse-even-better-errors-2.3.1.tgz?cache=0&sync_timestamp=1599064788298&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-parse-even-better-errors%2Fdownload%2Fjson-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha1-fEeAWpQxmSjgV3dAXcEuH3pO4C0= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz?cache=0&sync_timestamp=1589682771374&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-stringify-safe%2Fdownload%2Fjson-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.npm.taobao.org/json5/download/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/json5/download/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha1-d5+wAYYE+oVOrL9iUhgNg1Q+Pb4= + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.npm.taobao.org/jsonfile/download/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.npm.taobao.org/jsonify/download/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" + integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== + dependencies: + array-includes "^3.1.2" + object.assign "^4.1.2" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha1-cpyR4thXt6QZofmqZWhcTDP1hF0= + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0= + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.npm.taobao.org/klaw/download/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npm.taobao.org/kleur/download/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha1-p5yezIbuHOP6YgbRIWxQHxR/wH4= + +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= + dependencies: + package-json "^4.0.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/leven/download/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I= + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.npm.taobao.org/levn/download/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +line-reader@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/line-reader/-/line-reader-0.2.4.tgz#c4392b587dea38580c9678570e6e8e49fce52622" + integrity sha1-xDkrWH3qOFgMlnhXDm6OSfzlJiI= + +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.npm.taobao.org/lines-and-columns/download/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/load-json-file/download/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4= + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npm.taobao.org/locate-path/download/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha1-Gvujlq/WdqbUJQTQpno6frn2KqA= + dependencies: + p-locate "^4.1.0" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.frompairs@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/lodash.frompairs/download/lodash.frompairs-4.0.1.tgz#bc4e5207fa2757c136e573614e9664506b2b1bd2" + integrity sha1-vE5SB/onV8E25XNhTpZkUGsrG9I= + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npm.taobao.org/lodash.isequal/download/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/lodash.isstring/download/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.omit@^4.5.0: + version "4.5.0" + resolved "https://registry.npm.taobao.org/lodash.omit/download/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" + integrity sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA= + +lodash.pick@^4.4.0: + version "4.4.0" + resolved "https://registry.npm.taobao.org/lodash.pick/download/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.npm.taobao.org/lodash.sortby/download/lodash.sortby-4.7.0.tgz?cache=0&sync_timestamp=1589683608371&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.sortby%2Fdownload%2Flodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.npm.taobao.org/lodash.template/download/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha1-+XYZXPPzR9DV9SSDVp/oAxzM6Ks= + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/lodash.templatesettings/download/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha1-5IExDwSdPPbUfpEq0JMTsVTw+zM= + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + +lodash@4.17.x, lodash@^4.17.10, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lodash@^4.17.14, lodash@^4.17.15: + version "4.17.20" + resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.20.tgz?cache=0&sync_timestamp=1597335994883&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha1-tEqbYpe8tpjxxRo1RaKzs2jVnFI= + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/log-symbols/download/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo= + dependencies: + chalk "^2.0.1" + +logkitty@^0.7.1: + version "0.7.1" + resolved "https://registry.npm.taobao.org/logkitty/download/logkitty-0.7.1.tgz#8e8d62f4085a826e8d38987722570234e33c6aa7" + integrity sha1-jo1i9Ahagm6NOJh3IlcCNOM8aqc= + dependencies: + ansi-fragments "^0.2.1" + dayjs "^1.8.15" + yargs "^15.1.0" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lrc-file-parser@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/lrc-file-parser/-/lrc-file-parser-1.0.7.tgz#ef9f8cd53766a938b3a6fc5be45b4a97a35de632" + integrity sha512-YaPa3xMMlN+cLXyINorMlWkXfO5U+AWpPywHiyVaVLgvRnI7xjArOyLpKH/I8XHmIPmdtJQfxFxT3K3hdCS91Q== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha1-XwMQ4YuL6JjMBwCSlaMK5B6R5vU= + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/make-dir/download/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha1-QV6WcEazp/HRhSd9hKpYIDcmoT8= + dependencies: + semver "^6.0.0" + +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.npm.taobao.org/makeerror/download/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +matcher@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" + integrity sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng== + dependencies: + escape-string-regexp "^4.0.0" + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/merge-stream/download/merge-stream-2.0.0.tgz?cache=0&sync_timestamp=1589682763068&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmerge-stream%2Fdownload%2Fmerge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A= + +metro-babel-register@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-babel-register/-/metro-babel-register-0.64.0.tgz#1a2d23f68da8b8ee42e78dca37ad21a5f4d3647d" + integrity sha512-Kf6YvE3kIRumGnjK0Q9LqGDIdnsX9eFGtNBmBuCVDuB9wGGA/5CgX8We8W7Y44dz1RGTcHJRhfw5iGg+pwC3aQ== + dependencies: + "@babel/core" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/register" "^7.0.0" + escape-string-regexp "^1.0.5" + +metro-babel-transformer@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.64.0.tgz#a21f8a989a5ea60c1109456e21bd4d9374194ea0" + integrity sha512-itZaxKTgmKGEZWxNzbSZBc22NngrMZzoUNuU92aHSTGkYi2WH4XlvzEHsstmIKHMsRVKl75cA+mNmgk4gBFJKw== + dependencies: + "@babel/core" "^7.0.0" + metro-source-map "0.64.0" + nullthrows "^1.1.1" + +metro-cache-key@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.64.0.tgz#98d0a94332453c4c52b74f72c07cc62a5c264c4f" + integrity sha512-O9B65G8L/fopck45ZhdRosyVZdMtUQuX5mBWEC1NRj02iWBIUPLmYMjrunqIe8vHipCMp3DtTCm/65IlBmO8jg== + +metro-cache@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.64.0.tgz#a769503e12521d9e9d95ce5840ffb2efdb4e8703" + integrity sha512-QvGfxe/1QQYM9XOlR8W1xqE9eHDw/AgJIgYGn/TxZxBu9Zga+Rgs1omeSZju45D8w5VWgMr83ma5kACgzvOecg== + dependencies: + metro-core "0.64.0" + mkdirp "^0.5.1" + rimraf "^2.5.4" + +metro-config@0.64.0, metro-config@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.64.0.tgz#b634fa05cffd06b1e50e4339c200f90a42924afb" + integrity sha512-QhM4asnX5KhlRWaugwVGNNXhX0Z85u5nK0UQ/A90bBb4xWyXqUe20e788VtdA75rkQiiI6wXTCIHWT0afbnjwQ== + dependencies: + cosmiconfig "^5.0.5" + jest-validate "^26.5.2" + metro "0.64.0" + metro-cache "0.64.0" + metro-core "0.64.0" + metro-runtime "0.64.0" + +metro-core@0.64.0, metro-core@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.64.0.tgz#7616b27acfe7baa476f6cd6bd9e70ae64fa62541" + integrity sha512-v8ZQ5j72EaUwamQ8pLfHlOHTyp7SbdazvHPzFGDpHnwIQqIT0Bw3Syg8R4regTlVG3ngpeSEAi005UITljmMcQ== + dependencies: + jest-haste-map "^26.5.2" + lodash.throttle "^4.1.1" + metro-resolver "0.64.0" + +metro-hermes-compiler@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-hermes-compiler/-/metro-hermes-compiler-0.64.0.tgz#e6043d7aa924e5b2be99bd3f602e693685d15386" + integrity sha512-CLAjVDWGAoGhbi2ZyPHnH5YDdfrDIx6+tzFWfHGIMTZkYBXsYta9IfYXBV8lFb6BIbrXLjlXZAOoosknetMPOA== + +metro-inspector-proxy@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-inspector-proxy/-/metro-inspector-proxy-0.64.0.tgz#9a481b3f49773d5418e028178efec68f861bec88" + integrity sha512-KywbH3GNSz9Iqw4UH3smgaV2dBHHYMISeN7ORntDL/G+xfgPc6vt13d+zFb907YpUcXj5N0vdoiAHI5V/0y8IA== + dependencies: + connect "^3.6.5" + debug "^2.2.0" + ws "^1.1.5" + yargs "^15.3.1" + +metro-minify-uglify@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-minify-uglify/-/metro-minify-uglify-0.64.0.tgz#da6ab4dda030e3211f5924e7f41ed308d466068f" + integrity sha512-DRwRstqXR5qfte9Nuwoov5dRXxL7fJeVlO5fGyOajWeO3+AgPjvjXh/UcLJqftkMWTPGUFuzAD5/7JC5v5FLWw== + dependencies: + uglify-es "^3.1.9" + +metro-react-native-babel-preset@0.64.0, metro-react-native-babel-preset@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.64.0.tgz#76861408681dfda3c1d962eb31a8994918c976f8" + integrity sha512-HcZ0RWQRuJfpPiaHyFQJzcym+/dDIVUPwUAXWoub/C4GkGu+mPjp8vqK6g0FxokCnnI2TK0gZTza2IDfiNNscQ== + dependencies: + "@babel/core" "^7.0.0" + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-export-default-from" "^7.0.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" + "@babel/plugin-proposal-optional-chaining" "^7.0.0" + "@babel/plugin-syntax-dynamic-import" "^7.0.0" + "@babel/plugin-syntax-export-default-from" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.2.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0" + "@babel/plugin-syntax-optional-chaining" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-exponentiation-operator" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-assign" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-react-jsx-self" "^7.0.0" + "@babel/plugin-transform-react-jsx-source" "^7.0.0" + "@babel/plugin-transform-regenerator" "^7.0.0" + "@babel/plugin-transform-runtime" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-sticky-regex" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + "@babel/plugin-transform-typescript" "^7.5.0" + "@babel/plugin-transform-unicode-regex" "^7.0.0" + "@babel/template" "^7.0.0" + react-refresh "^0.4.0" + +metro-react-native-babel-transformer@0.64.0, metro-react-native-babel-transformer@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.64.0.tgz#eafef756972f20efdc51bd5361d55f8598355623" + integrity sha512-K1sHO3ODBFCr7uEiCQ4RvVr+cQg0EHQF8ChVPnecGh/WDD8udrTq9ECwB0dRfMjAvlsHtRUlJm6ZSI8UPgum2w== + dependencies: + "@babel/core" "^7.0.0" + babel-preset-fbjs "^3.3.0" + metro-babel-transformer "0.64.0" + metro-react-native-babel-preset "0.64.0" + metro-source-map "0.64.0" + nullthrows "^1.1.1" + +metro-resolver@0.64.0, metro-resolver@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.64.0.tgz#21126b44f31346ac2ce0b06b77ef65e8c9e2294a" + integrity sha512-cJ26Id8Zf+HmS/1vFwu71K3u7ep/+HeXXAJIeVDYf+niE7AWB9FijyMtAlQgbD8elWqv1leJCnQ/xHRFBfGKYA== + dependencies: + absolute-path "^0.0.0" + +metro-runtime@0.64.0, metro-runtime@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.64.0.tgz#cdaa1121d91041bf6345f2a69eb7c2fb289eff7b" + integrity sha512-m7XbWOaIOeFX7YcxUhmnOi6Pg8EaeL89xyZ+quZyZVF1aNoTr4w8FfbKxvijpjsytKHIZtd+43m2Wt5JrqyQmQ== + +metro-source-map@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.64.0.tgz#4310e17c3d4539c6369688022494ad66fa4d39a1" + integrity sha512-OCG2rtcp5cLEGYvAbfkl6mEc0J2FPRP4/UCEly+juBk7hawS9bCBMBfhJm/HIsvY1frk6nT2Vsl1O8YBbwyx2g== + dependencies: + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + invariant "^2.2.4" + metro-symbolicate "0.64.0" + nullthrows "^1.1.1" + ob1 "0.64.0" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-symbolicate@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.64.0.tgz#405c21438ab553c29f6841da52ca76ee87bb06ac" + integrity sha512-qIi+YRrDWnLVmydj6gwidYLPaBsakZRibGWSspuXgHAxOI3UuLwlo4dpQ73Et0gyHjI7ZvRMRY8JPiOntf9AQQ== + dependencies: + invariant "^2.2.4" + metro-source-map "0.64.0" + nullthrows "^1.1.1" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" + +metro-transform-plugins@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.64.0.tgz#41d3dce0f2966bbd79fea1ecff61bcc8a00e4665" + integrity sha512-iTIRBD/wBI98plfxj8jAoNUUXfXLNlyvcjPtshhpGvdwu9pzQilGfnDnOaaK+vbITcOk9w5oQectXyJwAqTr1A== + dependencies: + "@babel/core" "^7.0.0" + "@babel/generator" "^7.5.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.0.0" + nullthrows "^1.1.1" + +metro-transform-worker@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.64.0.tgz#f94429b2c42b13cb1c93be4c2e25e97f2d27ca60" + integrity sha512-wegRtK8GyLF6IPZRBJp+zsORgA4iX0h1DRpknyAMDCtSbJ4VU2xV/AojteOgAsDvY3ucAGsvfuZLNDJHUdUNHQ== + dependencies: + "@babel/core" "^7.0.0" + "@babel/generator" "^7.5.0" + "@babel/parser" "^7.0.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.3.0" + metro "0.64.0" + metro-babel-transformer "0.64.0" + metro-cache "0.64.0" + metro-cache-key "0.64.0" + metro-hermes-compiler "0.64.0" + metro-source-map "0.64.0" + metro-transform-plugins "0.64.0" + nullthrows "^1.1.1" + +metro@0.64.0, metro@^0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.64.0.tgz#0091a856cfbcc94dd576da563eee466e96186195" + integrity sha512-G2OC08Rzfs0kqnSEuKo2yZxR+/eNUpA93Ru45c60uN0Dw3HPrDi+ZBipgFftC6iLE0l+6hu8roFFIofotWxybw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/core" "^7.0.0" + "@babel/generator" "^7.5.0" + "@babel/parser" "^7.0.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + absolute-path "^0.0.0" + accepts "^1.3.7" + async "^2.4.0" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^2.2.0" + denodeify "^1.2.1" + error-stack-parser "^2.0.6" + fs-extra "^1.0.0" + graceful-fs "^4.1.3" + image-size "^0.6.0" + invariant "^2.2.4" + jest-haste-map "^26.5.2" + jest-worker "^26.0.0" + lodash.throttle "^4.1.1" + metro-babel-register "0.64.0" + metro-babel-transformer "0.64.0" + metro-cache "0.64.0" + metro-cache-key "0.64.0" + metro-config "0.64.0" + metro-core "0.64.0" + metro-hermes-compiler "0.64.0" + metro-inspector-proxy "0.64.0" + metro-minify-uglify "0.64.0" + metro-react-native-babel-preset "0.64.0" + metro-resolver "0.64.0" + metro-runtime "0.64.0" + metro-source-map "0.64.0" + metro-symbolicate "0.64.0" + metro-transform-plugins "0.64.0" + metro-transform-worker "0.64.0" + mime-types "^2.1.27" + mkdirp "^0.5.1" + node-fetch "^2.2.0" + nullthrows "^1.1.1" + rimraf "^2.5.4" + serialize-error "^2.1.0" + source-map "^0.5.6" + strip-ansi "^6.0.0" + temp "0.8.3" + throat "^5.0.0" + ws "^1.1.5" + yargs "^15.3.1" + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha1-cIWbyVyYQJUvNZoGij/En57PrCM= + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.npm.taobao.org/micromatch/download/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk= + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz?cache=0&sync_timestamp=1600831210195&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I= + +mime-db@1.46.0: + version "1.46.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" + integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== + +"mime-db@>= 1.43.0 < 2": + version "1.45.0" + resolved "https://registry.npm.taobao.org/mime-db/download/mime-db-1.45.0.tgz?cache=0&sync_timestamp=1600831210195&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + integrity sha1-zO7aIczXw6dF66LezVXUtz54eeo= + +mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.27" + resolved "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz?cache=0&sync_timestamp=1589682770020&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8= + dependencies: + mime-db "1.44.0" + +mime-types@^2.1.27: + version "2.1.29" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" + integrity sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ== + dependencies: + mime-db "1.46.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz?cache=0&sync_timestamp=1590635592890&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE= + +mime@^2.4.1: + version "2.4.6" + resolved "https://registry.npm.taobao.org/mime/download/mime-2.4.6.tgz?cache=0&sync_timestamp=1590635592890&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" + integrity sha1-5bQHyQ20QvK+tbFiNz0Htpr/pNE= + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-1.2.0.tgz?cache=0&sync_timestamp=1596095644798&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmimic-fn%2Fdownload%2Fmimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI= + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/mimic-fn/download/mimic-fn-2.1.0.tgz?cache=0&sync_timestamp=1596095644798&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmimic-fn%2Fdownload%2Fmimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha1-ftLCzMyvhNP/y3pptXcR/CCDQBs= + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.1.1, minimist@^1.1.2, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&sync_timestamp=1589682820731&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI= + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY= + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1, mkdirp@^0.5.4: + version "0.5.5" + resolved "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1589682820707&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8= + dependencies: + minimist "^1.2.5" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.npm.taobao.org/ms/download/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk= + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz?cache=0&sync_timestamp=1589682752355&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnegotiator%2Fdownload%2Fnegotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs= + +neo-async@^2.5.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y= + +nocache@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" + integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== + +node-dir@^0.1.17: + version "0.1.17" + resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" + integrity sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU= + dependencies: + minimatch "^3.0.2" + +node-fetch@^2.2.0, node-fetch@^2.6.0: + version "2.6.1" + resolved "https://registry.npm.taobao.org/node-fetch/download/node-fetch-2.6.1.tgz?cache=0&sync_timestamp=1599309179354&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-fetch%2Fdownload%2Fnode-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI= + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.npm.taobao.org/node-int64/download/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/node-modules-regexp/download/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + +node-notifier@^8.0.0: + version "8.0.0" + resolved "https://registry.npm.taobao.org/node-notifier/download/node-notifier-8.0.0.tgz?cache=0&sync_timestamp=1597311365226&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-notifier%2Fdownload%2Fnode-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620" + integrity sha1-p+7i1R2m0Pf/UJS8cQjJESQMFiA= + dependencies: + growly "^1.3.0" + is-wsl "^2.2.0" + semver "^7.3.2" + shellwords "^0.1.1" + uuid "^8.3.0" + which "^2.0.2" + +node-releases@^1.1.70: + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== + +node-stream-zip@^1.9.1: + version "1.11.3" + resolved "https://registry.npm.taobao.org/node-stream-zip/download/node-stream-zip-1.11.3.tgz#223892620b4889bce9782b256a76682631c507be" + integrity sha1-IjiSYgtIibzpeCslanZoJjHFB74= + +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg= + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/normalize-path/download/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU= + +normalize-url@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" + integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== + +npm-conf@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" + integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== + dependencies: + config-chain "^1.1.11" + pify "^3.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha1-t+zR5e1T2o43pV4cImnguX7XSOo= + dependencies: + path-key "^3.0.0" + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/nullthrows/download/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha1-eBgliEOFaulx6uQgitfX6xmkMbE= + +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/nwsapi/download/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha1-IEh5qePQaP8qVROcLHcngGgaOLc= + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz?cache=0&sync_timestamp=1589682811909&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Foauth-sign%2Fdownload%2Foauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU= + +ob1@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.64.0.tgz#f254a55a53ca395c4f9090e28a85483eac5eba19" + integrity sha512-CO1N+5dhvy+MoAwxz8+fymEUcwsT4a+wHhrHFb02LppcJdHxgcBWviwEhUwKOD2kLMQ7ijrrzybOqpGcqEtvpQ== + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.npm.taobao.org/object-copy/download/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.8.0: + version "1.8.0" + resolved "https://registry.npm.taobao.org/object-inspect/download/object-inspect-1.8.0.tgz?cache=0&sync_timestamp=1592545231350&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-inspect%2Fdownload%2Fobject-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha1-34B+Xs9TpgnMa/6T6sPMe+WzqdA= + +object-inspect@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/object-keys/download/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha1-HEfyct8nfzsdrwYWd9nILiMixg4= + +object-path@^0.11.3: + version "0.11.5" + resolved "https://registry.npm.taobao.org/object-path/download/object-path-0.11.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject-path%2Fdownload%2Fobject-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a" + integrity sha1-1OPPGWAaUUClWhatcSAZqcULV3o= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0, object.assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npm.taobao.org/object.assign/download/object.assign-4.1.1.tgz?cache=0&sync_timestamp=1599844927493&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fobject.assign%2Fdownload%2Fobject.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" + integrity sha1-MDhnpmbN1Bk27N7fsfjz4ypHjN0= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.0" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.entries@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6" + integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + +object.fromentries@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" + integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.2" + has "^1.0.3" + +object.pick@^1.1.1, object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.npm.taobao.org/object.pick/download/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/object.values/download/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha1-aKmezeNWt+kpWjxeDOMdyMlT3l4= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +object.values@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.3.tgz#eaa8b1e17589f02f698db093f7c62ee1699742ee" + integrity sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.2" + has "^1.0.3" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/on-headers/download/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha1-dysK5qqlJcOZ5Imt+tkMQD6zwo8= + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.npm.taobao.org/onetime/download/onetime-2.0.1.tgz?cache=0&sync_timestamp=1597005345612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fonetime%2Fdownload%2Fonetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.npm.taobao.org/onetime/download/onetime-5.1.2.tgz?cache=0&sync_timestamp=1597005345612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fonetime%2Fdownload%2Fonetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha1-0Oluu1awdHbfHdnEgG5SN5hcpF4= + dependencies: + mimic-fn "^2.1.0" + +open@^6.2.0: + version "6.4.0" + resolved "https://registry.npm.taobao.org/open/download/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" + integrity sha1-XBPpbQ3IlGhhZPGJZez+iJ7PyKk= + dependencies: + is-wsl "^1.1.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.npm.taobao.org/optionator/download/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha1-hPodA2/p08fiHZmIS2ARZ+yPtJU= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +options@>=0.0.5: + version "0.0.6" + resolved "https://registry.npm.taobao.org/options/download/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" + integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= + +ora@^3.4.0: + version "3.4.0" + resolved "https://registry.npm.taobao.org/ora/download/ora-3.4.0.tgz?cache=0&sync_timestamp=1599424857800&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fora%2Fdownload%2Fora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha1-vwdSSRBZo+8+1MhQl1Md6f280xg= + dependencies: + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-spinners "^2.0.0" + log-symbols "^2.2.0" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.npm.taobao.org/os-tmpdir/download/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-each-series@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/p-each-series/download/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" + integrity sha1-lhyN0/GV6pbHR+Y2smK4AKaxr0g= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.npm.taobao.org/p-limit/download/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg= + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE= + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ= + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npm.taobao.org/p-locate/download/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha1-o0KLtwiLOmApL2aRkni3wpetTwc= + dependencies: + p-limit "^2.2.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/p-try/download/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha1-yyhoVA4xPWHeWPr741zpAE1VQOY= + +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +pako@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.3.tgz#cdf475e31b678565251406de9e759196a0ea7a43" + integrity sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1598129182781&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/parse-json/download/parse-json-4.0.0.tgz?cache=0&sync_timestamp=1598129182781&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0: + version "5.1.0" + resolved "https://registry.npm.taobao.org/parse-json/download/parse-json-5.1.0.tgz?cache=0&sync_timestamp=1598129182781&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse-json%2Fdownload%2Fparse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" + integrity sha1-+WCIzfJKj6qa6poAny2dlCyZlkY= + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@5.1.1: + version "5.1.1" + resolved "https://registry.npm.taobao.org/parse5/download/parse5-5.1.1.tgz?cache=0&sync_timestamp=1595849263958&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fparse5%2Fdownload%2Fparse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha1-9o5OW6GFKsLK3AD0VV//bCq7YXg= + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ= + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/path-exists/download/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha1-UTvb4tO5XXdi6METfvoZXGxhtbM= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/path-key/download/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npm.taobao.org/path-key/download/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw= + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/path-type/download/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +pbkdf2@3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.8.tgz#2f8abf16ebecc82277945d748aba1d78761f61e2" + integrity sha1-L4q/FuvsyCJ3lF10irodeHYfYeI= + dependencies: + create-hmac "^1.1.2" + +pbkdf2@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picomatch@^2.0.4, picomatch@^2.0.5: + version "2.2.2" + resolved "https://registry.npm.taobao.org/picomatch/download/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha1-IfMz6ba46v8CRo9RRupAbTRfTa0= + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/pify/download/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE= + +pirates@^4.0.0, pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/pirates/download/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha1-ZDqSyviUVm+RsrmG0sZpUKji+4c= + dependencies: + node-modules-regexp "^1.0.0" + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha1-J0kCDyOe2ZCIGx9xIQ1R62UjvqM= + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/pkg-dir/download/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha1-8JkTPfft5CLoHR2ESCcO6z5CYfM= + dependencies: + find-up "^4.0.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/pkg-up/download/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha1-EA7CNcwVDk/UJRlBJZaihRKg3vU= + dependencies: + find-up "^3.0.0" + +plist@^3.0.1: + version "3.0.1" + resolved "https://registry.npm.taobao.org/plist/download/plist-3.0.1.tgz#a9b931d17c304e8912ef0ba3bdd6182baf2e1f8c" + integrity sha1-qbkx0XwwTokS7wujvdYYK68uH4w= + dependencies: + base64-js "^1.2.3" + xmlbuilder "^9.0.7" + xmldom "0.1.x" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +pretty-format@^26.5.2: + version "26.5.2" + resolved "https://registry.npm.taobao.org/pretty-format/download/pretty-format-26.5.2.tgz?cache=0&sync_timestamp=1601981759939&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-format%2Fdownload%2Fpretty-format-26.5.2.tgz#5d896acfdaa09210683d34b6dc0e6e21423cd3e1" + integrity sha1-XYlqz9qgkhBoPTS23A5uIUI80+E= + dependencies: + "@jest/types" "^26.5.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha1-eCDZsWEgzFXKmud5JoCufbptf+I= + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +progress@^2.0.0, progress@^2.0.3: + version "2.0.3" + resolved "https://registry.npm.taobao.org/progress/download/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha1-foz42PW48jnBvGi+tOt4Vn1XLvg= + +promise@^8.0.3: + version "8.1.0" + resolved "https://registry.npm.taobao.org/promise/download/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" + integrity sha1-aXwlw9/nQ13Xn81Yw4oTWIjq8F4= + dependencies: + asap "~2.0.6" + +prompts@^2.0.1: + version "2.3.2" + resolved "https://registry.npm.taobao.org/prompts/download/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" + integrity sha1-SAVy2J7POVZtK9P+LJ/Mt8TAsGg= + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.4" + +prompts@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7" + integrity sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@15.x.x, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.npm.taobao.org/prop-types/download/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha1-UsQedbjIfnK52TYOAga5ncv/psU= + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ= + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/pump/download/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha1-tKIRaBW94vTh6mAjVOjHVWUQemQ= + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz?cache=0&sync_timestamp=1589682803838&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpunycode%2Fdownload%2Fpunycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha1-yzroBuh0BERYTvFUzo7pjUA/PjY= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npm.taobao.org/range-parser/download/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha1-PPNwI9GZ4cJNGlW4SADC8+ZGgDE= + +rc@^1.0.1, rc@^1.1.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-devtools-core@4.13.2: + version "4.13.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.13.2.tgz#61399c6648d3ded5917eaa4e59b474b3fa838faa" + integrity sha512-/lA5FVLMhUHrkQwtEf5wZNCKsXmc2RBZMNS/kkq3WlXPg2Y7COUGMh0Lmz34jjMpM0kvLMDuj+DqsPT/jSADbw== + dependencies: + shell-quote "^1.6.1" + ws "^7" + +react-devtools-core@^4.6.0: + version "4.8.2" + resolved "https://registry.npm.taobao.org/react-devtools-core/download/react-devtools-core-4.8.2.tgz#4465f2e8de7795564aa20f28b2f3a9737586db23" + integrity sha1-RGXy6N53lVZKog8osvOpc3WG2yM= + dependencies: + shell-quote "^1.6.1" + ws "^7" + +react-devtools@^4.13.2: + version "4.13.2" + resolved "https://registry.yarnpkg.com/react-devtools/-/react-devtools-4.13.2.tgz#4eb3399a68ba33728f48e32fa1ffef2aec1371c2" + integrity sha512-JFNwahGsSQ8ilE25Dqysm7AH5jjKVqI6PhdleeXNGxcbJRMPTYBbR4UvlpZIeccr74pgfu217n6SXkIL6Lfl5w== + dependencies: + cross-spawn "^5.0.1" + electron "^11.1.0" + ip "^1.1.4" + minimist "^1.2.3" + react-devtools-core "4.13.2" + update-notifier "^2.1.0" + +react-i18next@^11.8.15: + version "11.8.15" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.15.tgz#89450d585298f18d4a8eb1628b0868863f3a4767" + integrity sha512-ZbKcbYYKukgDL0MiUWKJTEsEftjSTNVZv67/V+SjPqTRwuF/aL4NbUtuEcb4WjHk0HyZ1M+2wGd07Fp0RUNHKA== + dependencies: + "@babel/runtime" "^7.13.6" + html-parse-stringify "^3.0.1" + +react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-lifecycles-compat@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-2.0.0.tgz#71d9c4cde47114c4102454f76da055c2bc48c948" + integrity sha512-txfpPCQYiazVdcbMRhatqWKcAxJweUu2wDXvts5/7Wyp6+Y9cHojqXHsLPEckzutfHlxZhG8Oiundbmp8Fd6eQ== + +react-native-background-timer@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/react-native-background-timer/-/react-native-background-timer-2.4.1.tgz#a3bc1cafa8c1e3aeefd0611de120298b67978a0f" + integrity sha512-TE4Kiy7jUyv+hugxDxitzu38sW1NqjCk4uE5IgU2WevLv7sZacaBc6PZKOShNRPGirLl1NWkaG3LDEkdb9Um5g== + +react-native-clean-project@^3.6.3: + version "3.6.3" + resolved "https://registry.yarnpkg.com/react-native-clean-project/-/react-native-clean-project-3.6.3.tgz#ad43b8e1491512f285b7f455ac56db3328b5a65f" + integrity sha512-sBbv+Zl05O9LfQqamLu2Crb//W/d8+l59TICF8nKxQ0nJsvear06a1CB2+FaO3rCrPNHiSjDDNXZ/D6muHTUkw== + +react-native-codegen@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.0.6.tgz#b3173faa879cf71bfade8d030f9c4698388f6909" + integrity sha512-cMvrUelD81wiPitEPiwE/TCNscIVauXxmt4NTGcy18HrUd0WRWXfYzAQGXm0eI87u3NMudNhqFj2NISJenxQHg== + dependencies: + flow-parser "^0.121.0" + jscodeshift "^0.11.0" + nullthrows "^1.1.1" + +react-native-crypto@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/react-native-crypto/-/react-native-crypto-2.2.0.tgz#c999ed7c96064f830e1f958687f53d0c44025770" + integrity sha512-eZu9Y8pa8BN9FU2pIex7MLRAi+Cd1Y6bsxfiufKh7sfraAACJvjQTeW7/zcQAT93WMfM+D0OVk+bubvkrbrUkw== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.4" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "3.0.8" + public-encrypt "^4.0.0" + randomfill "^1.0.3" + +react-native-fs@^2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.18.0.tgz#987b99cc90518ef26663a8d60e62104694b41c21" + integrity sha512-9iQhkUNnN2JNED0in06JwZy88YEVyIGKWz4KLlQYxa5Y2U0U2AZh9FUHtA04oWj+xt2LlHh0LFPCzhmNsAsUDg== + dependencies: + base-64 "^0.1.0" + utf8 "^3.0.0" + +react-native-navigation@^7.14.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/react-native-navigation/-/react-native-navigation-7.14.0.tgz#a86e731bb33cddf0e9ea73c0f4b2a517e20e0c4e" + integrity sha512-Cq4nUfiwUln87pkO8+AWgXtTKAFwFINIVAovS1I4RdIC8Sw/9+MpSEPZncx8RpFSyUo2t6JnHl2A0eYSzSmwlw== + dependencies: + hoist-non-react-statics "3.x.x" + lodash "4.17.x" + prop-types "15.x.x" + react-lifecycles-compat "2.0.0" + tslib "1.9.3" + +react-native-pager-view@^5.1.8: + version "5.1.8" + resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-5.1.8.tgz#92222adcb271836950803fb6b3873b409f5f7ac3" + integrity sha512-ZOAMBlLweg79PG1vY+tbS7h09HdFEog5BmDM1mkQy6vj5WX5O1Lf+ipgvzWRJKc7LEC+g9UYWHG3EXaG6X/+Rg== + +react-native-randombytes@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/react-native-randombytes/-/react-native-randombytes-3.6.1.tgz#cac578093b5ca38e3e085becffdc6cbcf6f0d654" + integrity sha512-qxkwMbOZ0Hff1V7VqpaWrR6ItkA+oF6bnI79Qp9F3Tk8WBsdKDi6m1mi3dEdFWePoRLrhJ2L03rU0yabst1tVw== + dependencies: + buffer "^4.9.1" + sjcl "^1.0.3" + +react-native-splash-screen@^3.2.0: + version "3.2.0" + resolved "https://registry.npm.taobao.org/react-native-splash-screen/download/react-native-splash-screen-3.2.0.tgz#d47ec8557b1ba988ee3ea98d01463081b60fff45" + integrity sha1-1H7IVXsbqYjuPqmNAUYwgbYP/0U= + +react-native-track-player@lyswhut/react-native-track-player#63d6e5147bba3ce476ee751756d0a7de5fe88757: + version "1.2.5" + resolved "https://codeload.github.com/lyswhut/react-native-track-player/tar.gz/63d6e5147bba3ce476ee751756d0a7de5fe88757" + +react-native-vector-icons@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-8.1.0.tgz#e8ee2b17bc4d9f636da1c6f67feee8e2a850c3d8" + integrity sha512-sHIdBB6Y0dHaot2fMXgy5J/hhCn5YuyN7SKDNFgPzL8KA1oF2/v7mgYMavnK7LIIs2dJoGnDANKf61dsU+TZlg== + dependencies: + lodash.frompairs "^4.0.1" + lodash.isequal "^4.5.0" + lodash.isstring "^4.0.1" + lodash.omit "^4.5.0" + lodash.pick "^4.4.0" + lodash.template "^4.5.0" + prop-types "^15.7.2" + yargs "^16.1.1" + +react-native@0.64.0: + version "0.64.0" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.64.0.tgz#c3bde5b638bf8bcf12bae6e094930d39cb942ab7" + integrity sha512-8dhSHBthgGwAjU+OjqUEA49229ThPMQH7URH0u8L0xoQFCnZO2sZ9Wc6KcbxI0x9KSmjCMFFZqRe3w3QsRv64g== + dependencies: + "@jest/create-cache-key-function" "^26.5.0" + "@react-native-community/cli" "^5.0.1-alpha.0" + "@react-native-community/cli-platform-android" "^5.0.1-alpha.0" + "@react-native-community/cli-platform-ios" "^5.0.1-alpha.0" + "@react-native/assets" "1.0.0" + "@react-native/normalize-color" "1.0.0" + "@react-native/polyfills" "1.0.0" + abort-controller "^3.0.0" + anser "^1.4.9" + base64-js "^1.1.2" + event-target-shim "^5.0.1" + hermes-engine "~0.7.0" + invariant "^2.2.4" + jsc-android "^245459.0.0" + metro-babel-register "0.64.0" + metro-react-native-babel-transformer "0.64.0" + metro-runtime "0.64.0" + metro-source-map "0.64.0" + nullthrows "^1.1.1" + pretty-format "^26.5.2" + promise "^8.0.3" + prop-types "^15.7.2" + react-devtools-core "^4.6.0" + react-native-codegen "^0.0.6" + react-refresh "^0.4.0" + regenerator-runtime "^0.13.2" + scheduler "^0.20.1" + shelljs "^0.8.4" + stacktrace-parser "^0.1.3" + use-subscription "^1.0.0" + whatwg-fetch "^3.0.0" + ws "^6.1.4" + +react-redux@^7.2.4: + version "7.2.4" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225" + integrity sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA== + dependencies: + "@babel/runtime" "^7.12.1" + "@types/react-redux" "^7.1.16" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^16.13.1" + +react-refresh@^0.4.0: + version "0.4.3" + resolved "https://registry.npm.taobao.org/react-refresh/download/react-refresh-0.4.3.tgz#966f1750c191672e76e16c2efa569150cc73ab53" + integrity sha1-lm8XUMGRZy524Wwu+laRUMxzq1M= + +react-shallow-renderer@^16.13.1: + version "16.14.1" + resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124" + integrity sha512-rkIMcQi01/+kxiTE9D3fdS959U1g7gs+/rborw++42m1O9FAQiNI/UNRZExVUoAOprn4umcXf+pFRou8i4zuBg== + dependencies: + object-assign "^4.1.1" + react-is "^16.12.0 || ^17.0.0" + +react-test-renderer@17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-17.0.1.tgz#3187e636c3063e6ae498aedf21ecf972721574c7" + integrity sha512-/dRae3mj6aObwkjCcxZPlxDFh73XZLgvwhhyON2haZGUEhiaY5EjfAdw+d/rQmlcFwdTpMXCSGVk374QbCTlrA== + dependencies: + object-assign "^4.1.1" + react-is "^17.0.1" + react-shallow-renderer "^16.13.1" + scheduler "^0.20.1" + +react@17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" + integrity sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha1-86YTV1hFlzOuK5VjgFbhhU5+9Qc= + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/read-pkg/download/read-pkg-2.0.0.tgz?cache=0&sync_timestamp=1589682810106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg%2Fdownload%2Fread-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.npm.taobao.org/read-pkg/download/read-pkg-5.2.0.tgz?cache=0&sync_timestamp=1589682810106&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fread-pkg%2Fdownload%2Fread-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha1-e/KVQ4yloz5WzTDgU7NO5yUMk8w= + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +readable-stream@1.0.33: + version "1.0.33" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.33.tgz#3a360dd66c1b1d7fd4705389860eda1d0f61126c" + integrity sha1-OjYN1mwbHX/UcFOJhg7aHQ9hEmw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^1.0.27-1: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.2.2, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz?cache=0&sync_timestamp=1589682741447&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +recast@^0.20.3: + version "0.20.4" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.20.4.tgz#db55983eac70c46b3fff96c8e467d65ffb4a7abc" + integrity sha512-6qLIBGGRcwjrTZGIiBpJVC/NeuXpogXNyRQpqU1zWPUigCphvApoCs9KIwDYh1eDuJ6dAFlQoi/QUyE5KQ6RBQ== + dependencies: + ast-types "0.14.2" + esprima "~4.0.0" + source-map "~0.6.1" + tslib "^2.0.1" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +redux-logger@^3.0.6: + version "3.0.6" + resolved "https://registry.npm.taobao.org/redux-logger/download/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf" + integrity sha1-91VZZvMJjzyIYExEnPC69XeCdL8= + dependencies: + deep-diff "^0.3.5" + +redux-subscriber@^1.1.0: + version "1.1.0" + resolved "https://registry.npm.taobao.org/redux-subscriber/download/redux-subscriber-1.1.0.tgz#3cac28a674cec07b6e9e015ca7aabbbdac155543" + integrity sha1-PKwopnTOwHtungFcp6q7vawVVUM= + dependencies: + object-path "^0.11.3" + +redux-thunk@^2.3.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/redux-thunk/download/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" + integrity sha1-UcLBmhhe1Rh6qpotCLZm0NZGdiI= + +redux@^4.0.0: + version "4.0.5" + resolved "https://registry.npm.taobao.org/redux/download/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha1-TbXeWBbheJHeioDEJCMtBvBR2T8= + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + +redux@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4" + integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g== + dependencies: + "@babel/runtime" "^7.9.2" + +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.npm.taobao.org/regenerate-unicode-properties/download/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha1-5d5xEdZV57pgwFfb6f83yH5lzew= + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.1" + resolved "https://registry.npm.taobao.org/regenerate/download/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" + integrity sha1-ytkq2Oa1kXc0hfvgWkhcr09Ffm8= + +regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.13.7.tgz?cache=0&sync_timestamp=1595456311465&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha1-ysLazIoepnX+qrrriugziYrkb1U= + +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.npm.taobao.org/regenerator-transform/download/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha1-yY2hVGg2ccnE3LFuznNlF+G3/rQ= + dependencies: + "@babel/runtime" "^7.8.4" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw= + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.npm.taobao.org/regexpp/download/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha1-IG0K0KVkjP+9uK5GQ489xRyfeOI= + +regexpu-core@^4.7.0: + version "4.7.1" + resolved "https://registry.npm.taobao.org/regexpu-core/download/regexpu-core-4.7.1.tgz?cache=0&sync_timestamp=1600413461940&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregexpu-core%2Fdownload%2Fregexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha1-LepamgcjMpj78NuR+pq8TG4PitY= + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + +registry-auth-token@^3.0.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e" + integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A== + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= + dependencies: + rc "^1.0.1" + +regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.npm.taobao.org/regjsgen/download/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha1-kv8pX7He7L9uzaslQ9IH6RqjNzM= + +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.npm.taobao.org/regjsparser/download/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha1-p2n4aEMIQBpm6bUp0kNv9NBmYnI= + dependencies: + jsesc "~0.5.0" + +remove-markdown@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/remove-markdown/-/remove-markdown-0.2.2.tgz#66b0ceeba9fb77ca9636bb1b0307ce21a32a12a6" + integrity sha1-ZrDO66n7d8qWNrsbAwfOIaMqEqY= + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha1-eC4NglwMWjuzlzH4Tv7mt0Lmsc4= + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.npm.taobao.org/request-promise-core/download/request-promise-core-1.1.4.tgz?cache=0&sync_timestamp=1595378681719&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest-promise-core%2Fdownload%2Frequest-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha1-Pu3UIjII1BmGe3jOgVFn0QWToi8= + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.8: + version "1.0.9" + resolved "https://registry.npm.taobao.org/request-promise-native/download/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha1-5AcSBSal79yaObKKVnm/R7nZ3Cg= + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.88.2: + version "2.88.2" + resolved "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz?cache=0&sync_timestamp=1589682741998&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frequest%2Fdownload%2Frequest-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM= + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/require-main-filename/download/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs= + +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/reselect/download/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha1-8lKYMOXT0OAhQIskaiBu9OpEN/c= + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/resolve-cwd/download/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha1-DwB18bslRHZs9zumpuKt/ryxPy0= + dependencies: + resolve-from "^5.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/resolve-from/download/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npm.taobao.org/resolve-from/download/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha1-w1IlhD3493bfIcV1V7wIfp39/Gk= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.6, resolve@^1.18.1: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1: + version "1.17.0" + resolved "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz?cache=0&sync_timestamp=1589682751623&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha1-sllBtUloIxzC0bt2p5y38sC/hEQ= + dependencies: + path-parse "^1.0.6" + +resolve@^2.0.0-next.3: + version "2.0.0-next.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46" + integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/restore-cursor/download/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w= + +rimraf@^2.2.8, rimraf@^2.5.4: + version "2.7.1" + resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz?cache=0&sync_timestamp=1589682814592&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w= + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-3.0.2.tgz?cache=0&sync_timestamp=1589682814592&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho= + dependencies: + glob "^7.1.3" + +rimraf@~2.2.6: + version "2.2.8" + resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-2.2.8.tgz?cache=0&sync_timestamp=1589682814592&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frimraf%2Fdownload%2Frimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" + integrity sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI= + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rn-nodeify@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/rn-nodeify/-/rn-nodeify-10.3.0.tgz#06dc77819f7f500cdc41eda9654e60ecb140027a" + integrity sha512-EZB3M4M5i8yySCWF7AAZ31xU7cpdLuIKMlVxXji9t0aY8Ojy3BAyRt1sTp0OwBgy1ejShmlIu2L4f8mToJ+uvg== + dependencies: + "@yarnpkg/lockfile" "^1.0.0" + deep-equal "^1.0.0" + findit "^2.0.0" + fs-extra "^0.22.1" + minimist "^1.1.2" + object.pick "^1.1.1" + run-parallel "^1.1.2" + semver "^5.0.1" + xtend "^4.0.0" + +roarr@^2.15.3: + version "2.15.4" + resolved "https://registry.yarnpkg.com/roarr/-/roarr-2.15.4.tgz#f5fe795b7b838ccfe35dc608e0282b9eba2e7afd" + integrity sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A== + dependencies: + boolean "^3.0.1" + detect-node "^2.0.4" + globalthis "^1.0.1" + json-stringify-safe "^5.0.1" + semver-compare "^1.0.0" + sprintf-js "^1.1.2" + +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.npm.taobao.org/rsvp/download/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha1-yPFVMR0Wf2jyHhaN9x7FsIMRNzQ= + +run-parallel@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1589682795646&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha1-mR7GnSluAxN0fVm9/St0XDX4go0= + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.2.1.tgz?cache=0&sync_timestamp=1589682795646&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY= + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz?cache=0&sync_timestamp=1589682757445&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafe-regex%2Fdownload%2Fsafe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz?cache=0&sync_timestamp=1589682784154&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafer-buffer%2Fdownload%2Fsafer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= + +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.npm.taobao.org/sane/download/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha1-7Ygf2SJzOmxGG8GJ3CtsAG8//e0= + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + +sax@^1.2.1: + version "1.2.4" + resolved "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha1-KBYjTiN4vdxOU1T6tcqold9xANk= + +saxes@^5.0.0: + version "5.0.1" + resolved "https://registry.npm.taobao.org/saxes/download/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha1-7rq5U/o7dgjb6U5drbFciI+maW0= + dependencies: + xmlchars "^2.2.0" + +scheduler@^0.20.1: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= + dependencies: + semver "^5.0.3" + +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1589682805026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= + +semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +semver@^7.3.2: + version "7.3.2" + resolved "https://registry.npm.taobao.org/semver/download/semver-7.3.2.tgz?cache=0&sync_timestamp=1589682805026&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha1-YElisFK4HtB4aq6EOJ/7pw/9OTg= + +send@0.17.1: + version "0.17.1" + resolved "https://registry.npm.taobao.org/send/download/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha1-wdiwWfeQD3Rm3Uk4vcROEd2zdsg= + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/serialize-error/download/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha1-ULZ51WNc34Rme9yOWa9OW4HV9go= + +serialize-error@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-7.0.1.tgz#f1360b0447f61ffb483ec4157c737fab7d778e18" + integrity sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw== + dependencies: + type-fest "^0.13.1" + +serve-static@^1.13.1: + version "1.14.1" + resolved "https://registry.npm.taobao.org/serve-static/download/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha1-Zm5jbcTwEPfvKZcKiKZ0MgiYsvk= + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.npm.taobao.org/set-value/download/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha1-oY1AUw5vB95CKMfe/kInr4ytAFs= + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM= + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/shebang-regex/download/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@1.6.1: + version "1.6.1" + resolved "https://registry.npm.taobao.org/shell-quote/download/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +shell-quote@^1.6.1: + version "1.7.2" + resolved "https://registry.npm.taobao.org/shell-quote/download/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha1-Z6fQLHbJ2iT5nSCAj8re0ODgS+I= + +shelljs@^0.8.4: + version "0.8.4" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" + integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.npm.taobao.org/shellwords/download/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha1-1rkYHBpI05cyTISHHvvPxz/AZUs= + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.npm.taobao.org/signal-exit/download/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha1-oUEMLt2PB3sItOJTyOrPyvBXRhw= + +simple-plist@^1.0.0: + version "1.1.1" + resolved "https://registry.npm.taobao.org/simple-plist/download/simple-plist-1.1.1.tgz?cache=0&sync_timestamp=1601524932998&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsimple-plist%2Fdownload%2Fsimple-plist-1.1.1.tgz#54367ca28bc5996a982c325c1c4a4c1a05f4047c" + integrity sha1-VDZ8oovFmWqYLDJcHEpMGgX0BHw= + dependencies: + bplist-creator "0.0.8" + bplist-parser "0.2.0" + plist "^3.0.1" + +sisteransi@^1.0.4, sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +sjcl@^1.0.3: + version "1.0.8" + resolved "https://registry.yarnpkg.com/sjcl/-/sjcl-1.0.8.tgz#f2ec8d7dc1f0f21b069b8914a41a8f236b0e252a" + integrity sha512-LzIjEQ0S0DpIgnxMEayM1rq9aGwGRG4OnZhCdjx7glTaJtf4zRfpg87ImfjSJjoW9vKpagd82McDOwbRT5kQKQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/slash/download/slash-3.0.0.tgz?cache=0&sync_timestamp=1589682715547&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fslash%2Fdownload%2Fslash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ= + +slice-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/slice-ansi/download/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY= + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.npm.taobao.org/snapdragon-node/download/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha1-bBdfhv8UvbByRWPo88GwIaKGhTs= + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI= + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0= + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.npm.taobao.org/source-map-resolve/download/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha1-GQhmvs51U+H48mei7oLGBrVQmho= + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.5.16, source-map-support@^0.5.6: + version "0.5.19" + resolved "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.19.tgz?cache=0&sync_timestamp=1589682814927&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha1-qYti+G3K9PZzmWSMCFKRq56P7WE= + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.npm.taobao.org/source-map-url/download/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz?cache=0&sync_timestamp=1589682764497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz?cache=0&sync_timestamp=1589682764497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= + +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.npm.taobao.org/source-map/download/source-map-0.7.3.tgz?cache=0&sync_timestamp=1589682764497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map%2Fdownload%2Fsource-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha1-UwL4FpAxc1ImVECS5kmB91F1A4M= + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.npm.taobao.org/spdx-correct/download/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha1-3s6BrJweZxPl99G28X1Gj6U9iak= + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/spdx-exceptions/download/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha1-PyjOGnegA3JoPq3kpDMYNSeiFj0= + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.npm.taobao.org/spdx-expression-parse/download/spdx-expression-parse-3.0.1.tgz?cache=0&sync_timestamp=1589682794533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-expression-parse%2Fdownload%2Fspdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha1-z3D1BILu/cmOPOCmgz5KU87rpnk= + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.6" + resolved "https://registry.npm.taobao.org/spdx-license-ids/download/spdx-license-ids-3.0.6.tgz?cache=0&sync_timestamp=1600284873714&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fspdx-license-ids%2Fdownload%2Fspdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha1-yAdXODwoq/cpZ0SZjLwQaui4VM4= + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha1-fLCd2jqGWFcFxks5pkZgOGguj+I= + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" + integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha1-+2YcC+8ps520B2nuOfpwCT1vaHc= + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stack-utils@^2.0.2: + version "2.0.2" + resolved "https://registry.npm.taobao.org/stack-utils/download/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" + integrity sha1-XPSLRVe+y0Y40LxPIdI/XRlYZZM= + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" + integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== + +stacktrace-parser@^0.1.3: + version "0.1.10" + resolved "https://registry.npm.taobao.org/stacktrace-parser/download/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha1-KfsMrk4NC4UVWHlAKFehY562BRo= + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.npm.taobao.org/static-extend/download/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1589682739548&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/stealthy-require/download/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-1.0.0.tgz#bf9b4abfb42b274d751479e44e0ff2656b6f1193" + integrity sha1-v5tKv7QrJ011FHnkTg/yZWtvEZM= + dependencies: + inherits "~2.0.1" + readable-stream "^1.0.27-1" + +stream-buffers@~2.2.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/stream-buffers/download/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" + integrity sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ= + +string-length@^4.0.1: + version "4.0.1" + resolved "https://registry.npm.taobao.org/string-length/download/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" + integrity sha1-Spc78x73fE7bzq3WryYRmWmF+KE= + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0: + version "4.2.0" + resolved "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha1-lSGCxGzHssMT0VluYjmSvRY7crU= + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.matchall@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz#608f255e93e072107f5de066f81a2dfb78cf6b29" + integrity sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.2" + has-symbols "^1.0.1" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.3.1" + side-channel "^1.0.4" + +string.prototype.trimend@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/string.prototype.trimend/download/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha1-hYEqa4R6wAInD1gIFGBkyZX7aRM= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/string.prototype.trimstart/download/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha1-FK9tnzSwU/fPyJty+PLuFLkDmlQ= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha1-nPFhG6YmhdcDCunkujQUnDrwP8g= + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-5.2.0.tgz?cache=0&sync_timestamp=1589682795383&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4= + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/strip-bom/download/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/strip-bom/download/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha1-nDUFwdtFvO3KPZz3oW9cWqOQGHg= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/strip-final-newline/download/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha1-ibhS+y/L6Tb29LMYevsKEsGrWK0= + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +sudo-prompt@^9.0.0: + version "9.2.1" + resolved "https://registry.npm.taobao.org/sudo-prompt/download/sudo-prompt-9.2.1.tgz#77efb84309c9ca489527a4e749f287e6bdd52afd" + integrity sha1-d++4QwnJykiVJ6TnSfKH5r3VKv0= + +sumchecker@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" + integrity sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg== + dependencies: + debug "^4.1.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1598611709087&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha1-G33NyzK4E4gBs+R4umpRyqiWSNo= + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/supports-hyperlinks/download/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" + integrity sha1-9mPfJSr183xdSbvX7u+p4Lnlnkc= + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/symbol-observable/download/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha1-wiaIrtTqs83C3+rLtWFmBWCgCAQ= + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.npm.taobao.org/symbol-tree/download/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha1-QwY30ki6d+B4iDlR+5qg7tfGP6I= + +table@^6.0.4: + version "6.0.7" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== + dependencies: + ajv "^7.0.2" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" + +temp@0.8.3: + version "0.8.3" + resolved "https://registry.npm.taobao.org/temp/download/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" + integrity sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k= + dependencies: + os-tmpdir "^1.0.0" + rimraf "~2.2.6" + +temp@^0.8.1: + version "0.8.4" + resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2" + integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg== + dependencies: + rimraf "~2.6.2" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= + dependencies: + execa "^0.7.0" + +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.npm.taobao.org/terminal-link/download/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha1-FKZKJ6s8Dfkz6lRvulXy0HjtyZQ= + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npm.taobao.org/test-exclude/download/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha1-BKhphmHYBepvopO2y55jrARO8V4= + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.npm.taobao.org/throat/download/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + integrity sha1-xRmSNYA6rRh1SmZ9ZZtecs4Wdks= + +through2@^2.0.1: + version "2.0.5" + resolved "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha1-AcHjnrMdB8t9A6lqcIIyYLIxMs0= + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.npm.taobao.org/tmpl/download/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npm.taobao.org/to-regex-range/download/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ= + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4= + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM= + +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha1-zZ+yoKodWhK0c72fuW+j3P9lreI= + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-3.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftough-cookie%2Fdownload%2Ftough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + integrity sha1-nfT1fnOcJpMKAYGEiH9K233Kc7I= + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.npm.taobao.org/tr46/download/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha1-Ayc1ht7xWVrgj+2zjXczzukdJHk= + dependencies: + punycode "^2.1.1" + +tsconfig-paths@^3.9.0: + version "3.9.0" + resolved "https://registry.npm.taobao.org/tsconfig-paths/download/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + integrity sha1-CYVHpsREiAfo/Ljq4IEGTumjyQs= + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tslib@1.9.3: + version "1.9.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + +tslib@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz?cache=0&sync_timestamp=1589682745749&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftweetnacl%2Fdownload%2Ftweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.npm.taobao.org/type-check/download/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.npm.taobao.org/type-detect/download/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw= + +type-fest@^0.11.0: + version "0.11.0" + resolved "https://registry.npm.taobao.org/type-fest/download/type-fest-0.11.0.tgz?cache=0&sync_timestamp=1601425309553&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" + integrity sha1-l6vwhyMQ/tiKXEZrJWgVdhReM/E= + +type-fest@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" + integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.npm.taobao.org/type-fest/download/type-fest-0.6.0.tgz?cache=0&sync_timestamp=1601425309553&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha1-jSojcNPfiG61yQraHFv2GIrPg4s= + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.npm.taobao.org/type-fest/download/type-fest-0.7.1.tgz?cache=0&sync_timestamp=1601425309553&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftype-fest%2Fdownload%2Ftype-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha1-jdpl/q8D7Xjwo/lnjxhpFH98XEg= + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.npm.taobao.org/typedarray-to-buffer/download/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha1-qX7nqf9CaRufeD/xvFES/j/KkIA= + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uglify-es@^3.1.9: + version "3.3.9" + resolved "https://registry.npm.taobao.org/uglify-es/download/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677" + integrity sha1-DBxPBwC+2NvBJM2zBNJZLKID5nc= + dependencies: + commander "~2.13.0" + source-map "~0.6.1" + +ultron@1.0.x: + version "1.0.2" + resolved "https://registry.npm.taobao.org/ultron/download/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" + integrity sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po= + +unbox-primitive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f" + integrity sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.0" + has-symbols "^1.0.0" + which-boxed-primitive "^1.0.1" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.npm.taobao.org/unicode-canonical-property-names-ecmascript/download/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha1-JhmADEyCWADv3YNDr33Zkzy+KBg= + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.npm.taobao.org/unicode-match-property-ecmascript/download/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha1-jtKjJWmWG86SJ9Cc0/+7j+1fAgw= + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.npm.taobao.org/unicode-match-property-value-ecmascript/download/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha1-DZH2AO7rMJaqlisdb8iIduZOpTE= + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.npm.taobao.org/unicode-property-aliases-ecmascript/download/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha1-3Vepn2IHvt/0Yoq++5TFDblByPQ= + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc= + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= + dependencies: + crypto-random-string "^1.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY= + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz?cache=0&sync_timestamp=1589682745059&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funpipe%2Fdownload%2Funpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= + +update-notifier@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" + integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== + dependencies: + boxen "^1.2.1" + chalk "^2.0.1" + configstore "^3.0.0" + import-lazy "^2.1.0" + is-ci "^1.0.10" + is-installed-globally "^0.1.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url@~0.10.1: + version "0.10.3" + resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" + integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use-subscription@^1.0.0: + version "1.4.1" + resolved "https://registry.npm.taobao.org/use-subscription/download/use-subscription-1.4.1.tgz?cache=0&sync_timestamp=1602082774611&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fuse-subscription%2Fdownload%2Fuse-subscription-1.4.1.tgz#edcbcc220f1adb2dd4fa0b2f61b6cc308e620069" + integrity sha1-7cvMIg8a2y3U+gsvYbbMMI5iAGk= + dependencies: + object-assign "^4.1.1" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8= + +utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/utf8/download/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha1-8FLu0TZNaW52nvBYsYPfiMh/adE= + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util@~0.10.3: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.npm.taobao.org/uuid/download/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4= + +uuid@^8.3.0: + version "8.3.1" + resolved "https://registry.npm.taobao.org/uuid/download/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" + integrity sha1-K6LmygANpg/OWhlpVKskETHgWjE= + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +v8-to-istanbul@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.0.tgz#5b95cef45c0f83217ec79f8fc7ee1c8b486aee07" + integrity sha512-uXUVqNUCLa0AH1vuVxzi+MI4RfxEOKt9pBgKwHbgH7st8Kv2P1m+jvWNnektzBh5QShF3ODgKmUFCf38LnVz1g== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha1-/JH2uce6FchX9MssXe/uw51PQQo= + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.npm.taobao.org/vlq/download/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" + integrity sha1-wAP258C0we3WI/1u5Qu8DWod5Gg= + +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= + +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.npm.taobao.org/w3c-hr-time/download/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha1-ConN9cwVgi35w2BUNnaWPgzDCM0= + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/w3c-xmlserializer/download/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha1-PnEEoFt1FGzGD1ZDgLf2g6zxAgo= + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7, walker@~1.0.5: + version "1.0.7" + resolved "https://registry.npm.taobao.org/walker/download/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npm.taobao.org/wcwidth/download/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.npm.taobao.org/webidl-conversions/download/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha1-rlnIoAsSFUOirMZcBDT1ew/BGv8= + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.npm.taobao.org/webidl-conversions/download/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha1-kRG01+qArNQPUnDWZmIa+ni2lRQ= + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.npm.taobao.org/whatwg-encoding/download/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha1-WrrPd3wyFmpR0IXWtPPn0nET3bA= + dependencies: + iconv-lite "0.4.24" + +whatwg-fetch@^3.0.0: + version "3.4.1" + resolved "https://registry.npm.taobao.org/whatwg-fetch/download/whatwg-fetch-3.4.1.tgz?cache=0&sync_timestamp=1599473178098&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhatwg-fetch%2Fdownload%2Fwhatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" + integrity sha1-5fhxVy1oeWY/pWdMj4M/FahCWrM= + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.npm.taobao.org/whatwg-mimetype/download/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha1-PUseAxLSB5h5+Cav8Y2+7KWWD78= + +whatwg-url@^8.0.0: + version "8.3.0" + resolved "https://registry.npm.taobao.org/whatwg-url/download/whatwg-url-8.3.0.tgz#d1e11e565334486cdb280d3101b9c3fd1c867582" + integrity sha1-0eEeVlM0SGzbKA0xAbnD/RyGdYI= + dependencies: + lodash.sortby "^4.7.0" + tr46 "^2.0.2" + webidl-conversions "^6.1.0" + +which-boxed-primitive@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npm.taobao.org/which-module/download/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.npm.taobao.org/which/download/which-1.3.1.tgz?cache=0&sync_timestamp=1589682812246&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhich%2Fdownload%2Fwhich-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo= + dependencies: + isexe "^2.0.0" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.npm.taobao.org/which/download/which-2.0.2.tgz?cache=0&sync_timestamp=1589682812246&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fwhich%2Fdownload%2Fwhich-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE= + dependencies: + isexe "^2.0.0" + +widest-line@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== + dependencies: + string-width "^2.1.1" + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.npm.taobao.org/word-wrap/download/word-wrap-1.2.3.tgz?cache=0&sync_timestamp=1589683603678&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fword-wrap%2Fdownload%2Fword-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha1-YQY29rH3A4kb00dxzLF/uTtHB5w= + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.npm.taobao.org/wrap-ansi/download/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha1-6Tk7oHEC5skaOyIUePAlfNKFblM= + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.npm.taobao.org/write-file-atomic/download/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha1-Vr1cWlxwSBzRnFcb05q5ZaXeVug= + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^1.1.0, ws@^1.1.5: + version "1.1.5" + resolved "https://registry.npm.taobao.org/ws/download/ws-1.1.5.tgz#cbd9e6e75e09fc5d2c90015f21f0c40875e0dd51" + integrity sha1-y9nm514J/F0skAFfIfDECHXg3VE= + dependencies: + options ">=0.0.5" + ultron "1.0.x" + +ws@^6.1.4: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +ws@^7, ws@^7.2.3: + version "7.3.1" + resolved "https://registry.npm.taobao.org/ws/download/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" + integrity sha1-0FR79n985PEqct/jEmLGjX3FUcg= + +xcode@^2.0.0: + version "2.1.0" + resolved "https://registry.npm.taobao.org/xcode/download/xcode-2.1.0.tgz#bab64a7e954bb50ca8d19da7e09531c65a43ecfe" + integrity sha1-urZKfpVLtQyo0Z2n4JUxxlpD7P4= + dependencies: + simple-plist "^1.0.0" + uuid "^3.3.2" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.npm.taobao.org/xml-name-validator/download/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha1-auc+Bt5NjG5H+fsYH3jWSK1FfGo= + +xmlbuilder@^9.0.7: + version "9.0.7" + resolved "https://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.npm.taobao.org/xmlchars/download/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha1-Bg/hvLf5x2/ioX24apvDq4lCEMs= + +xmldoc@^1.1.2: + version "1.1.2" + resolved "https://registry.npm.taobao.org/xmldoc/download/xmldoc-1.1.2.tgz#6666e029fe25470d599cd30e23ff0d1ed50466d7" + integrity sha1-ZmbgKf4lRw1ZnNMOI/8NHtUEZtc= + dependencies: + sax "^1.2.1" + +xmldom@0.1.x: + version "0.1.31" + resolved "https://registry.npm.taobao.org/xmldom/download/xmldom-0.1.31.tgz#b76c9a1bd9f0a9737e5a72dc37231cf38375e2ff" + integrity sha1-t2yaG9nwqXN+WnLcNyMc84N14v8= + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.npm.taobao.org/xtend/download/xtend-4.0.2.tgz?cache=0&sync_timestamp=1589682817913&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fxtend%2Fdownload%2Fxtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.npm.taobao.org/y18n/download/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha1-le+U+F7MgdAHwmThkKEg8KPIVms= + +y18n@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" + integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha1-vmjEl1xrKr9GkjawyHA2L6sJp7A= + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^20.2.2: + version "20.2.6" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.6.tgz#69f920addf61aafc0b8b89002f5d66e28f2d8b20" + integrity sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA== + +yargs@^15.1.0, yargs@^15.3.1, yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.npm.taobao.org/yargs/download/yargs-15.4.1.tgz?cache=0&sync_timestamp=1600660037884&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha1-DYehbeAa7p2L7Cv7909nhRcw9Pg= + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^16.1.1: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yauzl@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0"