diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e48145 --- /dev/null +++ b/.gitignore @@ -0,0 +1,90 @@ +# Built application files +#*.apk +*.aar +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ +# Uncomment the following line in case you need and you don't have the release build type files in your app +# release/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# IntelliJ +*.iml +.idea/workspace.xml +.idea/tasks.xml +.idea/gradle.xml +.idea/assetWizardSettings.xml +.idea/dictionaries +.idea/libraries +# Android Studio 3 in .gitignore file. +.idea/caches +.idea/modules.xml +# Comment next line if keeping position of elements in Navigation Editor is relevant for you +.idea/navEditor.xml + +# Keystore files +# Uncomment the following lines if you do not want to check your keystore files in. +#*.jks +#*.keystore + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild +.cxx/ + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + +# Version control +vcs.xml + +# lint +lint/intermediates/ +lint/generated/ +lint/outputs/ +lint/tmp/ +# lint/reports/ + +/.idea +app/debug/ +app/release/ +app/sampledata/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef91bcc --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +# Eyepetizer +基于 [Kotlin][1] 语言仿写「[开眼 Eyepetizer][2]」的一个短视频 Android 客户端项目,采用 [Jetpack][3] + [协程][30]实现的 MVVM 架构。 + +## 简介 +这是一个高仿「[开眼 Eyepetizer][2]」的短视频 Android 客户端项目,个人觉得这款 App 的 UI 设计风格很好看,界面简洁清新,通过此项目,进行相关技术的学习与整合。 + +整个项目没有复杂的封装,同时项目开发规范参考了 [Kotlin 官方文档][4] 与第三方 [AndroidStandardDevelop][5]。个人认为代码还是比较容易阅读理解的,因此也非常适合新手入门 Kotlin 语言,同时更快地掌握 Jetpack 组件的使用。 + +另外值得一提的是,所有 UI 都是经过标注工具测量后的,无论是字体颜色、大小、间距等几乎都是**像素级**模仿的「开眼 Eyepetizer」Android 客户端 App,对应的 v6.3.1 版本(目前最新版)。 + +## 屏幕截图 + + + + + +

+ +

+ +

+ +图片加载不出来?附上[博客地址][6] +

+ +## 下载体验 +- 扫描二维码安装:

+ + +- [点击下载 eyepetizer.apk][7] + +## 主要功能 +- 观看优质高清短视频与评论。 +- 浏览社区图文与视频创作。 +- 查看每日新鲜资讯与热搜关键词。 +- 分享精彩短视频与新鲜资讯等。 + +## 使用工具 +- [Vector Asset Studio][8] 图标制作 +- [iconfont][9] 图标/设计 +- [Postman][10] API 调试工具 +- [Charles][11] API 数据抓包 +- [PxCook][12] 标注工具 +- [开发助手][13] 反编译应用、提取应用 Apk 等 + +## 关于我 +- RealName : 殷志威 +- NickName : vipyinzhiwei +- Email : vipyinzhiwei@gmail.com +- Blog : + +## 鼓励 +通过这个项目希望能够帮助大家更好地学习 Jetpack 与 MVVM 架构。如果你喜欢 Eyepetizer 的设计,感觉本项目的源代码对你的学习有所帮助,可以点右上角 **"Star"** 支持一下,谢谢!^_^ + +## 致谢 +- [Retrofit][14] 网络请求框架封装 +- [Glide][15] 图片加载 +- [OkHttp][16] 网络请求 +- [Gson][17] Gson 解析 +- [Glide Transformations][18] 图像转换 +- [Eventbus][19] 事件总线 +- [Permissionx][20] 动态请求权限封装 +- [FlycoTabLayout][21] TabLayout封装 +- [SmartRefreshLayout][22] 下拉刷新框架 +- [BannerViewPager][23] Banner轮播图 +- [Immersionbar][24] 状态栏管理 +- [PhotoView][25] 支持手势缩放图片 +- [Circleimageview][26] 圆形图像 +- [GSYVideoPlayer][27] 视频播放器 +- [VasSonic][28] 提升H5首屏加载速度 +- [Leakcanary][29] 内存泄漏检测 +- [Kotlinx Coroutines][30] 简化代码管理后台线程与回调 + + +## License + +**所有数据来源于开眼,仅供学习和交流使用,严禁用于任何商业用途,原作公司拥有所有权利。** + +``` +Copyright (c) 2020. vipyinzhiwei + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +``` + +[1]:https://kotlinlang.org +[2]:https://www.kaiyanapp.com +[3]:https://developer.android.com/jetpack +[4]:https://www.kotlincn.net/docs/reference/coding-conventions.html +[5]:https://github.com/Blankj/AndroidStandardDevelop +[6]:https://www.vipyinzhiwei.com/2020/06/19/pager05/#more +[7]:https://github.com/VIPyinzhiwei/Eyepetizer/raw/master/eyepetizer.apk +[8]:https://developer.android.com/studio/write/vector-asset-studio?hl=zh-cn +[9]:https://www.iconfont.cn +[10]:https://www.postman.com +[11]:https://www.charlesproxy.com +[12]:https://www.fancynode.com.cn/pxcook +[13]:https://github.com/Trinea/android-open-project/issues/314 +[14]:https://github.com/square/retrofit +[15]:https://github.com/bumptech/glide +[16]:https://github.com/square/okhttp +[17]:https://github.com/google/gson +[18]:https://github.com/wasabeef/glide-transformations +[19]:https://github.com/greenrobot/EventBus +[20]:https://github.com/guolindev/PermissionX +[21]:https://github.com/H07000223/FlycoTabLayout +[22]:https://github.com/scwang90/SmartRefreshLayout +[23]:https://github.com/zhpanvip/BannerViewPager +[24]:https://github.com/gyf-dev/ImmersionBar +[25]:https://github.com/chrisbanes/PhotoView +[26]:https://github.com/hdodenhof/CircleImageView +[27]:https://github.com/CarGuo/GSYVideoPlayer +[28]:https://github.com/Tencent/VasSonic +[29]:https://github.com/square/leakcanary +[30]:https://github.com/Kotlin/kotlinx.coroutines + + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..3fe82fd --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,3 @@ +/build +/src/test +/src/androidTest \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..dc0b620 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,117 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "com.eyepetizer.android" + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "1.0.0" + multiDexEnabled true + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + ndk { + abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' + } + } + + sourceSets { + main { + jniLibs.srcDirs = ['libs'] + } + } + + signingConfigs { + releaseConfig { + storeFile file(STORE_FILE) + storePassword STORE_PASSWORD + keyAlias KEY_ALIAS + keyPassword KEY_PASSWORD + } + } + + buildTypes { + release { + minifyEnabled false + signingConfig signingConfigs.releaseConfig + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + debug { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + dataBinding = true + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + lintOptions { + abortOnError false + disable 'ContentDescription' + disable 'SmallSp' + disable 'RtlSymmetry' + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.3.0-alpha01' + implementation 'androidx.core:core-ktx:1.3.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + + //常用依赖库 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7' + implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha03' + implementation 'com.google.android.material:material:1.1.0' + implementation 'com.squareup.retrofit2:retrofit:2.6.1' + implementation 'com.squareup.retrofit2:converter-gson:2.6.1' + implementation 'com.squareup.retrofit2:converter-scalars:2.5.0' + implementation 'com.github.bumptech.glide:glide:4.9.0' + kapt 'com.github.bumptech.glide:compiler:4.9.0' + implementation 'com.github.bumptech.glide:okhttp3-integration:4.9.0' + implementation 'jp.wasabeef:glide-transformations:4.1.0' + implementation 'org.greenrobot:eventbus:3.1.1' + implementation 'androidx.viewpager2:viewpager2:1.0.0' + implementation 'com.permissionx.guolindev:permissionx:1.2.2' + + //Android Jetpack 组件 + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.work:work-runtime:2.3.4' + + //特定功能依赖库 + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4' + implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar' + implementation 'com.scwang.smart:refresh-header-material:2.0.0' + implementation 'com.scwang.smart:refresh-layout-kernel:2.0.0' + implementation 'com.github.zhpanvip:BannerViewPager:3.1.2' + implementation 'com.gyf.immersionbar:immersionbar:3.0.0' + implementation 'com.github.chrisbanes:PhotoView:2.3.0' + implementation 'de.hdodenhof:circleimageview:3.1.0' + implementation 'com.android.support:multidex:1.0.3' + implementation 'com.shuyu:GSYVideoPlayer:7.1.3' + implementation 'com.tencent.sonic:sdk:3.1.0' + implementation 'com.umeng.umsdk:analytics:8.1.3' + implementation 'com.umeng.umsdk:common:2.1.0' + + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..acad71c --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/fonts/DIN-Condensed-Bold.ttf b/app/src/main/assets/fonts/DIN-Condensed-Bold.ttf new file mode 100644 index 0000000..f05a1a9 Binary files /dev/null and b/app/src/main/assets/fonts/DIN-Condensed-Bold.ttf differ diff --git a/app/src/main/assets/fonts/FZLanTingHeiS-DB1-GB-Regular.TTF b/app/src/main/assets/fonts/FZLanTingHeiS-DB1-GB-Regular.TTF new file mode 100644 index 0000000..16dfb67 Binary files /dev/null and b/app/src/main/assets/fonts/FZLanTingHeiS-DB1-GB-Regular.TTF differ diff --git a/app/src/main/assets/fonts/FZLanTingHeiS-L-GB-Regular.TTF b/app/src/main/assets/fonts/FZLanTingHeiS-L-GB-Regular.TTF new file mode 100644 index 0000000..e3c7f7c Binary files /dev/null and b/app/src/main/assets/fonts/FZLanTingHeiS-L-GB-Regular.TTF differ diff --git a/app/src/main/assets/fonts/Futura-CondensedMedium.ttf b/app/src/main/assets/fonts/Futura-CondensedMedium.ttf new file mode 100644 index 0000000..40a322c Binary files /dev/null and b/app/src/main/assets/fonts/Futura-CondensedMedium.ttf differ diff --git a/app/src/main/assets/fonts/Lobster-1.4.otf b/app/src/main/assets/fonts/Lobster-1.4.otf new file mode 100644 index 0000000..86effca Binary files /dev/null and b/app/src/main/assets/fonts/Lobster-1.4.otf differ diff --git a/app/src/main/ic_launcher_playstore.png b/app/src/main/ic_launcher_playstore.png new file mode 100644 index 0000000..2073ccf Binary files /dev/null and b/app/src/main/ic_launcher_playstore.png differ diff --git a/app/src/main/java/com/eyepetizer/android/Const.kt b/app/src/main/java/com/eyepetizer/android/Const.kt new file mode 100644 index 0000000..a186cfe --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/Const.kt @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android + +/** + * 项目所有全局通用常量的管理类。 + * + * @author vipyinzhiwei + * @since 2020/5/31 + */ +interface Const { + + interface ItemViewType { + + companion object { + + const val UNKNOWN = -1 //未知类型,使用EmptyViewHolder容错处理。 + + const val CUSTOM_HEADER = 0 //自定义头部类型。 + + const val TEXT_CARD_HEADER1 = 1 + + const val TEXT_CARD_HEADER2 = 2 + + const val TEXT_CARD_HEADER3 = 3 + + const val TEXT_CARD_HEADER4 = 4 //type:textCard -> dataType:TextCard,type:header4 + + const val TEXT_CARD_HEADER5 = 5 //type:textCard -> dataType:TextCard -> type:header5 + + const val TEXT_CARD_HEADER6 = 6 + + const val TEXT_CARD_HEADER7 = 7 //type:textCard -> dataType:TextCardWithRightAndLeftTitle,type:header7 + + const val TEXT_CARD_HEADER8 = 8 //type:textCard -> dataType:TextCardWithRightAndLeftTitle,type:header8 + + const val TEXT_CARD_FOOTER1 = 9 + + const val TEXT_CARD_FOOTER2 = 10 //type:textCard -> dataType:TextCard,type:footer2 + + const val TEXT_CARD_FOOTER3 = 11 //type:textCard -> dataType:TextCardWithTagId,type:footer3 + + const val BANNER = 12 //type:banner -> dataType:Banner + + const val BANNER3 = 13 //type:banner3-> dataType:Banner + + const val FOLLOW_CARD = 14 //type:followCard -> dataType:FollowCard -> type:video -> dataType:VideoBeanForClient + + const val TAG_BRIEFCARD = 15 //type:briefCard -> dataType:TagBriefCard + + const val TOPIC_BRIEFCARD = 16 //type:briefCard -> dataType:TopicBriefCard + + const val COLUMN_CARD_LIST = 17 //type:columnCardList -> dataType:ItemCollection + + const val VIDEO_SMALL_CARD = 18 //type:videoSmallCard -> dataType:VideoBeanForClient + + const val INFORMATION_CARD = 19 //type:informationCard -> dataType:InformationCard + + const val AUTO_PLAY_VIDEO_AD = 20 //type:autoPlayVideoAd -> dataType:AutoPlayVideoAdDetail + + const val HORIZONTAL_SCROLL_CARD = 21 //type:horizontalScrollCard -> dataType:HorizontalScrollCard + + const val SPECIAL_SQUARE_CARD_COLLECTION = 22 //type:specialSquareCardCollection -> dataType:ItemCollection + + const val UGC_SELECTED_CARD_COLLECTION = 23 //type:ugcSelectedCardCollection -> dataType:ItemCollection + + const val MAX = 100 //避免外部其他类型与此处包含的某个类型重复。 + } + } + + interface ActionUrl { + companion object { + + const val TAG = "eyepetizer://tag/" + + const val DETAIL = "eyepetizer://detail/" + + const val RANKLIST = "eyepetizer://ranklist/" + + const val WEBVIEW = "eyepetizer://webview/?title=" + + const val REPLIES_HOT = "eyepetizer://replies/hot?" + + const val TOPIC_DETAIL = "eyepetizer://topic/detail?" + + const val COMMON_TITLE = "eyepetizer://common/?title" + + const val LT_DETAIL = "eyepetizer://lightTopic/detail/" + + const val CM_TOPIC_SQUARE = "eyepetizer://community/topicSquare" + + const val HP_NOTIFI_TAB_ZERO = "eyepetizer://homepage/notification?tabIndex=0" + + const val CM_TAGSQUARE_TAB_ZERO = "eyepetizer://community/tagSquare?tabIndex=0" + + const val CM_TOPIC_SQUARE_TAB_ZERO = "eyepetizer://community/tagSquare?tabIndex=0" + + const val HP_SEL_TAB_TWO_NEWTAB_MINUS_THREE = "eyepetizer://homepage/selected?tabIndex=2&newTabIndex=-3" + } + } + + interface Toast { + + companion object { + + const val BIND_VIEWHOLDER_TYPE_WARN = "bindViewHolder Type Unprocessed" + } + } + + interface Url { + + companion object { + + const val AUTHOR_LOGIN = "http://open.eyepetizer.net/#!/login" + + const val AUTHOR_REGISTER = "http://open.eyepetizer.net/#!/register" + + const val FORGET_PASSWORD = "http://open.eyepetizer.net/#!/forget" + + const val USER_AGREEMENT = "http://www.eyepetizer.net/agreement.html" + + const val VIDEO_FUNCTION_STATEMENT = "http://www.eyepetizer.net/right.html" + + const val LEGAL_NOTICES = "http://www.kaiyanapp.com/legal_notices.html" + + const val AUTHOR_OPEN = "http://open.eyepetizer.net/#!/landing" + } + } + + interface Mobclick { + + companion object { + + const val EVENT1 = "10001" + + const val EVENT2 = "10002" + + const val EVENT3 = "10003" + + const val EVENT4 = "10004" + + const val EVENT5 = "10005" + + const val EVENT6 = "10006" + + const val EVENT7 = "10007" + + const val EVENT8 = "10008" + + const val EVENT9 = "10009" + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/EyepetizerApplication.kt b/app/src/main/java/com/eyepetizer/android/EyepetizerApplication.kt new file mode 100644 index 0000000..5fa121e --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/EyepetizerApplication.kt @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android + +import android.app.Application +import android.content.Context +import androidx.multidex.MultiDex +import androidx.work.WorkManager +import com.eyepetizer.android.extension.logD +import com.eyepetizer.android.extension.preCreateSession +import com.eyepetizer.android.ui.SplashActivity +import com.eyepetizer.android.ui.common.ui.WebViewActivity +import com.eyepetizer.android.ui.common.view.NoStatusFooter +import com.eyepetizer.android.util.DialogAppraiseTipsWorker +import com.google.gson.Gson +import com.scwang.smart.refresh.header.MaterialHeader +import com.scwang.smart.refresh.layout.SmartRefreshLayout +import com.shuyu.gsyvideoplayer.player.IjkPlayerManager +import com.umeng.commonsdk.UMConfigure +import tv.danmaku.ijk.media.player.IjkMediaPlayer + +/** + * Eyepetizer自定义Application,在这里进行全局的初始化操作。 + * + * @author vipyinzhiwei + * @since 2020/4/28 + */ +class EyepetizerApplication : Application() { + + init { + SmartRefreshLayout.setDefaultRefreshInitializer { context, layout -> + layout.setEnableLoadMore(true) + layout.setEnableLoadMoreWhenContentNotFull(true) + } + + SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout -> + layout.setEnableHeaderTranslationContent(true) + MaterialHeader(context).setColorSchemeResources(R.color.blue, R.color.blue, R.color.blue) + } + + SmartRefreshLayout.setDefaultRefreshFooterCreator { context, layout -> + layout.setEnableFooterFollowWhenNoMoreData(true) + layout.setEnableFooterTranslationContent(true) + layout.setFooterHeight(153f) + layout.setFooterTriggerRate(0.6f) + NoStatusFooter.REFRESH_FOOTER_NOTHING = "- The End -" + NoStatusFooter(context).apply { + setAccentColorId(R.color.colorTextPrimary) + setTextTitleSize(16f) + } + } + } + + override fun attachBaseContext(base: Context) { + super.attachBaseContext(base) + MultiDex.install(this) + } + + override fun onCreate() { + super.onCreate() + context = this + UMConfigure.init(this, null, null, UMConfigure.DEVICE_TYPE_PHONE, null) + UMConfigure.setLogEnabled(BuildConfig.DEBUG) + IjkPlayerManager.setLogLevel(if (BuildConfig.DEBUG) IjkMediaPlayer.IJK_LOG_WARN else IjkMediaPlayer.IJK_LOG_SILENT) + WebViewActivity.DEFAULT_URL.preCreateSession() + if (!SplashActivity.isFirstEntryApp && DialogAppraiseTipsWorker.isNeedShowDialog) { + WorkManager.getInstance(this).enqueue(DialogAppraiseTipsWorker.showDialogWorkRequest) + } + } + + companion object { + lateinit var context: Context + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/event/MessageEvent.kt b/app/src/main/java/com/eyepetizer/android/event/MessageEvent.kt new file mode 100644 index 0000000..51521bf --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/event/MessageEvent.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.event + +/** + * EventBus所有消息的基类。 + * + * @author vipyinzhiwei + * @since 2020/4/29 + */ +open class MessageEvent diff --git a/app/src/main/java/com/eyepetizer/android/event/RefreshEvent.kt b/app/src/main/java/com/eyepetizer/android/event/RefreshEvent.kt new file mode 100644 index 0000000..76e4437 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/event/RefreshEvent.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.event + +/** + * EventBus通知刷新界面消息。 + * + * @author vipyinzhiwei + * @since 2020/5/19 + */ +open class RefreshEvent(var activityClass: Class<*>? = null) : MessageEvent() \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/event/SwitchPagesEvent.kt b/app/src/main/java/com/eyepetizer/android/event/SwitchPagesEvent.kt new file mode 100644 index 0000000..590068b --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/event/SwitchPagesEvent.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.event + +/** + * EventBus通知Tab页切换界面。 + * + * @author vipyinzhiwei + * @since 2020/5/19 + */ +open class SwitchPagesEvent(var activityClass: Class<*>? = null) : MessageEvent() \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/extension/CharSequence.kt b/app/src/main/java/com/eyepetizer/android/extension/CharSequence.kt new file mode 100644 index 0000000..7c55fc3 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/CharSequence.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.widget.Toast +import com.eyepetizer.android.EyepetizerApplication +import com.eyepetizer.android.ui.common.ui.vassonic.SonicRuntimeImpl +import com.tencent.sonic.sdk.SonicConfig +import com.tencent.sonic.sdk.SonicEngine +import com.tencent.sonic.sdk.SonicSessionConfig + +/** + * 弹出Toast提示。 + * + * @param duration 显示消息的时间 Either {@link #LENGTH_SHORT} or {@link #LENGTH_LONG} + */ +fun CharSequence.showToast(duration: Int = Toast.LENGTH_SHORT) { + Toast.makeText(EyepetizerApplication.context, this, duration).show() +} + +/** + * VasSonic预加载session。 + * + * @param CharSequence 预加载url + */ +fun CharSequence.preCreateSession(): Boolean { + if (!SonicEngine.isGetInstanceAllowed()) { + SonicEngine.createInstance(SonicRuntimeImpl(EyepetizerApplication.context), SonicConfig.Builder().build()) + } + val sessionConfigBuilder = SonicSessionConfig.Builder().apply { setSupportLocalServer(true) } + val preloadSuccess = SonicEngine.getInstance().preCreateSession(this.toString(), sessionConfigBuilder.build()) + logD("preCreateSession()", "${this}\t:${if (preloadSuccess) "Preload start up success!" else "Preload start up fail!"}") + return preloadSuccess +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/extension/Density.kt b/app/src/main/java/com/eyepetizer/android/extension/Density.kt new file mode 100644 index 0000000..53aedf4 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/Density.kt @@ -0,0 +1,58 @@ +/* + * Copyright (C) guolin, Suzhou Quxiang Inc. Open source codes for study only. + * Do not use for commercial purpose. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import com.eyepetizer.android.EyepetizerApplication + + +/** + * 根据手机的分辨率将dp转成为px。 + */ +fun dp2px(dp: Float): Int { + val scale = EyepetizerApplication.context.resources.displayMetrics.density + return (dp * scale + 0.5f).toInt() +} + +/** + * 根据手机的分辨率将px转成dp。 + */ +fun px2dp(px: Float): Int { + val scale = EyepetizerApplication.context.resources.displayMetrics.density + return (px / scale + 0.5f).toInt() +} + +/** + * 获取屏幕宽值。 + */ +val screenWidth + get() = EyepetizerApplication.context.resources.displayMetrics.widthPixels + +/** + * 获取屏幕高值。 + */ +val screenHeight + get() = EyepetizerApplication.context.resources.displayMetrics.heightPixels + +/** + * 获取屏幕像素:对获取的宽高进行拼接。例:1080X2340。 + */ +fun screenPixel(): String { + EyepetizerApplication.context.resources.displayMetrics.run { + return "${widthPixels}X${heightPixels}" + } +} diff --git a/app/src/main/java/com/eyepetizer/android/extension/Global.kt b/app/src/main/java/com/eyepetizer/android/extension/Global.kt new file mode 100644 index 0000000..9142f36 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/Global.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.app.Activity +import android.content.Context +import android.content.SharedPreferences +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import com.eyepetizer.android.EyepetizerApplication +import com.eyepetizer.android.ui.common.ui.ShareDialogFragment +import com.eyepetizer.android.util.GlobalUtil +import com.eyepetizer.android.util.ShareUtil + +/** + * 获取SharedPreferences实例。 + */ +val sharedPreferences: SharedPreferences = EyepetizerApplication.context.getSharedPreferences(GlobalUtil.appPackage + "_preferences", Context.MODE_PRIVATE) + +/** + * 批量设置控件点击事件。 + * + * @param v 点击的控件 + * @param block 处理点击事件回调代码块 + */ +fun setOnClickListener(vararg v: View?, block: View.() -> Unit) { + val listener = View.OnClickListener { it.block() } + v.forEach { it?.setOnClickListener(listener) } +} + +/** + * 批量设置控件点击事件。 + * + * @param v 点击的控件 + * @param listener 处理点击事件监听器 + */ +fun setOnClickListener(vararg v: View?, listener: View.OnClickListener) { + v.forEach { it?.setOnClickListener(listener) } +} + +/** + * 调用系统原生分享。 + * + * @param activity 上下文 + * @param shareContent 分享内容 + * @param shareType SHARE_MORE=0,SHARE_QQ=1,SHARE_WECHAT=2,SHARE_WEIBO=3,SHARE_QQZONE=4 + */ +fun share(activity: Activity, shareContent: String, shareType: Int) { + ShareUtil.share(activity, shareContent, shareType) +} + +/** + * 弹出分享对话框。 + * + * @param activity 上下文 + * @param shareContent 分享内容 + */ +fun showDialogShare(activity: Activity, shareContent: String) { + if (activity is AppCompatActivity) { + ShareDialogFragment().showDialog(activity, shareContent) + } +} + + diff --git a/app/src/main/java/com/eyepetizer/android/extension/ImageView.kt b/app/src/main/java/com/eyepetizer/android/extension/ImageView.kt new file mode 100644 index 0000000..efa3318 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/ImageView.kt @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.widget.ImageView +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions +import com.eyepetizer.android.R +import jp.wasabeef.glide.transformations.RoundedCornersTransformation + +/** + * Glide加载图片,可以指定圆角弧度。 + * + * @param url 图片地址 + * @param round 圆角,单位dp + * @param cornerType 圆角角度 + */ +fun ImageView.load(url: String, round: Float = 0f, cornerType: RoundedCornersTransformation.CornerType = RoundedCornersTransformation.CornerType.ALL) { + if (round == 0f) { + Glide.with(this.context).load(url).into(this) + } else { + val option = RequestOptions.bitmapTransform(RoundedCornersTransformation(dp2px(round), 0, cornerType)).placeholder(R.drawable.shape_album_loading_bg) + Glide.with(this.context).load(url).apply(option).into(this) + } +} + +/** + * Glide加载图片,可以定义配置参数。 + * + * @param url 图片地址 + * @param options 配置参数 + */ +fun ImageView.load(url: String, options: RequestOptions.() -> RequestOptions) { + Glide.with(this.context).load(url).apply(RequestOptions().options()).into(this) +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/extension/Int.kt b/app/src/main/java/com/eyepetizer/android/extension/Int.kt new file mode 100644 index 0000000..3e275b1 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/Int.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import com.eyepetizer.android.EyepetizerApplication + +/** + * 弹出Toast提示。 + * + * @param duration 显示消息的时间 Either {@link #LENGTH_SHORT} or {@link #LENGTH_LONG} + */ +fun Int.showToast(duration: Int = Toast.LENGTH_SHORT) { + Toast.makeText(EyepetizerApplication.context, this, duration).show() +} + +/** + * 解析xml布局 + * + * @param parent 父布局 + * @param attachToRoot 是否依附到父布局 + */ +fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View { + return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot) +} + +/** + * 获取转换后的时间样式。 + * + * @return 处理后的时间样式,示例:06:50 + */ +fun Int.conversionVideoDuration(): String { + val minute = 1 * 60 + val hour = 60 * minute + val day = 24 * hour + + return when { + this < day -> { + String.format("%02d:%02d", this / minute, this % 60) + } + else -> { + String.format("%02d:%02d:%02d", this / hour, (this % hour) / minute, this % 60) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/extension/Log.kt b/app/src/main/java/com/eyepetizer/android/extension/Log.kt new file mode 100644 index 0000000..14c0afb --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/Log.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.util.Log +import com.eyepetizer.android.BuildConfig + +/** + * 日志调试工具类。 + * + * @author vipyinzhiwei + * @since 2020/4/29 + */ +private const val VERBOSE = 1 +private const val DEBUG = 2 +private const val INFO = 3 +private const val WARN = 4 +private const val ERROR = 5 + +private val level = if (BuildConfig.DEBUG) VERBOSE else WARN + +fun logV(tag: String, msg: String?) { + if (level <= VERBOSE) { + Log.v(tag, msg.toString()) + } +} + +fun logD(tag: String, msg: String?) { + if (level <= DEBUG) { + Log.d(tag, msg.toString()) + } +} + +fun logI(tag: String, msg: String?) { + if (level <= INFO) { + Log.i(tag, msg.toString()) + } +} + +fun logW(tag: String, msg: String?, tr: Throwable? = null) { + if (level <= WARN) { + if (tr == null) { + Log.w(tag, msg.toString()) + } else { + Log.w(tag, msg.toString(), tr) + } + } +} + +fun logE(tag: String, msg: String?, tr: Throwable) { + if (level <= ERROR) { + Log.e(tag, msg.toString(), tr) + } +} + diff --git a/app/src/main/java/com/eyepetizer/android/extension/SharedPreferences.kt b/app/src/main/java/com/eyepetizer/android/extension/SharedPreferences.kt new file mode 100644 index 0000000..bbf7a84 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/SharedPreferences.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.content.SharedPreferences + +/** + * 简化SharedPreferences调用。 + * + * @param action 拥有SharedPreferences.Editor对象上下文的回调代码块 + */ +fun SharedPreferences.edit(action: SharedPreferences.Editor.() -> Unit) { + val editor = edit() + action(editor) + editor.apply() +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/extension/TextView.kt b/app/src/main/java/com/eyepetizer/android/extension/TextView.kt new file mode 100644 index 0000000..35f7114 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/TextView.kt @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.graphics.drawable.Drawable +import android.widget.TextView + +/** + * 设置TextView图标 + * + * @param drawable 图标 + * @param iconWidth 图标宽dp:默认自动根据图标大小 + * @param iconHeight 图标高dp:默认自动根据图标大小 + * @param direction 图标方向,0左 1上 2右 3下 默认图标位于左侧0 + */ +fun TextView.setDrawable(drawable: Drawable?, iconWidth: Float? = null, iconHeight: Float? = null, direction: Int = 0) { + if (iconWidth != null && iconHeight != null) { + //第一个0是距左边距离,第二个0是距上边距离,iconWidth、iconHeight 分别是长宽 + drawable?.setBounds(0, 0, dp2px(iconWidth), dp2px(iconHeight)) + } + when (direction) { + 0 -> setCompoundDrawables(drawable, null, null, null) + 1 -> setCompoundDrawables(null, drawable, null, null) + 2 -> setCompoundDrawables(null, null, drawable, null) + 3 -> setCompoundDrawables(null, null, null, drawable) + else -> throw NoSuchMethodError() + } +} + +/** + * 设置TextView图标 + * + * @param lDrawable 左边图标 + * @param rDrawable 右边图标 + * @param lIconWidth 图标宽dp:默认自动根据图标大小 + * @param lIconHeight 图标高dp:默认自动根据图标大小 + * @param rIconWidth 图标宽dp:默认自动根据图标大小 + * @param rIconHeight 图标高dp:默认自动根据图标大小 + */ +fun TextView.setDrawables(lDrawable: Drawable?, rDrawable: Drawable?, lIconWidth: Float? = null, lIconHeight: Float? = null, rIconWidth: Float? = null, rIconHeight: Float? = null) { + if (lIconWidth != null && lIconHeight != null) { + lDrawable?.setBounds(0, 0, dp2px(lIconWidth), dp2px(lIconHeight)) + } + if (rIconWidth != null && rIconHeight != null) { + rDrawable?.setBounds(0, 0, dp2px(rIconWidth), dp2px(rIconHeight)) + } + setCompoundDrawables(lDrawable, null, rDrawable, null) +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/extension/View.kt b/app/src/main/java/com/eyepetizer/android/extension/View.kt new file mode 100644 index 0000000..0bc2a73 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/extension/View.kt @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.extension + +import android.view.View +import android.view.animation.AlphaAnimation + +/** + * 显示view + */ +fun View?.visible() { + this?.visibility = View.VISIBLE +} + +/** + * 显示view,带有渐显动画效果。 + * + * @param duration 毫秒,动画持续时长,默认500毫秒。 + */ +fun View?.visibleAlphaAnimation(duration: Long = 500L) { + this?.visibility = View.VISIBLE + this?.startAnimation(AlphaAnimation(0f, 1f).apply { + this.duration = duration + fillAfter = true + }) +} + +/** + * 隐藏view + */ +fun View?.gone() { + this?.visibility = View.GONE +} + +/** + * 隐藏view,带有渐隐动画效果。 + * + * @param duration 毫秒,动画持续时长,默认500毫秒。 + */ +fun View?.goneAlphaAnimation(duration: Long = 500L) { + this?.visibility = View.GONE + this?.startAnimation(AlphaAnimation(1f, 0f).apply { + this.duration = duration + fillAfter = true + }) +} + +/** + * 占位隐藏view + */ +fun View?.invisible() { + this?.visibility = View.INVISIBLE +} + +/** + * 占位隐藏view,带有渐隐动画效果。 + * + * @param duration 毫秒,动画持续时长,默认500毫秒。 + */ +fun View?.invisibleAlphaAnimation(duration: Long = 500L) { + this?.visibility = View.INVISIBLE + this?.startAnimation(AlphaAnimation(1f, 0f).apply { + this.duration = duration + fillAfter = true + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/MainPageRepository.kt b/app/src/main/java/com/eyepetizer/android/logic/MainPageRepository.kt new file mode 100644 index 0000000..14af7d2 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/MainPageRepository.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic + +import com.eyepetizer.android.logic.dao.MainPageDao +import com.eyepetizer.android.logic.network.EyepetizerNetwork +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +/** + * 主页界面,主要包含:(首页,社区,通知,我的),对应的仓库数据管理。 + * + * @author vipyinzhiwei + * @since 2020/5/2 + */ +class MainPageRepository private constructor(private val mainPageDao: MainPageDao, private val eyepetizerNetwork: EyepetizerNetwork) { + + suspend fun refreshDiscovery(url: String) = requestDiscovery(url) + + suspend fun refreshHomePageRecommend(url: String) = requestHomePageRecommend(url) + + suspend fun refreshDaily(url: String) = requestDaily(url) + + suspend fun refreshCommunityRecommend(url: String) = requestCommunityRecommend(url) + + suspend fun refreshFollow(url: String) = requestFollow(url) + + suspend fun refreshPushMessage(url: String) = requestPushMessage(url) + + suspend fun refreshHotSearch() = requestHotSearch() + + private suspend fun requestDiscovery(url: String) = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchDiscovery(url) + mainPageDao.cacheDiscovery(response) + response + } + + private suspend fun requestHomePageRecommend(url: String) = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchHomePageRecommend(url) + mainPageDao.cacheHomePageRecommend(response) + response + } + + private suspend fun requestDaily(url: String) = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchDaily(url) + mainPageDao.cacheDaily(response) + response + } + + private suspend fun requestCommunityRecommend(url: String) = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchCommunityRecommend(url) + mainPageDao.cacheCommunityRecommend(response) + response + } + + private suspend fun requestFollow(url: String) = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchFollow(url) + mainPageDao.cacheFollow(response) + response + } + + private suspend fun requestPushMessage(url: String) = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchPushMessage(url) + mainPageDao.cachePushMessageInfo(response) + response + } + + private suspend fun requestHotSearch() = withContext(Dispatchers.IO) { + val response = eyepetizerNetwork.fetchHotSearch() + mainPageDao.cacheHotSearch(response) + response + } + + companion object { + + private var repository: MainPageRepository? = null + + fun getInstance(dao: MainPageDao, network: EyepetizerNetwork): MainPageRepository { + if (repository == null) { + synchronized(MainPageRepository::class.java) { + if (repository == null) { + repository = MainPageRepository(dao, network) + } + } + } + + return repository!! + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/VideoRepository.kt b/app/src/main/java/com/eyepetizer/android/logic/VideoRepository.kt new file mode 100644 index 0000000..9491a00 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/VideoRepository.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic + +import com.eyepetizer.android.logic.dao.VideoDao +import com.eyepetizer.android.logic.model.VideoDetail +import com.eyepetizer.android.logic.network.EyepetizerNetwork +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.withContext + +/** + * 视频相关,对应的仓库数据管理。 + * + * @author vipyinzhiwei + * @since 2020/5/15 + */ +class VideoRepository(private val dao: VideoDao, private val network: EyepetizerNetwork) { + + suspend fun refreshVideoReplies(repliesUrl: String) = requestVideoReplies(repliesUrl) + + suspend fun refreshVideoRelatedAndVideoReplies(videoId: Long, repliesUrl: String) = requestVideoRelatedAndVideoReplies(videoId, repliesUrl) + + suspend fun refreshVideoDetail(videoId: Long, repliesUrl: String) = requestVideoDetail(videoId, repliesUrl) + + private suspend fun requestVideoReplies(url: String) = withContext(Dispatchers.IO) { + coroutineScope { + val deferredVideoReplies = async { network.fetchVideoReplies(url) } + val videoReplies = deferredVideoReplies.await() + videoReplies + } + } + + private suspend fun requestVideoRelatedAndVideoReplies(videoId: Long, repliesUrl: String) = withContext(Dispatchers.IO) { + coroutineScope { + val deferredVideoRelated = async { network.fetchVideoRelated(videoId) } + val deferredVideoReplies = async { network.fetchVideoReplies(repliesUrl) } + val videoRelated = deferredVideoRelated.await() + val videoReplies = deferredVideoReplies.await() + val videoDetail = VideoDetail(null, videoRelated, videoReplies) + videoDetail + } + } + + private suspend fun requestVideoDetail(videoId: Long, repliesUrl: String) = withContext(Dispatchers.IO) { + coroutineScope { + val deferredVideoRelated = async { network.fetchVideoRelated(videoId) } + val deferredVideoReplies = async { network.fetchVideoReplies(repliesUrl) } + val deferredVideoBeanForClient = async { network.fetchVideoBeanForClient(videoId) } + val videoBeanForClient = deferredVideoBeanForClient.await() + val videoRelated = deferredVideoRelated.await() + val videoReplies = deferredVideoReplies.await() + val videoDetail = VideoDetail(videoBeanForClient, videoRelated, videoReplies) + + if (videoDetail.videoBeanForClient != null && videoDetail.videoRelated?.count ?: 0 > 0 && videoDetail.videoReplies.count > 0) { + dao.cacheVideoDetail(videoDetail) + } + videoDetail + } + } + + companion object { + + private var repository: VideoRepository? = null + + fun getInstance(dao: VideoDao, network: EyepetizerNetwork): VideoRepository { + if (repository == null) { + synchronized(VideoRepository::class.java) { + if (repository == null) { + repository = VideoRepository(dao, network) + } + } + } + + return repository!! + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/dao/EyepetizerDatabase.kt b/app/src/main/java/com/eyepetizer/android/logic/dao/EyepetizerDatabase.kt new file mode 100644 index 0000000..fd7efc2 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/dao/EyepetizerDatabase.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic.dao + +/** + * 应用程序所有Dao操作管理类。 + * + * @author vipyinzhiwei + * @since 2020/5/2 + */ +object EyepetizerDatabase { + + private var mainPageDao: MainPageDao? = null + + private var videoDao: VideoDao? = null + + fun getMainPageDao(): MainPageDao { + if (mainPageDao == null) { + mainPageDao = MainPageDao() + } + return mainPageDao!! + } + + fun getVideoDao(): VideoDao { + if (videoDao == null) { + videoDao = VideoDao() + } + return videoDao!! + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/dao/MainPageDao.kt b/app/src/main/java/com/eyepetizer/android/logic/dao/MainPageDao.kt new file mode 100644 index 0000000..190b792 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/dao/MainPageDao.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic.dao + +import com.eyepetizer.android.logic.model.* + +/** + * 主页界面(主要包含:首页,社区,通知,我的),对应的Dao操作类。 + * + * @author vipyinzhiwei + * @since 2020/5/15 + */ +class MainPageDao { + + /*----------------------------首页相关----------------------------*/ + + fun cacheDiscovery(bean: Discovery?) { + //TODO("存储数据到本地") + } + + fun getCachedDiscovery(): Discovery? { + TODO("获取本地存储的数据") + } + + fun cacheHomePageRecommend(bean: HomePageRecommend?) { + //TODO("存储数据到本地") + } + + fun getCachedHomePageRecommend(): HomePageRecommend? { + TODO("获取本地存储的数据") + } + + fun cacheDaily(bean: Daily?) { + //TODO("存储数据到本地") + } + + fun getCachedDaily(): Daily? { + TODO("获取本地存储的数据") + } + + /*----------------------------社区相关----------------------------*/ + + fun cacheCommunityRecommend(bean: CommunityRecommend?) { + //TODO("存储数据到本地") + } + + fun getCachedCommunityRecommend(): CommunityRecommend? { + TODO("获取本地存储的数据") + } + + fun cacheFollow(bean: Follow?) { + //TODO("存储数据到本地") + } + + fun getCachedFollow(): Follow? { + TODO("获取本地存储的数据") + } + + /*----------------------------通知相关----------------------------*/ + + fun cachePushMessageInfo(bean: PushMessage?) { + //TODO("存储数据到本地") + } + + fun getCachedPushMessageInfo(): PushMessage? { + TODO("获取本地存储的数据") + } + + /*----------------------------搜索相关----------------------------*/ + + fun cacheHotSearch(bean: List?) { + //TODO("存储数据到本地") + } + + fun getHotSearch(): List? { + TODO("获取本地存储的数据") + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/dao/VideoDao.kt b/app/src/main/java/com/eyepetizer/android/logic/dao/VideoDao.kt new file mode 100644 index 0000000..01a2ea0 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/dao/VideoDao.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic.dao + +import com.eyepetizer.android.logic.model.VideoBeanForClient +import com.eyepetizer.android.logic.model.VideoDetail +import com.eyepetizer.android.logic.model.VideoRelated +import com.eyepetizer.android.logic.model.VideoReplies + +/** + * 视频相关,对应的Dao操作类。 + * + * @author vipyinzhiwei + * @since 2020/5/15 + */ +class VideoDao { + + fun cacheVideoDetail(bean: VideoDetail?) { + //TODO("存储数据到本地") + } + + fun getCachedVideoDetail(): VideoDetail? { + TODO("获取本地存储的数据") + } + + fun cacheVideoBeanForClient(bean: VideoBeanForClient?) { + //TODO("存储数据到本地") + } + + fun getCachedVideoBeanForClient(): VideoBeanForClient? { + TODO("获取本地存储的数据") + } + + fun cacheVideoRelated(bean: VideoRelated?) { + //TODO("存储数据到本地") + } + + fun getCachedVideoRelated(): VideoRelated? { + TODO("获取本地存储的数据") + } + + fun cacheVideoReplies(bean: VideoReplies?) { + //TODO("存储数据到本地") + } + + fun getCachedVideoReplies(): VideoReplies? { + TODO("获取本地存储的数据") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/model/CommunityRecommend.kt b/app/src/main/java/com/eyepetizer/android/logic/model/CommunityRecommend.kt new file mode 100644 index 0000000..82bfc7f --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/model/CommunityRecommend.kt @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic.model + +/** + * 社区-推荐列表,响应实体类。 + * + * @author vipyinzhiwei + * @since 2020/5/6 + */ +data class CommunityRecommend(val itemList: List, val count: Int, val total: Int, val nextPageUrl: String?, val adExist: Boolean) : Model() { + + data class Item(val `data`: Data, val type: String, val tag: Any?, val id: Int = 0, val adIndex: Int) + + data class Data(val adTrack: Any, val content: Content, val count: Int, val dataType: String, val footer: Any, val header: Header?, val itemList: List) + + data class Header( + val actionUrl: String, + val followType: String, + val icon: String, + val iconType: String, + val id: Int, + val issuerName: String, + val labelList: Any, + val showHateVideo: Boolean, + val tagId: Int, + val tagName: Any, + val time: Long, + val topShow: Boolean + ) + + data class Content(val adIndex: Int, val `data`: DataX, val id: Int, val tag: Any, val type: String) + + data class ItemX(val `data`: DataXX, val type: String, val tag: Any?, val id: Int = 0, val adIndex: Int) + + data class DataX( + val addWatermark: Boolean, + val area: String, + val checkStatus: String, + val city: String, + val collected: Boolean, + val consumption: Consumption, + val cover: Cover, + val createTime: Long, + val dataType: String, + val description: String, + val duration: Int, + val height: Int, + val id: Long, + val ifMock: Boolean, + val latitude: Double, + val library: String, + val longitude: Double, + val owner: Owner, + val playUrl: String, + val playUrlWatermark: String, + val privateMessageActionUrl: String, + val reallyCollected: Boolean, + val recentOnceReply: RecentOnceReply, + val releaseTime: Long, + val resourceType: String, + val selectedTime: Long, + val status: Any, + val tags: List?, + val title: String, + val transId: Any, + val type: String, + val uid: Int, + val updateTime: Long, + val url: String, + val urls: List?, + val urlsWithWatermark: List, + val validateResult: String, + val validateStatus: String, + val validateTaskId: String, + val width: Int + ) + + data class Owner( + val actionUrl: String, + val area: Any, + val avatar: String, + val birthday: Long, + val city: String, + val country: String, + val cover: String, + val description: String, + val expert: Boolean, + val followed: Boolean, + val gender: String, + val ifPgc: Boolean, + val job: String, + val library: String, + val limitVideoOpen: Boolean, + val nickname: String, + val registDate: Long, + val releaseDate: Long, + val uid: Int, + val university: String, + val userType: String + ) + + data class RecentOnceReply( + val actionUrl: String, + val contentType: Any, + val dataType: String, + val message: String, + val nickname: String + ) + + data class DataXX( + val actionUrl: String?, + val adTrack: List, + val autoPlay: Boolean, + val bgPicture: String, + val dataType: String, + val description: String, + val header: HeaderX?, + val id: Int, + val image: String, + val label: Label?, + val labelList: List, + val shade: Boolean, + val subTitle: String, + val title: String + ) + + data class HeaderX( + val actionUrl: Any, + val cover: Any, + val description: Any, + val font: Any, + val icon: Any, + val id: Int, + val label: Any, + val labelList: Any, + val rightText: Any, + val subTitle: Any, + val subTitleFont: Any, + val textAlign: String, + val title: Any + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/eyepetizer/android/logic/model/Daily.kt b/app/src/main/java/com/eyepetizer/android/logic/model/Daily.kt new file mode 100644 index 0000000..7920234 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/model/Daily.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic.model + +/** + * 首页-日报列表,响应实体类。 + * + * @author vipyinzhiwei + * @since 2020/5/9 + */ +data class Daily(val itemList: List, val count: Int, val total: Int, val nextPageUrl: String?, val adExist: Boolean) : Model() { + + data class Item(val `data`: Data, val type: String, val tag: Any?, val id: Int = 0, val adIndex: Int) + + data class Data( + val actionUrl: String?, + val adTrack: Any, + val backgroundImage: String, + val content: Content, + val dataType: String, + val follow: Author.Follow?, + val header: Header, + val id: Int, + val rightText: String, + val subTitle: Any, + val text: String, + val titleList: List, + val type: String, + val image: String, + val label: Label? + ) + + data class Header( + val actionUrl: String?, + val cover: Any, + val description: String, + val font: Any, + val icon: String, + val iconType: String, + val id: Int, + val label: Any, + val labelList: Any, + val rightText: Any, + val showHateVideo: Boolean, + val subTitle: Any, + val subTitleFont: Any, + val textAlign: String, + val time: Long, + val title: String + ) +} diff --git a/app/src/main/java/com/eyepetizer/android/logic/model/Discovery.kt b/app/src/main/java/com/eyepetizer/android/logic/model/Discovery.kt new file mode 100644 index 0000000..6c10418 --- /dev/null +++ b/app/src/main/java/com/eyepetizer/android/logic/model/Discovery.kt @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2020. vipyinzhiwei + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.eyepetizer.android.logic.model + +/** + * 首页-发现列表,响应实体类。 + * + * @author vipyinzhiwei + * @since 2020/5/9 + */ +data class Discovery(val itemList: List, val count: Int, val total: Int, val nextPageUrl: String?, val adExist: Boolean) : Model() { + + data class Item(val `data`: Data, val type: String, val tag: Any?, val id: Int = 0, val adIndex: Int) + + data class Data( + val actionUrl: String?, + val ad: Boolean, + val adTrack: Any, + val author: Author, + val content: Content, + val autoPlay: Boolean, + val brandWebsiteInfo: Any, + val campaign: Any, + val category: String, + val collected: Boolean, + val consumption: Consumption, + val count: Int, + val cover: Cover, + val dataType: String, + val date: Long, + val description: String, + val descriptionEditor: String, + val descriptionPgc: Any, + val duration: Int, + val expert: Boolean, + val favoriteAdTrack: Any, + val follow: Author.Follow?, + val footer: Any, + val haveReward: Boolean, + val header: Header, + val icon: String, + val iconType: String, + val id: Long, + val idx: Int, + val ifLimitVideo: Boolean, + val ifNewest: Boolean, + val ifPgc: Boolean, + val ifShowNotificationIcon: Boolean, + val image: String, + val itemList: List, + val label: Label?, + val labelList: List