├── settings.gradle ├── app ├── .gitignore ├── src │ ├── main │ │ ├── ic_launcher-web.png │ │ ├── res │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── logo.png │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── news_host_bg.png │ │ │ │ ├── sign_github.png │ │ │ │ ├── sign_weibo.png │ │ │ │ ├── user_divider.png │ │ │ │ ├── avatar_plusend.png │ │ │ │ ├── logo_actionbar.png │ │ │ │ └── ic_avatar_error.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── logo.png │ │ │ │ ├── ic_launcher.png │ │ │ │ ├── sign_github.png │ │ │ │ ├── sign_weibo.png │ │ │ │ └── logo_actionbar.png │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values │ │ │ │ ├── ids.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── xml │ │ │ │ ├── searchable.xml │ │ │ │ ├── provider_paths.xml │ │ │ │ └── preferences.xml │ │ │ ├── drawable │ │ │ │ ├── sign.xml │ │ │ │ ├── sign_divider.xml │ │ │ │ ├── item_divider_horizontal.xml │ │ │ │ ├── item_divider_vertical.xml │ │ │ │ ├── side_nav_bar.xml │ │ │ │ ├── ic_menu_add.xml │ │ │ │ ├── ic_menu_about.xml │ │ │ │ ├── ic_menu_send.xml │ │ │ │ ├── ic_menu_back.xml │ │ │ │ ├── ic_favorite.xml │ │ │ │ ├── topic_top_bg.xml │ │ │ │ ├── ic_menu_collect.xml │ │ │ │ ├── ic_reply.xml │ │ │ │ ├── ic_menu_close.xml │ │ │ │ ├── bg_list_view_item.xml │ │ │ │ ├── ic_favorite_not.xml │ │ │ │ ├── ic_menu_reply.xml │ │ │ │ ├── ic_menu_comment.xml │ │ │ │ ├── ic_menu_notifications.xml │ │ │ │ ├── ic_follow.xml │ │ │ │ ├── ic_like.xml │ │ │ │ ├── ic_menu_search.xml │ │ │ │ ├── ic_menu_post.xml │ │ │ │ ├── about_page_card.xml │ │ │ │ ├── ic_like_not.xml │ │ │ │ ├── about_page_button_dark.xml │ │ │ │ ├── about_page_button_light.xml │ │ │ │ ├── ic_menu_share.xml │ │ │ │ ├── ic_follow_not.xml │ │ │ │ └── ic_menu_settings.xml │ │ │ ├── menu │ │ │ │ ├── activity_create_news.xml │ │ │ │ ├── activity_create_topic.xml │ │ │ │ ├── activity_create_topic_reply.xml │ │ │ │ ├── activity_search.xml │ │ │ │ ├── activity_web.xml │ │ │ │ ├── main.xml │ │ │ │ └── activity_main_drawer.xml │ │ │ ├── layout │ │ │ │ ├── toolbar.xml │ │ │ │ ├── about_page_item_category.xml │ │ │ │ ├── item_notification_else.xml │ │ │ │ ├── item_site_name.xml │ │ │ │ ├── preference_category_widget.xml │ │ │ │ ├── activity_settings.xml │ │ │ │ ├── fragment_news.xml │ │ │ │ ├── fragment_site.xml │ │ │ │ ├── item_topic_reply_load_more.xml │ │ │ │ ├── fragment_topic.xml │ │ │ │ ├── item_topic_footer.xml │ │ │ │ ├── content_main.xml │ │ │ │ ├── item_sites_name.xml │ │ │ │ ├── activity_web.xml │ │ │ │ ├── activity_my_topics.xml │ │ │ │ ├── about_page_item_card.xml │ │ │ │ ├── about_page_item_license.xml │ │ │ │ ├── nav_header_main.xml │ │ │ │ ├── item_notification_reply.xml │ │ │ │ ├── activity_image.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── item_notification_mention.xml │ │ │ │ ├── item_notification_follow.xml │ │ │ │ ├── item_reply.xml │ │ │ │ ├── activity_search.xml │ │ │ │ ├── activity_notification.xml │ │ │ │ ├── activity_my_replies.xml │ │ │ │ ├── about_page_item_contributor.xml │ │ │ │ ├── preference_item.xml │ │ │ │ ├── activity_create_topic_reply.xml │ │ │ │ ├── app_bar_main.xml │ │ │ │ ├── activity_topic.xml │ │ │ │ └── item_topic.xml │ │ │ └── color │ │ │ │ └── item_color.xml │ │ └── java │ │ │ └── com │ │ │ └── plusend │ │ │ └── diycode │ │ │ ├── model │ │ │ ├── base │ │ │ │ ├── BaseData.java │ │ │ │ ├── BaseView.java │ │ │ │ └── BasePresenter.java │ │ │ ├── topic │ │ │ │ ├── event │ │ │ │ │ ├── SignInEvent.java │ │ │ │ │ ├── LoadTopicDetailFinishEvent.java │ │ │ │ │ ├── UnLikeEvent.java │ │ │ │ │ ├── LikeEvent.java │ │ │ │ │ ├── FollowEvent.java │ │ │ │ │ ├── FavoriteEvent.java │ │ │ │ │ ├── UnFollowEvent.java │ │ │ │ │ ├── UnFavoriteEvent.java │ │ │ │ │ ├── CreateTopicReplyEvent.java │ │ │ │ │ ├── TopicsEvent.java │ │ │ │ │ ├── CreateTopicEvent.java │ │ │ │ │ ├── RepliesEvent.java │ │ │ │ │ ├── TopicDetailEvent.java │ │ │ │ │ ├── TopTopicsEvent.java │ │ │ │ │ └── TopicRepliesEvent.java │ │ │ │ ├── node │ │ │ │ │ ├── data │ │ │ │ │ │ ├── NodeData.java │ │ │ │ │ │ ├── NodeService.java │ │ │ │ │ │ └── NodeDataNetwork.java │ │ │ │ │ ├── view │ │ │ │ │ │ └── NodesView.java │ │ │ │ │ ├── event │ │ │ │ │ │ └── NodesEvent.java │ │ │ │ │ ├── presenter │ │ │ │ │ │ └── NodesBasePresenter.java │ │ │ │ │ └── entity │ │ │ │ │ │ └── Node.java │ │ │ │ ├── view │ │ │ │ │ ├── CreateTopicView.java │ │ │ │ │ ├── CreateTopicReplyView.java │ │ │ │ │ ├── UserRepliesView.java │ │ │ │ │ ├── TopicsView.java │ │ │ │ │ ├── TopicRepliesView.java │ │ │ │ │ └── TopicView.java │ │ │ │ ├── entity │ │ │ │ │ ├── UnFollowTopic.java │ │ │ │ │ ├── UnFavoriteTopic.java │ │ │ │ │ ├── FollowTopic.java │ │ │ │ │ ├── FavoriteTopic.java │ │ │ │ │ └── Like.java │ │ │ │ ├── presenter │ │ │ │ │ ├── CreateTopicPresenter.java │ │ │ │ │ ├── UserRepliesPresenter.java │ │ │ │ │ ├── CreateTopicReplyPresenter.java │ │ │ │ │ └── TopicsPresenter.java │ │ │ │ └── data │ │ │ │ │ └── TopicData.java │ │ │ ├── notification │ │ │ │ ├── entity │ │ │ │ │ ├── NotificationDelete.java │ │ │ │ │ ├── NotificationsRead.java │ │ │ │ │ ├── NotificationsDelete.java │ │ │ │ │ └── NotificationsUnreadCount.java │ │ │ │ ├── view │ │ │ │ │ └── NotificationsView.java │ │ │ │ ├── event │ │ │ │ │ ├── NotificationsEvent.java │ │ │ │ │ ├── NotificationDeleteEvent.java │ │ │ │ │ └── NotificationsUnreadCountEvent.java │ │ │ │ ├── data │ │ │ │ │ ├── NotificationData.java │ │ │ │ │ └── NotificationService.java │ │ │ │ └── presenter │ │ │ │ │ └── NotificationsBasePresenter.java │ │ │ ├── site │ │ │ │ ├── data │ │ │ │ │ ├── SiteData.java │ │ │ │ │ ├── SiteService.java │ │ │ │ │ └── SiteDataNetwork.java │ │ │ │ ├── view │ │ │ │ │ └── SiteView.java │ │ │ │ ├── event │ │ │ │ │ └── SiteEvent.java │ │ │ │ ├── presenter │ │ │ │ │ └── SiteBasePresenter.java │ │ │ │ └── entity │ │ │ │ │ └── Site.java │ │ │ ├── news │ │ │ │ ├── view │ │ │ │ │ ├── CreateNewsView.java │ │ │ │ │ └── NewsView.java │ │ │ │ ├── node │ │ │ │ │ ├── data │ │ │ │ │ │ ├── NewsNodeData.java │ │ │ │ │ │ ├── NewsNodeService.java │ │ │ │ │ │ └── NewsNodeDataNetwork.java │ │ │ │ │ ├── view │ │ │ │ │ │ └── NewsNodesView.java │ │ │ │ │ ├── event │ │ │ │ │ │ └── NewsNodesEvent.java │ │ │ │ │ ├── entity │ │ │ │ │ │ └── NewsNode.java │ │ │ │ │ └── presenter │ │ │ │ │ │ └── NewsNodesBasePresenter.java │ │ │ │ ├── event │ │ │ │ │ ├── CreateNewsEvent.java │ │ │ │ │ └── NewsEvent.java │ │ │ │ ├── data │ │ │ │ │ ├── NewsData.java │ │ │ │ │ └── NewsService.java │ │ │ │ └── presenter │ │ │ │ │ ├── NewsBasePresenter.java │ │ │ │ │ └── CreateNewsBasePresenter.java │ │ │ └── user │ │ │ │ ├── view │ │ │ │ ├── FollowView.java │ │ │ │ ├── SignInView.java │ │ │ │ └── UserView.java │ │ │ │ ├── entity │ │ │ │ ├── UserBlock.java │ │ │ │ ├── UserFollow.java │ │ │ │ ├── UserUnBlock.java │ │ │ │ ├── UserUnFollow.java │ │ │ │ ├── UserInfo.java │ │ │ │ └── Token.java │ │ │ │ ├── event │ │ │ │ ├── RefreshTokenEvent.java │ │ │ │ ├── UserBlockEvent.java │ │ │ │ ├── TokenEvent.java │ │ │ │ ├── UserFollowEvent.java │ │ │ │ ├── UserUnBlockEvent.java │ │ │ │ ├── UserUnFollowEvent.java │ │ │ │ ├── UserFavoriteTopicsEvent.java │ │ │ │ ├── UserBlockedEvent.java │ │ │ │ ├── UserDetailInfoEvent.java │ │ │ │ ├── UserFollowersEvent.java │ │ │ │ ├── UserFollowingEvent.java │ │ │ │ ├── MeEvent.java │ │ │ │ └── UserTopicsEvent.java │ │ │ │ └── presenter │ │ │ │ ├── SignInPresenter.java │ │ │ │ ├── UserPresenter.java │ │ │ │ └── UserTopicsPresenter.java │ │ │ ├── view │ │ │ ├── widget │ │ │ │ ├── OnWebViewImageListener.java │ │ │ │ ├── DividerListItemDecoration.java │ │ │ │ └── EmptyRecyclerView.java │ │ │ ├── adapter │ │ │ │ ├── about │ │ │ │ │ ├── Card.java │ │ │ │ │ ├── Category.java │ │ │ │ │ ├── Contributor.java │ │ │ │ │ ├── License.java │ │ │ │ │ ├── CardViewProvider.java │ │ │ │ │ ├── CategoryViewProvider.java │ │ │ │ │ ├── LicenseViewProvider.java │ │ │ │ │ └── ContributorViewProvider.java │ │ │ │ ├── notification │ │ │ │ │ ├── NotificationElse.java │ │ │ │ │ ├── NotificationFollow.java │ │ │ │ │ ├── NotificationReply.java │ │ │ │ │ ├── NotificationMention.java │ │ │ │ │ └── NotificationElseViewProvider.java │ │ │ │ ├── topic │ │ │ │ │ ├── Footer.java │ │ │ │ │ ├── TopicReplyWithTopic.java │ │ │ │ │ └── FooterViewProvider.java │ │ │ │ ├── site │ │ │ │ │ ├── SiteName.java │ │ │ │ │ ├── SitesName.java │ │ │ │ │ └── SiteNameViewProvider.java │ │ │ │ └── main │ │ │ │ │ └── MainPagerAdapter.java │ │ │ ├── activity │ │ │ │ ├── SignUpActivity.java │ │ │ │ ├── SettingsActivity.java │ │ │ │ └── SearchActivity.java │ │ │ └── fragment │ │ │ │ └── BaseFragment.java │ │ │ ├── util │ │ │ ├── SpanClickListener.java │ │ │ ├── ToastUtil.java │ │ │ ├── IntentUtil.java │ │ │ ├── HtmlUtil.java │ │ │ ├── PackageUtil.java │ │ │ ├── AppOperator.java │ │ │ ├── UrlUtil.java │ │ │ ├── Constant.java │ │ │ ├── UrlDrawable.java │ │ │ └── TimeUtil.java │ │ │ └── app │ │ │ └── DiyCodeApplication.java │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── plusend │ │ │ └── diycode │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── plusend │ │ └── diycode │ │ └── ExampleInstrumentedTest.java ├── release │ └── output.json └── build.gradle ├── screenshot ├── Diycode.jpg └── ic_launcher.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── .gitignore └── README.md /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | gradle.properties -------------------------------------------------------------------------------- /screenshot/Diycode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/screenshot/Diycode.jpg -------------------------------------------------------------------------------- /screenshot/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/screenshot/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xxhdpi/logo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/news_host_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/news_host_bg.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/sign_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/sign_github.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/sign_weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/sign_weibo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/user_divider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/user_divider.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/sign_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xxhdpi/sign_github.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/sign_weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xxhdpi/sign_weibo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/avatar_plusend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/avatar_plusend.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/logo_actionbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/logo_actionbar.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/base/BaseData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.base; 2 | 3 | public interface BaseData { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_avatar_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xhdpi/ic_avatar_error.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/logo_actionbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plusend/DiyCode/HEAD/app/src/main/res/mipmap-xxhdpi/logo_actionbar.png -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/SignInEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | public class SignInEvent { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/LoadTopicDetailFinishEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | public class LoadTopicDetailFinishEvent { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/base/BaseView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.base; 2 | 3 | import android.content.Context; 4 | 5 | public interface BaseView { 6 | Context getContext(); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/xml/searchable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/base/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.base; 2 | 3 | public abstract class BasePresenter { 4 | public abstract void start(); 5 | 6 | public abstract void stop(); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sign.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/sign_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_divider_horizontal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_divider_vertical.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/entity/NotificationDelete.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.entity; 2 | 3 | /** 4 | * Created by plusend on 2016/12/13. 5 | */ 6 | 7 | public class NotificationDelete { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/entity/NotificationsRead.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.entity; 2 | 3 | /** 4 | * Created by plusend on 2016/12/13. 5 | */ 6 | 7 | public class NotificationsRead { 8 | } 9 | -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":18,"versionName":"0.4.8","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/entity/NotificationsDelete.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.entity; 2 | 3 | /** 4 | * Created by plusend on 2016/12/13. 5 | */ 6 | 7 | public class NotificationsDelete { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/xml/provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Jun 25 17:34:56 CST 2018 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-4.4-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/widget/OnWebViewImageListener.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.widget; 2 | 3 | public interface OnWebViewImageListener { 4 | 5 | /** 6 | * 点击webview上的图片,传入该缩略图的大图Url 7 | */ 8 | void showImagePreview(String bigImageUrl); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/data/SiteData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.data; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | 5 | public interface SiteData extends BaseData { 6 | 7 | /** 8 | * 获取酷站信息 9 | */ 10 | void getSite(); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/SpanClickListener.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | /** 4 | * 说明:html 中图片被点击后的回调 5 | * 用于自定义图片点击事件 6 | * 7 | * @author chenyou 8 | * @date 2016/04/05 9 | */ 10 | public interface SpanClickListener { 11 | void onClick(int type, String url); 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/data/NodeData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.data; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | 5 | public interface NodeData extends BaseData { 6 | 7 | /** 8 | * 获取节点列表 9 | */ 10 | void readNodes(); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/view/CreateNewsView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.news.entity.News; 5 | 6 | public interface CreateNewsView extends BaseView { 7 | void showNews(News news); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/data/NewsNodeData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.data; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | 5 | public interface NewsNodeData extends BaseData { 6 | 7 | /** 8 | * 获取节点列表 9 | */ 10 | void readNewsNodes(); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/view/CreateTopicView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.topic.entity.TopicDetail; 5 | 6 | public interface CreateTopicView extends BaseView { 7 | void getNewTopic(TopicDetail topicDetail); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/Card.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | public class Card { 6 | 7 | @NonNull public final String content; 8 | 9 | public Card(@NonNull String content) { 10 | this.content = content; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/view/CreateTopicReplyView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | 5 | /** 6 | * Created by plusend on 2016/12/1. 7 | */ 8 | 9 | public interface CreateTopicReplyView extends BaseView { 10 | void getResult(boolean isSuccessful); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/view/UserRepliesView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.topic.entity.Reply; 5 | import java.util.List; 6 | 7 | public interface UserRepliesView extends BaseView { 8 | void showReplies(List replyList); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 16dp 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/notification/NotificationElse.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.notification; 2 | 3 | public class NotificationElse { 4 | private String type; 5 | 6 | public NotificationElse(String type) { 7 | this.type = type; 8 | } 9 | 10 | public String getType() { 11 | return type; 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/view/FollowView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | 5 | /** 6 | * Created by plusend on 2016/12/7. 7 | */ 8 | 9 | public interface FollowView extends BaseView { 10 | void setFollow(boolean isFollowed); 11 | 12 | void setFavorite(boolean isFavorite); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/view/SignInView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.user.entity.Token; 5 | 6 | /** 7 | * Created by plusend on 2016/11/28. 8 | */ 9 | 10 | public interface SignInView extends BaseView { 11 | void getToken(Token token); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/Category.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | /** 6 | * @author drakeet 7 | */ 8 | public class Category { 9 | 10 | @NonNull public final String value; 11 | 12 | public Category(@NonNull String value) { 13 | this.value = value; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_about.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_create_news.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/data/SiteService.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.data; 2 | 3 | import com.plusend.diycode.model.site.entity.Site; 4 | import java.util.List; 5 | import retrofit2.Call; 6 | import retrofit2.http.GET; 7 | 8 | interface SiteService { 9 | 10 | /** 11 | * 获取酷站信息 12 | */ 13 | @GET("sites.json") Call> getSite(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_back.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_create_topic.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/UnLikeEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Like; 4 | 5 | public class UnLikeEvent { 6 | private Like like; 7 | 8 | public UnLikeEvent(Like like) { 9 | this.like = like; 10 | } 11 | 12 | public Like getLike() { 13 | return like; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_create_topic_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/entity/UserBlock.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class UserBlock { 6 | 7 | @SerializedName("ok") private int ok; 8 | 9 | public int getOk() { 10 | return ok; 11 | } 12 | 13 | public void setOk(int ok) { 14 | this.ok = ok; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/entity/UserFollow.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class UserFollow { 6 | @SerializedName("ok") private int ok; 7 | 8 | public int getOk() { 9 | return ok; 10 | } 11 | 12 | public void setOk(int ok) { 13 | this.ok = ok; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/entity/UserUnBlock.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class UserUnBlock { 6 | @SerializedName("ok") private int ok; 7 | 8 | public int getOk() { 9 | return ok; 10 | } 11 | 12 | public void setOk(int ok) { 13 | this.ok = ok; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/entity/UserUnFollow.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class UserUnFollow { 6 | @SerializedName("ok") private int ok; 7 | 8 | public int getOk() { 9 | return ok; 10 | } 11 | 12 | public void setOk(int ok) { 13 | this.ok = ok; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favorite.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/event/CreateNewsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.event; 2 | 3 | import com.plusend.diycode.model.news.entity.News; 4 | 5 | public class CreateNewsEvent { 6 | private News news; 7 | 8 | public CreateNewsEvent(News news) { 9 | this.news = news; 10 | } 11 | 12 | public News getNews() { 13 | return news; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/view/NewsView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.news.entity.News; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/12/2. 9 | */ 10 | 11 | public interface NewsView extends BaseView { 12 | void showNews(List newsList); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/view/SiteView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.site.entity.Site; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/11/27. 9 | */ 10 | 11 | public interface SiteView extends BaseView { 12 | void showSite(List siteList); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/LikeEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Like; 4 | 5 | public class LikeEvent { 6 | private Like like; 7 | 8 | public LikeEvent(Like like) { 9 | this.like = like; 10 | } 11 | 12 | public void setLike(Like like) { 13 | this.like = like; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/data/NodeService.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.data; 2 | 3 | import com.plusend.diycode.model.topic.node.entity.Node; 4 | import java.util.List; 5 | import retrofit2.Call; 6 | import retrofit2.http.GET; 7 | 8 | interface NodeService { 9 | 10 | /** 11 | * 获取节点列表 12 | */ 13 | @GET("nodes.json") Call> readNodes(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/topic_top_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/FollowEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | /** 4 | * Created by plusend on 2016/12/6. 5 | */ 6 | 7 | public class FollowEvent { 8 | private boolean result; 9 | 10 | public FollowEvent(boolean result) { 11 | this.result = result; 12 | } 13 | 14 | public boolean isResult() { 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_collect.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/RefreshTokenEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.Token; 4 | 5 | public class RefreshTokenEvent { 6 | private Token token; 7 | 8 | public RefreshTokenEvent(Token token) { 9 | this.token = token; 10 | } 11 | 12 | public Token getToken() { 13 | return token; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/FavoriteEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | /** 4 | * Created by plusend on 2016/12/6. 5 | */ 6 | 7 | public class FavoriteEvent { 8 | private boolean result; 9 | 10 | public FavoriteEvent(boolean result) { 11 | this.result = result; 12 | } 13 | 14 | public boolean isResult() { 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/UnFollowEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | /** 4 | * Created by plusend on 2016/12/6. 5 | */ 6 | 7 | public class UnFollowEvent { 8 | private boolean result; 9 | 10 | public UnFollowEvent(boolean result) { 11 | this.result = result; 12 | } 13 | 14 | public boolean isResult() { 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/view/NodesView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.topic.node.entity.Node; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/12/5. 9 | */ 10 | 11 | public interface NodesView extends BaseView { 12 | void showNodes(List nodeList); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/data/NewsNodeService.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.data; 2 | 3 | import com.plusend.diycode.model.news.node.entity.NewsNode; 4 | import java.util.List; 5 | import retrofit2.Call; 6 | import retrofit2.http.GET; 7 | 8 | interface NewsNodeService { 9 | 10 | /** 11 | * 获取节点列表 12 | */ 13 | @GET("news/nodes.json") Call> readNewsNodes(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/UnFavoriteEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | /** 4 | * Created by plusend on 2016/12/6. 5 | */ 6 | 7 | public class UnFavoriteEvent { 8 | private boolean result; 9 | 10 | public UnFavoriteEvent(boolean result) { 11 | this.result = result; 12 | } 13 | 14 | public boolean isResult() { 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/ToastUtil.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | public class ToastUtil { 7 | 8 | public static void showText(Context context, String message) { 9 | if (context != null) { 10 | Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_SHORT).show(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/view/NewsNodesView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.news.node.entity.NewsNode; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/12/5. 9 | */ 10 | 11 | public interface NewsNodesView extends BaseView { 12 | void showNodes(List newsNodeList); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_reply.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_close.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserBlockEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserBlock; 4 | 5 | public class UserBlockEvent { 6 | private UserBlock userBlock; 7 | 8 | public UserBlockEvent(UserBlock userBlock) { 9 | this.userBlock = userBlock; 10 | } 11 | 12 | public UserBlock getUserBlock() { 13 | return userBlock; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/view/UserView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.user.entity.UserDetailInfo; 5 | 6 | /** 7 | * Created by plusend on 2016/11/28. 8 | */ 9 | 10 | public interface UserView extends BaseView { 11 | void getMe(UserDetailInfo userDetailInfo); 12 | 13 | void getUser(UserDetailInfo userDetailInfo); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_list_view_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favorite_not.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/data/NewsData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.data; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | 5 | public interface NewsData extends BaseData { 6 | 7 | /** 8 | * 获取 news 列表 9 | */ 10 | void readNews(Integer nodeId, Integer offset, Integer limit); 11 | 12 | /** 13 | * 创建 news 14 | */ 15 | void createNews(String title, String address, Integer node_id); 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/TokenEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.Token; 4 | 5 | /** 6 | * Created by plusend on 2016/11/28. 7 | */ 8 | 9 | public class TokenEvent { 10 | private Token token; 11 | 12 | public TokenEvent(Token token) { 13 | this.token = token; 14 | } 15 | 16 | public Token getToken() { 17 | return token; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserFollowEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserFollow; 4 | 5 | public class UserFollowEvent { 6 | private UserFollow userFollow; 7 | 8 | public UserFollowEvent(UserFollow userFollow) { 9 | this.userFollow = userFollow; 10 | } 11 | 12 | public UserFollow getUserFollow() { 13 | return userFollow; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/entity/NotificationsUnreadCount.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class NotificationsUnreadCount { 6 | 7 | @SerializedName("count") private int count; 8 | 9 | public int getCount() { 10 | return count; 11 | } 12 | 13 | public void setCount(int count) { 14 | this.count = count; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/entity/UnFollowTopic.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by plusend on 2016/12/6. 7 | */ 8 | 9 | public class UnFollowTopic { 10 | @SerializedName("ok") private int ok; 11 | 12 | public int getOk() { 13 | return ok; 14 | } 15 | 16 | public void setOk(int ok) { 17 | this.ok = ok; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/entity/UnFavoriteTopic.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by plusend on 2016/12/6. 7 | */ 8 | 9 | public class UnFavoriteTopic { 10 | @SerializedName("ok") private int ok; 11 | 12 | public int getOk() { 13 | return ok; 14 | } 15 | 16 | public void setOk(int ok) { 17 | this.ok = ok; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/view/TopicsView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.topic.entity.Topic; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/11/24. 9 | */ 10 | 11 | public interface TopicsView extends BaseView { 12 | void showTopics(List topicList); 13 | 14 | void showTopTopics(List topicList); 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserUnBlockEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserUnBlock; 4 | 5 | public class UserUnBlockEvent { 6 | private UserUnBlock userUnBlock; 7 | 8 | public UserUnBlockEvent(UserUnBlock userUnBlock) { 9 | this.userUnBlock = userUnBlock; 10 | } 11 | 12 | public UserUnBlock getUserUnBlock() { 13 | return userUnBlock; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/view/NotificationsView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.notification.entity.Notification; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/12/13. 9 | */ 10 | 11 | public interface NotificationsView extends BaseView { 12 | void showNotifications(List notificationList); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/CreateTopicReplyEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | /** 4 | * Created by plusend on 2016/12/1. 5 | */ 6 | 7 | public class CreateTopicReplyEvent { 8 | private boolean isSuccessful; 9 | 10 | public CreateTopicReplyEvent(boolean isSuccessful) { 11 | this.isSuccessful = isSuccessful; 12 | } 13 | 14 | public boolean isSuccessful() { 15 | return isSuccessful; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/activity/SignUpActivity.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import com.plusend.diycode.R; 6 | 7 | public class SignUpActivity extends AppCompatActivity { 8 | 9 | @Override protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_sign_up); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserUnFollowEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserUnFollow; 4 | 5 | public class UserUnFollowEvent { 6 | private UserUnFollow userUnFollow; 7 | 8 | public UserUnFollowEvent(UserUnFollow userUnFollow) { 9 | this.userUnFollow = userUnFollow; 10 | } 11 | 12 | public UserUnFollow getUserUnFollow() { 13 | return userUnFollow; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_reply.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_comment.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/test/java/com/plusend/diycode/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode; 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 public void addition_isCorrect() throws Exception { 14 | assertEquals(4, 2 + 2); 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserFavoriteTopicsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Topic; 4 | import java.util.List; 5 | 6 | public class UserFavoriteTopicsEvent { 7 | private List topicList; 8 | 9 | public UserFavoriteTopicsEvent(List topicList) { 10 | this.topicList = topicList; 11 | } 12 | 13 | public List getTopicList() { 14 | return topicList; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserBlockedEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserInfo; 4 | import java.util.List; 5 | 6 | public class UserBlockedEvent { 7 | private List userInfoList; 8 | 9 | public UserBlockedEvent(List userInfoList) { 10 | this.userInfoList = userInfoList; 11 | } 12 | 13 | public List getUserInfoList() { 14 | return userInfoList; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserDetailInfoEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserDetailInfo; 4 | 5 | public class UserDetailInfoEvent { 6 | private UserDetailInfo userDetailInfo; 7 | 8 | public UserDetailInfoEvent(UserDetailInfo userDetailInfo) { 9 | this.userDetailInfo = userDetailInfo; 10 | } 11 | 12 | public UserDetailInfo getUserDetailInfo() { 13 | return userDetailInfo; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/event/NewsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.event; 2 | 3 | import com.plusend.diycode.model.news.entity.News; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/12/2. 8 | */ 9 | 10 | public class NewsEvent { 11 | private List newsList; 12 | 13 | public NewsEvent(List newsList) { 14 | this.newsList = newsList; 15 | } 16 | 17 | public List getNewsList() { 18 | return newsList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/event/SiteEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.event; 2 | 3 | import com.plusend.diycode.model.site.entity.Site; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/11/27. 8 | */ 9 | 10 | public class SiteEvent { 11 | private List siteList; 12 | 13 | public SiteEvent(List siteList) { 14 | this.siteList = siteList; 15 | } 16 | 17 | public List getSiteList() { 18 | return siteList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/entity/FollowTopic.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class FollowTopic { 6 | @SerializedName("ok") private int ok; 7 | 8 | public int getOk() { 9 | return ok; 10 | } 11 | 12 | public void setOk(int ok) { 13 | this.ok = ok; 14 | } 15 | 16 | @Override public String toString() { 17 | return "FollowTopic{" + "ok=" + ok + '}'; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/event/NewsNodesEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.event; 2 | 3 | import com.plusend.diycode.model.news.node.entity.NewsNode; 4 | import java.util.List; 5 | 6 | public class NewsNodesEvent { 7 | private List newsNodeList; 8 | 9 | public NewsNodesEvent(List newsNodeList) { 10 | this.newsNodeList = newsNodeList; 11 | } 12 | 13 | public List getNewsNodeList() { 14 | return newsNodeList; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/entity/FavoriteTopic.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class FavoriteTopic { 6 | @SerializedName("ok") private int ok; 7 | 8 | public int getOk() { 9 | return ok; 10 | } 11 | 12 | public void setOk(int ok) { 13 | this.ok = ok; 14 | } 15 | 16 | @Override public String toString() { 17 | return "FavoriteTopic{" + "ok=" + ok + '}'; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserFollowersEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserInfo; 4 | import java.util.List; 5 | 6 | public class UserFollowersEvent { 7 | private List userInfoList; 8 | 9 | public UserFollowersEvent(List userInfoList) { 10 | this.userInfoList = userInfoList; 11 | } 12 | 13 | public List getUserInfoList() { 14 | return userInfoList; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserFollowingEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserInfo; 4 | import java.util.List; 5 | 6 | public class UserFollowingEvent { 7 | private List userInfoList; 8 | 9 | public UserFollowingEvent(List userInfoList) { 10 | this.userInfoList = userInfoList; 11 | } 12 | 13 | public List getUserInfoList() { 14 | return userInfoList; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/TopicsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Topic; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/11/24. 8 | */ 9 | 10 | public class TopicsEvent { 11 | private List topicList; 12 | 13 | public TopicsEvent(List topicList) { 14 | this.topicList = topicList; 15 | } 16 | 17 | public List getTopicList() { 18 | return topicList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/event/NodesEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.event; 2 | 3 | import com.plusend.diycode.model.topic.node.entity.Node; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/12/5. 8 | */ 9 | 10 | public class NodesEvent { 11 | private List nodeList; 12 | 13 | public NodesEvent(List nodeList) { 14 | this.nodeList = nodeList; 15 | } 16 | 17 | public List getNodeList() { 18 | return nodeList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_notifications.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/about_page_item_category.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/CreateTopicEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.TopicDetail; 4 | 5 | /** 6 | * Created by plusend on 2016/11/30. 7 | */ 8 | 9 | public class CreateTopicEvent { 10 | private TopicDetail topicDetail; 11 | 12 | public CreateTopicEvent(TopicDetail topicDetail) { 13 | this.topicDetail = topicDetail; 14 | } 15 | 16 | public TopicDetail getTopicDetail() { 17 | return topicDetail; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/RepliesEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Reply; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/12/18. 8 | */ 9 | 10 | public class RepliesEvent { 11 | private List replyList; 12 | 13 | public RepliesEvent(List replyList) { 14 | this.replyList = replyList; 15 | } 16 | 17 | public List getReplyList() { 18 | return replyList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/TopicDetailEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.TopicDetail; 4 | 5 | /** 6 | * Created by plusend on 2016/11/25. 7 | */ 8 | 9 | public class TopicDetailEvent { 10 | private TopicDetail topicDetail; 11 | 12 | public TopicDetailEvent(TopicDetail topicDetail) { 13 | this.topicDetail = topicDetail; 14 | } 15 | 16 | public TopicDetail getTopicDetail() { 17 | return topicDetail; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/view/TopicRepliesView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.topic.entity.TopicReply; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by plusend on 2016/11/26. 9 | */ 10 | 11 | public interface TopicRepliesView extends BaseView { 12 | void showReplies(List topicReplyList); 13 | 14 | void addReplies(List topicReplyList); 15 | 16 | void showNewReply(); 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/MeEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.user.entity.UserDetailInfo; 4 | 5 | /** 6 | * Created by plusend on 2016/11/28. 7 | */ 8 | 9 | public class MeEvent { 10 | private UserDetailInfo userDetailInfo; 11 | 12 | public MeEvent(UserDetailInfo userDetailInfo) { 13 | this.userDetailInfo = userDetailInfo; 14 | } 15 | 16 | public UserDetailInfo getUserDetailInfo() { 17 | return userDetailInfo; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/TopTopicsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Topic; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/11/24. 8 | */ 9 | 10 | public class TopTopicsEvent { 11 | private List topicList; 12 | 13 | public TopTopicsEvent(List topicList) { 14 | this.topicList = topicList; 15 | } 16 | 17 | public List getTopicList() { 18 | return topicList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/event/UserTopicsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.Topic; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/11/29. 8 | */ 9 | 10 | public class UserTopicsEvent { 11 | private List topicList; 12 | 13 | public UserTopicsEvent(List topicList) { 14 | this.topicList = topicList; 15 | } 16 | 17 | public List getTopicList() { 18 | return topicList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/notification/NotificationFollow.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.notification; 2 | 3 | public class NotificationFollow { 4 | private String avatarUrl; 5 | private String login; 6 | 7 | public NotificationFollow(String avatarUrl, String login) { 8 | this.avatarUrl = avatarUrl; 9 | this.login = login; 10 | } 11 | 12 | public String getAvatarUrl() { 13 | return avatarUrl; 14 | } 15 | 16 | public String getLogin() { 17 | return login; 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/IntentUtil.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import com.plusend.diycode.view.activity.UserActivity; 6 | 7 | public class IntentUtil { 8 | /** 9 | * 调起用户详情页 10 | */ 11 | public static void startUserActivity(Context context, String loginName) { 12 | Intent intent = new Intent(context, UserActivity.class); 13 | intent.putExtra(UserActivity.LOGIN_NAME, loginName); 14 | context.startActivity(intent); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_follow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_notification_else.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_web.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/color/item_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_like.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/topic/Footer.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.topic; 2 | 3 | public class Footer { 4 | public static final int STATUS_NORMAL = 1;//正常状态 5 | public static final int STATUS_LOADING = 2;//正在加载中 6 | public static final int STATUS_NO_MORE = 3;//没有更多了 7 | private int status; 8 | 9 | public Footer(int status) { 10 | this.status = status; 11 | } 12 | 13 | public int getStatus() { 14 | return status; 15 | } 16 | 17 | public void setStatus(int status) { 18 | this.status = status; 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/event/TopicRepliesEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.event; 2 | 3 | import com.plusend.diycode.model.topic.entity.TopicReply; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/11/26. 8 | */ 9 | 10 | public class TopicRepliesEvent { 11 | private List topicReplyList; 12 | 13 | public TopicRepliesEvent(List topicReplyList) { 14 | this.topicReplyList = topicReplyList; 15 | } 16 | 17 | public List getTopicReplyList() { 18 | return topicReplyList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_post.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/entity/NewsNode.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class NewsNode { 6 | 7 | @SerializedName("id") private int id; 8 | @SerializedName("name") private String name; 9 | 10 | public int getId() { 11 | return id; 12 | } 13 | 14 | public void setId(int id) { 15 | this.id = id; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/about_page_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_like_not.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/event/NotificationsEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.event; 2 | 3 | import com.plusend.diycode.model.notification.entity.Notification; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/12/12. 8 | */ 9 | 10 | public class NotificationsEvent { 11 | private List notificationList; 12 | 13 | public NotificationsEvent(List notificationList) { 14 | this.notificationList = notificationList; 15 | } 16 | 17 | public List getNotificationList() { 18 | return notificationList; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/event/NotificationDeleteEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.event; 2 | 3 | import com.plusend.diycode.model.notification.entity.NotificationDelete; 4 | 5 | /** 6 | * Created by plusend on 2016/12/13. 7 | */ 8 | 9 | public class NotificationDeleteEvent { 10 | private NotificationDelete notificationDelete; 11 | 12 | public NotificationDeleteEvent(NotificationDelete notificationDelete) { 13 | this.notificationDelete = notificationDelete; 14 | } 15 | 16 | public NotificationDelete getNotificationDelete() { 17 | return notificationDelete; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/event/NotificationsUnreadCountEvent.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.event; 2 | 3 | import com.plusend.diycode.model.notification.entity.NotificationsUnreadCount; 4 | 5 | public class NotificationsUnreadCountEvent { 6 | private NotificationsUnreadCount notificationsUnreadCount; 7 | 8 | public NotificationsUnreadCountEvent(NotificationsUnreadCount notificationsUnreadCount) { 9 | this.notificationsUnreadCount = notificationsUnreadCount; 10 | } 11 | 12 | public NotificationsUnreadCount getNotificationsUnreadCount() { 13 | return notificationsUnreadCount; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/view/TopicView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.view; 2 | 3 | import com.plusend.diycode.model.base.BaseView; 4 | import com.plusend.diycode.model.topic.entity.TopicDetail; 5 | 6 | public interface TopicView extends BaseView { 7 | void showTopic(TopicDetail topicDetail); 8 | 9 | void loadTopicFinish(); 10 | 11 | void showFavorite(boolean bool); 12 | 13 | void showUnFavorite(boolean bool); 14 | 15 | void showFollow(boolean bool); 16 | 17 | void showUnFollow(boolean bool); 18 | 19 | void showLike(boolean bool); 20 | 21 | void showUnLike(boolean bool); 22 | 23 | void showSignIn(); 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/site/SiteName.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.site; 2 | 3 | /** 4 | * Created by plusend on 2016/12/13. 5 | */ 6 | public class SiteName { 7 | private String name; 8 | private int id; 9 | 10 | public SiteName(String name, int id) { 11 | this.name = name; 12 | this.id = id; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public int getId() { 24 | return id; 25 | } 26 | 27 | public void setId(int id) { 28 | this.id = id; 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/Contributor.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.support.annotation.DrawableRes; 4 | import android.support.annotation.NonNull; 5 | 6 | /** 7 | * @author drakeet 8 | */ 9 | public class Contributor { 10 | 11 | @DrawableRes public final int avatarResId; 12 | @NonNull public final String name; 13 | @NonNull public final String desc; 14 | public final String url; 15 | 16 | public Contributor(@DrawableRes int avatarResId, @NonNull String name, @NonNull String desc, 17 | String url) { 18 | this.avatarResId = avatarResId; 19 | this.name = name; 20 | this.desc = desc; 21 | this.url = url; 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/about_page_button_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/about_page_button_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/topic/TopicReplyWithTopic.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.topic; 2 | 3 | import com.plusend.diycode.model.topic.entity.TopicDetail; 4 | import com.plusend.diycode.model.topic.entity.TopicReply; 5 | 6 | public class TopicReplyWithTopic { 7 | private TopicDetail topicDetail; 8 | private TopicReply topicReply; 9 | 10 | public TopicReplyWithTopic(TopicDetail topicDetail, TopicReply topicReply) { 11 | this.topicDetail = topicDetail; 12 | this.topicReply = topicReply; 13 | } 14 | 15 | public TopicDetail getTopicDetail() { 16 | return topicDetail; 17 | } 18 | 19 | public TopicReply getTopicReply() { 20 | return topicReply; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_site_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/data/NotificationData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.data; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | 5 | public interface NotificationData extends BaseData { 6 | 7 | /** 8 | * 获取当前用户的通知列表 9 | */ 10 | void readNotifications(Integer offset, Integer limit); 11 | 12 | /** 13 | * 删除当前用户的某个通知 14 | */ 15 | void deleteNotification(int id); 16 | 17 | /** 18 | * 删除当前用户的所有通知 19 | */ 20 | void deleteAllNotifications(); 21 | 22 | /** 23 | * 将当前用户的一些通知设成已读状态 24 | */ 25 | void markNotificationsAsRead(int[] ids); 26 | 27 | /** 28 | * 获得未读通知数量 29 | */ 30 | void unReadNotificationCount(); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_category_widget.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /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=-Xmx1536m 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 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | 28 | # Android Studio Navigation editor temp files 29 | .navigation/ 30 | 31 | # Android Studio captures folder 32 | captures/ 33 | 34 | # Eclipse project files 35 | .classpath 36 | .project 37 | 38 | # Intellij project files 39 | *.iml 40 | *.ipr 41 | *.iws 42 | .idea/ 43 | 44 | # OSX files 45 | .DS_Store 46 | 47 | # 保存编译好供下载的 apk 48 | !apk/*.apk 49 | 50 | # 密钥 51 | *.jks 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/HtmlUtil.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.util.Log; 4 | 5 | public class HtmlUtil { 6 | private static final String TAG = "HtmlUtil"; 7 | 8 | public static String removeP(String html) { 9 | String result = html; 10 | Log.d(TAG, "html: " + html); 11 | if (result.contains("

") && result.contains("

")) { 12 | result = result.replace("

", ""); 13 | result = result.replace("

", "
"); 14 | Log.d(TAG, "result: " + result); 15 | if (result.endsWith("
")) { 16 | result = result.substring(0, result.length() - 4); 17 | Log.d(TAG, "final: " + result); 18 | } 19 | } 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_news.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_site.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_topic_reply_load_more.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 15 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/PackageUtil.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | 7 | public class PackageUtil { 8 | public static int getVersionCode(Context context) { 9 | int version; 10 | PackageManager packageManager = context.getPackageManager(); 11 | // getPackageName()是你当前类的包名,0代表是获取版本信息 12 | PackageInfo packInfo = null; 13 | try { 14 | packInfo = packageManager.getPackageInfo(context.getPackageName(), 0); 15 | } catch (PackageManager.NameNotFoundException e) { 16 | e.printStackTrace(); 17 | } 18 | version = packInfo != null ? packInfo.versionCode : 0; 19 | return version; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/AppOperator.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import java.util.concurrent.Executor; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | 7 | public final class AppOperator { 8 | private static ExecutorService EXECUTORS_INSTANCE; 9 | 10 | public static Executor getExecutor() { 11 | if (EXECUTORS_INSTANCE == null) { 12 | synchronized (AppOperator.class) { 13 | if (EXECUTORS_INSTANCE == null) { 14 | EXECUTORS_INSTANCE = Executors.newFixedThreadPool(6); 15 | } 16 | } 17 | } 18 | return EXECUTORS_INSTANCE; 19 | } 20 | 21 | public static void runOnThread(Runnable runnable) { 22 | getExecutor().execute(runnable); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_topic.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_topic_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 16 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/License.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | /** 6 | * @author drakeet 7 | */ 8 | public class License { 9 | 10 | public static final String MIT = "MIT License"; 11 | public static final String APACHE_2 = "Apache Software License 2.0"; 12 | public static final String GPL_V3 = "GNU general public license Version 3"; 13 | 14 | public String name; 15 | public String author; 16 | public String type; 17 | public String url; 18 | 19 | public License() { 20 | } 21 | 22 | public License(@NonNull String name, @NonNull String author, @NonNull String type, 23 | @NonNull String url) { 24 | this.name = name; 25 | this.author = author; 26 | this.type = type; 27 | this.url = url; 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/plusend/diycode/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.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 | * Instrumentation test, which will execute on an Android device. 13 | * 14 | * @see Testing documentation 15 | */ 16 | @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { 17 | @Test public void useAppContext() throws Exception { 18 | // Context of the app under test. 19 | Context appContext = InstrumentationRegistry.getTargetContext(); 20 | 21 | assertEquals("com.plusend.diycode", appContext.getPackageName()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/widget/DividerListItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.widget; 2 | 3 | import android.content.Context; 4 | import android.graphics.Rect; 5 | import android.graphics.drawable.Drawable; 6 | import android.support.v7.widget.RecyclerView; 7 | import android.view.View; 8 | import com.plusend.diycode.R; 9 | 10 | /** 11 | * Created by plusend on 2016/12/4. 12 | */ 13 | 14 | public class DividerListItemDecoration extends RecyclerView.ItemDecoration { 15 | 16 | private Drawable divider; 17 | 18 | public DividerListItemDecoration(Context context) { 19 | divider = context.getResources().getDrawable(R.drawable.item_divider_vertical); 20 | } 21 | 22 | @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, 23 | RecyclerView.State state) { 24 | outRect.set(0, 0, 0, divider.getIntrinsicHeight()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_sites_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 16 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_follow_not.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Diycode 3 | 4 | Open navigation drawer 5 | Close navigation drawer 6 | 7 | 设置 8 | UserActivity 9 | 设置 10 | 11 | com.plusend.diycode.Logout 12 | com.plusend.diycode.Test 13 | Diycode由众多开发者共同维护,致力于构建开发工程师高端交流分享社区。 14 | 15 | pref_key_check_update 16 | pref_key_feedback 17 | pref_key_sign_out 18 | com.pgyersdk.provider 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/site/SitesName.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.site; 2 | 3 | /** 4 | * Created by plusend on 2016/12/13. 5 | */ 6 | public class SitesName { 7 | private String name; 8 | private String url; 9 | private String avatarUrl; 10 | 11 | public SitesName(String name, String url, String avatarUrl) { 12 | this.name = name; 13 | this.url = url; 14 | this.avatarUrl = avatarUrl; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | public String getUrl() { 26 | return url; 27 | } 28 | 29 | public void setUrl(String url) { 30 | this.url = url; 31 | } 32 | 33 | public String getAvatarUrl() { 34 | return avatarUrl; 35 | } 36 | 37 | public void setAvatarUrl(String avatarUrl) { 38 | this.avatarUrl = avatarUrl; 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_web.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 21 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/data/NewsService.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.data; 2 | 3 | import com.plusend.diycode.model.news.entity.News; 4 | import com.plusend.diycode.util.Constant; 5 | import java.util.List; 6 | import retrofit2.Call; 7 | import retrofit2.http.Field; 8 | import retrofit2.http.FormUrlEncoded; 9 | import retrofit2.http.GET; 10 | import retrofit2.http.Header; 11 | import retrofit2.http.POST; 12 | import retrofit2.http.Query; 13 | 14 | interface NewsService { 15 | 16 | /** 17 | * 获取 news 列表 18 | */ 19 | @GET("news.json") Call> readNews(@Query("node_id") Integer nodeId, 20 | @Query("offset") Integer offset, @Query("limit") Integer limit); 21 | 22 | /** 23 | * 创建 News 24 | */ 25 | @POST("news.json") @FormUrlEncoded Call createNews( 26 | @Header(Constant.KEY_TOKEN) String token, @Field("title") String title, 27 | @Field("address") String address, @Field("node_id") Integer node_id); 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_my_topics.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 20 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiyCode 社区的第三方 Android 客户端 2 | ## 动机 3 | [深夜发布个小消息,Diycode 社区、项目、News、sites 的 API 发布了 - DiyCode](https://www.diycode.cc/topics/411) 4 | 5 | ## 开发记录 6 | 7 | [项目结构和功能点整理](https://plusend.com/%E5%BC%80%E5%8F%91-diycode-android-%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E8%AE%B0%E5%BD%95/) 8 | 9 | ## 下载 10 | 11 | [![](screenshot/ic_launcher.png)](https://www.pgyer.com/diycode) 12 | 13 | ## 预览 14 | 15 | ![](screenshot/Diycode.jpg) 16 | 17 | ## 功能 18 | 19 | 1. Topics 的浏览、回复、新建; 20 | 2. News 的浏览、分享、新建; 21 | 3. Sites 的浏览; 22 | 4. 浏览个人通知; 23 | 5. 查看我的帖子、收藏、评论。 24 | 25 | ## FAQ 26 | 27 | 1. 编译本工程需要在 app module 下新建一个 gradle.properties 文件,并在其中声明变量: 28 | 29 | ``` 30 | PGYER_APPID_VALUE=12345678901234567890123456789012 31 | ``` 32 | 33 | 该变量是在 [蒲公英](https://www.pgyer.com/) (应用内测专家)申请的 APPID,用于在其平台上发布内测应用。你需要用你的 APPID 替换上面的 “1234***9012”。 34 | 35 | ## 版权 36 | 采用 [GNU General Public License v3.0](https://github.com/plusend/DiyCode/blob/master/LICENSE.md) 37 | 38 | ## 鸣谢 39 | [DiyCode - 致力于构建开发工程师高端交流分享社区](https://www.diycode.cc) 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/about_page_item_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/notification/NotificationReply.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.notification; 2 | 3 | public class NotificationReply { 4 | private String avatarUrl; 5 | private String login; 6 | private String topicTitle; 7 | private String bodyHtml; 8 | private int topicId; 9 | 10 | public NotificationReply(String avatarUrl, String login, String topicTitle, String bodyHtml, 11 | int topicId) { 12 | this.avatarUrl = avatarUrl; 13 | this.login = login; 14 | this.topicTitle = topicTitle; 15 | this.bodyHtml = bodyHtml; 16 | this.topicId = topicId; 17 | } 18 | 19 | public String getAvatarUrl() { 20 | return avatarUrl; 21 | } 22 | 23 | public String getLogin() { 24 | return login; 25 | } 26 | 27 | public String getTopicTitle() { 28 | return topicTitle; 29 | } 30 | 31 | public String getBodyHtml() { 32 | return bodyHtml; 33 | } 34 | 35 | public int getTopicId() { 36 | return topicId; 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/notification/NotificationMention.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.notification; 2 | 3 | public class NotificationMention { 4 | private String avatarUrl; 5 | private String login; 6 | private String topicTitle; 7 | private String bodyHtml; 8 | private int topicId; 9 | 10 | public NotificationMention(String avatarUrl, String login, String topicTitle, String bodyHtml, 11 | int topicId) { 12 | this.avatarUrl = avatarUrl; 13 | this.login = login; 14 | this.topicTitle = topicTitle; 15 | this.bodyHtml = bodyHtml; 16 | this.topicId = topicId; 17 | } 18 | 19 | public String getAvatarUrl() { 20 | return avatarUrl; 21 | } 22 | 23 | public String getLogin() { 24 | return login; 25 | } 26 | 27 | public String getTopicTitle() { 28 | return topicTitle; 29 | } 30 | 31 | public String getBodyHtml() { 32 | return bodyHtml; 33 | } 34 | 35 | public int getTopicId() { 36 | return topicId; 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/app/DiyCodeApplication.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.app; 2 | 3 | import android.app.Application; 4 | import cn.bingoogolapple.swipebacklayout.BGASwipeBackManager; 5 | import com.pgyersdk.crash.PgyCrashManager; 6 | import com.plusend.diycode.util.Constant; 7 | import com.plusend.diycode.util.KeyStoreHelper; 8 | import java.security.InvalidAlgorithmParameterException; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.security.NoSuchProviderException; 11 | 12 | public class DiyCodeApplication extends Application { 13 | 14 | @Override public void onCreate() { 15 | super.onCreate(); 16 | 17 | // 初始化蒲公英 18 | PgyCrashManager.register(this); 19 | 20 | try { 21 | KeyStoreHelper.createKeys(getApplicationContext(), Constant.KEYSTORE_KEY_ALIAS); 22 | } catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { 23 | e.printStackTrace(); 24 | } 25 | 26 | // 滑动返回 27 | BGASwipeBackManager.getInstance().init(this); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/UrlUtil.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.util.Patterns; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | /** 10 | * Created by plusend on 2016/12/4. 11 | */ 12 | 13 | public class UrlUtil { 14 | /** 15 | * 获取 URL 的 Host 16 | */ 17 | public static String getHost(String urlString) { 18 | String result = urlString; 19 | try { 20 | URL url = new URL(urlString); 21 | result = url.getHost(); 22 | } catch (MalformedURLException e) { 23 | e.printStackTrace(); 24 | } 25 | 26 | return result; 27 | } 28 | 29 | /** 30 | * 提取文本中的链接 31 | */ 32 | public static String getUrl(String text) { 33 | Pattern p = Patterns.WEB_URL; 34 | Matcher matcher = p.matcher(text); 35 | if (matcher.find()) { 36 | return matcher.group(); 37 | } else { 38 | return null; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/about_page_item_license.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 21 | 22 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/nav_header_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 20 | 21 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/entity/Like.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Like { 6 | @SerializedName("obj_type") private String objType; 7 | @SerializedName("obj_id") private int objId; 8 | @SerializedName("count") private int count; 9 | 10 | public String getObjType() { 11 | return objType; 12 | } 13 | 14 | public void setObjType(String objType) { 15 | this.objType = objType; 16 | } 17 | 18 | public int getObjId() { 19 | return objId; 20 | } 21 | 22 | public void setObjId(int objId) { 23 | this.objId = objId; 24 | } 25 | 26 | public int getCount() { 27 | return count; 28 | } 29 | 30 | public void setCount(int count) { 31 | this.count = count; 32 | } 33 | 34 | @Override public String toString() { 35 | return "Like{" 36 | + "objType='" 37 | + objType 38 | + '\'' 39 | + ", objId=" 40 | + objId 41 | + ", count=" 42 | + count 43 | + '}'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_settings.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/activity_main_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 11 | 15 | 19 | 20 | 21 | 24 | 28 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_notification_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 16 | 24 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 19 | 25 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_notification_mention.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 16 | 24 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_notification_follow.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 16 | 24 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/CardViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | import com.plusend.diycode.R; 10 | import me.drakeet.multitype.ItemViewProvider; 11 | 12 | public class CardViewProvider extends ItemViewProvider { 13 | 14 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 15 | @NonNull ViewGroup parent) { 16 | View root = inflater.inflate(R.layout.about_page_item_card, parent, false); 17 | return new ViewHolder(root); 18 | } 19 | 20 | @Override protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Card card) { 21 | holder.content.setText(card.content); 22 | } 23 | 24 | class ViewHolder extends RecyclerView.ViewHolder { 25 | 26 | TextView content; 27 | 28 | ViewHolder(View itemView) { 29 | super(itemView); 30 | content = (TextView) itemView.findViewById(R.id.content); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/item_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 17 | 25 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 21 | 29 | 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/activity/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.widget.Toolbar; 5 | import android.widget.FrameLayout; 6 | import butterknife.BindView; 7 | import butterknife.ButterKnife; 8 | import com.plusend.diycode.R; 9 | import com.plusend.diycode.model.base.BasePresenter; 10 | import com.plusend.diycode.view.fragment.SettingsFragment; 11 | import java.util.List; 12 | 13 | public class SettingsActivity extends BaseActivity { 14 | private static final String TAG = "SettingsActivity"; 15 | @BindView(R.id.container) FrameLayout container; 16 | @BindView(R.id.toolbar) Toolbar toolbar; 17 | 18 | @Override protected void onCreate(Bundle savedInstanceState) { 19 | setContentView(R.layout.activity_settings); 20 | ButterKnife.bind(this); 21 | super.onCreate(savedInstanceState); 22 | 23 | getFragmentManager().beginTransaction() 24 | .replace(R.id.container, new SettingsFragment()) 25 | .commit(); 26 | } 27 | 28 | @Override protected Toolbar getToolbar() { 29 | return toolbar; 30 | } 31 | 32 | @Override protected List getPresenter() { 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/CategoryViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | import com.plusend.diycode.R; 10 | import me.drakeet.multitype.ItemViewProvider; 11 | 12 | /** 13 | * @author drakeet 14 | */ 15 | public class CategoryViewProvider 16 | extends ItemViewProvider { 17 | 18 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 19 | @NonNull ViewGroup parent) { 20 | View root = inflater.inflate(R.layout.about_page_item_category, parent, false); 21 | return new ViewHolder(root); 22 | } 23 | 24 | @Override 25 | protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Category category) { 26 | holder.category.setText(category.value); 27 | } 28 | 29 | static class ViewHolder extends RecyclerView.ViewHolder { 30 | 31 | TextView category; 32 | 33 | ViewHolder(View itemView) { 34 | super(itemView); 35 | category = (TextView) itemView.findViewById(R.id.category); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 20 | 25 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/presenter/NewsBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.presenter; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | import com.plusend.diycode.model.base.BasePresenter; 5 | import com.plusend.diycode.model.news.data.NewsDataNetwork; 6 | import com.plusend.diycode.model.news.event.NewsEvent; 7 | import com.plusend.diycode.model.news.view.NewsView; 8 | import org.greenrobot.eventbus.EventBus; 9 | import org.greenrobot.eventbus.Subscribe; 10 | import org.greenrobot.eventbus.ThreadMode; 11 | 12 | public class NewsBasePresenter extends BasePresenter { 13 | private static final String TAG = "NewsPresenter"; 14 | 15 | private NewsView newsView; 16 | private BaseData data; 17 | 18 | public NewsBasePresenter(NewsView newsView) { 19 | this.newsView = newsView; 20 | this.data = NewsDataNetwork.getInstance(); 21 | } 22 | 23 | public void readNews(int offset) { 24 | ((NewsDataNetwork) data).readNews(null, offset, null); 25 | } 26 | 27 | @Subscribe(threadMode = ThreadMode.MAIN) public void showNews(NewsEvent event) { 28 | newsView.showNews(event.getNewsList()); 29 | } 30 | 31 | @Override public void start() { 32 | EventBus.getDefault().register(this); 33 | } 34 | 35 | @Override public void stop() { 36 | EventBus.getDefault().unregister(this); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/Constant.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | public class Constant { 4 | 5 | public static final String KEYSTORE_KEY_ALIAS = "DiyCode"; 6 | public static final String VALUE_CLIENT_ID = "c2b56685"; 7 | public static final String VALUE_CLIENT_SECRET = 8 | "869e0541ea80b2c48eea4a5c710d79448f2f9133abfbe203995801a8bc644068"; 9 | public static final String VALUE_GRANT_TYPE_PASSWORD = "password"; 10 | public static final String VALUE_GRANT_TYPE_REFRESH_TOKEN = "refresh_token"; 11 | public static final String KEY_TOKEN = "Authorization"; 12 | public static final String VALUE_TOKEN_PREFIX = "Bearer "; 13 | 14 | public static String VALUE_TOKEN = ""; 15 | 16 | public static class Token { 17 | public static final String SHARED_PREFERENCES_NAME = "sign"; 18 | public static final String ACCESS_TOKEN = "access_token"; 19 | public static final String TOKEN_TYPE = "token_type"; 20 | public static final String EXPIRES_IN = "expires_in"; 21 | public static final String REFRESH_TOKEN = "refresh_token"; 22 | public static final String CREATED_AT = "created_at"; 23 | } 24 | 25 | public static class User { 26 | public static final String LOGIN = "login"; 27 | public static final String AVATAR_URL = "avatar_url"; 28 | public static final String EMAIL = "email"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/presenter/CreateNewsBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.presenter; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | import com.plusend.diycode.model.base.BasePresenter; 5 | import com.plusend.diycode.model.news.data.NewsDataNetwork; 6 | import com.plusend.diycode.model.news.event.CreateNewsEvent; 7 | import com.plusend.diycode.model.news.view.CreateNewsView; 8 | import org.greenrobot.eventbus.EventBus; 9 | import org.greenrobot.eventbus.Subscribe; 10 | import org.greenrobot.eventbus.ThreadMode; 11 | 12 | public class CreateNewsBasePresenter extends BasePresenter { 13 | private BaseData mData; 14 | private CreateNewsView mView; 15 | 16 | public CreateNewsBasePresenter(CreateNewsView createNewsView) { 17 | this.mView = createNewsView; 18 | mData = NewsDataNetwork.getInstance(); 19 | } 20 | 21 | @Override public void start() { 22 | EventBus.getDefault().register(this); 23 | } 24 | 25 | @Override public void stop() { 26 | EventBus.getDefault().unregister(this); 27 | } 28 | 29 | public void createNews(String title, String address, Integer node_id) { 30 | ((NewsDataNetwork) mData).createNews(title, address, node_id); 31 | } 32 | 33 | @Subscribe(threadMode = ThreadMode.MAIN) public void showNews(CreateNewsEvent event) { 34 | mView.showNews(event.getNews()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/site/SiteNameViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.site; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | import butterknife.BindView; 10 | import butterknife.ButterKnife; 11 | import com.plusend.diycode.R; 12 | import me.drakeet.multitype.ItemViewProvider; 13 | 14 | /** 15 | * Created by plusend on 2016/12/13. 16 | */ 17 | public class SiteNameViewProvider 18 | extends ItemViewProvider { 19 | 20 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 21 | @NonNull ViewGroup parent) { 22 | View root = inflater.inflate(R.layout.item_site_name, parent, false); 23 | return new ViewHolder(root); 24 | } 25 | 26 | @Override 27 | protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull SiteName siteName) { 28 | holder.title.setText(siteName.getName()); 29 | } 30 | 31 | static class ViewHolder extends RecyclerView.ViewHolder { 32 | @BindView(R.id.title) TextView title; 33 | 34 | ViewHolder(View itemView) { 35 | super(itemView); 36 | ButterKnife.bind(this, itemView); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #ffffff 5 | #EB5424 6 | #F0F0F0 7 | #ff0099cc 8 | #356DD0 9 | #62646c 10 | #4d4d4d 11 | #999999 12 | 13 | 14 | #ffffff 15 | #666666 16 | #216b74ff 17 | 18 | 19 | #ffffff 20 | #10000000 21 | #f1f1f1 22 | #757575 23 | #424242 24 | #44000000 25 | #9e9e9e 26 | #424242 27 | #757575 28 | #424242 29 | #757575 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/notification/NotificationElseViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.notification; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | import butterknife.BindView; 10 | import butterknife.ButterKnife; 11 | import com.plusend.diycode.R; 12 | import me.drakeet.multitype.ItemViewProvider; 13 | 14 | public class NotificationElseViewProvider 15 | extends ItemViewProvider { 16 | 17 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 18 | @NonNull ViewGroup parent) { 19 | View root = inflater.inflate(R.layout.item_notification_else, parent, false); 20 | return new ViewHolder(root); 21 | } 22 | 23 | @Override protected void onBindViewHolder(@NonNull ViewHolder holder, 24 | @NonNull NotificationElse notificationElse) { 25 | holder.content.setText(notificationElse.getType()); 26 | } 27 | 28 | static class ViewHolder extends RecyclerView.ViewHolder { 29 | @BindView(R.id.content) TextView content; 30 | 31 | ViewHolder(View itemView) { 32 | super(itemView); 33 | ButterKnife.bind(this, itemView); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_my_replies.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 20 | 27 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/presenter/SiteBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.site.data.SiteDataNetwork; 7 | import com.plusend.diycode.model.site.event.SiteEvent; 8 | import com.plusend.diycode.model.site.view.SiteView; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class SiteBasePresenter extends BasePresenter { 14 | private static final String TAG = "SitePresenter"; 15 | private BaseData data; 16 | private SiteView siteView; 17 | 18 | public SiteBasePresenter(SiteView siteView) { 19 | this.siteView = siteView; 20 | data = SiteDataNetwork.getInstance(); 21 | } 22 | 23 | @Subscribe(threadMode = ThreadMode.MAIN) public void showSite(SiteEvent siteEvent) { 24 | this.siteView.showSite(siteEvent.getSiteList()); 25 | } 26 | 27 | public void getSite() { 28 | ((SiteDataNetwork) data).getSite(); 29 | } 30 | 31 | @Override public void start() { 32 | Log.d(TAG, "register"); 33 | EventBus.getDefault().register(this); 34 | } 35 | 36 | @Override public void stop() { 37 | Log.d(TAG, "unregister"); 38 | EventBus.getDefault().unregister(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/presenter/CreateTopicPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.presenter; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | import com.plusend.diycode.model.base.BasePresenter; 5 | import com.plusend.diycode.model.topic.data.TopicDataNetwork; 6 | import com.plusend.diycode.model.topic.event.CreateTopicEvent; 7 | import com.plusend.diycode.model.topic.view.CreateTopicView; 8 | import org.greenrobot.eventbus.EventBus; 9 | import org.greenrobot.eventbus.Subscribe; 10 | import org.greenrobot.eventbus.ThreadMode; 11 | 12 | public class CreateTopicPresenter extends BasePresenter { 13 | private BaseData data; 14 | private CreateTopicView createTopicView; 15 | 16 | public CreateTopicPresenter(CreateTopicView createTopicView) { 17 | this.createTopicView = createTopicView; 18 | this.data = TopicDataNetwork.getInstance(); 19 | } 20 | 21 | @Subscribe(threadMode = ThreadMode.MAIN) 22 | public void getNewTopic(CreateTopicEvent createTopicEvent) { 23 | createTopicView.getNewTopic(createTopicEvent.getTopicDetail()); 24 | } 25 | 26 | public void newTopic(String title, String body, int node_id) { 27 | ((TopicDataNetwork) data).newTopic(title, body, node_id); 28 | } 29 | 30 | @Override public void start() { 31 | EventBus.getDefault().register(this); 32 | } 33 | 34 | @Override public void stop() { 35 | EventBus.getDefault().unregister(this); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 13 | 14 | 15 | 16 | 19 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/presenter/SignInPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.user.event.TokenEvent; 7 | import com.plusend.diycode.model.user.model.UserDataNetwork; 8 | import com.plusend.diycode.model.user.view.SignInView; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class SignInPresenter extends BasePresenter { 14 | private static final String TAG = "SignInPresenter"; 15 | private SignInView signInView; 16 | private BaseData data; 17 | 18 | public SignInPresenter(SignInView signInView) { 19 | this.signInView = signInView; 20 | this.data = UserDataNetwork.getInstance(); 21 | } 22 | 23 | @Subscribe(threadMode = ThreadMode.MAIN) public void getToken(TokenEvent tokenEvent) { 24 | signInView.getToken(tokenEvent.getToken()); 25 | } 26 | 27 | public void getToken(String username, String password) { 28 | ((UserDataNetwork) data).getToken(username, password); 29 | } 30 | 31 | @Override public void start() { 32 | Log.d(TAG, "register"); 33 | EventBus.getDefault().register(this); 34 | } 35 | 36 | @Override public void stop() { 37 | Log.d(TAG, "unregister"); 38 | EventBus.getDefault().unregister(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/main/MainPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.main; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | import com.plusend.diycode.view.fragment.NewsFragment; 7 | import com.plusend.diycode.view.fragment.SitesFragment; 8 | import com.plusend.diycode.view.fragment.TopicFragment; 9 | 10 | /** 11 | * Created by plusend on 2016/11/22. 12 | */ 13 | 14 | public class MainPagerAdapter extends FragmentPagerAdapter { 15 | public MainPagerAdapter(FragmentManager fm) { 16 | super(fm); 17 | } 18 | 19 | @Override public Fragment getItem(int position) { 20 | switch (position) { 21 | case 0: 22 | return TopicFragment.newInstance("", TopicFragment.TYPE_ALL); 23 | case 1: 24 | return new NewsFragment(); 25 | case 2: 26 | return new SitesFragment(); 27 | default: 28 | return null; 29 | } 30 | } 31 | 32 | @Override public int getCount() { 33 | return 3; 34 | } 35 | 36 | @Override public CharSequence getPageTitle(int position) { 37 | switch (position) { 38 | case 0: 39 | return "topics"; 40 | case 1: 41 | return "news"; 42 | case 2: 43 | return "sites"; 44 | default: 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/entity/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * 用于记录用户收藏的用户,屏蔽的用户等 7 | */ 8 | public class UserInfo { 9 | 10 | @SerializedName("id") private int id; 11 | @SerializedName("login") private String login; 12 | @SerializedName("name") private String name; 13 | @SerializedName("avatar_url") private String avatarUrl; 14 | 15 | public int getId() { 16 | return id; 17 | } 18 | 19 | public void setId(int id) { 20 | this.id = id; 21 | } 22 | 23 | public String getLogin() { 24 | return login; 25 | } 26 | 27 | public void setLogin(String login) { 28 | this.login = login; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | public String getAvatarUrl() { 40 | return avatarUrl; 41 | } 42 | 43 | public void setAvatarUrl(String avatarUrl) { 44 | this.avatarUrl = avatarUrl; 45 | } 46 | 47 | @Override public String toString() { 48 | return "UserInfo{" 49 | + "id=" 50 | + id 51 | + ", login='" 52 | + login 53 | + '\'' 54 | + ", name='" 55 | + name 56 | + '\'' 57 | + ", avatarUrl='" 58 | + avatarUrl 59 | + '\'' 60 | + '}'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/res/layout/about_page_item_contributor.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 23 | 24 | 32 | 33 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/presenter/NodesBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.topic.node.data.NodeDataNetwork; 7 | import com.plusend.diycode.model.topic.node.event.NodesEvent; 8 | import com.plusend.diycode.model.topic.node.view.NodesView; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class NodesBasePresenter extends BasePresenter { 14 | private static final String TAG = "NodesPresenter"; 15 | private NodesView nodesView; 16 | private BaseData data; 17 | 18 | public NodesBasePresenter(NodesView nodesView) { 19 | this.nodesView = nodesView; 20 | data = NodeDataNetwork.getInstance(); 21 | } 22 | 23 | public void readNodes() { 24 | ((NodeDataNetwork) data).readNodes(); 25 | } 26 | 27 | @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) 28 | public void showNodes(NodesEvent nodesEvent) { 29 | Log.d(TAG, "showNodes"); 30 | nodesView.showNodes(nodesEvent.getNodeList()); 31 | EventBus.getDefault().removeStickyEvent(nodesEvent); 32 | } 33 | 34 | @Override public void start() { 35 | EventBus.getDefault().register(this); 36 | } 37 | 38 | @Override public void stop() { 39 | EventBus.getDefault().unregister(this); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/presenter/NewsNodesBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.news.node.data.NewsNodeDataNetwork; 7 | import com.plusend.diycode.model.news.node.event.NewsNodesEvent; 8 | import com.plusend.diycode.model.news.node.view.NewsNodesView; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class NewsNodesBasePresenter extends BasePresenter { 14 | private static final String TAG = "NodesPresenter"; 15 | private NewsNodesView newsNodesView; 16 | private BaseData data; 17 | 18 | public NewsNodesBasePresenter(NewsNodesView newsNodesView) { 19 | this.newsNodesView = newsNodesView; 20 | data = NewsNodeDataNetwork.getInstance(); 21 | } 22 | 23 | public void readNodes() { 24 | ((NewsNodeDataNetwork) data).readNewsNodes(); 25 | } 26 | 27 | @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) 28 | public void showNewsNodes(NewsNodesEvent newsNodesEvent) { 29 | Log.d(TAG, "showNewsNodes"); 30 | newsNodesView.showNodes(newsNodesEvent.getNewsNodeList()); 31 | EventBus.getDefault().removeStickyEvent(newsNodesEvent); 32 | } 33 | 34 | @Override public void start() { 35 | EventBus.getDefault().register(this); 36 | } 37 | 38 | @Override public void stop() { 39 | EventBus.getDefault().unregister(this); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/presenter/UserRepliesPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.topic.event.RepliesEvent; 7 | import com.plusend.diycode.model.topic.view.UserRepliesView; 8 | import com.plusend.diycode.model.user.model.UserDataNetwork; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class UserRepliesPresenter extends BasePresenter { 14 | private static final String TAG = "RepliesPresenter"; 15 | private UserRepliesView userRepliesView; 16 | private BaseData data; 17 | 18 | public UserRepliesPresenter(UserRepliesView userRepliesView) { 19 | this.userRepliesView = userRepliesView; 20 | data = UserDataNetwork.getInstance(); 21 | } 22 | 23 | @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) 24 | public void showReplies(RepliesEvent event) { 25 | Log.d(TAG, "showReplies"); 26 | userRepliesView.showReplies(event.getReplyList()); 27 | EventBus.getDefault().removeStickyEvent(event); 28 | } 29 | 30 | public void getReplies(String loginName, Integer offset) { 31 | ((UserDataNetwork) data).getUserReplies(loginName, offset, null); 32 | } 33 | 34 | @Override public void start() { 35 | EventBus.getDefault().register(this); 36 | } 37 | 38 | @Override public void stop() { 39 | EventBus.getDefault().unregister(this); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/presenter/CreateTopicReplyPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.topic.data.TopicDataNetwork; 7 | import com.plusend.diycode.model.topic.event.CreateTopicReplyEvent; 8 | import com.plusend.diycode.model.topic.view.CreateTopicReplyView; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class CreateTopicReplyPresenter extends BasePresenter { 14 | private static final String TAG = "CreateTopicReplyPresent"; 15 | private CreateTopicReplyView createTopicReplyView; 16 | private BaseData data; 17 | 18 | public CreateTopicReplyPresenter(CreateTopicReplyView createTopicReplyView) { 19 | this.createTopicReplyView = createTopicReplyView; 20 | data = TopicDataNetwork.getInstance(); 21 | } 22 | 23 | public void createTopicReply(int id, String body) { 24 | ((TopicDataNetwork) data).createReply(id, body); 25 | } 26 | 27 | @Subscribe(threadMode = ThreadMode.MAIN) 28 | public void getResult(CreateTopicReplyEvent createTopicReplyEvent) { 29 | Log.d(TAG, "getResult"); 30 | createTopicReplyView.getResult(createTopicReplyEvent.isSuccessful()); 31 | } 32 | 33 | @Override public void start() { 34 | EventBus.getDefault().register(this); 35 | } 36 | 37 | @Override public void stop() { 38 | EventBus.getDefault().unregister(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/entity/Site.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by plusend on 2016/11/27. 8 | */ 9 | 10 | public class Site { 11 | @SerializedName("name") private String name; 12 | @SerializedName("id") private int id; 13 | @SerializedName("sites") private List sites; 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | public int getId() { 24 | return id; 25 | } 26 | 27 | public void setId(int id) { 28 | this.id = id; 29 | } 30 | 31 | public List getSites() { 32 | return sites; 33 | } 34 | 35 | public void setSites(List sites) { 36 | this.sites = sites; 37 | } 38 | 39 | public static class Sites { 40 | @SerializedName("name") private String name; 41 | @SerializedName("url") private String url; 42 | @SerializedName("avatar_url") private String avatarUrl; 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | public String getUrl() { 53 | return url; 54 | } 55 | 56 | public void setUrl(String url) { 57 | this.url = url; 58 | } 59 | 60 | public String getAvatarUrl() { 61 | return avatarUrl; 62 | } 63 | 64 | public void setAvatarUrl(String avatarUrl) { 65 | this.avatarUrl = avatarUrl; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/presenter/NotificationsBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.notification.data.NotificationDataNetwork; 7 | import com.plusend.diycode.model.notification.event.NotificationsEvent; 8 | import com.plusend.diycode.model.notification.view.NotificationsView; 9 | import org.greenrobot.eventbus.EventBus; 10 | import org.greenrobot.eventbus.Subscribe; 11 | import org.greenrobot.eventbus.ThreadMode; 12 | 13 | public class NotificationsBasePresenter extends BasePresenter { 14 | private static final String TAG = "NotificationsPresenter"; 15 | private BaseData topicData; 16 | private NotificationsView view; 17 | 18 | public NotificationsBasePresenter(NotificationsView view) { 19 | this.view = view; 20 | this.topicData = NotificationDataNetwork.getInstance(); 21 | } 22 | 23 | public void readNotifications(int offset) { 24 | Log.d(TAG, "readNotifications"); 25 | ((NotificationDataNetwork) topicData).readNotifications(offset, null); 26 | } 27 | 28 | @Subscribe(sticky = true, threadMode = ThreadMode.MAIN) 29 | public void showNotifications(NotificationsEvent event) { 30 | Log.d(TAG, "showNotifications"); 31 | view.showNotifications(event.getNotificationList()); 32 | EventBus.getDefault().removeStickyEvent(event); 33 | } 34 | 35 | @Override public void start() { 36 | EventBus.getDefault().register(this); 37 | } 38 | 39 | @Override public void stop() { 40 | EventBus.getDefault().unregister(this); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 19 | 30 | 31 | 40 | 41 | 42 | 43 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/UrlDrawable.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.ColorFilter; 5 | import android.graphics.drawable.Drawable; 6 | 7 | public class UrlDrawable extends Drawable implements Drawable.Callback { 8 | 9 | private Drawable mDrawable; 10 | 11 | @Override public void draw(Canvas canvas) { 12 | if (mDrawable != null) { 13 | mDrawable.draw(canvas); 14 | } 15 | } 16 | 17 | @Override public void setAlpha(int alpha) { 18 | if (mDrawable != null) { 19 | mDrawable.setAlpha(alpha); 20 | } 21 | } 22 | 23 | @Override public void setColorFilter(ColorFilter cf) { 24 | if (mDrawable != null) { 25 | mDrawable.setColorFilter(cf); 26 | } 27 | } 28 | 29 | @Override public int getOpacity() { 30 | if (mDrawable != null) { 31 | return mDrawable.getOpacity(); 32 | } 33 | return 0; 34 | } 35 | 36 | public void setDrawable(Drawable drawable) { 37 | if (this.mDrawable != null) { 38 | this.mDrawable.setCallback(null); 39 | } 40 | drawable.setCallback(this); 41 | this.mDrawable = drawable; 42 | } 43 | 44 | @Override public void invalidateDrawable(Drawable who) { 45 | if (getCallback() != null) { 46 | getCallback().invalidateDrawable(who); 47 | } 48 | } 49 | 50 | @Override public void scheduleDrawable(Drawable who, Runnable what, long when) { 51 | if (getCallback() != null) { 52 | getCallback().scheduleDrawable(who, what, when); 53 | } 54 | } 55 | 56 | @Override public void unscheduleDrawable(Drawable who, Runnable what) { 57 | if (getCallback() != null) { 58 | getCallback().unscheduleDrawable(who, what); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_create_topic_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 15 | 22 | 23 | 31 | 32 | 39 | 40 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/notification/data/NotificationService.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.notification.data; 2 | 3 | import com.plusend.diycode.model.notification.entity.Notification; 4 | import com.plusend.diycode.model.notification.entity.NotificationDelete; 5 | import com.plusend.diycode.model.notification.entity.NotificationsDelete; 6 | import com.plusend.diycode.model.notification.entity.NotificationsRead; 7 | import com.plusend.diycode.model.notification.entity.NotificationsUnreadCount; 8 | import com.plusend.diycode.util.Constant; 9 | import java.util.List; 10 | import retrofit2.Call; 11 | import retrofit2.http.DELETE; 12 | import retrofit2.http.GET; 13 | import retrofit2.http.Header; 14 | import retrofit2.http.POST; 15 | import retrofit2.http.Path; 16 | import retrofit2.http.Query; 17 | 18 | interface NotificationService { 19 | 20 | /** 21 | * 获取当前用户的通知列表 22 | */ 23 | @GET("notifications.json") Call> readNotifications( 24 | @Header(Constant.KEY_TOKEN) String token, @Query("offset") Integer offset, 25 | @Query("limit") Integer limit); 26 | 27 | /** 28 | * 删除当前用户的某个通知 29 | */ 30 | @DELETE("notifications/{id}.json") Call deleteNotification( 31 | @Header(Constant.KEY_TOKEN) String token, @Path("id") int id); 32 | 33 | /** 34 | * 删除当前用户的所有通知 35 | */ 36 | @DELETE("notifications/all.json") Call deleteAllNotifications( 37 | @Header(Constant.KEY_TOKEN) String token); 38 | 39 | /** 40 | * 将当前用户的一些通知设成已读状态 41 | */ 42 | @POST("notifications/read.json") Call markNotificationsAsRead( 43 | @Header(Constant.KEY_TOKEN) String token, @Query("ids") int[] ids); 44 | 45 | /** 46 | * 获得未读通知数量 47 | */ 48 | @GET("notifications/unread_count.json") Call unReadNotificationCount( 49 | @Header(Constant.KEY_TOKEN) String token); 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/presenter/UserPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.user.event.MeEvent; 7 | import com.plusend.diycode.model.user.event.UserDetailInfoEvent; 8 | import com.plusend.diycode.model.user.model.UserDataNetwork; 9 | import com.plusend.diycode.model.user.view.UserView; 10 | import org.greenrobot.eventbus.EventBus; 11 | import org.greenrobot.eventbus.Subscribe; 12 | import org.greenrobot.eventbus.ThreadMode; 13 | 14 | public class UserPresenter extends BasePresenter { 15 | private static final String TAG = "UserPresenter"; 16 | private UserView userView; 17 | private BaseData data; 18 | 19 | public UserPresenter(UserView userView) { 20 | this.userView = userView; 21 | this.data = UserDataNetwork.getInstance(); 22 | } 23 | 24 | @Subscribe(threadMode = ThreadMode.MAIN) public void getMe(MeEvent event) { 25 | userView.getMe(event.getUserDetailInfo()); 26 | } 27 | 28 | @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) 29 | public void getMe(UserDetailInfoEvent userDetailInfoEvent) { 30 | Log.d(TAG, "getMe"); 31 | userView.getUser(userDetailInfoEvent.getUserDetailInfo()); 32 | EventBus.getDefault().removeStickyEvent(userDetailInfoEvent); 33 | } 34 | 35 | public void getMe() { 36 | ((UserDataNetwork) data).getMe(); 37 | } 38 | 39 | public void getUser(String loginName) { 40 | ((UserDataNetwork) data).getUser(loginName); 41 | } 42 | 43 | @Override public void start() { 44 | Log.d(TAG, "register"); 45 | EventBus.getDefault().register(this); 46 | } 47 | 48 | @Override public void stop() { 49 | Log.d(TAG, "unregister"); 50 | EventBus.getDefault().unregister(this); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/topic/FooterViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.topic; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ProgressBar; 9 | import android.widget.TextView; 10 | import butterknife.BindView; 11 | import butterknife.ButterKnife; 12 | import com.plusend.diycode.R; 13 | import me.drakeet.multitype.ItemViewProvider; 14 | 15 | public class FooterViewProvider extends ItemViewProvider { 16 | 17 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 18 | @NonNull ViewGroup parent) { 19 | View root = inflater.inflate(R.layout.item_topic_reply_load_more, parent, false); 20 | return new ViewHolder(root); 21 | } 22 | 23 | @Override protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Footer footer) { 24 | switch (footer.getStatus()) { 25 | case Footer.STATUS_NORMAL: 26 | holder.tips.setText("上拉加载更多"); 27 | holder.progressBar.setVisibility(View.GONE); 28 | break; 29 | case Footer.STATUS_LOADING: 30 | holder.tips.setText("加载中"); 31 | holder.progressBar.setVisibility(View.VISIBLE); 32 | break; 33 | case Footer.STATUS_NO_MORE: 34 | holder.tips.setText("没有更多了"); 35 | holder.progressBar.setVisibility(View.GONE); 36 | break; 37 | } 38 | } 39 | 40 | static class ViewHolder extends RecyclerView.ViewHolder { 41 | @BindView(R.id.tips) TextView tips; 42 | @BindView(R.id.progress_bar) ProgressBar progressBar; 43 | 44 | ViewHolder(View itemView) { 45 | super(itemView); 46 | ButterKnife.bind(this, itemView); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/LicenseViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | import com.plusend.diycode.R; 11 | import com.plusend.diycode.view.activity.WebActivity; 12 | import me.drakeet.multitype.ItemViewProvider; 13 | 14 | /** 15 | * @author drakeet 16 | */ 17 | public class LicenseViewProvider extends ItemViewProvider { 18 | 19 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 20 | @NonNull ViewGroup parent) { 21 | View root = inflater.inflate(R.layout.about_page_item_license, parent, false); 22 | return new ViewHolder(root); 23 | } 24 | 25 | @Override protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull License data) { 26 | holder.content.setText(data.name + " - " + data.author); 27 | holder.hint.setText(data.url + "\n" + data.type); 28 | holder.url = data.url; 29 | } 30 | 31 | static class ViewHolder extends RecyclerView.ViewHolder { 32 | 33 | TextView content; 34 | TextView hint; 35 | String url; 36 | 37 | ViewHolder(View itemView) { 38 | super(itemView); 39 | content = (TextView) itemView.findViewById(R.id.content); 40 | hint = (TextView) itemView.findViewById(R.id.hint); 41 | itemView.setOnClickListener(new View.OnClickListener() { 42 | @Override public void onClick(View v) { 43 | Intent intent = new Intent(v.getContext(), WebActivity.class); 44 | intent.putExtra(WebActivity.URL, url); 45 | v.getContext().startActivity(intent); 46 | } 47 | }); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/entity/Token.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Token { 6 | @SerializedName("access_token") private String accessToken; 7 | @SerializedName("token_type") private String tokenType; 8 | // accessToken 有效期60天 9 | @SerializedName("expires_in") private int expiresIn; 10 | @SerializedName("refresh_token") private String refreshToken; 11 | // accessToken 创建时间距 1970-01-01 00:00:00 的秒数 12 | @SerializedName("created_at") private int createdAt; 13 | 14 | public String getAccessToken() { 15 | return accessToken; 16 | } 17 | 18 | public void setAccessToken(String accessToken) { 19 | this.accessToken = accessToken; 20 | } 21 | 22 | public String getTokenType() { 23 | return tokenType; 24 | } 25 | 26 | public void setTokenType(String tokenType) { 27 | this.tokenType = tokenType; 28 | } 29 | 30 | public int getExpiresIn() { 31 | return expiresIn; 32 | } 33 | 34 | public void setExpiresIn(int expiresIn) { 35 | this.expiresIn = expiresIn; 36 | } 37 | 38 | public String getRefreshToken() { 39 | return refreshToken; 40 | } 41 | 42 | public void setRefreshToken(String refreshToken) { 43 | this.refreshToken = refreshToken; 44 | } 45 | 46 | public int getCreatedAt() { 47 | return createdAt; 48 | } 49 | 50 | public void setCreatedAt(int createdAt) { 51 | this.createdAt = createdAt; 52 | } 53 | 54 | @Override public String toString() { 55 | return "Token{" 56 | + "accessToken='" 57 | + accessToken 58 | + '\'' 59 | + ", tokenType='" 60 | + tokenType 61 | + '\'' 62 | + ", expiresIn=" 63 | + expiresIn 64 | + ", refreshToken='" 65 | + refreshToken 66 | + '\'' 67 | + ", createdAt=" 68 | + createdAt 69 | + '}'; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/site/data/SiteDataNetwork.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.site.data; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.site.entity.Site; 5 | import com.plusend.diycode.model.site.event.SiteEvent; 6 | import java.util.List; 7 | import org.greenrobot.eventbus.EventBus; 8 | import retrofit2.Call; 9 | import retrofit2.Callback; 10 | import retrofit2.Response; 11 | import retrofit2.Retrofit; 12 | import retrofit2.converter.gson.GsonConverterFactory; 13 | 14 | public class SiteDataNetwork implements SiteData { 15 | private static final String TAG = "NetworkData"; 16 | private static SiteDataNetwork networkData = new SiteDataNetwork(); 17 | private SiteService service; 18 | 19 | private SiteDataNetwork() { 20 | Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.diycode.cc/api/v3/") 21 | .addConverterFactory(GsonConverterFactory.create()) 22 | .build(); 23 | service = retrofit.create(SiteService.class); 24 | } 25 | 26 | public static SiteDataNetwork getInstance() { 27 | return networkData; 28 | } 29 | 30 | @Override public void getSite() { 31 | Call> call = service.getSite(); 32 | 33 | call.enqueue(new Callback>() { 34 | @Override public void onResponse(Call> call, Response> response) { 35 | if (response.isSuccessful()) { 36 | List siteList = response.body(); 37 | Log.v(TAG, "siteList:" + siteList); 38 | EventBus.getDefault().post(new SiteEvent(siteList)); 39 | } else { 40 | Log.e(TAG, "getSite STATUS: " + response.code()); 41 | EventBus.getDefault().post(new SiteEvent(null)); 42 | } 43 | } 44 | 45 | @Override public void onFailure(Call> call, Throwable t) { 46 | Log.e(TAG, t.getMessage()); 47 | EventBus.getDefault().post(new SiteEvent(null)); 48 | } 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 20 | 21 | 22 | 26 | 27 | 30 | 31 | 41 | 42 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/util/TimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.util; 2 | 3 | import android.util.Log; 4 | import java.text.ParseException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | import java.util.Locale; 8 | 9 | /** 10 | * Created by plusend on 2016/11/26. 11 | */ 12 | 13 | public class TimeUtil { 14 | private static final String TAG = "TimeUtil"; 15 | 16 | public static String computePastTime(String time) { 17 | Log.v(TAG, "computePastTime: " + time); 18 | String result = "刚刚"; 19 | //2016-11-25T16:55:21.791+08:00 20 | time = time.replace("T", " "); 21 | time = time.substring(0, 22); 22 | Log.v(TAG, "computePastTime time: " + time); 23 | SimpleDateFormat simpleDateFormat = 24 | new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.SIMPLIFIED_CHINESE); 25 | try { 26 | Date t = simpleDateFormat.parse(time); 27 | Date now = new Date(System.currentTimeMillis()); 28 | long diff = (now.getTime() - t.getTime()) / 1000; 29 | if (diff < 60) { 30 | result = "刚刚"; 31 | } else if ((diff /= 60) < 60) { 32 | result = diff + "分钟前"; 33 | } else if ((diff /= 60) < 24) { 34 | result = diff + "小时前"; 35 | } else if ((diff /= 24) < 30) { 36 | result = diff + "天前"; 37 | } else if ((diff /= 30) < 12) { 38 | result = diff + "月前"; 39 | } else { 40 | diff /= 12; 41 | result = diff + "年前"; 42 | } 43 | } catch (ParseException e) { 44 | e.printStackTrace(); 45 | } 46 | Log.v(TAG, "computePastTime result: " + result); 47 | return result; 48 | } 49 | 50 | public static String formatTime(String time) { 51 | Log.v(TAG, "formatTime: " + time); 52 | //2016-11-25T16:55:21.791+08:00 53 | time = time.replace("T", " "); 54 | time = time.substring(0, 16); 55 | Log.v(TAG, "formatTime result: " + time); 56 | return time; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/presenter/TopicsPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.topic.data.TopicDataNetwork; 7 | import com.plusend.diycode.model.topic.event.TopTopicsEvent; 8 | import com.plusend.diycode.model.topic.event.TopicsEvent; 9 | import com.plusend.diycode.model.topic.view.TopicsView; 10 | import org.greenrobot.eventbus.EventBus; 11 | import org.greenrobot.eventbus.Subscribe; 12 | import org.greenrobot.eventbus.ThreadMode; 13 | 14 | public class TopicsPresenter extends BasePresenter { 15 | private static final String TAG = "TopicsPresenter"; 16 | 17 | private BaseData data; 18 | private TopicsView topicsView; 19 | 20 | public TopicsPresenter(TopicsView topicsView) { 21 | this.data = TopicDataNetwork.getInstance(); 22 | this.topicsView = topicsView; 23 | } 24 | 25 | @Subscribe(threadMode = ThreadMode.MAIN) public void showTopics(TopicsEvent topicsEvent) { 26 | Log.d(TAG, "showTopics: " + topicsEvent.getTopicList()); 27 | topicsView.showTopics(topicsEvent.getTopicList()); 28 | } 29 | 30 | @Subscribe(threadMode = ThreadMode.MAIN) public void showTopTopics(TopTopicsEvent topicsEvent) { 31 | Log.d(TAG, "showTopTopics: " + topicsEvent.getTopicList()); 32 | topicsView.showTopTopics(topicsEvent.getTopicList()); 33 | } 34 | 35 | public void getTopics(Integer offset) { 36 | Log.d(TAG, "getTopics: offset: " + offset); 37 | ((TopicDataNetwork) data).getTopics(null, null, offset, null); 38 | } 39 | 40 | public void getTopTopics() { 41 | Log.d(TAG, "getTopTopics"); 42 | ((TopicDataNetwork) data).getTopTopics(); 43 | } 44 | 45 | @Override public void start() { 46 | Log.d(TAG, "register"); 47 | EventBus.getDefault().register(this); 48 | } 49 | 50 | @Override public void stop() { 51 | Log.d(TAG, "unregister"); 52 | EventBus.getDefault().unregister(this); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/data/NodeDataNetwork.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.data; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.topic.node.entity.Node; 5 | import com.plusend.diycode.model.topic.node.event.NodesEvent; 6 | import java.util.List; 7 | import org.greenrobot.eventbus.EventBus; 8 | import retrofit2.Call; 9 | import retrofit2.Callback; 10 | import retrofit2.Response; 11 | import retrofit2.Retrofit; 12 | import retrofit2.converter.gson.GsonConverterFactory; 13 | 14 | public class NodeDataNetwork implements NodeData { 15 | private static final String TAG = "NetworkData"; 16 | private static NodeDataNetwork networkData = new NodeDataNetwork(); 17 | private NodeService service; 18 | 19 | private NodeDataNetwork() { 20 | Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.diycode.cc/api/v3/") 21 | .addConverterFactory(GsonConverterFactory.create()) 22 | .build(); 23 | service = retrofit.create(NodeService.class); 24 | } 25 | 26 | public static NodeDataNetwork getInstance() { 27 | return networkData; 28 | } 29 | 30 | @Override public void readNodes() { 31 | Call> call = service.readNodes(); 32 | call.enqueue(new Callback>() { 33 | @Override public void onResponse(Call> call, Response> response) { 34 | if (response.isSuccessful()) { 35 | List nodeList = response.body(); 36 | Log.v(TAG, "nodeList:" + nodeList); 37 | EventBus.getDefault().postSticky(new NodesEvent(nodeList)); 38 | } else { 39 | Log.e(TAG, "readNodes STATUS: " + response.code()); 40 | EventBus.getDefault().postSticky(new NodesEvent(null)); 41 | } 42 | } 43 | 44 | @Override public void onFailure(Call> call, Throwable t) { 45 | Log.e(TAG, t.getMessage()); 46 | EventBus.getDefault().postSticky(new NodesEvent(null)); 47 | } 48 | }); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/node/entity/Node.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.node.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by plusend on 2016/12/5. 7 | */ 8 | 9 | public class Node { 10 | @SerializedName("id") private int id; 11 | @SerializedName("name") private String name; 12 | @SerializedName("topics_count") private int topicsCount; 13 | @SerializedName("summary") private String summary; 14 | @SerializedName("section_id") private int sectionId; 15 | @SerializedName("sort") private int sort; 16 | @SerializedName("section_name") private String sectionName; 17 | @SerializedName("updated_at") private String updatedAt; 18 | 19 | public int getId() { 20 | return id; 21 | } 22 | 23 | public void setId(int id) { 24 | this.id = id; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public int getTopicsCount() { 36 | return topicsCount; 37 | } 38 | 39 | public void setTopicsCount(int topicsCount) { 40 | this.topicsCount = topicsCount; 41 | } 42 | 43 | public String getSummary() { 44 | return summary; 45 | } 46 | 47 | public void setSummary(String summary) { 48 | this.summary = summary; 49 | } 50 | 51 | public int getSectionId() { 52 | return sectionId; 53 | } 54 | 55 | public void setSectionId(int sectionId) { 56 | this.sectionId = sectionId; 57 | } 58 | 59 | public int getSort() { 60 | return sort; 61 | } 62 | 63 | public void setSort(int sort) { 64 | this.sort = sort; 65 | } 66 | 67 | public String getSectionName() { 68 | return sectionName; 69 | } 70 | 71 | public void setSectionName(String sectionName) { 72 | this.sectionName = sectionName; 73 | } 74 | 75 | public String getUpdatedAt() { 76 | return updatedAt; 77 | } 78 | 79 | public void setUpdatedAt(String updatedAt) { 80 | this.updatedAt = updatedAt; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/res/layout/app_bar_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 18 | 26 | 33 | 34 | 35 | 38 | 39 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/user/presenter/UserTopicsPresenter.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.user.presenter; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.base.BaseData; 5 | import com.plusend.diycode.model.base.BasePresenter; 6 | import com.plusend.diycode.model.topic.view.TopicsView; 7 | import com.plusend.diycode.model.user.event.UserFavoriteTopicsEvent; 8 | import com.plusend.diycode.model.user.event.UserTopicsEvent; 9 | import com.plusend.diycode.model.user.model.UserDataNetwork; 10 | import org.greenrobot.eventbus.EventBus; 11 | import org.greenrobot.eventbus.Subscribe; 12 | import org.greenrobot.eventbus.ThreadMode; 13 | 14 | public class UserTopicsPresenter extends BasePresenter { 15 | private static final String TAG = "UserTopicsPresenter"; 16 | 17 | private BaseData data; 18 | private TopicsView topicsView; 19 | 20 | public UserTopicsPresenter(TopicsView topicsView) { 21 | this.data = UserDataNetwork.getInstance(); 22 | this.topicsView = topicsView; 23 | } 24 | 25 | @Subscribe(threadMode = ThreadMode.MAIN) 26 | public void showUserCreateTopics(UserTopicsEvent userTopicsEvent) { 27 | Log.d(TAG, "showUserCreateTopics: " + userTopicsEvent.getTopicList().size()); 28 | topicsView.showTopics(userTopicsEvent.getTopicList()); 29 | } 30 | 31 | @Subscribe(threadMode = ThreadMode.MAIN) 32 | public void showUserFavoriteTopics(UserFavoriteTopicsEvent event) { 33 | Log.d(TAG, "showUserFavoriteTopics: " + event.getTopicList().size()); 34 | topicsView.showTopics(event.getTopicList()); 35 | } 36 | 37 | public void getUserCreateTopics(String loginName, Integer offset) { 38 | ((UserDataNetwork) data).getUserCreateTopics(loginName, offset, null); 39 | } 40 | 41 | public void getUserFavoriteTopics(String loginName, Integer offset) { 42 | ((UserDataNetwork) data).getUserFavoriteTopics(loginName, offset, null); 43 | } 44 | 45 | @Override public void start() { 46 | Log.d(TAG, "register"); 47 | EventBus.getDefault().register(this); 48 | } 49 | 50 | @Override public void stop() { 51 | Log.d(TAG, "unregister"); 52 | EventBus.getDefault().unregister(this); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/news/node/data/NewsNodeDataNetwork.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.news.node.data; 2 | 3 | import android.util.Log; 4 | import com.plusend.diycode.model.news.node.entity.NewsNode; 5 | import com.plusend.diycode.model.news.node.event.NewsNodesEvent; 6 | import java.util.List; 7 | import org.greenrobot.eventbus.EventBus; 8 | import retrofit2.Call; 9 | import retrofit2.Callback; 10 | import retrofit2.Response; 11 | import retrofit2.Retrofit; 12 | import retrofit2.converter.gson.GsonConverterFactory; 13 | 14 | public class NewsNodeDataNetwork implements NewsNodeData { 15 | private static final String TAG = "NetworkData"; 16 | private static NewsNodeDataNetwork networkData = new NewsNodeDataNetwork(); 17 | private NewsNodeService service; 18 | 19 | private NewsNodeDataNetwork() { 20 | Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.diycode.cc/api/v3/") 21 | .addConverterFactory(GsonConverterFactory.create()) 22 | .build(); 23 | service = retrofit.create(NewsNodeService.class); 24 | } 25 | 26 | public static NewsNodeDataNetwork getInstance() { 27 | return networkData; 28 | } 29 | 30 | @Override public void readNewsNodes() { 31 | Call> call = service.readNewsNodes(); 32 | call.enqueue(new Callback>() { 33 | @Override 34 | public void onResponse(Call> call, Response> response) { 35 | if (response.isSuccessful()) { 36 | List newsNodeList = response.body(); 37 | Log.v(TAG, "newsNodeList:" + newsNodeList); 38 | EventBus.getDefault().postSticky(new NewsNodesEvent(newsNodeList)); 39 | } else { 40 | Log.e(TAG, "readNewsNodes STATUS: " + response.code()); 41 | EventBus.getDefault().postSticky(new NewsNodesEvent(null)); 42 | } 43 | } 44 | 45 | @Override public void onFailure(Call> call, Throwable t) { 46 | Log.e(TAG, t.getMessage()); 47 | EventBus.getDefault().postSticky(new NewsNodesEvent(null)); 48 | } 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/adapter/about/ContributorViewProvider.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.adapter.about; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | import com.plusend.diycode.R; 12 | import com.plusend.diycode.view.activity.WebActivity; 13 | import me.drakeet.multitype.ItemViewProvider; 14 | 15 | /** 16 | * @author drakeet 17 | */ 18 | public class ContributorViewProvider 19 | extends ItemViewProvider { 20 | 21 | @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, 22 | @NonNull ViewGroup parent) { 23 | View root = inflater.inflate(R.layout.about_page_item_contributor, parent, false); 24 | return new ViewHolder(root); 25 | } 26 | 27 | @Override 28 | protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Contributor contributor) { 29 | holder.avatar.setImageResource(contributor.avatarResId); 30 | holder.name.setText(contributor.name); 31 | holder.desc.setText(contributor.desc); 32 | holder.url = contributor.url; 33 | } 34 | 35 | static class ViewHolder extends RecyclerView.ViewHolder { 36 | 37 | ImageView avatar; 38 | TextView name; 39 | TextView desc; 40 | String url; 41 | 42 | ViewHolder(View itemView) { 43 | super(itemView); 44 | avatar = (ImageView) itemView.findViewById(R.id.avatar); 45 | name = (TextView) itemView.findViewById(R.id.name); 46 | desc = (TextView) itemView.findViewById(R.id.desc); 47 | 48 | itemView.setOnClickListener(new View.OnClickListener() { 49 | @Override public void onClick(View view) { 50 | Intent intent = new Intent(view.getContext(), WebActivity.class); 51 | intent.putExtra(WebActivity.URL, url); 52 | view.getContext().startActivity(intent); 53 | } 54 | }); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/model/topic/data/TopicData.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.model.topic.data; 2 | 3 | import com.plusend.diycode.model.base.BaseData; 4 | 5 | interface TopicData extends BaseData { 6 | 7 | /** 8 | * 获取话题列表 9 | * 10 | * @param type 默认值 last_actived 范围 ["last_actived", "recent", "no_reply", "popular", 11 | * "excellent"] 12 | * @param nodeId 如果你需要只看某个节点的,请传此参数 13 | * @param offset 默认 0,从第 21 条开始就传 20 14 | * @param limit 默认 20 范围 [1..150] 15 | */ 16 | void getTopics(String type, Integer nodeId, Integer offset, Integer limit); 17 | 18 | /** 19 | * 获取置顶话题 20 | */ 21 | void getTopTopics(); 22 | 23 | /** 24 | * 获取话题详情 25 | * 26 | * @param id 帖子 id 27 | */ 28 | void getTopic(int id); 29 | 30 | /** 31 | * 获取话题评论 32 | * 33 | * @param id 帖子 id 34 | * @param offset 默认 0 35 | * @param limit 默认 20 范围 [1..150] 36 | */ 37 | void getReplies(int id, Integer offset, Integer limit); 38 | 39 | /** 40 | * 创建话题 41 | * 42 | * @param title 话题标题 43 | * @param body 话题内容, Markdown 格式 44 | * @param nodeId 节点编号 45 | */ 46 | void newTopic(String title, String body, int nodeId); 47 | 48 | /** 49 | * 收藏话题 50 | * 51 | * @param id 话题 id 52 | */ 53 | void favorite(int id); 54 | 55 | /** 56 | * 取消收藏话题 57 | * 58 | * @param id 话题 id 59 | */ 60 | void unFavorite(int id); 61 | 62 | /** 63 | * 关注话题 64 | * 65 | * @param id 话题 id 66 | */ 67 | void follow(int id); 68 | 69 | /** 70 | * 取消关注话题 71 | * 72 | * @param id 话题 id 73 | */ 74 | void unFollow(int id); 75 | 76 | /** 77 | * 赞 78 | * 79 | * @param obj_type ["topic", "reply", "news"] 80 | * @param obj_id id 81 | */ 82 | void like(String obj_type, Integer obj_id); 83 | 84 | /** 85 | * 取消赞 86 | * 87 | * @param obj_type ["topic", "reply", "news"] 88 | * @param obj_id id 89 | */ 90 | void unLike(String obj_type, Integer obj_id); 91 | 92 | /** 93 | * 创建回帖 94 | * 95 | * @param id 帖子 id 96 | * @param body 回帖内容, Markdown 格式 97 | */ 98 | void createReply(int id, String body); 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/widget/EmptyRecyclerView.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.widget; 2 | 3 | /** 4 | * Created by plusend on 2016/12/18. 5 | */ 6 | 7 | import android.content.Context; 8 | import android.support.annotation.NonNull; 9 | import android.support.annotation.Nullable; 10 | import android.support.v7.widget.RecyclerView; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | 14 | public class EmptyRecyclerView extends RecyclerView { 15 | @Nullable View emptyView; 16 | final @NonNull AdapterDataObserver observer = new AdapterDataObserver() { 17 | 18 | @Override public void onChanged() { 19 | super.onChanged(); 20 | checkIfEmpty(); 21 | } 22 | 23 | @Override public void onItemRangeInserted(int positionStart, int itemCount) { 24 | super.onItemRangeInserted(positionStart, itemCount); 25 | checkIfEmpty(); 26 | } 27 | 28 | @Override public void onItemRangeRemoved(int positionStart, int itemCount) { 29 | super.onItemRangeRemoved(positionStart, itemCount); 30 | checkIfEmpty(); 31 | } 32 | }; 33 | 34 | public EmptyRecyclerView(Context context) { 35 | super(context); 36 | } 37 | 38 | public EmptyRecyclerView(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | } 41 | 42 | public EmptyRecyclerView(Context context, AttributeSet attrs, int defStyle) { 43 | super(context, attrs, defStyle); 44 | } 45 | 46 | void checkIfEmpty() { 47 | if (emptyView != null && getAdapter() != null) { 48 | emptyView.setVisibility(getAdapter().getItemCount() > 0 ? GONE : VISIBLE); 49 | this.setVisibility(getAdapter().getItemCount() > 0 ? VISIBLE : GONE); 50 | } 51 | } 52 | 53 | @Override public void setAdapter(@Nullable Adapter adapter) { 54 | final Adapter oldAdapter = getAdapter(); 55 | if (oldAdapter != null) { 56 | oldAdapter.unregisterAdapterDataObserver(observer); 57 | } 58 | super.setAdapter(adapter); 59 | if (adapter != null) { 60 | adapter.registerAdapterDataObserver(observer); 61 | } 62 | } 63 | 64 | public void setEmptyView(@Nullable View emptyView) { 65 | this.emptyView = emptyView; 66 | checkIfEmpty(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion '27.0.3' 6 | defaultConfig { 7 | applicationId "com.plusend.diycode" 8 | minSdkVersion 21 9 | targetSdkVersion 27 10 | versionCode 18 11 | versionName "0.4.8" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | vectorDrawables.useSupportLibrary = true 14 | manifestPlaceholders = [PGYER_APPID: "${PGYER_APPID_VALUE}"] 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | zipAlignEnabled true 21 | shrinkResources true 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | implementation('me.drakeet.multitype:multitype:2.5.0', { 29 | exclude group: 'com.android.support' 30 | }) 31 | implementation 'com.android.support:appcompat-v7:27.1.1' 32 | implementation 'com.android.support:preference-v7:27.1.1' 33 | implementation 'com.android.support:design:27.1.1' 34 | implementation 'com.jakewharton:butterknife:8.8.1' 35 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 36 | implementation 'com.google.code.gson:gson:2.8.1' 37 | implementation 'com.github.bumptech.glide:glide:4.3.0' 38 | implementation 'jp.wasabeef:glide-transformations:2.0.2' 39 | implementation 'com.squareup.retrofit2:retrofit:2.3.0' 40 | implementation 'com.squareup.retrofit2:converter-gson:2.3.0' 41 | implementation 'org.greenrobot:eventbus:3.0.0' 42 | implementation 'com.android.support:support-v4:27.1.1' 43 | implementation 'com.android.support:support-vector-drawable:27.1.1' 44 | implementation 'com.github.chrisbanes:PhotoView:2.1.3' 45 | implementation 'cn.bingoogolapple:bga-swipebacklayout:1.0.8@aar' 46 | implementation 'com.jaeger.statusbaruitl:library:1.3.6' 47 | implementation 'com.pgyersdk:sdk:2.5.4' 48 | implementation 'com.github.hotchemi:permissionsdispatcher:3.2.0' 49 | annotationProcessor "com.github.hotchemi:permissionsdispatcher-processor:3.2.0" 50 | implementation 'com.android.support:support-v13:27.1.1' 51 | implementation 'org.jsoup:jsoup:1.10.2' 52 | implementation 'com.android.support.constraint:constraint-layout:1.1.2' 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.fragment; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | import android.support.v4.app.Fragment; 6 | import android.util.Log; 7 | import com.plusend.diycode.model.base.BasePresenter; 8 | 9 | public abstract class BaseFragment extends Fragment { 10 | private static final String TAG = "BaseFragment"; 11 | private OnFragmentInteractionListener mListener; 12 | 13 | public BaseFragment() { 14 | // Required empty public constructor 15 | } 16 | 17 | protected abstract BasePresenter getPresenter(); 18 | 19 | @Override public void onAttach(Context context) { 20 | super.onAttach(context); 21 | if (context instanceof OnFragmentInteractionListener) { 22 | mListener = (OnFragmentInteractionListener) context; 23 | } else { 24 | // TODO 25 | //throw new RuntimeException( 26 | // context.toString() + " must implement OnFragmentInteractionListener"); 27 | } 28 | } 29 | 30 | @Override public void onDetach() { 31 | 32 | super.onDetach(); 33 | mListener = null; 34 | } 35 | 36 | @Override public void onStart() { 37 | super.onStart(); 38 | if (getPresenter() != null) { 39 | getPresenter().start(); 40 | } else { 41 | Log.d(TAG, "onStart getPresenter() == null"); 42 | } 43 | } 44 | 45 | @Override public void onStop() { 46 | if (getPresenter() != null) { 47 | getPresenter().stop(); 48 | } else { 49 | Log.d(TAG, "onStop getPresenter() == null"); 50 | } 51 | super.onStop(); 52 | } 53 | 54 | public void onButtonPressed(Uri uri) { 55 | if (mListener != null) { 56 | mListener.onFragmentInteraction(uri); 57 | } 58 | } 59 | 60 | /** 61 | * This interface must be implemented by activities that contain this 62 | * fragment to allow an interaction in this fragment to be communicated 63 | * to the activity and potentially other fragments contained in that 64 | * activity. 65 | *

66 | * See the Android Training lesson Communicating with Other Fragments for more information. 69 | */ 70 | public interface OnFragmentInteractionListener { 71 | void onFragmentInteraction(Uri uri); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_topic.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 20 | 26 | 27 | 28 | 33 | 34 | 41 | 47 | 48 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_topic.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 19 | 24 | 32 | 40 | 50 | 51 | 52 | 61 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/plusend/diycode/view/activity/SearchActivity.java: -------------------------------------------------------------------------------- 1 | package com.plusend.diycode.view.activity; 2 | 3 | import android.app.SearchManager; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.support.v7.widget.SearchView; 8 | import android.support.v7.widget.Toolbar; 9 | import android.util.Log; 10 | import android.view.Menu; 11 | import android.view.MenuInflater; 12 | import android.view.MenuItem; 13 | import android.widget.TextView; 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | import com.plusend.diycode.R; 17 | import com.plusend.diycode.model.base.BasePresenter; 18 | import java.util.List; 19 | 20 | public class SearchActivity extends BaseActivity { 21 | private static final String TAG = "SearchActivity"; 22 | @BindView(R.id.toolbar) Toolbar toolbar; 23 | @BindView(R.id.result) TextView result; 24 | SearchView searchView; 25 | private String fromQuery; 26 | 27 | @Override protected void onCreate(Bundle savedInstanceState) { 28 | setContentView(R.layout.activity_search); 29 | ButterKnife.bind(this); 30 | super.onCreate(savedInstanceState); 31 | 32 | handleIntent(getIntent()); 33 | } 34 | 35 | @Override protected Toolbar getToolbar() { 36 | return toolbar; 37 | } 38 | 39 | @Override protected List getPresenter() { 40 | return null; 41 | } 42 | 43 | @Override protected void onNewIntent(Intent intent) { 44 | handleIntent(intent); 45 | } 46 | 47 | private void handleIntent(Intent intent) { 48 | 49 | if (Intent.ACTION_SEARCH.equals(intent.getAction())) { 50 | String query = intent.getStringExtra(SearchManager.QUERY); 51 | Log.d(TAG, "query: " + query); 52 | fromQuery = query; 53 | result.setText(query); 54 | } 55 | } 56 | 57 | @Override public boolean onCreateOptionsMenu(Menu menu) { 58 | MenuInflater inflater = getMenuInflater(); 59 | inflater.inflate(R.menu.activity_search, menu); 60 | MenuItem search = menu.findItem(R.id.action_search); 61 | SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); 62 | searchView = (SearchView) search.getActionView(); 63 | searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); 64 | // 更改输入法中的搜索 65 | searchView.setImeOptions(3); 66 | // 展开 67 | search.expandActionView(); 68 | // 设置初始值 69 | searchView.setQuery(fromQuery, false); 70 | return true; 71 | } 72 | } 73 | --------------------------------------------------------------------------------