├── .circleci └── config.yml ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── blank.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── README_EN.md ├── alibaba ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── neday │ │ └── alibaba │ │ └── ExampleInstrumentedTest.java │ ├── debug │ └── res │ │ └── drawable │ │ └── yw_1222.jpg │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── neday │ │ │ └── alibaba │ │ │ ├── AliTradeHelper.kt │ │ │ └── AlibabaServiceImpl.kt │ └── res │ │ ├── drawable │ │ └── yw_1222.jpg │ │ └── raw │ │ └── keep.xml │ └── test │ └── java │ └── cn │ └── neday │ └── alibaba │ └── ExampleUnitTest.java ├── app ├── .gitignore ├── bugly.gradle ├── build.gradle ├── jacoco.gradle ├── jiagu.gradle ├── keystore │ ├── debug-signing.properties │ ├── neday-debug-keystore.jks │ └── neday-release-keystore.jks ├── mob.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── neday │ │ └── sheep │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── cn │ │ │ └── neday │ │ │ └── sheep │ │ │ ├── Constants.kt │ │ │ ├── ThisApplication.kt │ │ │ ├── activity │ │ │ ├── AboutActivity.kt │ │ │ ├── AccountActivity.java │ │ │ ├── ChangeSkinActivity.java │ │ │ ├── ConfigActivity.kt │ │ │ ├── CreditHistoryActivity.kt │ │ │ ├── CreditsHistoryActivity.java │ │ │ ├── GoodsDetailsActivity.kt │ │ │ ├── GuideActivity.kt │ │ │ ├── LoginActivity.kt │ │ │ ├── LostPasswordActivity.java │ │ │ ├── MainActivity.kt │ │ │ ├── PushSettingActivity.java │ │ │ ├── SearchActivity.kt │ │ │ ├── SearchResultActivity.kt │ │ │ ├── Shake11Activity.java │ │ │ ├── ShakeActivity.kt │ │ │ ├── SignInActivity.kt │ │ │ ├── SplashActivity.kt │ │ │ ├── UpdateInfoActivity.java │ │ │ ├── UpdateNewPasswordActivity.java │ │ │ ├── Vip1Activity.java │ │ │ ├── VipActivity.kt │ │ │ └── VipHelpActivity.java │ │ │ ├── adapter │ │ │ ├── CreditHistoryListAdapter.kt │ │ │ ├── GoodsListAdapter.kt │ │ │ └── KeyWordsListAdapter.kt │ │ │ ├── di │ │ │ ├── RepositoryModule.kt │ │ │ └── ViewModelModule.kt │ │ │ ├── enum │ │ │ ├── NineType.kt │ │ │ ├── OrderType.kt │ │ │ └── RankType.kt │ │ │ ├── fragment │ │ │ ├── GoodsListFragment.kt │ │ │ ├── IndexFragment.kt │ │ │ ├── MeFragment.kt │ │ │ ├── NineGoodsFragment.kt │ │ │ ├── NineListFragment.kt │ │ │ ├── RankingGoodsFragment.kt │ │ │ ├── RankingListFragment.kt │ │ │ └── SearchResultFragment.kt │ │ │ ├── model │ │ │ ├── Banner.kt │ │ │ ├── CommonGoods.kt │ │ │ ├── CreditHistory.kt │ │ │ ├── Goods.kt │ │ │ ├── HotWords.kt │ │ │ ├── RankingGoods.kt │ │ │ └── User.kt │ │ │ ├── network │ │ │ ├── api │ │ │ │ ├── BannerApi.kt │ │ │ │ ├── CategoryApi.kt │ │ │ │ ├── GoodsApi.kt │ │ │ │ └── UserApi.kt │ │ │ └── repository │ │ │ │ ├── BannerRepository.kt │ │ │ │ ├── CategoryRepository.kt │ │ │ │ ├── GoodsRepository.kt │ │ │ │ └── UserRepository.kt │ │ │ ├── util │ │ │ └── CommonUtils.kt │ │ │ ├── view │ │ │ ├── DampView.java │ │ │ ├── GuideBanner.kt │ │ │ ├── IndexBanner.kt │ │ │ ├── ShareDialog.kt │ │ │ └── rise_number │ │ │ │ ├── IRiseNumber.java │ │ │ │ └── RiseNumberTextView.kt │ │ │ └── viewmodel │ │ │ ├── ConfigViewModel.kt │ │ │ ├── CreditHistoryViewModel.kt │ │ │ ├── IndexViewModel.kt │ │ │ ├── LoginViewModel.kt │ │ │ ├── MainViewModel.kt │ │ │ ├── MeViewModel.kt │ │ │ ├── NineListViewModel.kt │ │ │ ├── RankingListViewModel.kt │ │ │ ├── SearchResultViewModel.kt │ │ │ ├── SearchViewModel.kt │ │ │ ├── ShakeViewModel.kt │ │ │ └── SignInViewModel.kt │ └── res │ │ ├── drawable-anydpi │ │ ├── ic_back_white_24dp.xml │ │ ├── ic_lock_white_24dp.xml │ │ ├── ic_phone_white_24dp.xml │ │ ├── ic_share_black_24dp.xml │ │ └── ic_sms_white_24dp.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xxhdpi │ │ ├── acc_avatar.webp │ │ ├── acc_change_key.webp │ │ ├── acc_change_skin.webp │ │ ├── acc_clear.webp │ │ ├── acc_nickname.webp │ │ ├── acc_province_flow.webp │ │ ├── acc_setting_center.webp │ │ ├── acc_update.webp │ │ ├── acc_user.webp │ │ ├── avatar_default.webp │ │ ├── bg_shake.webp │ │ ├── bg_vip.webp │ │ ├── bg_welcome_page.webp │ │ ├── check_normal.webp │ │ ├── check_pressed.webp │ │ ├── good_morning_img.webp │ │ ├── good_night_img.webp │ │ ├── guide_img_1.webp │ │ ├── guide_img_2.webp │ │ ├── guide_img_3.webp │ │ ├── ic_ac.webp │ │ ├── ic_add_to_cart.webp │ │ ├── ic_buy.webp │ │ ├── ic_cart.webp │ │ ├── ic_close.webp │ │ ├── ic_delete.webp │ │ ├── ic_get.webp │ │ ├── ic_hc.webp │ │ ├── ic_index_integration_shop.webp │ │ ├── ic_index_question.webp │ │ ├── ic_index_shake.webp │ │ ├── ic_index_sign_in.webp │ │ ├── ic_level.webp │ │ ├── ic_line.webp │ │ ├── ic_logo_kb.webp │ │ ├── ic_me_about.webp │ │ ├── ic_me_attention.webp │ │ ├── ic_me_encourage.webp │ │ ├── ic_me_feedback.webp │ │ ├── ic_me_option.webp │ │ ├── ic_me_share.webp │ │ ├── ic_message.webp │ │ ├── ic_nc.webp │ │ ├── ic_network_disabled.webp │ │ ├── ic_nickname.webp │ │ ├── ic_no_data.webp │ │ ├── ic_open.webp │ │ ├── ic_order_1.webp │ │ ├── ic_order_2.webp │ │ ├── ic_order_3.webp │ │ ├── ic_order_4.webp │ │ ├── ic_price.webp │ │ ├── ic_risk_money.webp │ │ ├── ic_search.webp │ │ ├── ic_select.webp │ │ ├── ic_top.webp │ │ ├── ic_top_bar.webp │ │ ├── ic_type_baby.webp │ │ ├── ic_type_bag.webp │ │ ├── ic_type_beauty.webp │ │ ├── ic_type_car.webp │ │ ├── ic_type_clothes.webp │ │ ├── ic_type_digital.webp │ │ ├── ic_type_life.webp │ │ ├── ic_type_snacks.webp │ │ ├── ic_unselect.webp │ │ ├── ic_update_banner.webp │ │ ├── ic_voice_close.webp │ │ ├── ic_voice_open.webp │ │ ├── level_0.webp │ │ ├── level_1.webp │ │ ├── level_10.webp │ │ ├── level_2.webp │ │ ├── level_3.webp │ │ ├── level_4.webp │ │ ├── level_5.webp │ │ ├── level_6.webp │ │ ├── level_7.webp │ │ ├── level_8.webp │ │ ├── level_9.webp │ │ ├── sc_arrow_right.webp │ │ ├── selfcenter_bg_0.webp │ │ ├── selfcenter_bg_1.webp │ │ ├── selfcenter_bg_2.webp │ │ ├── selfcenter_bg_3.webp │ │ ├── selfcenter_bg_4.webp │ │ ├── selfcenter_bg_banner_0.webp │ │ ├── selfcenter_bg_banner_1.webp │ │ ├── selfcenter_bg_banner_2.webp │ │ ├── selfcenter_bg_banner_3.webp │ │ ├── selfcenter_bg_banner_4.webp │ │ ├── selfcenter_bg_main_0.webp │ │ ├── selfcenter_bg_main_1.webp │ │ ├── selfcenter_bg_main_2.webp │ │ ├── selfcenter_bg_main_3.webp │ │ ├── selfcenter_bg_main_4.webp │ │ ├── shake_image.webp │ │ ├── shake_luck.webp │ │ ├── shake_original_image.webp │ │ ├── shake_unluck.webp │ │ ├── sign_in_a.webp │ │ ├── sign_in_b.webp │ │ └── sign_in_c.webp │ │ ├── drawable │ │ ├── bg_buy_btn.xml │ │ ├── bg_buy_btn_pressed.xml │ │ ├── bg_corner_pink.xml │ │ ├── bg_corner_white.xml │ │ ├── bg_edit_text.xml │ │ ├── bg_edit_text_focused.xml │ │ ├── bg_edit_text_normal.xml │ │ ├── bg_get_btn.xml │ │ ├── bg_get_btn_pressed.xml │ │ ├── bg_type.xml │ │ ├── global_click_selector.xml │ │ ├── global_red_click_with_corner_selector.xml │ │ ├── global_red_clickable_selector.xml │ │ ├── ic_home_black_24dp.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_local_mall_black_24dp.xml │ │ ├── ic_local_offer_black_24dp.xml │ │ ├── ic_person_black_24dp.xml │ │ ├── ic_search_white_24dp.xml │ │ ├── ic_subject_white_24dp.xml │ │ ├── ic_visibility_off_white_24dp.xml │ │ ├── ic_visibility_white_24dp.xml │ │ ├── icon_error.9.png │ │ ├── icon_stub.9.png │ │ └── shape_card_view.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_config.xml │ │ ├── activity_credit_history.xml │ │ ├── activity_goods_details.xml │ │ ├── activity_guide.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_search.xml │ │ ├── activity_search_result.xml │ │ ├── activity_shake.xml │ │ ├── activity_sign_in.xml │ │ ├── activity_vip.xml │ │ ├── adapter_banner.xml │ │ ├── adapter_guide.xml │ │ ├── fragment_goods_list.xml │ │ ├── fragment_main_index.xml │ │ ├── fragment_main_me.xml │ │ ├── fragment_main_nine_goods.xml │ │ ├── fragment_main_ranking_goods.xml │ │ ├── include_anything_list.xml │ │ ├── include_credit_history_header.xml │ │ ├── include_item_action.xml │ │ ├── include_main_index_header.xml │ │ ├── include_main_index_icon.xml │ │ ├── include_main_index_menu.xml │ │ ├── include_no_data.xml │ │ ├── include_pop_six_icon.xml │ │ ├── include_port_item_details.xml │ │ ├── list_item_credit_history.xml │ │ ├── list_item_goods.xml │ │ └── list_item_key_words.xml │ │ ├── menu │ │ └── bottom_nav_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── cn │ └── neday │ └── sheep │ └── ExampleUnitTest.kt ├── base ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cn │ │ └── neday │ │ └── base │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── cn │ │ │ └── neday │ │ │ └── base │ │ │ ├── SingleLiveEvent.java │ │ │ ├── activity │ │ │ ├── BaseActivity.kt │ │ │ └── BaseVMActivity.kt │ │ │ ├── config │ │ │ ├── BuglyConfig.kt │ │ │ ├── DoraemonKitConfig.kt │ │ │ ├── LogConfig.kt │ │ │ └── MMKVConfig.kt │ │ │ ├── di │ │ │ └── HttpClientModule.kt │ │ │ ├── fragment │ │ │ ├── BaseFragment.kt │ │ │ └── BaseVMFragment.kt │ │ │ ├── model │ │ │ ├── BaseModel.kt │ │ │ ├── Pages.kt │ │ │ └── Response.kt │ │ │ ├── network │ │ │ ├── CoroutineDSL.kt │ │ │ └── interceptor │ │ │ │ └── AuthenticationInterceptor.kt │ │ │ ├── router │ │ │ ├── AlibabaService.kt │ │ │ ├── AppService.kt │ │ │ ├── Router.kt │ │ │ └── RouterPath.kt │ │ │ ├── util │ │ │ ├── AppStoreUtils.java │ │ │ ├── ClipboardUtils.java │ │ │ └── SecurityUtils.kt │ │ │ └── viewmodel │ │ │ └── BaseViewModel.kt │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── cn │ └── neday │ └── base │ ├── ExampleUnitTest.java │ └── SingleLiveEventTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/Sheep 5 | docker: 6 | - image: circleci/android:api-29 7 | environment: 8 | JVM_OPTS: -Xmx3200m 9 | steps: 10 | - checkout 11 | - restore_cache: 12 | key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} 13 | - run: echo $ENCODED_KEYSTORE | base64 --decode >> ${HOME}/Sheep/app/keystore/release-signing.properties 14 | - run: 15 | name: Chmod permissions #if permission for Gradlew Dependencies fail, use this. 16 | command: sudo chmod +x ./gradlew 17 | - run: 18 | name: Download Dependencies 19 | command: ./gradlew androidDependencies 20 | - save_cache: 21 | paths: 22 | - ~/.gradle 23 | key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} 24 | - run: 25 | name: Run Tests 26 | command: ./gradlew lint test 27 | - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ 28 | path: app/build/reports 29 | destination: reports 30 | - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ 31 | path: app/build/test-results 32 | # See https://circleci.com/docs/2.0/deployment-integrations/ for deploy examples 33 | 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/blank.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - release/* 8 | schedule: 9 | - cron: 0 2 * * 1-5 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v1 18 | - name: Run a one-line script 19 | run: echo Hello, world! 20 | - name: Run a multi-line script 21 | run: | 22 | echo Add other actions to build, 23 | echo test, and deploy your project. 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | # Android Studio Navigation editor temp files 30 | .navigation/ 31 | 32 | # Android Studio captures folder 33 | captures/ 34 | 35 | # IntelliJ 36 | *.iml 37 | .idea/ 38 | 39 | # Keystore files 40 | # Uncomment the following line if you do not want to check your keystore files in. 41 | #*.jks 42 | 43 | # External native build folder generated in Android Studio 2.2 and later 44 | .externalNativeBuild 45 | 46 | # Google Services (e.g. APIs or Firebase) 47 | google-services.json 48 | 49 | # Freeline 50 | freeline.py 51 | freeline/ 52 | freeline_project_description.json 53 | 54 | # fastlane 55 | fastlane/report.xml 56 | fastlane/Preview.html 57 | fastlane/screenshots 58 | fastlane/test_output 59 | fastlane/readme.md 60 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | jdk: oraclejdk8 3 | dist: trusty 4 | sudo: false 5 | android: 6 | components: 7 | # Uncomment the lines below if you want to 8 | # use the latest revision of Android SDK Tools 9 | - tools 10 | - platform-tools 11 | # The BuildTools version used by your project 12 | - build-tools-29.0.1 13 | # The SDK version used to compile your project 14 | - android-29 15 | # - android-21 16 | # Additional components 17 | - extra-google-google_play_services 18 | - extra-google-m2repository 19 | - extra-android-m2repository 20 | # Specify at least one system image, 21 | # if you need to run emulator(s) during your tests 22 | # - sys-img-armeabi-v7a-android-21 23 | licenses: 24 | - 'android-sdk-preview-license-.+' 25 | - 'android-sdk-license-.+' 26 | - 'google-gdk-license-.+' 27 | 28 | before_cache: 29 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 30 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 31 | cache: 32 | directories: 33 | - $HOME/.gradle/caches/ 34 | - $HOME/.gradle/wrapper/ 35 | - $HOME/.android/build-cache 36 | 37 | before_script: 38 | # - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a 39 | # - emulator -avd test -no-skin -no-audio -no-window & 40 | # - android-wait-for-emulator 41 | # - adb shell input keyevent 82 & 42 | - echo $ENCODED_KEYSTORE | base64 --decode >> app/keystore/release-signing.properties 43 | - chmod +x gradlew 44 | 45 | script: 46 | - ./gradlew assembleRelease 47 | - ./gradlew jacocoTestDebugUnitTestCoverage 48 | # - ./gradlew connectedCheck 49 | 50 | #deploy: 51 | # provider: releases 52 | # api_key: 53 | # secure: 55899123919929d9c123f1200414174e299f07e9 54 | # file: app/build/outputs/apk/app-release.apk 55 | # skip_cleanup: true 56 | # on: 57 | # tags: true 58 | 59 | # 添加蒲公英上传脚本 60 | before_install: 61 | # - cd $TRAVIS_BUILD_DIR 62 | # - wget -c https://raw.githubusercontent.com/Pgyer/TravisFile/master/pgyer_upload.sh 63 | # -O pgyer_upload.sh 64 | # - chmod +x pgyer_upload.sh 65 | # - gem install fir-cli 66 | - touch $HOME/.android/repositories.cfg 67 | - yes | sdkmanager "platforms;android-28" 68 | - yes | sdkmanager "build-tools;28.0.3" 69 | 70 | ## 在apk上传到GitHub后,使用蒲公英的上传脚本将apk上传到蒲公英 71 | #after_deploy: 72 | # - set -e 73 | # - $TRAVIS_BUILD_DIR/pgyer_upload.sh "${TRAVIS_BUILD_DIR}/app/build/outputs/apk/release/app-release.apk" $PGYER_API_KEY 74 | # - fir p app/build/outputs/apk/release/app-release.apk -T $FIR_API_TOKEN -c "`git cat-file tag $TRAVIS_TAG`" 75 | 76 | after_success: 77 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/CHANGELOG.md -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 苏晟 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /alibaba/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /alibaba/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | android { 7 | compileSdkVersion rootProject.ext.compileSdkVersion 8 | defaultConfig { 9 | minSdkVersion rootProject.ext.minSdkVersion 10 | targetSdkVersion rootProject.ext.targetSdkVersion 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | 15 | buildTypes { 16 | debug { 17 | testCoverageEnabled true 18 | } 19 | release { 20 | minifyEnabled false 21 | consumerProguardFiles 'proguard-rules.pro' 22 | } 23 | } 24 | 25 | compileOptions { 26 | sourceCompatibility JavaVersion.VERSION_1_8 27 | targetCompatibility JavaVersion.VERSION_1_8 28 | } 29 | 30 | lintOptions { 31 | abortOnError false 32 | } 33 | } 34 | 35 | kapt { 36 | arguments { 37 | arg("AROUTER_MODULE_NAME", project.getName()) 38 | } 39 | } 40 | 41 | dependencies { 42 | implementation fileTree(dir: 'libs', include: ['*.jar']) 43 | 44 | implementation project(':base') 45 | 46 | kapt 'com.alibaba:arouter-compiler:1.2.2' 47 | 48 | // 支付宝 49 | implementation 'com.alipay.android.app.cashier:standardcashier-single:15.6.5@aar' 50 | compileOnly 'com.alipay.mobile.android.securitysdk:apsecuritysdk-all:3.3.0' 51 | // 安全组件 52 | implementation 'com.taobao.android:securityguardaar3:5.4.171@aar' 53 | implementation 'com.taobao.android:securitybodyaar3:5.4.99@aar' 54 | implementation 'com.taobao.android:avmpaar3:5.4.36@aar' 55 | implementation 'com.taobao.android:sgmiddletieraar3:5.4.9@aar' 56 | // Mtop 57 | implementation 'com.taobao.android:mtopsdk_allinone_open:3.1.2.5@jar' 58 | // 登录授权 59 | implementation 'com.ali.auth.sdk:alibabauth_core:2.0.0.6@aar' 60 | implementation 'com.ali.auth.sdk:alibabauth_ui:2.0.0.6@aar' 61 | implementation 'com.ali.auth.sdk:alibabauth_ext:2.0.0.6@aar' 62 | // AppLink 63 | implementation 'com.alibaba.sdk.android:alibc_link_partner:4.1.15@aar' 64 | // UT 65 | implementation 'com.taobao.android:utdid4all:1.5.2' 66 | implementation 'com.alibaba.mtl:app-monitor-sdk:2.6.4.5_for_bc' 67 | // 电商基础组件 68 | implementation 'com.alibaba.sdk.android:AlibcTradeCommon:4.0.0.8@aar' 69 | implementation 'com.alibaba.sdk.android:AlibcTradeBiz:4.0.0.8@aar' 70 | implementation 'com.alibaba.sdk.android:nb_trade:4.0.0.8@aar' 71 | implementation 'com.alibaba:fastjson:1.2.48' 72 | 73 | // Unit Test 74 | testImplementation 'junit:junit:4.12' 75 | } 76 | -------------------------------------------------------------------------------- /alibaba/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -keepattributes Signature 24 | -ignorewarnings 25 | -keep class javax.ws.rs.** { *; } 26 | -keep class com.alibaba.fastjson.** { *; } 27 | -dontwarn com.alibaba.fastjson.** 28 | -keep class sun.misc.Unsafe { *; } 29 | -dontwarn sun.misc.** 30 | -keep class com.taobao.** {*;} 31 | -keep class com.alibaba.** {*;} 32 | -keep class com.alipay.** {*;} 33 | 34 | -dontwarn com.taobao.** 35 | -dontwarn com.alibaba.** 36 | -dontwarn com.alipay.** 37 | 38 | -keep class com.ut.** {*;} 39 | -dontwarn com.ut.** 40 | 41 | -keep class com.ta.** {*;} 42 | -dontwarn com.ta.** 43 | -keep class org.json.** {*;} 44 | -keep class com.ali.auth.** {*;} 45 | -dontwarn com.ali.auth.** 46 | 47 | -keep class com.taobao.securityjni.** {*;} 48 | -keep class com.taobao.wireless.security.** {*;} 49 | -keep class com.taobao.dp.**{*;} 50 | -keep class com.alibaba.wireless.security.**{*;} 51 | 52 | -keep interface mtopsdk.mtop.global.init.IMtopInitTask {*;} 53 | -keep class * implements mtopsdk.mtop.global.init.IMtopInitTask {*;} -------------------------------------------------------------------------------- /alibaba/src/androidTest/java/cn/neday/alibaba/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.neday.alibaba; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import static org.junit.Assert.*; 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * @see Testing documentation 15 | */ 16 | @RunWith(AndroidJUnit4.class) 17 | public class ExampleInstrumentedTest { 18 | @Test 19 | public void useAppContext() { 20 | // Context of the app under test. 21 | Context appContext = InstrumentationRegistry.getTargetContext(); 22 | 23 | assertEquals("cn.neday.alibaba.test", appContext.getPackageName()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /alibaba/src/debug/res/drawable/yw_1222.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/alibaba/src/debug/res/drawable/yw_1222.jpg -------------------------------------------------------------------------------- /alibaba/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /alibaba/src/main/java/cn/neday/alibaba/AlibabaServiceImpl.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.alibaba 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.text.TextUtils 6 | import cn.neday.base.router.AlibabaService 7 | import cn.neday.base.router.RouterPath 8 | import com.alibaba.android.arouter.facade.annotation.Route 9 | import com.alibaba.baichuan.android.trade.AlibcTradeSDK 10 | import com.alibaba.baichuan.android.trade.page.AlibcDetailPage 11 | import com.alibaba.baichuan.android.trade.page.AlibcMyCartsPage 12 | import com.alibaba.baichuan.android.trade.page.AlibcShopPage 13 | import com.blankj.utilcode.util.LogUtils 14 | import com.blankj.utilcode.util.StringUtils 15 | import com.blankj.utilcode.util.ToastUtils 16 | 17 | @Route(path = RouterPath.AlibabaService) 18 | class AlibabaServiceImpl : AlibabaService { 19 | 20 | override fun destroySDK() { 21 | AlibcTradeSDK.destory() 22 | } 23 | 24 | /** 25 | * 根据商品ID打开商品页 26 | * 27 | * @param itemId 支持itemId和openItemId的商品,必填,不允许为null; 28 | * eg.37196464781L;AAHd5d-HAAeGwJedwSnHktBI; 29 | */ 30 | override fun showDetailPage(activity: Activity?, itemId: String) { 31 | AliTradeHelper(activity).showAlibcTradePage(AlibcDetailPage(itemId), "detail") 32 | } 33 | 34 | /** 35 | * 根据店铺ID打开店铺页 36 | * 37 | * @param shopId 店铺id,支持明文id 38 | */ 39 | override fun showShopPage(activity: Activity?, shopId: String) { 40 | AliTradeHelper(activity).showAlibcTradePage(AlibcShopPage(shopId), "shop") 41 | } 42 | 43 | /** 44 | * 添加指定商品ID的商品到购物车 45 | * 46 | * @param itemId 支持itemId和openItemId的商品,必填,不允许为null; 47 | * eg.37196464781L;AAHd5d-HAAeGwJedwSnHktBI; 48 | */ 49 | override fun showAddCartPage(activity: Activity?, itemId: String) { 50 | ToastUtils.showShort(StringUtils.getString(R.string.tx_todo_fun)) 51 | // AliTradeHelper(activity).showAlibcTradePage(AlibcAddCartPage(itemId), "cart") 52 | } 53 | 54 | /** 55 | * 打开购物订单页 参数表示的是待发货、已付款等 56 | * 57 | * @param status 默认跳转页面;填写:0:全部;1:待付款;2:待发货;3:待收货;4:待评价 58 | * @param allOrder false 进行订单分域(只展示通过当前app下单的订单),true 显示所有订单 59 | */ 60 | override fun showMyOrdersPage(activity: Activity?, status: Int, allOrder: Boolean) { 61 | ToastUtils.showShort(StringUtils.getString(R.string.tx_todo_fun)) 62 | // AliTradeHelper(activity).showAlibcTradePage(AlibcMyOrdersPage(status, allOrder), "trade") 63 | } 64 | 65 | /** 66 | * 打开用户购物车 67 | */ 68 | override fun showMyCartsPage(activity: Activity?) { 69 | AliTradeHelper(activity).showAlibcTradePage(AlibcMyCartsPage(), "cart") 70 | } 71 | 72 | /** 73 | * 根据url打开阿里自带的webView 74 | * 75 | * @param url 要展示的url 76 | */ 77 | override fun showItemURLPage(activity: Activity?, url: String) { 78 | if (!TextUtils.isEmpty(url)) { 79 | AliTradeHelper(activity).openByUrl(url) 80 | } 81 | } 82 | 83 | override fun init(context: Context?) { 84 | AliTradeHelper.asyncInit() 85 | LogUtils.d("Alibaba service impl init") 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /alibaba/src/main/res/drawable/yw_1222.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/alibaba/src/main/res/drawable/yw_1222.jpg -------------------------------------------------------------------------------- /alibaba/src/main/res/raw/keep.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /alibaba/src/test/java/cn/neday/alibaba/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.neday.alibaba; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /keystore/release-signing.properties 3 | /bugly -------------------------------------------------------------------------------- /app/bugly.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'bugly' 2 | 3 | bugly { 4 | appId = '923c0825a2' 5 | appKey = '0decf1a9-d0a5-4cd9-878f-b48bba4f270d' 6 | } -------------------------------------------------------------------------------- /app/jacoco.gradle: -------------------------------------------------------------------------------- 1 | // Android Gradle Plugin out of the box only supports code coverage for instrumentation espresso) tests. 2 | // This add support for unit tests as well. 3 | apply plugin: 'jacoco' 4 | 5 | jacoco { 6 | toolVersion = "0.8.5" 7 | reportsDir = file("$buildDir/reports") 8 | } 9 | 10 | task jacocoTestDebugUnitTestCoverage(type: JacocoReport) { 11 | group = 'Reporting' 12 | description = "Generate Jacoco coverage reports for the Debug build. Only unit tests." 13 | 14 | reports { 15 | csv.enabled false 16 | xml.enabled = true 17 | html.enabled = true 18 | } 19 | 20 | // Make sure that tests from all modules are run before coverage report 21 | dependsOn ":app:testDebugUnitTest" 22 | dependsOn ":alibaba:testDebugUnitTest" 23 | dependsOn ":base:testDebugUnitTest" 24 | 25 | // what to exclude from coverage report, UI, "noise", generated classes, platform classes, etc. 26 | def excludes = [ 27 | // Platform classes 28 | '**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*', 'androidx/**/*.*', 29 | // Ui, View, Adapter, Dialog, Application, HTTP 30 | '**/*Activity.*', '**/*Fragment.*', '**/*View.*', '**/*Adapter.*', '**/*Dialog.*', '**/ui/**', '**/activity/**', '**/fragment/**', '**/view/**', '**/adapter/**', '**/dialog/**', "**/ThisApplication.*", "**/network/**", 31 | // Anonymous inner class 32 | '**/*$*', 33 | ] 34 | 35 | // generated classes 36 | classDirectories.from = files([ 37 | fileTree( 38 | dir: "$project.rootDir/app/build/intermediates/javac/debug", 39 | excludes: excludes), 40 | fileTree( 41 | dir: "$project.rootDir/app/build/tmp/kotlin-classes/debug", 42 | excludes: excludes), 43 | fileTree( 44 | dir: "$project.rootDir/alibaba/build/intermediates/javac/debug", 45 | excludes: excludes), 46 | fileTree( 47 | dir: "$project.rootDir/alibaba/build/tmp/kotlin-classes/debug", 48 | excludes: excludes), 49 | fileTree( 50 | dir: "$project.rootDir/base/build/intermediates/javac/debug", 51 | excludes: excludes), 52 | fileTree( 53 | dir: "$project.rootDir/base/build/tmp/kotlin-classes/debug", 54 | excludes: excludes) 55 | ]) 56 | 57 | // sources 58 | sourceDirectories.from = fileTree(dir: project.rootDir, includes: [ 59 | "app/src/main/java", 60 | "alibaba/src/main/java", 61 | "base/src/main/java" 62 | ]) 63 | 64 | // execution 65 | executionData.from = fileTree(dir: project.rootDir, includes: [ 66 | 'app/build/jacoco/testDebugUnitTest.exec', 67 | 'alibaba/build/jacoco/testDebugUnitTest.exec', 68 | 'base/build/jacoco/testDebugUnitTest.exec' 69 | ]) 70 | } -------------------------------------------------------------------------------- /app/jiagu.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'jiagu360' 2 | 3 | Properties debugSigning = new Properties() 4 | debugSigning.load(new FileInputStream(file(project.property("debug-signing.properties")))) 5 | 6 | Properties releaseSigning = new Properties() 7 | releaseSigning.load(new FileInputStream(file(project.property("release-signing.properties")))) 8 | 9 | jiaGu360Config { 10 | // 必填, 360用户名 11 | userName "neday@bk.ru" 12 | // 必填, 360密码 13 | passWord "y17096..." 14 | // 必填, 360加固jar包位置 15 | jiaGuJarPath new File("D:\\Program\\360firm_windows_64\\jiagu\\jiagu.jar").absolutePath 16 | // 加固配置项服务是否都支持 17 | isSupportAll false 18 | // 加固apk的输出目录 19 | outputApkDirPath new File("D:\\Program\\360firm_windows_64\\jiagu\\output\\neday@bk.ru\\").absolutePath 20 | // 加固完成后是否打开输出目录。默认false 21 | openOutputDir false 22 | 23 | // 可选增强服务--------------start---------------------- 24 | isSupportCrashLong false //【崩溃日志分析】 25 | isSupportX86 false //【x86支持】 26 | isSupportAnalyse false//【加固数据分析】 27 | isNocert false//【跳过签名校验】 28 | // 可选增强服务--------------end---------------------- 29 | 30 | // 高级加固选项-------------start------------------ 31 | isSupportVmp false//【全VMP保护】 32 | isSupportDataProtection false//【本地数据文件保护】 33 | isSupportAssetsProtection false// 【资源文件保护】 34 | isSupportFileCheck false//【文件完整性校验】 35 | isSupportPtrace false//【Ptrace防注入】 36 | isSupportSoProtection false//【SO文件保护】 37 | isSupportDex2cProtection false//【dex2C保护】 38 | isSupportStringObfusProtection false//【字符串加密】 39 | isSupportDexShadowProtection false//【DexShadow】 40 | isSupportSoPrivateProtection false//【SO防盗用】 41 | // 高级加固选项-------------end------------------ 42 | 43 | // 自动签名 44 | autosign true 45 | 46 | items { 47 | debug { 48 | // 必填, 需要加固的APK 路径 49 | inputApkFilePath file("build/outputs/apk/debug/app-debug.apk").absolutePath 50 | 51 | // android 签名配置名称 52 | signingName 'debug' 53 | 54 | // 签名配置项 55 | signingInfo { 56 | storeFilePath debugSigning['storeFile'] 57 | storePassword debugSigning['storePassword'] 58 | keyAlias debugSigning['keyAlias'] 59 | keyPassword debugSigning['keyPassword'] 60 | } 61 | } 62 | 63 | release { 64 | // 必填, 需要加固的APK 路径 65 | inputApkFilePath file("build/outputs/apk/release/app-release.apk").absolutePath 66 | 67 | // android 签名配置名称 68 | signingName 'release' 69 | 70 | // 自定义文件生成多渠道 71 | // mulpkgFilePath = new File("D:\\Program\\360firm_windows_64\\jiagu\\多渠道模板.txt") 72 | 73 | // 签名配置项 74 | signingInfo { 75 | storeFilePath releaseSigning['storeFile'] 76 | storePassword releaseSigning['storePassword'] 77 | keyAlias releaseSigning['keyAlias'] 78 | keyPassword releaseSigning['keyPassword'] 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /app/keystore/debug-signing.properties: -------------------------------------------------------------------------------- 1 | storeFile=./keystore/neday-debug-keystore.jks 2 | storePassword=abcd1234 3 | keyAlias=debug 4 | keyPassword=abcd1234 5 | -------------------------------------------------------------------------------- /app/keystore/neday-debug-keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/keystore/neday-debug-keystore.jks -------------------------------------------------------------------------------- /app/keystore/neday-release-keystore.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/keystore/neday-release-keystore.jks -------------------------------------------------------------------------------- /app/mob.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.mob.sdk' 2 | 3 | MobSDK { 4 | appKey "2b8365a15465f" 5 | appSecret "d25eaed975d84f7c8ca253756ffd7387" 6 | SMSSDK { 7 | // 默认使用GUI,若不使用GUI,通过以下开关关闭 8 | gui false 9 | // 若使用GUI的自动填充验证码功能,需打开此设置 10 | autoSMS false 11 | } 12 | ShareSDK { 13 | loopShare true 14 | devInfo { 15 | Wechat { 16 | appId "wx4868b35061f87885" 17 | appSecret "64020361b8ec4c99936c0e3999a9f249" 18 | userName "gh_afb25ac019c9" 19 | path "pages/index/index.html?id=1" 20 | withShareTicket true 21 | miniprogramType 2 22 | } 23 | QQ { 24 | appId "100371282" 25 | appKey "aed9b0303e3ed1e27bae87c33761161d" 26 | } 27 | SinaWeibo { 28 | appKey "568898243" 29 | appSecret "38a4f8204cc784f81f9f0daaf31e02e3" 30 | callbackUri "http://www.sharesdk.cn" 31 | } 32 | ShortMessage {} 33 | WechatMoments { 34 | appId "wx4868b35061f87885" 35 | appSecret "64020361b8ec4c99936c0e3999a9f249" 36 | } 37 | WechatFavorite { 38 | appId "wx4868b35061f87885" 39 | appSecret "64020361b8ec4c99936c0e3999a9f249" 40 | } 41 | } 42 | } 43 | MobPush { 44 | bradge true 45 | devInfo { 46 | HUAWEI { 47 | appId "华为的appid" 48 | } 49 | MEIZU { 50 | appId "魅族的appid" 51 | appKey "魅族的appkey" 52 | } 53 | XIAOMI { 54 | appId "小米的appId" 55 | appKey "小米的appKey" 56 | } 57 | FCM { 58 | iconRes "@mipmap/ic_launcher" 59 | } 60 | OPPO { 61 | appKey "OPPO的appKey" 62 | appSecret "OPPO的appSecret" 63 | } 64 | VIVO { 65 | appId "VIVO的appId" 66 | appKey "VIVO的appSecret" 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/cn/neday/sheep/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep 2 | 3 | import androidx.test.InstrumentationRegistry 4 | import androidx.test.runner.AndroidJUnit4 5 | import org.junit.Assert.assertEquals 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * See [testing documentation](http://d.android.com/tools/testing). 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getTargetContext() 20 | assertEquals("cn.neday.sheep", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/Constants.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep 2 | 3 | const val PAGE_SIZE = 50 4 | const val PREFETCH_DISTANCE = 20 5 | const val LOAD_INITIAL_PAGE_ID = "1" 6 | 7 | // 用户使用协议 8 | const val KZ_YHSYXY = "http://kz.neday.cn/81/26/p3336309366de35" 9 | // 天天摇活动介绍 10 | const val KZ_TTY = "http://kz.neday.cn/91/85/p333138498122d7" 11 | // 积分规则说明 12 | const val KZ_JF = "http://kz.neday.cn/89/30/p33312925275824" 13 | // 邀请活动奖励规则 14 | const val KZ_YQ = "http://kz.neday.cn/71/75/p333127659e894d" -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/ThisApplication.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep 2 | 3 | import android.app.Application 4 | import cn.neday.base.config.BuglyConfig 5 | import cn.neday.base.config.DoraemonKitConfig 6 | import cn.neday.base.config.LogConfig 7 | import cn.neday.base.config.MMKVConfig 8 | import cn.neday.base.di.httpClientModule 9 | import cn.neday.sheep.di.repositoryModule 10 | import cn.neday.sheep.di.viewModelModule 11 | import com.alibaba.android.arouter.launcher.ARouter 12 | import com.blankj.utilcode.util.ProcessUtils 13 | import com.blankj.utilcode.util.Utils 14 | import com.mob.MobSDK 15 | import org.koin.android.ext.koin.androidContext 16 | import org.koin.android.ext.koin.androidFileProperties 17 | import org.koin.android.ext.koin.androidLogger 18 | import org.koin.core.context.startKoin 19 | 20 | /** 21 | *         ┏┓   ┏┓+ + 22 | *        ┏┛┻━━━┛┻┓ + + 23 | *        ┃       ┃ 24 | *        ┃   ━   ┃ ++ + + + 25 | *        ████━████ ┃+ 26 | *        ┃       ┃ + 27 | *        ┃   ┻   ┃ 28 | *        ┃       ┃ + + 29 | *        ┗━┓   ┏━┛ 30 | *          ┃   ┃ 31 | *          ┃   ┃ + + + + 32 | *          ┃   ┃    Code is far away from bug with the animal protecting 33 | *          ┃   ┃ +     神兽保佑,代码无bug 34 | *          ┃   ┃ 35 | *          ┃   ┃  + 36 | *          ┃    ┗━━━┓ + + 37 | *          ┃        ┣┓ 38 | *          ┃        ┏┛ 39 | *          ┗┓┓┏━┳┓┏┛ + + + + 40 | *           ┃┫┫ ┃┫┫ 41 | *           ┗┻┛ ┗┻┛+ + + + 42 | * 自定义全局Application类 43 | * 44 | * @author nEdAy 45 | */ 46 | class ThisApplication : Application() { 47 | 48 | override fun onCreate() { 49 | super.onCreate() 50 | Utils.init(this) 51 | LogConfig.init() 52 | initARouter() 53 | initKoin() 54 | if (ProcessUtils.isMainProcess()) { 55 | BuglyConfig.init() 56 | MMKVConfig.init() 57 | DoraemonKitConfig.init() 58 | MobSDK.init(this) 59 | } 60 | } 61 | 62 | private fun initKoin() { 63 | startKoin { 64 | androidLogger() 65 | androidContext(this@ThisApplication) 66 | androidFileProperties() 67 | modules(listOf(repositoryModule, httpClientModule, viewModelModule)) 68 | } 69 | } 70 | 71 | private fun initARouter() { 72 | if (BuildConfig.DEBUG) { 73 | ARouter.openLog() 74 | ARouter.openDebug() 75 | } 76 | ARouter.init(this) 77 | } 78 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/AboutActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import cn.neday.base.activity.BaseActivity 4 | import cn.neday.sheep.R 5 | import com.blankj.utilcode.util.ActivityUtils 6 | import com.wuhenzhizao.titlebar.widget.CommonTitleBar 7 | import kotlinx.android.synthetic.main.activity_about.* 8 | 9 | /** 10 | * 关于与合作页 11 | * 12 | * @author nEdAy 13 | */ 14 | class AboutActivity : BaseActivity(R.layout.activity_about) { 15 | 16 | override fun initView() { 17 | titleBar_about.setListener { _, action, _ -> 18 | if (action == CommonTitleBar.ACTION_LEFT_BUTTON) { 19 | ActivityUtils.finishActivity(this) 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/ChangeSkinActivity.java: -------------------------------------------------------------------------------- 1 | //package cn.neday.sheep.activity; 2 | // 3 | // 4 | //import android.os.Bundle; 5 | //import android.view.Gravity; 6 | //import android.view.View; 7 | //import android.widget.ImageView; 8 | //import android.widget.LinearLayout; 9 | //import android.widget.RelativeLayout; 10 | // 11 | //import com.neday.bomb.CustomApplication; 12 | //import com.neday.bomb.R; 13 | //import com.neday.bomb.base.BaseActivity; 14 | //import com.neday.bomb.util.CommonUtils; 15 | //import com.neday.bomb.util.SharedPreferencesHelper; 16 | // 17 | ///** 18 | // * 修改背景皮肤页 19 | // * 20 | // * @author nEdAy 21 | // */ 22 | //public class ChangeSkinActivity extends BaseActivity { 23 | // //背景示例图(上) 24 | // private static final int[] selfcenter_bg_main = {R.drawable.selfcenter_bg_main_0, R.drawable.selfcenter_bg_main_1, 25 | // R.drawable.selfcenter_bg_main_2, R.drawable.selfcenter_bg_main_3, R.drawable.selfcenter_bg_main_4,}; 26 | // //背景选择图(下) 27 | // private static final int[] selfcenter_bg_banner = {R.drawable.selfcenter_bg_banner_0, R.drawable.selfcenter_bg_banner_1, 28 | // R.drawable.selfcenter_bg_banner_2, R.drawable.selfcenter_bg_banner_3, R.drawable.selfcenter_bg_banner_4,}; 29 | // private ImageView skin_image; 30 | // private SharedPreferencesHelper sharedPreferencesHelper; 31 | // 32 | // @Override 33 | // public int bindLayout() { 34 | // return R.layout.activity_change_skin; 35 | // } 36 | // 37 | // @Override 38 | // public void initView(Bundle savedInstanceState) { 39 | // setTintManager(); 40 | // initTopBarForLeft("自定义皮肤", getString(R.string.tx_back)); 41 | // skin_image = findViewById(R.id.skin_image); 42 | // LinearLayout mLinearLayout = findViewById(R.id.my_gallery); 43 | // sharedPreferencesHelper = CustomApplication.getInstance().getSpHelper(); 44 | // int centerBg = sharedPreferencesHelper.getCenterBg(); 45 | // skin_image.setImageResource(selfcenter_bg_main[centerBg]); 46 | // for (int i = 0; i < 5; i++) { 47 | // mLinearLayout.addView(getImageView(i)); 48 | // } 49 | // } 50 | // 51 | // /** 52 | // * 构造每个背景图片的画廊显示 53 | // * 54 | // * @param number 构造序数 55 | // * @return 视图 56 | // */ 57 | // private View getImageView(final int number) { 58 | // RelativeLayout layout = new RelativeLayout(getApplicationContext()); 59 | // layout.setLayoutParams(new RelativeLayout.LayoutParams(250, 250)); 60 | // layout.setGravity(Gravity.CENTER); 61 | // ImageView imageView = new ImageView(mContext); 62 | // imageView.setLayoutParams(new LinearLayout.LayoutParams(200, 200)); 63 | // imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 64 | // imageView.setImageResource(selfcenter_bg_banner[number]); 65 | // layout.addView(imageView); 66 | // layout.setOnClickListener(view -> { 67 | // skin_image.setImageResource(selfcenter_bg_main[number]); 68 | // CommonUtils.showToast("已设置此背景皮肤"); 69 | // sharedPreferencesHelper.setCenterBg(number); 70 | // }); 71 | // return layout; 72 | // } 73 | // 74 | //} -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/ConfigActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import android.view.View 4 | import cn.neday.base.activity.BaseVMActivity 5 | import cn.neday.base.config.BuglyConfig 6 | import cn.neday.base.config.MMKVConfig 7 | import cn.neday.sheep.R 8 | import cn.neday.sheep.viewmodel.ConfigViewModel 9 | import com.blankj.utilcode.util.ActivityUtils 10 | import com.blankj.utilcode.util.AppUtils 11 | import com.blankj.utilcode.util.StringUtils 12 | import com.flyco.dialog.listener.OnBtnClickL 13 | import com.flyco.dialog.widget.NormalDialog 14 | import com.wuhenzhizao.titlebar.widget.CommonTitleBar 15 | import kotlinx.android.synthetic.main.activity_config.* 16 | 17 | /** 18 | * 账户设置页 19 | * 20 | * @author nEdAy 21 | */ 22 | class ConfigActivity : BaseVMActivity(R.layout.activity_config) { 23 | 24 | override val isCheckLogin = true 25 | 26 | override fun initView() { 27 | titleBar_config.setListener { _, action, _ -> 28 | if (action == CommonTitleBar.ACTION_LEFT_BUTTON) { 29 | ActivityUtils.finishActivity(this) 30 | } 31 | } 32 | 33 | rl_update.setOnClickListener { BuglyConfig.checkUpgrade() } 34 | rl_clear.setOnClickListener { clearCache() } 35 | tv_btn_logout.setOnClickListener { logout() } 36 | 37 | showAppVersion() 38 | showCacheSize() 39 | } 40 | 41 | /** 42 | * 刷新显示缓存大小 43 | */ 44 | private fun showCacheSize() { 45 | cacheSize.text = "FileUtil.getFormatSize(FileUtil.getFolderSize(file))" 46 | } 47 | 48 | /** 49 | * 清除缓存 50 | */ 51 | private fun clearCache() { 52 | // 清除图片缓存 53 | // 清除图片上传中各步骤的垃圾 54 | // FileUtil.deleteFolderFile() 55 | // 重新刷新显示缓存大小 56 | // showCacheSize() 57 | } 58 | 59 | /** 60 | * 显示版本号 61 | */ 62 | private fun showAppVersion() { 63 | curVersion.visibility = View.VISIBLE 64 | curVersion.text = StringUtils.getString(R.string.app_version, AppUtils.getAppVersionName()) 65 | } 66 | 67 | /** 68 | * 退出登录 69 | */ 70 | private fun logout() { 71 | val dialog = NormalDialog(this) 72 | dialog.content(getString(R.string.tx_inquiry_logout)) 73 | .title(getString(R.string.logout_prompt)) 74 | .style(NormalDialog.STYLE_TWO) 75 | .titleTextSize(23f) 76 | .show() 77 | dialog.setOnBtnClickL( 78 | OnBtnClickL { dialog.dismiss() }, 79 | OnBtnClickL { 80 | dialog.dismiss() 81 | MMKVConfig.logout() 82 | ActivityUtils.startActivity(LoginActivity::class.java) 83 | ActivityUtils.finishActivity(this) 84 | }) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/GuideActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import cn.neday.base.activity.BaseActivity 4 | import cn.neday.base.config.MMKVConfig.IS_FIRST_START_APP 5 | import cn.neday.base.config.MMKVConfig.kv 6 | import cn.neday.sheep.R 7 | import com.blankj.utilcode.util.ActivityUtils 8 | import kotlinx.android.synthetic.main.activity_guide.* 9 | 10 | /** 11 | * 导航页 12 | * 13 | * @author nEdAy 14 | */ 15 | class GuideActivity : BaseActivity(R.layout.activity_guide) { 16 | 17 | override fun initView() { 18 | guide_banner.setIndicatorWidth(6f) 19 | .setIndicatorHeight(6f) 20 | .setIndicatorGap(12f) 21 | .setIndicatorCornerRadius(3.5f) 22 | .setBarColor(R.color.gray) 23 | .barPadding(0f, 10f, 0f, 10f) 24 | .setSource(arrayListOf(R.drawable.guide_img_1, R.drawable.guide_img_2, R.drawable.guide_img_3)) 25 | .startScroll() 26 | guide_banner.setOnGuideJumpClick { 27 | kv.encode(IS_FIRST_START_APP, false) 28 | ActivityUtils.startActivity(MainActivity::class.java) 29 | ActivityUtils.finishActivity(this) 30 | } 31 | } 32 | 33 | override fun onResume() { 34 | super.onResume() 35 | guide_banner.goOnScroll() 36 | } 37 | 38 | override fun onPause() { 39 | super.onPause() 40 | guide_banner.pauseScroll() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/SearchResultActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import androidx.fragment.app.commit 4 | import cn.neday.base.activity.BaseVMActivity 5 | import cn.neday.sheep.R 6 | import cn.neday.sheep.fragment.SearchResultFragment 7 | import cn.neday.sheep.viewmodel.SearchResultViewModel 8 | import com.blankj.utilcode.util.ActivityUtils 9 | import com.wuhenzhizao.titlebar.widget.CommonTitleBar 10 | import kotlinx.android.synthetic.main.activity_search_result.* 11 | 12 | /** 13 | * 搜索结果列表页 14 | * 15 | * @author nEdAy 16 | */ 17 | class SearchResultActivity : BaseVMActivity(R.layout.activity_search_result) { 18 | 19 | override fun initView() { 20 | val keyWord = intent.extras?.get(EXTRA) as String? 21 | keyWord?.let { 22 | initSearchBar(keyWord) 23 | initFragment(keyWord) 24 | } ?: ActivityUtils.finishActivity(this) 25 | } 26 | 27 | private fun initSearchBar(keyWord: String) { 28 | titleBar_search_result.centerSearchEditText.setText(keyWord) 29 | titleBar_search_result.setListener { _, action, _ -> 30 | if (action == CommonTitleBar.ACTION_SEARCH_SUBMIT || action == CommonTitleBar.ACTION_RIGHT_BUTTON) { 31 | mViewModel.getDtkSearchGoods(titleBar_search_result.searchKey) 32 | } else if (action == CommonTitleBar.ACTION_LEFT_BUTTON) { 33 | ActivityUtils.finishActivity(this) 34 | } 35 | } 36 | } 37 | 38 | private fun initFragment(keyWord: String) { 39 | supportFragmentManager.commit(allowStateLoss = true) { 40 | replace(R.id.fragment, SearchResultFragment(keyWord)) 41 | } 42 | } 43 | 44 | companion object { 45 | 46 | const val EXTRA = "keyWord" 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/ShakeActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import cn.neday.base.activity.BaseVMActivity 4 | import cn.neday.base.router.Router 5 | import cn.neday.sheep.KZ_TTY 6 | import cn.neday.sheep.R 7 | import cn.neday.sheep.viewmodel.ShakeViewModel 8 | import com.blankj.utilcode.util.ActivityUtils 9 | import com.wuhenzhizao.titlebar.widget.CommonTitleBar 10 | import kotlinx.android.synthetic.main.activity_shake.* 11 | 12 | class ShakeActivity : BaseVMActivity(R.layout.activity_shake) { 13 | 14 | override val isCheckLogin = true 15 | 16 | override fun initView() { 17 | titleBar_shake.setListener { _, action, _ -> 18 | if (action == CommonTitleBar.ACTION_LEFT_BUTTON) { 19 | ActivityUtils.finishActivity(this) 20 | } else if (action == CommonTitleBar.ACTION_RIGHT_TEXT) { 21 | Router.alibabaService.showItemURLPage(this, KZ_TTY) 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import android.view.KeyEvent 4 | import cn.neday.base.activity.BaseActivity 5 | import cn.neday.base.config.MMKVConfig.IS_FIRST_START_APP 6 | import cn.neday.base.config.MMKVConfig.kv 7 | import cn.neday.base.util.SecurityUtils 8 | import com.blankj.utilcode.util.ActivityUtils 9 | import kotlinx.coroutines.* 10 | 11 | 12 | /** 13 | * 启动页 14 | * 15 | * @author nEdAy 16 | */ 17 | class SplashActivity : BaseActivity(null) { 18 | 19 | private var job: Job? = null 20 | 21 | override fun initView() { 22 | checkIntentAndIsTaskRoot() 23 | checkSecurity() 24 | delayJumpNextPage() 25 | } 26 | 27 | private fun checkIntentAndIsTaskRoot() { 28 | if (!(intent != null && intent.extras != null) && !isTaskRoot) { 29 | ActivityUtils.finishActivity(this) 30 | } 31 | } 32 | 33 | private fun checkSecurity() { 34 | SecurityUtils.checkIsAppRoot() 35 | SecurityUtils.checkIsAppDebug() 36 | SecurityUtils.checkSignature() 37 | } 38 | 39 | private fun delayJumpNextPage() { 40 | job = GlobalScope.launch(Dispatchers.Main) { 41 | delay(SHOW_TIME_MIN) 42 | jumpNextPage() 43 | } 44 | } 45 | 46 | /** 47 | * 检测是否是第一次启动并指定跳转页 48 | */ 49 | private fun jumpNextPage() { 50 | val userFirst = kv.decodeBool(IS_FIRST_START_APP, true) 51 | if (userFirst) { 52 | ActivityUtils.startActivity(GuideActivity::class.java) 53 | } else { 54 | ActivityUtils.startActivity(MainActivity::class.java) 55 | } 56 | ActivityUtils.finishActivity(this) 57 | } 58 | 59 | /** 60 | * 屏蔽物理返回按钮 61 | */ 62 | override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { 63 | return keyCode == KeyEvent.KEYCODE_BACK || super.onKeyDown(keyCode, event) 64 | } 65 | 66 | override fun onDestroy() { 67 | super.onDestroy() 68 | job?.cancel() 69 | } 70 | 71 | 72 | companion object { 73 | 74 | private const val SHOW_TIME_MIN = 233L 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/activity/VipActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.activity 2 | 3 | import cn.neday.base.activity.BaseActivity 4 | import cn.neday.sheep.R 5 | import com.blankj.utilcode.util.ActivityUtils 6 | import com.blankj.utilcode.util.ToastUtils 7 | import com.wuhenzhizao.titlebar.widget.CommonTitleBar 8 | import kotlinx.android.synthetic.main.activity_vip.* 9 | 10 | /** 11 | * 会员中心页 12 | * 13 | * @author nEdAy 14 | */ 15 | class VipActivity : BaseActivity(R.layout.activity_vip) { 16 | 17 | override val isCheckLogin = true 18 | 19 | override fun initView() { 20 | titleBar_vip.setListener { _, action, _ -> 21 | if (action == CommonTitleBar.ACTION_LEFT_BUTTON) { 22 | ActivityUtils.finishActivity(this) 23 | } else if (action == CommonTitleBar.ACTION_RIGHT_TEXT) { 24 | // ActivityUtils.startActivity(VipHelpActivity::class.java) 25 | } 26 | } 27 | 28 | tv_sign_in.setOnClickListener { ActivityUtils.startActivity(SignInActivity::class.java) } 29 | rl_privilege.setOnClickListener { ToastUtils.showShort(R.string.tx_todo_fun) } 30 | rl_achievement.setOnClickListener { ToastUtils.showShort(R.string.tx_todo_fun) } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/adapter/CreditHistoryListAdapter.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.adapter 2 | 3 | import androidx.recyclerview.widget.RecyclerView 4 | import cn.neday.sheep.R 5 | import cn.neday.sheep.model.CreditHistory 6 | import com.chad.library.adapter.base.BaseQuickAdapter 7 | import com.chad.library.adapter.base.BaseViewHolder 8 | 9 | 10 | /** 11 | * Adapter for the [RecyclerView] 12 | * 13 | * @author nEdAy 14 | */ 15 | class CreditHistoryListAdapter : 16 | BaseQuickAdapter(R.layout.list_item_credit_history, null) { 17 | 18 | override fun convert(helper: BaseViewHolder, creditHistory: CreditHistory) { 19 | val value = creditHistory.change ?: 0 20 | val isNegative = value shr 31 == -1 // 得到符号位,0 为正数,-1 为负数 21 | helper.setText(R.id.tv_creditsHistory_type, creditHistory.message) 22 | .setText(R.id.tv_creditsHistory_time, creditHistory.createAt) 23 | .setText( 24 | R.id.tv_creditsHistory_change, if (isNegative) { 25 | value.toString() 26 | } else { 27 | "+$value" 28 | } 29 | ) 30 | .setTextColor( 31 | R.id.tv_creditsHistory_change, 32 | if (isNegative) { 33 | R.color.red 34 | } else { 35 | R.color.green 36 | } 37 | ) 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/adapter/GoodsListAdapter.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.adapter 2 | 3 | import android.widget.ImageView 4 | import androidx.recyclerview.widget.RecyclerView 5 | import cn.neday.sheep.R 6 | import cn.neday.sheep.model.Goods 7 | import cn.neday.sheep.util.CommonUtils 8 | import coil.api.load 9 | import coil.transform.RoundedCornersTransformation 10 | import com.blankj.utilcode.util.NetworkUtils 11 | import com.blankj.utilcode.util.StringUtils 12 | import com.chad.library.adapter.base.BaseQuickAdapter 13 | import com.chad.library.adapter.base.BaseViewHolder 14 | 15 | /** 16 | * Adapter for the [RecyclerView] 17 | * 18 | * @author nEdAy 19 | */ 20 | class GoodsListAdapter : BaseQuickAdapter(R.layout.list_item_goods, null) { 21 | 22 | override fun convert(helper: BaseViewHolder, goods: Goods) { 23 | helper.setText(R.id.tv_title, goods.dtitle) 24 | .setText(R.id.tv_money, goods.actualPrice.toString()) 25 | .setText( 26 | R.id.tv_sales_num, 27 | StringUtils.getString(R.string.tx_goods_monthSales, goods.monthSales) 28 | ) 29 | .setText( 30 | R.id.tx_get_value, 31 | StringUtils.getString( 32 | R.string.tx_goods_couponPrice, 33 | CommonUtils.getPrettyNumber(goods.couponPrice) 34 | ) 35 | ) 36 | .setText( 37 | R.id.tv_mall_name, StringUtils.getString( 38 | if (goods.isTmall()) { 39 | R.string.tx_tianmao 40 | } else { 41 | R.string.tx_taobao 42 | } 43 | ) 44 | ) 45 | .addOnClickListener(R.id.ll_get, R.id.tx_buy_url) 46 | (helper.getView(R.id.iv_img_shower) as? ImageView)?.load( 47 | goods.getPicUrl() + if (NetworkUtils.is4G()) { 48 | ("_100x100.jpg") 49 | } else { 50 | ("_300x300.jpg") 51 | } 52 | ) { 53 | crossfade(true) 54 | placeholder(R.drawable.icon_stub) 55 | error(R.drawable.icon_error) 56 | transformations(RoundedCornersTransformation(10f)) 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/adapter/KeyWordsListAdapter.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.adapter 2 | 3 | import cn.neday.sheep.R 4 | import com.chad.library.adapter.base.BaseQuickAdapter 5 | import com.chad.library.adapter.base.BaseViewHolder 6 | 7 | class KeyWordsListAdapter : BaseQuickAdapter(R.layout.list_item_key_words, null) { 8 | 9 | override fun convert(helper: BaseViewHolder, keyWords: String) { 10 | helper.setText(R.id.rtv_keyWords, keyWords) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/di/RepositoryModule.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.di 2 | 3 | import cn.neday.sheep.network.api.BannerApi 4 | import cn.neday.sheep.network.api.CategoryApi 5 | import cn.neday.sheep.network.api.GoodsApi 6 | import cn.neday.sheep.network.api.UserApi 7 | import cn.neday.sheep.network.repository.BannerRepository 8 | import cn.neday.sheep.network.repository.CategoryRepository 9 | import cn.neday.sheep.network.repository.GoodsRepository 10 | import cn.neday.sheep.network.repository.UserRepository 11 | import org.koin.dsl.module 12 | import retrofit2.Retrofit 13 | 14 | val repositoryModule = module { 15 | 16 | single { 17 | get().create(BannerApi::class.java) 18 | } 19 | single { BannerRepository(get()) } 20 | 21 | single { 22 | get().create(CategoryApi::class.java) 23 | } 24 | single { CategoryRepository(get()) } 25 | 26 | single { 27 | get().create(GoodsApi::class.java) 28 | } 29 | single { GoodsRepository(get()) } 30 | 31 | single { 32 | get().create(UserApi::class.java) 33 | } 34 | single { UserRepository(get()) } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/di/ViewModelModule.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.di 2 | 3 | import cn.neday.sheep.viewmodel.* 4 | import org.koin.androidx.viewmodel.dsl.viewModel 5 | import org.koin.dsl.module 6 | 7 | val viewModelModule = module { 8 | 9 | viewModel { CreditHistoryViewModel(get()) } 10 | 11 | viewModel { NineListViewModel(get()) } 12 | 13 | viewModel { IndexViewModel(get(), get()) } 14 | 15 | viewModel { LoginViewModel(get()) } 16 | 17 | viewModel { MainViewModel() } 18 | 19 | viewModel { MeViewModel(get()) } 20 | 21 | viewModel { RankingListViewModel(get()) } 22 | 23 | viewModel { SearchResultViewModel(get()) } 24 | 25 | viewModel { SearchViewModel(get()) } 26 | 27 | viewModel { SignInViewModel(get()) } 28 | 29 | viewModel { ShakeViewModel(get()) } 30 | 31 | viewModel { ConfigViewModel(get()) } 32 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/enum/NineType.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.enum 2 | 3 | /** 4 | * 9.9精选 5 | * -1-精选 6 | * 1 -居家百货 7 | * 2 -美食 8 | * 3 -服饰 9 | * 4 -配饰 10 | * 5 -美妆 11 | * 6 -内衣 12 | * 7 -母婴 13 | * 8 -箱包 14 | * 9 -数码配件 15 | * 10 -文娱车品 16 | */ 17 | enum class NineType(val index: Int) { 18 | JING_XUAN(-1), 19 | JU_JUA_BAI_HUO(1), 20 | MEI_SHI(2), 21 | FU_SHI(3), 22 | PEI_SHI(4), 23 | MEI_ZHUANG(5), 24 | NEI_YI(6), 25 | MU_YING(7), 26 | XIANG_BAO(8), 27 | SHU_MA_PEI_JIAN(9), 28 | WEN_YU_CHE_PIN(10) 29 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/enum/OrderType.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.enum 2 | 3 | /** 4 | * 淘宝订单 5 | * 0:全部 6 | * 1:待付款 7 | * 2:待发货 8 | * 3:待收货 9 | * 4:待评价 10 | */ 11 | enum class OrderType(val index: Int) { 12 | ALL(0), 13 | DAT_FU_KUAN(1), 14 | DAT_FA_HUO(2), 15 | DAT_SHOU_HUO(3), 16 | DAY_PING_JIA(4) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/enum/RankType.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.enum 2 | 3 | /** 4 | * 各大榜单 5 | * 1.实时销量榜 6 | * 2.全天销量榜 7 | * 3.热推榜 8 | */ 9 | enum class RankType(val index: Int) { 10 | SHI_SHI_XIAO_XIANG_BANG(1), 11 | QUAN_TIAN_XIAO_LIANG_BANG(2), 12 | RE_TUI_BANG(3), 13 | FU_GOU_BANG(4) 14 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/fragment/NineGoodsFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.fragment 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.viewpager2.adapter.FragmentStateAdapter 5 | import cn.neday.base.fragment.BaseFragment 6 | import cn.neday.sheep.R 7 | import cn.neday.sheep.enum.NineType 8 | import com.google.android.material.tabs.TabLayoutMediator 9 | import kotlinx.android.synthetic.main.fragment_main_nine_goods.* 10 | 11 | /** 12 | * 9.9精选 13 | * -1-精选,1 -居家百货,2 -美食,3 -服饰,4 -配饰,5 -美妆,6 -内衣,7 -母婴,8 -箱包,9 -数码配件,10 -文娱车品 14 | */ 15 | class NineGoodsFragment : BaseFragment(R.layout.fragment_main_nine_goods) { 16 | 17 | override fun initView() { 18 | initViewPager() 19 | } 20 | 21 | private fun initViewPager() { 22 | val fragmentTitleList = resources.getStringArray(R.array.nine_type_array) 23 | vp2_nine.adapter = object : FragmentStateAdapter(this) { 24 | override fun createFragment(position: Int): Fragment { 25 | return arrayListOf( 26 | NineListFragment(NineType.JING_XUAN), 27 | NineListFragment(NineType.JU_JUA_BAI_HUO), 28 | NineListFragment(NineType.MEI_SHI), 29 | NineListFragment(NineType.FU_SHI), 30 | NineListFragment(NineType.PEI_SHI), 31 | NineListFragment(NineType.MEI_ZHUANG), 32 | NineListFragment(NineType.NEI_YI), 33 | NineListFragment(NineType.MU_YING), 34 | NineListFragment(NineType.XIANG_BAO), 35 | NineListFragment(NineType.SHU_MA_PEI_JIAN), 36 | NineListFragment(NineType.WEN_YU_CHE_PIN) 37 | )[position] 38 | } 39 | 40 | override fun getItemCount(): Int { 41 | return fragmentTitleList.size 42 | } 43 | } 44 | TabLayoutMediator(tl_nine, vp2_nine) { tab, position -> 45 | tab.text = fragmentTitleList[position] 46 | }.attach() 47 | vp2_nine.offscreenPageLimit = 1 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/fragment/NineListFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.fragment 2 | 3 | import androidx.lifecycle.Observer 4 | import cn.neday.base.model.Pages 5 | import cn.neday.sheep.LOAD_INITIAL_PAGE_ID 6 | import cn.neday.sheep.PREFETCH_DISTANCE 7 | import cn.neday.sheep.R 8 | import cn.neday.sheep.adapter.GoodsListAdapter 9 | import cn.neday.sheep.enum.NineType 10 | import cn.neday.sheep.model.CommonGoods 11 | import cn.neday.sheep.viewmodel.NineListViewModel 12 | import kotlinx.android.synthetic.main.include_anything_list.* 13 | 14 | /** 15 | * 超值精选 16 | */ 17 | class NineListFragment(private val nineType: NineType) : 18 | GoodsListFragment(R.layout.fragment_goods_list) { 19 | 20 | override fun loadInitial() { 21 | mViewModel.getNineOpGoodsList(nineType.index.toString()) 22 | } 23 | 24 | override fun initAdapter() { 25 | super.initAdapter() 26 | adapter.setPreLoadNumber(PREFETCH_DISTANCE) 27 | adapter.setOnLoadMoreListener({ 28 | mViewModel.getNineOpGoodsList(nineType.index.toString(), mViewModel.mCurrentPageId) 29 | }, rv_goods) 30 | mViewModel.pageGoods.observe(this, Observer> { 31 | if (adapter.itemCount >= it.totalNum ?: 0) { 32 | adapter.loadMoreEnd() 33 | } else { 34 | setAdapterData(adapter, it) 35 | mViewModel.mCurrentPageId = it.pageId ?: LOAD_INITIAL_PAGE_ID 36 | adapter.loadMoreComplete() 37 | } 38 | }) 39 | } 40 | 41 | private fun setAdapterData(adapter: GoodsListAdapter, data: Pages) { 42 | if (mViewModel.mCurrentPageId == LOAD_INITIAL_PAGE_ID) { 43 | srl_goods.isRefreshing = false 44 | adapter.setNewData(data.list) 45 | adapter.disableLoadMoreIfNotFullPage() 46 | } else { 47 | data.list?.let { adapter.addData(it) } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/fragment/RankingGoodsFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.fragment 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.viewpager2.adapter.FragmentStateAdapter 5 | import cn.neday.base.fragment.BaseFragment 6 | import cn.neday.sheep.R 7 | import cn.neday.sheep.enum.RankType 8 | import com.google.android.material.tabs.TabLayoutMediator 9 | import kotlinx.android.synthetic.main.fragment_main_ranking_goods.* 10 | 11 | class RankingGoodsFragment : BaseFragment(R.layout.fragment_main_ranking_goods) { 12 | 13 | override fun initView() { 14 | initViewPager() 15 | } 16 | 17 | private fun initViewPager() { 18 | val fragmentTitleList = resources.getStringArray(R.array.ranking_type_array) 19 | vp2_ranking.adapter = object : FragmentStateAdapter(this) { 20 | override fun createFragment(position: Int): Fragment { 21 | return arrayListOf( 22 | RankingListFragment(RankType.SHI_SHI_XIAO_XIANG_BANG), 23 | RankingListFragment(RankType.QUAN_TIAN_XIAO_LIANG_BANG), 24 | RankingListFragment(RankType.RE_TUI_BANG), 25 | RankingListFragment(RankType.FU_GOU_BANG) 26 | )[position] 27 | } 28 | 29 | override fun getItemCount(): Int { 30 | return fragmentTitleList.size 31 | } 32 | } 33 | TabLayoutMediator(tl_ranking, vp2_ranking) { tab, position -> 34 | tab.text = fragmentTitleList[position] 35 | }.attach() 36 | vp2_ranking.offscreenPageLimit = 1 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/fragment/RankingListFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.fragment 2 | 3 | import androidx.lifecycle.Observer 4 | import cn.neday.sheep.R 5 | import cn.neday.sheep.enum.RankType 6 | import cn.neday.sheep.viewmodel.RankingListViewModel 7 | 8 | /** 9 | * 各大榜单 10 | * 1.实时销量榜 11 | * 2.全天销量榜 12 | * 3.热推榜 13 | * 4.复购榜 14 | */ 15 | class RankingListFragment(private val rankType: RankType) : 16 | GoodsListFragment(R.layout.fragment_goods_list) { 17 | 18 | override fun loadInitial() { 19 | mViewModel.getRankingList(rankType.index) 20 | } 21 | 22 | override fun initAdapter() { 23 | super.initAdapter() 24 | mViewModel.rankGoods.observe(this, Observer { 25 | adapter.setNewData(it) 26 | }) 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/fragment/SearchResultFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.fragment 2 | 3 | import androidx.lifecycle.Observer 4 | import cn.neday.base.model.Pages 5 | import cn.neday.sheep.LOAD_INITIAL_PAGE_ID 6 | import cn.neday.sheep.PREFETCH_DISTANCE 7 | import cn.neday.sheep.R 8 | import cn.neday.sheep.adapter.GoodsListAdapter 9 | import cn.neday.sheep.model.CommonGoods 10 | import cn.neday.sheep.viewmodel.SearchResultViewModel 11 | import kotlinx.android.synthetic.main.include_anything_list.* 12 | 13 | /** 14 | * 搜索结果列表页 15 | * 16 | * @author nEdAy 17 | */ 18 | class SearchResultFragment(private val keyWord: String) : 19 | GoodsListFragment(R.layout.fragment_goods_list) { 20 | 21 | override fun loadInitial() { 22 | mViewModel.getDtkSearchGoods(keyWord) 23 | } 24 | 25 | override fun initAdapter() { 26 | super.initAdapter() 27 | adapter.setPreLoadNumber(PREFETCH_DISTANCE) 28 | adapter.setOnLoadMoreListener({ 29 | mViewModel.getDtkSearchGoods(keyWord, mViewModel.mCurrentPageId) 30 | }, rv_goods) 31 | mViewModel.pageGoods.observe(this, Observer> { 32 | if (adapter.itemCount >= it.totalNum ?: 0) { 33 | adapter.loadMoreEnd() 34 | } else { 35 | setAdapterData(adapter, it) 36 | mViewModel.mCurrentPageId = it.pageId ?: LOAD_INITIAL_PAGE_ID 37 | adapter.loadMoreComplete() 38 | } 39 | }) 40 | } 41 | 42 | private fun setAdapterData(adapter: GoodsListAdapter, data: Pages) { 43 | if (mViewModel.mCurrentPageId == LOAD_INITIAL_PAGE_ID) { 44 | srl_goods.isRefreshing = false 45 | adapter.setNewData(data.list) 46 | adapter.disableLoadMoreIfNotFullPage() 47 | } else { 48 | data.list?.let { adapter.addData(it) } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/Banner.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | import cn.neday.base.model.BaseModel 4 | 5 | /** 6 | * 广告 7 | */ 8 | data class Banner( 9 | // 序号 10 | val index: Int?, 11 | // 标题 12 | val title: String?, 13 | // 图片链接 14 | val picture: String?, 15 | // 点击链接 16 | val url: String? 17 | ) : BaseModel() 18 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/CommonGoods.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | data class CommonGoods( 4 | // 商品淘宝链接 String “https://detail.tmall.com/item.htm?id=589284195570“ 5 | val itemLink: String?, 6 | // 活动开始时间 String “2019-03-29 10:00:06” 7 | val activityStartTime: String?, 8 | // 活动结束时间 String “2019-04-29 10:00:06” 9 | val activityEndTime: String?, 10 | // 店铺类型,1-天猫,0-淘宝 Number 1 11 | val shopType: Int?, 12 | // goldSellers 是否金牌卖家,1-金牌卖家,0-非金牌卖家 Number 0 13 | val goldSellers: Int?, 14 | // 2小时销量 Number 30 15 | val twoHoursSales: Int?, 16 | // 当日销量 Number 20 17 | val dailySales: Int?, 18 | // 佣金类型,0-通用,1-定向,2-高佣,3-营销计划 Number 3 19 | val commissionType: Int?, 20 | // 活动类型,1-无活动,2-淘抢购,3-聚划算 Number 1 21 | val activityType: Int?, 22 | // 商品上架时间 String “2019-03-29 10:00:06” 23 | val createTime: String?, 24 | // 商品主图链接 String “img.alicdn.com/imgextra/i2/4014489195/O1CN01kYlVPs2HnMKYwLLRm_!!4014489195.jpg” 25 | val mainPic: String?, 26 | // 营销主图链接 String “https://sr.ffquan.com/super_pic/o_1d6fpckjs1ii3h9dkibk9b7h38.jpg“ 27 | val marketingMainPic: String?, 28 | // 淘宝卖家id String “4014489195” 29 | val sellerId: String?, 30 | // 商品在大淘客的分类id Number 10 31 | val cid: Int?, 32 | // 二级类目id 否 Number 大淘客的二级类目id,通过超级分类API获取。仅允许传一个二级id,当一级类目id和二级类目id同时传入时,会自动忽略二级类目id 33 | val scid: Int?, 34 | // 商品在淘宝的分类id Number 50012772 35 | val tbcid: Int?, 36 | // 折扣力度 Number 0.74 37 | val discounts: Double?, 38 | // 佣金比例 Number 20.01 39 | val commissionRate: Double?, 40 | // 是否海淘,1-海淘商品,0-非海淘商品 Number 0 41 | val haitao: Int?, 42 | // 店铺名称 String “西维里旗舰店” 43 | val shopName: String?, 44 | // 淘宝店铺等级 Number 11 45 | val shopLevel: Int?, 46 | // 描述相符 Number 4.8 47 | val dsrScore: Double?, 48 | // 描述同行比 Number 0.0 49 | val dsrPercent: Double?, 50 | // 服务态度 Number 4.8 51 | val shipScore: Double?, 52 | // 服务同行比 Number 10.32 53 | val shipPercent: Double?, 54 | // 物流服务 Number 4.8 55 | val serviceScore: Double?, 56 | // 物流同行比 Number 5.82 57 | val servicePercent: Double?, 58 | // 是否是品牌商品,0-不是品牌商品,1-是品牌商品 Number 1 59 | val brand: Int?, 60 | // 品牌id Number 2301323020 61 | val brandId: Long?, 62 | // 品牌名称 String “西维里” 63 | val brandName: String?, 64 | // 热推值 Number 456 65 | val hotPush: Int?, 66 | // 放单人名称 String “啊甘团队” 67 | val teamName: String?, 68 | // 是否天猫超市商品,1-天猫超市商品,0-非天猫超市商品 Number 0 69 | val tchaoshi: Int? 70 | ) : Goods() { 71 | 72 | override fun getPicUrl(): String? { 73 | return mainPic 74 | } 75 | 76 | override fun isTmall(): Boolean { 77 | return shopType == 1 78 | } 79 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/CreditHistory.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | import cn.neday.base.model.BaseModel 4 | 5 | data class CreditHistory( 6 | val userId: Int?, 7 | val credit: Int?, 8 | // 增减数值 9 | val change: Int?, 10 | // 增减原因 11 | val message: String? 12 | ) : BaseModel() -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/Goods.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | import java.io.Serializable 4 | 5 | abstract class Goods : Serializable { 6 | 7 | // 大淘客的商品id Number 19259135 8 | val id: Int? = null 9 | // 淘宝商品id Number 590858626868 10 | val goodsId: String? = null 11 | // 淘宝标题 String “西维里男士睡衣夏季韩版真丝短袖丝绸薄款宽松青年冰丝家居服套装” 12 | val title: String? = null 13 | // 短标题 String 【李佳琦推荐】奢华芯肌素颜爆水霜 14 | val dtitle: String? = null 15 | // 推广文案 String “宽松舒适,难以磨损典,雅而优美,倍感丝滑,质感优越,庄严而心仪,简约设计,色调清新脱俗,适合各种场合” 16 | val desc: String? = null 17 | // 商品原价 Number 38.5 18 | val originalPrice: Double? = null 19 | // 券后价 Number 39.9 20 | val actualPrice: Double? = null 21 | // 描述分 Number 4.8 22 | val descScore: Double? = null 23 | // 30天销量 Number 1030 24 | val monthSales: Int? = null 25 | // 优惠券链接 String "" 26 | val couponLink: String? = null 27 | // 优惠券金额 Number 10 28 | val couponPrice: Double? = null 29 | // 领券量 Number 1000 30 | val couponReceiveNum: Int? = null 31 | // 券总量 Number 7000 32 | val couponTotalNum: Int? = null 33 | // 优惠券结束时间 String “2019-04-08 23:59:59” 34 | val couponEndTime: String? = null 35 | // 优惠券开始时间 String “2019-04-01 00:00:00” 36 | val couponStartTime: String? = null 37 | // 优惠券使用条件 String “38” 38 | val couponConditions: String? = null 39 | 40 | abstract fun getPicUrl(): String? 41 | abstract fun isTmall(): Boolean 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/HotWords.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | data class HotWords(val hotWords: Set) 4 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/RankingGoods.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | data class RankingGoods( 4 | // 榜单名次 Number 1 5 | val ranking: Int?, 6 | // 佣金比例 Number 20.01 7 | val commissionRate: Double?, 8 | // 2小时销量 Number 1138 9 | val twoHoursSales: Int?, 10 | // 当天销量 Number 389 11 | val dailySales: Int?, 12 | // 热推值 Number 42 13 | val hotPush: Int?, 14 | // 商品主图 String https://img.alicdn.com/imgextra/i2/748376657/O1CN01LKI9Km1z2x8p5sGeN_!!748376657.jpg 15 | val pic: String?, 16 | // 商品描述 String ‘多款可选!显瘦高腰韩版阔腿裤五分裤,不起球,不掉色。舒适面料,不挑身材,高腰设计’ 17 | val description: String?, 18 | // 商品原价 Number 22.9 19 | val originPrice: Double?, 20 | // 佣金类型 Number 3 21 | val commissionType: Int?, 22 | // onSaleTime String ‘2019-06-03 17:55:18’ 23 | val onSaleTime: String?, 24 | // 活动类型 Number 1 25 | val activityType: Int?, 26 | // 营销图 Array ‘https://img.alicdn.com/imgextra/i2/1687451966/O1CN01WNuZcl1QOTCM9NsrO_!!1687451966.jpg,https://img.alicdn.com/imgextra/i4/1687451966/O1CN01h2ih4v1QOTCOxlZDj_!!1687451966.jpg‘ 27 | val picList: String?, 28 | // 放单人名称 String 易折网 29 | val guideName: String?, 30 | // 店铺类型 Number 1 31 | val istmall: Int?, 32 | // 优惠券使用条件 Number 22.01 33 | val quanUsageCondition: Double? 34 | ) : Goods() { 35 | 36 | override fun getPicUrl(): String? { 37 | return pic 38 | } 39 | 40 | override fun isTmall(): Boolean { 41 | return istmall == 1 42 | } 43 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/model/User.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.model 2 | 3 | import cn.neday.base.model.BaseModel 4 | 5 | data class User( 6 | // 手机号 11位 主键 7 | val mobile: String?, 8 | // 用户密码 9 | val password: String?, 10 | // 用户昵称 11 | val nickname: String?, 12 | // 用户头像URL 13 | val avatar: String?, 14 | // 口袋币 即等级 0=0 1>=100 2>=200 3>=500 4>=1000 5>=2000 6>=5000 7>=15000 8>=50000 9>=100000 10>=200000 15 | val credit: Int?, 16 | // Token 17 | val token: String? 18 | ) : BaseModel() -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/network/api/BannerApi.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.network.api 2 | 3 | import cn.neday.base.model.Response 4 | import cn.neday.sheep.model.Banner 5 | import retrofit2.http.GET 6 | 7 | interface BannerApi { 8 | 9 | @GET("banner") 10 | suspend fun bannerList(): Response> 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/network/api/CategoryApi.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.network.api 2 | 3 | import cn.neday.base.model.Response 4 | import cn.neday.sheep.model.HotWords 5 | import retrofit2.http.GET 6 | 7 | interface CategoryApi { 8 | 9 | @GET("category/get-top100") 10 | suspend fun getTop100(): Response 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/network/repository/BannerRepository.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.network.repository 2 | 3 | import cn.neday.base.model.Response 4 | import cn.neday.sheep.model.Banner 5 | import cn.neday.sheep.network.api.BannerApi 6 | 7 | /** 8 | * Banner Repository 9 | * 10 | * @author nEdAy 11 | */ 12 | class BannerRepository(private val bannerApi: BannerApi) { 13 | 14 | suspend fun getBannerList(): Response> = bannerApi.bannerList() 15 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/network/repository/CategoryRepository.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.network.repository 2 | 3 | import cn.neday.base.model.Response 4 | import cn.neday.sheep.model.HotWords 5 | import cn.neday.sheep.network.api.CategoryApi 6 | 7 | /** 8 | * RankingGoods Repository 9 | * 10 | * @author nEdAy 11 | */ 12 | class CategoryRepository(private val categoryApi: CategoryApi) { 13 | 14 | suspend fun getTop100(): Response = categoryApi.getTop100() 15 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/network/repository/GoodsRepository.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.network.repository 2 | 3 | import cn.neday.base.model.Pages 4 | import cn.neday.base.model.Response 5 | import cn.neday.sheep.model.CommonGoods 6 | import cn.neday.sheep.model.RankingGoods 7 | import cn.neday.sheep.network.api.GoodsApi 8 | 9 | /** 10 | * RankingGoods Repository 11 | * 12 | * @author nEdAy 13 | */ 14 | class GoodsRepository(private val goodsApi: GoodsApi) { 15 | 16 | suspend fun getRankingList(rankType: Int, cid: String): Response> = 17 | goodsApi.rankingList(rankType, cid) 18 | 19 | suspend fun getNineOpGoodsList( 20 | pageSize: Int, 21 | pageId: String, 22 | nineCid: String 23 | ): Response> = goodsApi.nineOpGoodsList(pageSize, pageId, nineCid) 24 | 25 | suspend fun getDtkSearchGoods( 26 | pageSize: Int, 27 | pageId: String, 28 | keyWords: String 29 | ): Response> = goodsApi.getDtkSearchGoods(pageSize, pageId, keyWords) 30 | 31 | suspend fun getListSimilerGoodsByOpen(id: Int, size: Int): Response> = 32 | goodsApi.listSimilerGoodsByOpen(id, size) 33 | 34 | suspend fun getListSuperGoods( 35 | type: Int, keyWords: String, 36 | tmall: Int, haitao: Int, sort: String 37 | ): Response> = goodsApi.listSuperGoods(type, keyWords, tmall, haitao, sort) 38 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/network/repository/UserRepository.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.network.repository 2 | 3 | import cn.neday.base.model.Pages 4 | import cn.neday.base.model.Response 5 | import cn.neday.sheep.model.CreditHistory 6 | import cn.neday.sheep.model.User 7 | import cn.neday.sheep.network.api.UserApi 8 | 9 | /** 10 | * User Repository 11 | * 12 | * @author nEdAy 13 | */ 14 | class UserRepository(private val userApi: UserApi) { 15 | 16 | suspend fun registerOrLogin(register: Map): Response = 17 | userApi.registerOrLogin(register) 18 | 19 | suspend fun getUserById(id: Int): Response = 20 | userApi.getUserById(id) 21 | 22 | suspend fun getCreditHistoryListByUserId( 23 | userId: Int, 24 | pageId: String, 25 | pageSize: Int 26 | ): Response> = 27 | userApi.creditHistoryListByUserId(userId, pageId, pageSize) 28 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/util/CommonUtils.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.util 2 | 3 | import android.annotation.SuppressLint 4 | import android.app.Activity 5 | import android.content.Intent 6 | import android.os.Handler 7 | import android.view.View 8 | import androidx.core.net.toUri 9 | import java.math.BigDecimal 10 | 11 | /** 12 | * 常用工具 13 | * 14 | * @author nEdAy 15 | */ 16 | object CommonUtils { 17 | 18 | /** 19 | * 去除数字里多余的0 20 | */ 21 | fun getPrettyNumber(number: Double?): String { 22 | return number?.let { BigDecimal.valueOf(it).stripTrailingZeros().toPlainString() } ?: "0" 23 | } 24 | 25 | /** 26 | * 检验密码长度是否正确 27 | */ 28 | fun isValidPassword(target: CharSequence?): Boolean { 29 | return target != null && target.length > 5 && target.length < 17 30 | } 31 | 32 | /** 33 | * 检验短信验证码长度是否正确 34 | */ 35 | fun isValidSmsCode(target: CharSequence?): Boolean { 36 | return target != null && target.length == 4 37 | } 38 | 39 | /** 40 | * 点击时修改子控件背景样式并在0.5s后恢复 41 | * 42 | * @param view 要修改的子控件 43 | * @param bg 要恢复的背景 44 | * @param bgPressed 要变化的背景 45 | */ 46 | @SuppressLint("CheckResult") 47 | fun changePressedViewBg(view: View, bg: Int, bgPressed: Int) { 48 | view.isPressed = true 49 | view.setBackgroundResource(bgPressed) 50 | Handler().postDelayed({ 51 | view.isPressed = false 52 | view.setBackgroundResource(bg) 53 | }, 500) 54 | } 55 | 56 | /** 57 | * 发起添加群流程。群号:神马快爆15群(109339243) 的 key 为: seYgbMRGSIw_QOjspDBVp-1r1GTUGHCg 58 | * 调用 joinQQGroup(seYgbMRGSIw_QOjspDBVp-1r1GTUGHCg) 即可发起手Q客户端申请加群 神马快爆15群(109339243) 59 | * 60 | * @return 返回true表示呼起手Q成功,返回false表示呼起失败 61 | */ 62 | fun joinQQGroup(activity: Activity?): Boolean { 63 | return try { 64 | activity?.startActivity(Intent().apply { 65 | data = 66 | ("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + "seYgbMRGSIw_QOjspDBVp-1r1GTUGHCg").toUri() 67 | // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 68 | // addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 69 | }) 70 | true 71 | } catch (e: RuntimeException) { 72 | // 未安装手Q或安装的版本不支持 73 | false 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/view/GuideBanner.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | import android.widget.ImageView 7 | import android.widget.TextView 8 | import cn.neday.sheep.R 9 | import com.flyco.banner.widget.Banner.BaseIndicatorBanner 10 | 11 | /** 12 | * 导航滚动翻页 13 | * 14 | * @author nEdAy 15 | */ 16 | class GuideBanner @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) : 17 | BaseIndicatorBanner(context, attrs, defStyle) { 18 | 19 | private var mOnGuideJumpClick: (() -> Unit)? = null 20 | 21 | override fun onCreateItemView(position: Int): View { 22 | setBarShowWhenLast(false) 23 | val inflate = View.inflate(mContext, R.layout.adapter_guide, null) 24 | 25 | val ivGuideImg = inflate.findViewById(R.id.iv_guide_img) 26 | ivGuideImg.setImageResource(mDatas[position]) 27 | 28 | val tvGuideJumpBtn = inflate.findViewById(R.id.tv_guide_jump_btn) 29 | val lastPageIndex = mDatas.size - 1 30 | tvGuideJumpBtn.visibility = if (position == lastPageIndex) View.VISIBLE else View.GONE 31 | tvGuideJumpBtn.setOnClickListener { 32 | mOnGuideJumpClick?.invoke() 33 | } 34 | return inflate 35 | } 36 | 37 | fun setOnGuideJumpClick(onGuideJumpClick: () -> Unit) { 38 | mOnGuideJumpClick = onGuideJumpClick 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/view/IndexBanner.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.view 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | import android.widget.ImageView 7 | import android.widget.LinearLayout 8 | import cn.neday.sheep.R 9 | import cn.neday.sheep.model.Banner 10 | import coil.api.load 11 | import com.flyco.banner.widget.Banner.BaseIndicatorBanner 12 | 13 | 14 | /** 15 | * 广告图片轮播 16 | * 17 | * @author nEdAy 18 | */ 19 | class IndexBanner @JvmOverloads constructor( 20 | context: Context, 21 | attrs: AttributeSet? = null, 22 | defStyle: Int = 0 23 | ) : 24 | BaseIndicatorBanner(context, attrs, defStyle) { 25 | 26 | override fun onCreateItemView(position: Int): View { 27 | val inflate = View.inflate(mContext, R.layout.adapter_banner, null) 28 | if (position < mDatas.size) { 29 | val data = mDatas[position] 30 | val itemWidth = mDisplayMetrics.widthPixels 31 | val itemHeight = (itemWidth * 0.417f).toInt() 32 | val ivBanner = inflate.findViewById(R.id.iv_banner) 33 | ivBanner.layoutParams = LinearLayout.LayoutParams(itemWidth, itemHeight) 34 | ivBanner.load(data.picture) { 35 | crossfade(true) 36 | placeholder(R.drawable.ic_update_banner) 37 | error(R.drawable.ic_update_banner) 38 | } 39 | } 40 | return inflate 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/view/rise_number/IRiseNumber.java: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.view.rise_number; 2 | 3 | /** 4 | * 动画增长的数字 5 | * 6 | * @author nEdAy 7 | */ 8 | interface IRiseNumber { 9 | /** 10 | * 开始播放动画的方法 11 | */ 12 | void start(); 13 | 14 | /** 15 | * 设置小数 16 | */ 17 | void withNumber(float number); 18 | 19 | /** 20 | * 设置整数 21 | */ 22 | void withNumber(int number); 23 | 24 | /** 25 | * 设置动画播放时长 26 | */ 27 | void setDuration(long duration); 28 | 29 | /** 30 | * 设置动画结束监听器 31 | */ 32 | void setOnEndListener(RiseNumberTextView.EndListener callback); 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/ConfigViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.viewModelScope 4 | import cn.neday.base.SingleLiveEvent 5 | import cn.neday.base.config.MMKVConfig.ID 6 | import cn.neday.base.config.MMKVConfig.kv 7 | import cn.neday.base.network.requestAsync 8 | import cn.neday.base.network.then 9 | import cn.neday.base.viewmodel.BaseViewModel 10 | import cn.neday.sheep.model.User 11 | import cn.neday.sheep.network.repository.UserRepository 12 | 13 | /** 14 | * ConfigViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class ConfigViewModel(private val repository: UserRepository) : BaseViewModel() { 19 | 20 | val user = SingleLiveEvent() 21 | 22 | /** 23 | * 获取当前用户信息 24 | */ 25 | fun getUserById() { 26 | requestAsync { 27 | repository.getUserById(kv.decodeInt(ID)) 28 | }.then(viewModelScope, { 29 | user.value = it.data 30 | }, { 31 | errMsg.value = it 32 | }) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/CreditHistoryViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.viewModelScope 5 | import cn.neday.base.model.Pages 6 | import cn.neday.base.network.requestAsync 7 | import cn.neday.base.network.then 8 | import cn.neday.base.viewmodel.BaseViewModel 9 | import cn.neday.sheep.LOAD_INITIAL_PAGE_ID 10 | import cn.neday.sheep.model.CreditHistory 11 | import cn.neday.sheep.network.repository.UserRepository 12 | 13 | /** 14 | * CreditHistoryViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class CreditHistoryViewModel(private val repository: UserRepository) : BaseViewModel() { 19 | 20 | val creditHistories: MutableLiveData> = MutableLiveData() 21 | 22 | var mCurrentPageId: String = LOAD_INITIAL_PAGE_ID 23 | 24 | fun getCreditByUserId() { 25 | // requestAsync { 26 | // repository.getUserById("DDD") 27 | // }.then({ 28 | //// creditHistories.value = it.data 29 | // }, { 30 | // errMsg.value = it 31 | // }) 32 | } 33 | 34 | 35 | fun getCreditHistoryListByUserId(userId: Int) { 36 | requestAsync { 37 | repository.getCreditHistoryListByUserId(userId, "1", 1) 38 | }.then(viewModelScope, { 39 | creditHistories.value = it.data 40 | }, { 41 | errMsg.value = it 42 | }) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/IndexViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.viewModelScope 5 | import cn.neday.base.network.requestAsync 6 | import cn.neday.base.network.then 7 | import cn.neday.base.viewmodel.BaseViewModel 8 | import cn.neday.sheep.model.Banner 9 | import cn.neday.sheep.model.RankingGoods 10 | import cn.neday.sheep.network.repository.BannerRepository 11 | import cn.neday.sheep.network.repository.GoodsRepository 12 | 13 | /** 14 | * IndexViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class IndexViewModel( 19 | private val bannerRepository: BannerRepository, 20 | private val goodsRepository: GoodsRepository 21 | ) : 22 | BaseViewModel() { 23 | 24 | val banners: MutableLiveData> = MutableLiveData() 25 | val rankGoods: MutableLiveData> = MutableLiveData() 26 | 27 | fun getBannerList() { 28 | requestAsync { 29 | bannerRepository.getBannerList() 30 | }.then(viewModelScope, { 31 | banners.value = it.data 32 | }, { 33 | errMsg.value = it 34 | }) 35 | } 36 | 37 | fun getRankingList(rankType: Int, cid: String = "") { 38 | requestAsync { 39 | goodsRepository.getRankingList(rankType, cid) 40 | }.then(viewModelScope, { 41 | rankGoods.value = it.data 42 | }, { 43 | errMsg.value = it 44 | }, { 45 | onComplete.call() 46 | }) 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/LoginViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.viewModelScope 4 | import cn.neday.base.SingleLiveEvent 5 | import cn.neday.base.network.requestAsync 6 | import cn.neday.base.network.then 7 | import cn.neday.base.viewmodel.BaseViewModel 8 | import cn.neday.sheep.model.User 9 | import cn.neday.sheep.network.repository.UserRepository 10 | import com.blankj.utilcode.util.EncryptUtils 11 | import java.util.* 12 | 13 | /** 14 | * LoginViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class LoginViewModel(private val repository: UserRepository) : BaseViewModel() { 19 | 20 | val user = SingleLiveEvent() 21 | 22 | /** 23 | * 注册用户 / 用户登录(密码) / 用户登录(短信验证码) 24 | * 25 | * @param mobile 手机号 26 | * @param password 原始密码 27 | * @param smsCode 短信验证码 28 | * @param inviteCode 邀请码 29 | */ 30 | fun registerOrLogin(mobile: String, password: String, smsCode: String, inviteCode: String) { 31 | val map = HashMap() 32 | map["mobile"] = mobile 33 | map["password"] = EncryptUtils.encryptMD5ToString(password).toUpperCase(Locale.getDefault()) 34 | map["smsCode"] = smsCode 35 | map["inviteCode"] = inviteCode 36 | requestAsync { 37 | repository.registerOrLogin(map) 38 | }.then(viewModelScope, { 39 | user.value = it.data 40 | }, { 41 | errMsg.value = it 42 | }) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/MainViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import cn.neday.base.viewmodel.BaseViewModel 4 | 5 | /** 6 | * IndexViewModel 7 | * 8 | * @author nEdAy 9 | */ 10 | class MainViewModel : BaseViewModel() { 11 | 12 | var mLastActiveFragmentTag: String? = null 13 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/MeViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.viewModelScope 4 | import cn.neday.base.SingleLiveEvent 5 | import cn.neday.base.config.MMKVConfig.ID 6 | import cn.neday.base.config.MMKVConfig.kv 7 | import cn.neday.base.network.requestAsync 8 | import cn.neday.base.network.then 9 | import cn.neday.base.viewmodel.BaseViewModel 10 | import cn.neday.sheep.model.User 11 | import cn.neday.sheep.network.repository.UserRepository 12 | 13 | /** 14 | * MeViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class MeViewModel(private val repository: UserRepository) : BaseViewModel() { 19 | 20 | val user = SingleLiveEvent() 21 | 22 | /** 23 | * 获取当前用户信息 24 | */ 25 | fun getUserById() { 26 | requestAsync { 27 | repository.getUserById(kv.decodeInt(ID)) 28 | }.then(viewModelScope, { 29 | user.value = it.data 30 | }, { 31 | errMsg.value = it 32 | }) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/NineListViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.viewModelScope 5 | import cn.neday.base.model.Pages 6 | import cn.neday.base.network.requestAsync 7 | import cn.neday.base.network.then 8 | import cn.neday.base.viewmodel.BaseViewModel 9 | import cn.neday.sheep.LOAD_INITIAL_PAGE_ID 10 | import cn.neday.sheep.PAGE_SIZE 11 | import cn.neday.sheep.model.CommonGoods 12 | import cn.neday.sheep.network.repository.GoodsRepository 13 | 14 | /** 15 | * NineListViewModel 16 | * 17 | * @author nEdAy 18 | */ 19 | class NineListViewModel(private val repository: GoodsRepository) : BaseViewModel() { 20 | 21 | val pageGoods: MutableLiveData> = MutableLiveData() 22 | 23 | var mCurrentPageId: String = LOAD_INITIAL_PAGE_ID 24 | 25 | fun getNineOpGoodsList(nineCid: String, pageId: String = LOAD_INITIAL_PAGE_ID) { 26 | mCurrentPageId = pageId 27 | requestAsync { 28 | repository.getNineOpGoodsList(PAGE_SIZE, pageId, nineCid) 29 | }.then(viewModelScope, { 30 | pageGoods.value = it.data 31 | }, { 32 | errMsg.value = it 33 | }, { 34 | onComplete.call() 35 | }) 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/RankingListViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.viewModelScope 5 | import cn.neday.base.network.requestAsync 6 | import cn.neday.base.network.then 7 | import cn.neday.base.viewmodel.BaseViewModel 8 | import cn.neday.sheep.model.RankingGoods 9 | import cn.neday.sheep.network.repository.GoodsRepository 10 | 11 | /** 12 | * RankingListViewModel 13 | * 14 | * @author nEdAy 15 | */ 16 | class RankingListViewModel(private val repository: GoodsRepository) : BaseViewModel() { 17 | 18 | val rankGoods: MutableLiveData> = MutableLiveData() 19 | 20 | fun getRankingList(rankType: Int, cid: String = "") { 21 | requestAsync { 22 | repository.getRankingList(rankType, cid) 23 | }.then(viewModelScope, { 24 | rankGoods.value = it.data 25 | }, { 26 | errMsg.value = it 27 | }, { 28 | onComplete.call() 29 | }) 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/SearchViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.viewModelScope 5 | import cn.neday.base.config.MMKVConfig 6 | import cn.neday.base.config.MMKVConfig.kv 7 | import cn.neday.base.network.requestAsync 8 | import cn.neday.base.network.then 9 | import cn.neday.base.viewmodel.BaseViewModel 10 | import cn.neday.sheep.network.repository.CategoryRepository 11 | import com.google.gson.Gson 12 | import com.google.gson.reflect.TypeToken 13 | import java.util.* 14 | 15 | /** 16 | * SearchViewModel 17 | * 18 | * @author nEdAy 19 | */ 20 | class SearchViewModel(private val repository: CategoryRepository) : BaseViewModel() { 21 | 22 | val hotWords: MutableLiveData> = MutableLiveData() 23 | val historyWords: MutableLiveData> = MutableLiveData() 24 | 25 | /** 26 | * 热搜记录 27 | * 该接口提供了昨日CMS端大淘客采集统计的前100名搜索热词 28 | */ 29 | fun getHotWords() { 30 | hotWords.value = kv.decodeStringSet(MMKVConfig.HOTWORDS) 31 | requestAsync { 32 | repository.getTop100() 33 | }.then(viewModelScope, { 34 | hotWords.value = it.data?.hotWords 35 | kv.encode(MMKVConfig.HOTWORDS, it.data?.hotWords ?: setOf()) 36 | }, { 37 | errMsg.value = it 38 | }) 39 | } 40 | 41 | fun getHistoryWords() { 42 | val historyWordsJson: String? = kv.decodeString(MMKVConfig.HISTORY_WORDS) 43 | historyWords.value = Gson().fromJson(historyWordsJson, object : TypeToken>() {}.type) 44 | } 45 | 46 | fun removeHistoryWords(keyWords: String) { 47 | val historyWordsJson: String? = kv.decodeString(MMKVConfig.HISTORY_WORDS) 48 | val historyWords: LinkedHashSet = 49 | Gson().fromJson(historyWordsJson, object : TypeToken>() {}.type) 50 | historyWords.remove(keyWords) 51 | kv.encode(MMKVConfig.HISTORY_WORDS, Gson().toJson(historyWords)) 52 | this.historyWords.value = historyWords 53 | } 54 | 55 | fun cleanHistoryWords() { 56 | historyWords.value = null 57 | kv.removeValueForKey(MMKVConfig.HISTORY_WORDS) 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/ShakeViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.viewModelScope 4 | import cn.neday.base.SingleLiveEvent 5 | import cn.neday.base.config.MMKVConfig 6 | import cn.neday.base.config.MMKVConfig.kv 7 | import cn.neday.base.network.requestAsync 8 | import cn.neday.base.network.then 9 | import cn.neday.base.viewmodel.BaseViewModel 10 | import cn.neday.sheep.model.User 11 | import cn.neday.sheep.network.repository.UserRepository 12 | 13 | /** 14 | * ShakeViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class ShakeViewModel(private val repository: UserRepository) : BaseViewModel() { 19 | 20 | val user = SingleLiveEvent() 21 | 22 | /** 23 | * 获取当前用户信息 24 | */ 25 | fun getUserById() { 26 | requestAsync { 27 | repository.getUserById(kv.decodeInt(MMKVConfig.ID)) 28 | }.then(viewModelScope, { 29 | user.value = it.data 30 | }, { 31 | errMsg.value = it 32 | }) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/cn/neday/sheep/viewmodel/SignInViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep.viewmodel 2 | 3 | import androidx.lifecycle.viewModelScope 4 | import cn.neday.base.SingleLiveEvent 5 | import cn.neday.base.config.MMKVConfig.ID 6 | import cn.neday.base.config.MMKVConfig.kv 7 | import cn.neday.base.network.requestAsync 8 | import cn.neday.base.network.then 9 | import cn.neday.base.viewmodel.BaseViewModel 10 | import cn.neday.sheep.model.User 11 | import cn.neday.sheep.network.repository.UserRepository 12 | 13 | /** 14 | * SignInViewModel 15 | * 16 | * @author nEdAy 17 | */ 18 | class SignInViewModel(private val repository: UserRepository) : BaseViewModel() { 19 | 20 | val user = SingleLiveEvent() 21 | 22 | /** 23 | * 获取当前用户信息 24 | */ 25 | fun getUserById() { 26 | requestAsync { 27 | repository.getUserById(kv.decodeInt(ID)) 28 | }.then(viewModelScope, { 29 | user.value = it.data 30 | }, { 31 | errMsg.value = it 32 | }) 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_back_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_lock_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_phone_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_share_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_sms_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_avatar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_avatar.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_change_key.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_change_key.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_change_skin.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_change_skin.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_clear.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_clear.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_nickname.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_nickname.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_province_flow.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_province_flow.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_setting_center.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_setting_center.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_update.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_update.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/acc_user.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/acc_user.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/avatar_default.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/avatar_default.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/bg_shake.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/bg_shake.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/bg_vip.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/bg_vip.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/bg_welcome_page.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/bg_welcome_page.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/check_normal.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/check_normal.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/check_pressed.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/check_pressed.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/good_morning_img.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/good_morning_img.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/good_night_img.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/good_night_img.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/guide_img_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/guide_img_1.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/guide_img_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/guide_img_2.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/guide_img_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/guide_img_3.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_ac.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_ac.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_to_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_add_to_cart.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_buy.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_buy.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_cart.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_cart.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_close.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_close.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_delete.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_delete.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_get.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_get.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_hc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_hc.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_index_integration_shop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_index_integration_shop.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_index_question.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_index_question.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_index_shake.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_index_shake.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_index_sign_in.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_index_sign_in.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_level.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_level.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_line.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_line.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_logo_kb.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_logo_kb.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_me_about.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_me_about.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_me_attention.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_me_attention.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_me_encourage.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_me_encourage.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_me_feedback.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_me_feedback.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_me_option.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_me_option.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_me_share.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_me_share.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_message.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_message.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_nc.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_nc.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_network_disabled.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_network_disabled.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_nickname.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_nickname.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_no_data.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_no_data.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_open.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_open.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_order_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_order_1.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_order_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_order_2.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_order_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_order_3.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_order_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_order_4.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_price.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_price.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_risk_money.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_risk_money.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_search.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_search.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_select.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_select.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_top.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_top.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_top_bar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_top_bar.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_baby.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_baby.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_bag.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_bag.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_beauty.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_beauty.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_car.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_car.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_clothes.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_clothes.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_digital.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_digital.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_life.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_life.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_type_snacks.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_type_snacks.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_unselect.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_unselect.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_update_banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_update_banner.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_voice_close.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_voice_close.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_voice_open.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/ic_voice_open.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_0.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_1.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_10.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_10.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_2.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_3.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_4.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_5.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_6.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_6.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_7.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_7.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_8.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_8.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/level_9.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/level_9.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sc_arrow_right.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/sc_arrow_right.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_0.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_1.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_2.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_3.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_4.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_0.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_1.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_2.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_3.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_banner_4.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_0.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_1.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_2.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_3.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/selfcenter_bg_main_4.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/shake_image.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/shake_image.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/shake_luck.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/shake_luck.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/shake_original_image.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/shake_original_image.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/shake_unluck.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/shake_unluck.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sign_in_a.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/sign_in_a.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sign_in_b.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/sign_in_b.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sign_in_c.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable-xxhdpi/sign_in_c.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_buy_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_buy_btn_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_corner_pink.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_corner_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_edit_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_edit_text_focused.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_edit_text_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_get_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_get_btn_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_type.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/global_click_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/global_red_click_with_corner_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/global_red_clickable_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_local_mall_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_local_offer_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_person_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_subject_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_visibility_off_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_visibility_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_error.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable/icon_error.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_stub.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/drawable/icon_stub.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_card_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_credit_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 26 | 27 | 28 | 29 | 33 | 34 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_goods_details.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 25 | 26 | 32 | 33 | 37 | 38 | 46 | 47 | 50 | 51 | 52 | 53 | 60 | 61 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_guide.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_search_result.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 25 | 26 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/adapter_banner.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/adapter_guide.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_goods_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_main_index.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_main_nine_goods.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 21 | 22 | 29 | 30 | 34 | 35 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_main_ranking_goods.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 21 | 22 | 29 | 30 | 34 | 35 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/include_credit_history_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/include_main_index_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 21 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/include_no_data.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 18 | 19 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_credit_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 22 | 23 | 30 | 31 | 39 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_item_key_words.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 21 | 22 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/menu/bottom_nav_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #fd5353 4 | #e41e1e 5 | #D81B60 6 | 7 | 8 | #5f606d 9 | #d7d7d7 10 | #999999 11 | #f2f2f2 12 | #96ffffff 13 | #80C0C0C0 14 | 15 | 16 | #af000000 17 | #44d6d4d4 18 | 19 | 20 | #fd5353 21 | #e41e1e 22 | #ff40dc91 23 | #333333 24 | #037BFF 25 | #fe9200 26 | #F88283 27 | #b6b6b6 28 | 29 | #FF181821 30 | #FFFFFFFF 31 | #FF2371FA 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12.0sp 4 | 16.0sp 5 | 18.0sp 6 | 7 | 45.0dip 8 | 18.0dip 9 | 0.5dip 10 | 11 | 10.0dip 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | 28 | 29 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/test/java/cn/neday/sheep/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.sheep 2 | 3 | import org.junit.Assert.assertEquals 4 | import org.junit.Test 5 | 6 | /** 7 | * Example local unit test, which will execute on the development machine (host). 8 | * 9 | * See [testing documentation](http://d.android.com/tools/testing). 10 | */ 11 | class ExampleUnitTest { 12 | @Test 13 | fun addition_isCorrect() { 14 | assertEquals(4, 2 + 2) 15 | } 16 | } -------------------------------------------------------------------------------- /base/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /base/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /base/src/androidTest/java/cn/neday/base/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package cn.neday.base; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * @see Testing documentation 15 | */ 16 | @RunWith(AndroidJUnit4.class) 17 | public class ExampleInstrumentedTest { 18 | @Test 19 | public void useAppContext() { 20 | // Context of the app under test. 21 | Context appContext = InstrumentationRegistry.getTargetContext(); 22 | 23 | assertEquals("cn.neday.base.test", appContext.getPackageName()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /base/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/SingleLiveEvent.java: -------------------------------------------------------------------------------- 1 | package cn.neday.base; 2 | 3 | import android.util.Log; 4 | import androidx.annotation.MainThread; 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.lifecycle.LifecycleOwner; 8 | import androidx.lifecycle.MutableLiveData; 9 | import androidx.lifecycle.Observer; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | import java.util.concurrent.atomic.AtomicBoolean; 13 | 14 | /** 15 | * A lifecycle-aware observable that sends only new updates after subscription, used for events like 16 | * navigation and Snackbar messages. 17 | *

18 | * This avoids a common problem with events: on configuration change (like rotation) an update 19 | * can be emitted if the observer is active. This LiveData only calls the observable if there's an 20 | * explicit call to setValue() or call(). 21 | *

22 | * Note that only one observer is going to be notified of changes. 23 | */ 24 | public class SingleLiveEvent extends MutableLiveData { 25 | 26 | private static final String TAG = "SingleLiveEvent"; 27 | 28 | private final AtomicBoolean mPending = new AtomicBoolean(false); 29 | 30 | @MainThread 31 | @Override 32 | public void observe(@NonNull LifecycleOwner owner, @NotNull final Observer observer) { 33 | if (hasActiveObservers()) { 34 | Log.w(TAG, "Multiple observers registered but only one will be notified of changes."); 35 | } 36 | 37 | // Observe the internal MutableLiveData 38 | super.observe(owner, t -> { 39 | if (mPending.compareAndSet(true, false)) { 40 | observer.onChanged(t); 41 | } 42 | }); 43 | } 44 | 45 | @MainThread 46 | @Override 47 | public void setValue(@Nullable T t) { 48 | mPending.set(true); 49 | super.setValue(t); 50 | } 51 | 52 | /** 53 | * Used for cases where T is Void, to make calls cleaner. 54 | */ 55 | @MainThread 56 | public void call() { 57 | setValue(null); 58 | } 59 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/activity/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.activity 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import androidx.annotation.LayoutRes 6 | import androidx.appcompat.app.AppCompatActivity 7 | import cn.neday.base.config.MMKVConfig.TOKEN 8 | import cn.neday.base.config.MMKVConfig.kv 9 | import cn.neday.base.router.Router 10 | import cn.neday.base.router.RouterPath 11 | import com.blankj.utilcode.util.ActivityUtils 12 | import com.blankj.utilcode.util.StringUtils 13 | 14 | /** 15 | * Activity基类 16 | * 17 | * @author nEdAy 18 | */ 19 | abstract class BaseActivity(@get:LayoutRes val layoutId: Int?) : AppCompatActivity() { 20 | 21 | open val isCheckLogin = false 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | if (isCheckLogin && StringUtils.isTrimEmpty(kv.decodeString(TOKEN))) { 26 | Router.navigation(RouterPath.LoginActivity) 27 | ActivityUtils.finishActivity(this) 28 | } 29 | layoutId?.let { 30 | setContentView(LayoutInflater.from(this).inflate(it, null)) 31 | } 32 | prepareInitView() 33 | initView() 34 | } 35 | 36 | open fun prepareInitView() { 37 | // do nothing 38 | } 39 | 40 | /** 41 | * onCreate 42 | */ 43 | abstract fun initView() 44 | 45 | override fun onDestroy() { 46 | super.onDestroy() 47 | Router.alibabaService.destroySDK() 48 | } 49 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/activity/BaseVMActivity.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.activity 2 | 3 | import androidx.lifecycle.Observer 4 | import cn.neday.base.viewmodel.BaseViewModel 5 | import com.blankj.utilcode.util.LogUtils 6 | import org.koin.androidx.viewmodel.ext.android.viewModel 7 | import java.lang.reflect.ParameterizedType 8 | 9 | /** 10 | * Activity基类 + ViewModel 11 | * 12 | * @author nEdAy 13 | */ 14 | abstract class BaseVMActivity(layoutId: Int) : BaseActivity(layoutId) { 15 | 16 | @Suppress("UNCHECKED_CAST") 17 | protected val mViewModel: VM by viewModel(((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class).kotlin) 18 | 19 | override fun prepareInitView() { 20 | super.prepareInitView() 21 | lifecycle.addObserver(mViewModel) 22 | mViewModel.errMsg.observe(this, Observer { 23 | LogUtils.e(it) 24 | }) 25 | } 26 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/config/BuglyConfig.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.config 2 | 3 | import cn.neday.base.BuildConfig 4 | import com.blankj.utilcode.util.Utils 5 | import com.tencent.bugly.Bugly 6 | import com.tencent.bugly.beta.Beta 7 | 8 | object BuglyConfig { 9 | 10 | private const val BUGLY_APP_ID = "923c0825a2" 11 | 12 | fun init() { 13 | Bugly.init(Utils.getApp(), BUGLY_APP_ID, BuildConfig.DEBUG) 14 | } 15 | 16 | fun checkUpgrade() { 17 | Beta.checkUpgrade() 18 | } 19 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/config/DoraemonKitConfig.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.config 2 | 3 | import com.blankj.utilcode.util.Utils 4 | import com.didichuxing.doraemonkit.DoraemonKit 5 | 6 | object DoraemonKitConfig { 7 | 8 | fun init() { 9 | DoraemonKit.install(Utils.getApp()) 10 | } 11 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/config/LogConfig.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.config 2 | 3 | import com.blankj.utilcode.util.AppUtils 4 | import com.blankj.utilcode.util.LogUtils 5 | 6 | object LogConfig { 7 | 8 | fun init() { 9 | LogUtils.getConfig().isLogSwitch = AppUtils.isAppDebug() 10 | } 11 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/config/MMKVConfig.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.config 2 | 3 | import com.blankj.utilcode.util.Utils 4 | import com.tencent.mmkv.MMKV 5 | 6 | object MMKVConfig { 7 | 8 | lateinit var kv: MMKV 9 | 10 | fun init() { 11 | MMKV.initialize(Utils.getApp()) 12 | kv = MMKV.defaultMMKV() 13 | } 14 | 15 | const val ID = "Id" 16 | const val TOKEN = "Token" 17 | const val MOBILE = "Mobile" 18 | const val HOTWORDS = "HotWords" 19 | const val HISTORY_WORDS = "HistoryWords" 20 | const val IS_FIRST_START_APP = "isFirstStartApp" 21 | 22 | fun login(id: Int?, token: String?, mobile: String?) { 23 | kv.encode(ID, id ?: 0) 24 | kv.encode(TOKEN, token) 25 | kv.encode(MOBILE, mobile) 26 | } 27 | 28 | fun logout() { 29 | kv.removeValueForKey(ID) 30 | kv.removeValueForKey(TOKEN) 31 | kv.removeValueForKey(MOBILE) 32 | } 33 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/di/HttpClientModule.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.di 2 | 3 | import cn.neday.base.BuildConfig 4 | import cn.neday.base.network.interceptor.AuthenticationInterceptor 5 | import com.blankj.utilcode.util.Utils 6 | import com.readystatesoftware.chuck.ChuckInterceptor 7 | import okhttp3.Interceptor 8 | import okhttp3.OkHttpClient 9 | import okhttp3.logging.HttpLoggingInterceptor 10 | import org.koin.core.qualifier.named 11 | import org.koin.dsl.module 12 | import retrofit2.Retrofit 13 | import retrofit2.converter.moshi.MoshiConverterFactory 14 | import java.util.concurrent.TimeUnit 15 | 16 | private const val TIME_OUT_SECONDS = 10L 17 | private const val BASE_URL = "https://www.neday.cn/v1/" 18 | 19 | val httpClientModule = module { 20 | 21 | single { Retrofit.Builder() } 22 | 23 | single { OkHttpClient.Builder() } 24 | 25 | single { 26 | get() 27 | .baseUrl(BASE_URL) 28 | .client(get()) 29 | .addConverterFactory(MoshiConverterFactory.create()) 30 | .build() 31 | } 32 | 33 | single(named()) { 34 | AuthenticationInterceptor() 35 | } 36 | 37 | single(named()) { 38 | HttpLoggingInterceptor().apply { 39 | level = when (BuildConfig.DEBUG) { 40 | true -> HttpLoggingInterceptor.Level.BODY 41 | false -> HttpLoggingInterceptor.Level.NONE 42 | } 43 | } 44 | } 45 | 46 | single(named()) { 47 | ChuckInterceptor(Utils.getApp()) 48 | } 49 | 50 | single { 51 | get() 52 | .connectTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS) 53 | .readTimeout(TIME_OUT_SECONDS, TimeUnit.SECONDS) 54 | .addInterceptor(get(named()) as Interceptor) 55 | .addInterceptor(get(named()) as Interceptor) 56 | .addInterceptor(get(named()) as Interceptor) 57 | .build() 58 | } 59 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/fragment/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.fragment 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.annotation.LayoutRes 8 | import androidx.fragment.app.Fragment 9 | import cn.neday.base.router.Router 10 | 11 | /** 12 | * Fragment基类 13 | * 14 | * @author nEdAy 15 | */ 16 | abstract class BaseFragment(@get:LayoutRes val layoutId: Int) : Fragment() { 17 | 18 | private var mRootView: View? = null 19 | 20 | override fun onCreateView( 21 | inflater: LayoutInflater, 22 | container: ViewGroup?, 23 | savedInstanceState: Bundle? 24 | ): View { 25 | mRootView = LayoutInflater.from(context).inflate(layoutId, container, false) 26 | return mRootView!! 27 | } 28 | 29 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 30 | super.onViewCreated(view, savedInstanceState) 31 | prepareInitView() 32 | initView() 33 | } 34 | 35 | open fun prepareInitView() { 36 | // do nothing 37 | } 38 | 39 | abstract fun initView() 40 | 41 | override fun onDestroyView() { 42 | super.onDestroyView() 43 | Router.alibabaService.destroySDK() 44 | mRootView = null 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/fragment/BaseVMFragment.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.fragment 2 | 3 | import androidx.lifecycle.Observer 4 | import cn.neday.base.viewmodel.BaseViewModel 5 | import com.blankj.utilcode.util.LogUtils 6 | import org.koin.androidx.viewmodel.ext.android.viewModel 7 | import java.lang.reflect.ParameterizedType 8 | 9 | /** 10 | * Fragment基类 + ViewModel 11 | * 12 | * @author nEdAy 13 | */ 14 | abstract class BaseVMFragment(layoutId: Int) : BaseFragment(layoutId) { 15 | 16 | @Suppress("UNCHECKED_CAST") 17 | protected val mViewModel: VM by viewModel(((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class).kotlin) 18 | 19 | override fun prepareInitView() { 20 | super.prepareInitView() 21 | lifecycle.addObserver(mViewModel) 22 | mViewModel.errMsg.observe(this, Observer { 23 | LogUtils.e(it) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/model/BaseModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.model 2 | 3 | import com.squareup.moshi.Json 4 | 5 | open class BaseModel { 6 | @Json(name = "ID") 7 | val id: Int? = null 8 | @Json(name = "CreateAt") 9 | val createAt: String? = null 10 | @Json(name = "UpdatedAt") 11 | val updatedAt: String? = null 12 | @Json(name = "DeletedAt") 13 | val deletedAt: String? = null 14 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/model/Pages.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.model 2 | 3 | data class Pages( 4 | val list: List?, 5 | val totalNum: Int?, 6 | val pageId: String? 7 | ) -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/model/Response.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.model 2 | 3 | data class Response( 4 | // 时间戳 1556418473705 5 | val time: Long?, 6 | // 返回状态,0-正确,其他见错误码列表 7 | val code: Int?, 8 | // 返回状态描述 “成功” 9 | val msg: String?, 10 | val data: T? 11 | ) -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/network/CoroutineDSL.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.network 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.viewModelScope 5 | import cn.neday.base.model.Response 6 | import com.blankj.utilcode.util.NetworkUtils 7 | import kotlinx.coroutines.* 8 | import java.net.SocketTimeoutException 9 | import java.net.UnknownHostException 10 | import java.util.concurrent.TimeoutException 11 | 12 | /** 13 | * execute in main thread 14 | * @param start doSomeThing first 15 | */ 16 | fun ViewModel.start(start: (() -> Unit)): ViewModel { 17 | viewModelScope.launch(Dispatchers.Main) { 18 | if (NetworkUtils.isConnected()) { 19 | start() 20 | } else { 21 | // errMsg.value = StringUtils.getString(R.string.network_tips) 22 | } 23 | } 24 | return this 25 | } 26 | 27 | /** 28 | * execute in io thread pool 29 | * @param loader http request 30 | */ 31 | fun ViewModel.requestAsync(loader: suspend () -> Response): Deferred> { 32 | return viewModelScope.async(Dispatchers.IO, start = CoroutineStart.LAZY) { 33 | loader() 34 | } 35 | } 36 | 37 | /** 38 | * execute in main thread 39 | * @param onSuccess callback for onSuccess 40 | * @param onError callback for onError 41 | * @param onComplete callback for onComplete 42 | */ 43 | fun Deferred>.then( 44 | viewModelScope: CoroutineScope, 45 | onSuccess: suspend (Response) -> Unit, 46 | onError: suspend (String) -> Unit, 47 | onComplete: (() -> Unit)? = null 48 | ): Job { 49 | return viewModelScope.launch(context = Dispatchers.Main) { 50 | try { 51 | val response = this@then.await() 52 | if (response.code != 0) { 53 | onError("code : " + response.code + "msg : " + response.msg) 54 | } else { 55 | onSuccess(response) 56 | } 57 | } catch (e: Exception) { 58 | if (e is CancellationException) { 59 | return@launch 60 | } 61 | e.printStackTrace() 62 | when (e) { 63 | is UnknownHostException -> onError("Unknown Host Exception!") 64 | is TimeoutException -> onError("Timeout Exception!") 65 | is SocketTimeoutException -> onError("Socket Timeout Exception!") 66 | else -> onError("Other Exception!") 67 | } 68 | } finally { 69 | onComplete?.invoke() 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/network/interceptor/AuthenticationInterceptor.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.network.interceptor 2 | 3 | import cn.neday.base.config.MMKVConfig.TOKEN 4 | import com.tencent.mmkv.MMKV 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | 8 | class AuthenticationInterceptor : Interceptor { 9 | 10 | override fun intercept(chain: Interceptor.Chain): Response = chain 11 | .request() 12 | .newBuilder() 13 | .header("Authorization", MMKV.defaultMMKV().decodeString(TOKEN) ?: "") 14 | .build() 15 | .let { chain.proceed(it) } 16 | } 17 | -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/router/AlibabaService.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.router 2 | 3 | import android.app.Activity 4 | import com.alibaba.android.arouter.facade.template.IProvider 5 | 6 | interface AlibabaService : IProvider { 7 | 8 | fun destroySDK() 9 | 10 | fun showDetailPage(activity: Activity?, itemId: String) 11 | 12 | fun showShopPage(activity: Activity?, shopId: String) 13 | 14 | fun showAddCartPage(activity: Activity?, itemId: String) 15 | 16 | fun showMyOrdersPage(activity: Activity?, status: Int, allOrder: Boolean) 17 | 18 | fun showMyCartsPage(activity: Activity?) 19 | 20 | fun showItemURLPage(activity: Activity?, url: String) 21 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/router/AppService.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.router 2 | 3 | import com.alibaba.android.arouter.facade.template.IProvider 4 | 5 | interface AppService : IProvider -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/router/Router.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.router 2 | 3 | import com.alibaba.android.arouter.facade.Postcard 4 | import com.alibaba.android.arouter.launcher.ARouter 5 | 6 | /** 7 | * SMT Router 8 | * ARouter Helper 9 | * 10 | * @author Kevin.SuTJ 11 | */ 12 | object Router { 13 | /** 14 | * Get instance of router. A 15 | * All feature U use, will be starts here. 16 | */ 17 | private val instance = ARouter.getInstance() 18 | 19 | val alibabaService = getService(AlibabaService::class.java) 20 | val appService = getService(AppService::class.java) 21 | 22 | /** 23 | * Build the road map, draw a postcard. 24 | * 25 | * @param path Where you go. 26 | */ 27 | fun build(path: String): Postcard { 28 | return instance.build(path) 29 | } 30 | 31 | /** 32 | * Navigation to the route with path in postcard. 33 | * No param, will be use application context. 34 | */ 35 | fun navigation(path: String) { 36 | build(path).navigation() 37 | } 38 | 39 | /** 40 | * Launch the navigation by type 41 | * 42 | * @param service interface of service 43 | * @param return type 44 | * @return instance of service 45 | */ 46 | private fun getService(service: Class): T { 47 | return instance.navigation(service) 48 | } 49 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/router/RouterPath.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.router 2 | 3 | object RouterPath { 4 | 5 | /** 6 | * app 7 | */ 8 | const val AppService = "/app/AppService" 9 | const val LoginActivity = "/app/LoginActivity" 10 | 11 | /** 12 | * alibaba 13 | */ 14 | const val AlibabaService = "/alibaba/AlibabaService" 15 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/util/ClipboardUtils.java: -------------------------------------------------------------------------------- 1 | package cn.neday.base.util; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import com.blankj.utilcode.util.Utils; 7 | 8 | /** 9 | *

10 |  *     author: Blankj
11 |  *     blog  : http://blankj.com
12 |  *     time  : 2016/09/25
13 |  *     desc  : 剪贴板相关工具类
14 |  * 
15 | */ 16 | public final class ClipboardUtils { 17 | 18 | private ClipboardUtils() { 19 | throw new UnsupportedOperationException("u can't instantiate me..."); 20 | } 21 | 22 | /** 23 | * 复制文本到剪贴板 24 | * 25 | * @param text 文本 26 | */ 27 | public static void copyText(final CharSequence text) { 28 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 29 | // noinspection ConstantConditions 30 | cm.setPrimaryClip(ClipData.newPlainText("text", text)); 31 | } 32 | 33 | /** 34 | * 获取剪贴板的文本 35 | * 36 | * @return 剪贴板的文本 37 | */ 38 | public static CharSequence getText() { 39 | ClipboardManager cm = (ClipboardManager) Utils.getApp().getSystemService(Context.CLIPBOARD_SERVICE); 40 | // noinspection ConstantConditions 41 | ClipData clip = cm.getPrimaryClip(); 42 | if (clip != null && clip.getItemCount() > 0) { 43 | return clip.getItemAt(0).coerceToText(Utils.getApp()); 44 | } 45 | return null; 46 | } 47 | } -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/util/SecurityUtils.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.util 2 | 3 | import cn.neday.base.BuildConfig 4 | import cn.neday.base.R 5 | import com.blankj.utilcode.util.AppUtils 6 | import com.blankj.utilcode.util.DeviceUtils 7 | import com.blankj.utilcode.util.StringUtils 8 | import com.blankj.utilcode.util.StringUtils.getString 9 | import com.blankj.utilcode.util.ToastUtils 10 | 11 | object SecurityUtils { 12 | 13 | private const val SIGNATURE_RELEASE = "EBB32FEB587FAA0B80C7DB915B3511ECC33BD7FF" 14 | 15 | fun checkIsAppRoot() { 16 | if (DeviceUtils.isDeviceRooted() && AppUtils.isAppRoot()) { 17 | ToastUtils.showLong(getString(R.string.root_tips)) 18 | } 19 | } 20 | 21 | fun checkIsAppDebug() { 22 | if (!BuildConfig.DEBUG && AppUtils.isAppDebug()) { 23 | ToastUtils.showLong(getString(R.string.debug_tips)) 24 | AppUtils.exitApp() 25 | } 26 | } 27 | 28 | // TODO : 类似token, 修改为网络验证 29 | fun checkSignature() { 30 | if (!BuildConfig.DEBUG && StringUtils.equalsIgnoreCase(SIGNATURE_RELEASE, AppUtils.getAppSignatureSHA1())) { 31 | ToastUtils.showLong(getString(R.string.signature_tips)) 32 | AppUtils.exitApp() 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /base/src/main/java/cn/neday/base/viewmodel/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package cn.neday.base.viewmodel 2 | 3 | import androidx.lifecycle.LifecycleObserver 4 | import androidx.lifecycle.ViewModel 5 | import cn.neday.base.SingleLiveEvent 6 | 7 | /** 8 | * ViewModel基类 9 | * 10 | * @author nEdAy 11 | */ 12 | open class BaseViewModel : ViewModel(), LifecycleObserver { 13 | 14 | val errMsg = SingleLiveEvent() 15 | val onComplete = SingleLiveEvent() 16 | } -------------------------------------------------------------------------------- /base/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 口袋快爆 3 | 实 惠 多 到 爆 4 | 当前版本v%1$s 5 | 6 | neday@bk.ru 7 | www.neday.cn 8 | nEdAy_ 9 | 1582703866 10 | 11 | TODO 12 | 尚未开放,敬请期待 13 | 14 | 程序被修改为可调试状态 15 | 证书签名已被篡改 16 | 出于安全原因,不建议在已经ROOT的设备上运行 17 | 您已进入没有网络的异次元,请检查您的网络 18 | 19 | -------------------------------------------------------------------------------- /base/src/test/java/cn/neday/base/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package cn.neday.base; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.61' 3 | repositories { 4 | google() 5 | jcenter() 6 | maven { url 'https://maven.aliyun.com/repository/public' } 7 | maven { url 'https://maven.aliyun.com/repository/google' } 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.6.0' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | classpath "com.alibaba:arouter-register:1.0.2" 13 | classpath 'org.jacoco:org.jacoco.core:0.8.5' 14 | classpath 'com.tencent.bugly:symtabfileuploader:2.2.1' 15 | classpath 'com.mob.sdk:MobSDK:2018.0319.1724' 16 | classpath 'com.zf.plugins:JiaGu360:1.0.1' 17 | } 18 | } 19 | 20 | allprojects { 21 | repositories { 22 | google() 23 | jcenter() 24 | maven { url 'https://jitpack.io' } 25 | maven { url 'https://maven.aliyun.com/repository/public' } 26 | maven { url 'https://maven.aliyun.com/repository/google' } 27 | maven { url 'https://maven.aliyun.com/repository/jcenter' } 28 | maven { url 'https://dl.bintray.com/umsdk/release' } 29 | maven { url 'http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/' } 30 | } 31 | } 32 | 33 | task clean(type: Delete) { 34 | delete rootProject.buildDir 35 | } 36 | 37 | ext { 38 | compileSdkVersion = 29 39 | minSdkVersion = 21 40 | targetSdkVersion = 29 41 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx4096m -XX\:MaxPermSize\=1024m -XX\:+HeapDumpOnOutOfMemoryError -Dfile.encoding\=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | # Signing properties 23 | debug-signing.properties=./keystore/debug-signing.properties 24 | release-signing.properties=./keystore/release-signing.properties 25 | # Gradle 26 | org.gradle.daemon=true 27 | org.gradle.caching=true 28 | android.enableBuildCache=true 29 | # Kotlin 30 | kotlin.incremental=true 31 | kotlin.incremental.java=true 32 | kotlin.incremental.js=true 33 | kotlin.caching.enabled=true 34 | kotlin.parallel.tasks.in.project=true 35 | kapt.use.worker.api=true 36 | kapt.incremental.apt=true 37 | kapt.include.compile.classpath=false -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Sheep/584bc01304ba9faf03b341fb0d6590830118f572/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 22 17:51:04 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':base', ':alibaba' 2 | --------------------------------------------------------------------------------