├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── bg_flower.png │ │ │ │ ├── bg_sakura.jpg │ │ │ │ ├── ic_autumn.png │ │ │ │ ├── ic_spring.png │ │ │ │ ├── ic_summer.png │ │ │ │ ├── ic_winter.png │ │ │ │ ├── bg_flower_sakura.png │ │ │ │ ├── ic_google_paly_store.png │ │ │ │ ├── bg_tag_pressed.xml │ │ │ │ ├── bg_button_pressed.xml │ │ │ │ ├── bg_tag_default.xml │ │ │ │ ├── bg_no_cover.xml │ │ │ │ ├── bg_drawer_header.xml │ │ │ │ ├── bg_button_default.xml │ │ │ │ ├── bg_tag.xml │ │ │ │ ├── bg_button.xml │ │ │ │ ├── ic_add_white_24dp.xml │ │ │ │ ├── ic_clear_all_white_24dp.xml │ │ │ │ ├── ic_music_black_24dp.xml │ │ │ │ ├── ic_game_black_24dp.xml │ │ │ │ ├── ic_manga_black_24dp.xml │ │ │ │ ├── ic_subs_black_24dp.xml │ │ │ │ ├── ic_news_black_24dp.xml │ │ │ │ ├── ic_raw_black_24dp.xml │ │ │ │ ├── ic_fan_black_24dp.xml │ │ │ │ ├── ic_category_white_24dp.xml │ │ │ │ ├── ic_anime_black_24dp.xml │ │ │ │ ├── ic_favorite_white_24dp.xml │ │ │ │ ├── ic_weekly_fans_black_24dp.xml │ │ │ │ ├── ic_jp_tv_black_24dp.xml │ │ │ │ ├── ic_search_white_24dp.xml │ │ │ │ ├── ic_perm_contact_calendar_black_24dp.xml │ │ │ │ ├── ic_export_white_24dp.xml │ │ │ │ ├── ic_import_white_24dp.xml │ │ │ │ ├── ic_other_black_24dp.xml │ │ │ │ ├── ic_collection_list_black_24dp.xml │ │ │ │ ├── ic_rss_feed_black_24dp.xml │ │ │ │ ├── ic_group_black_24dp.xml │ │ │ │ ├── ic_tokusatsu_black_24dp.xml │ │ │ │ ├── ic_category_black_24dp.xml │ │ │ │ ├── ic_favorite_border_white_24dp.xml │ │ │ │ ├── ic_new_post_black_24dp.xml │ │ │ │ ├── ic_item_black_24dp.xml │ │ │ │ ├── ic_history_fans_black_24dp.xml │ │ │ │ └── ic_action_menu.xml │ │ │ ├── mipmap-xhdpi │ │ │ │ └── app_icon.png │ │ │ ├── xml │ │ │ │ └── searchable.xml │ │ │ ├── values │ │ │ │ ├── dimens.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ ├── layout │ │ │ │ ├── item_index_season.xml │ │ │ │ ├── item_sub.xml │ │ │ │ ├── fragment_recycler_view_with_refresh_layout.xml │ │ │ │ ├── dialog_info.xml │ │ │ │ ├── item_index.xml │ │ │ │ ├── dialog_info_with_progressbar.xml │ │ │ │ ├── item_fan.xml │ │ │ │ ├── item_team.xml │ │ │ │ ├── item_fans.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── drawer_header_view.xml │ │ │ │ ├── item_rss_post_no_cover.xml │ │ │ │ └── item_local_fan.xml │ │ │ ├── menu │ │ │ │ ├── menu_main.xml │ │ │ │ └── menu_local.xml │ │ │ ├── animator │ │ │ │ └── touch_floating.xml │ │ │ └── layout-v21 │ │ │ │ ├── item_index.xml │ │ │ │ ├── item_fan.xml │ │ │ │ ├── item_team.xml │ │ │ │ ├── item_fans.xml │ │ │ │ ├── item_rss_post_no_cover.xml │ │ │ │ └── item_local_fan.xml │ │ ├── java │ │ │ └── star │ │ │ │ └── iota │ │ │ │ └── sakura │ │ │ │ ├── base │ │ │ │ ├── PVContract.java │ │ │ │ ├── BaseViewHolder.java │ │ │ │ ├── PagerAdapter.java │ │ │ │ ├── BaseAdapter.java │ │ │ │ ├── StringPresenter.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseActivity.java │ │ │ │ └── ScrollAwareFABBehavior.java │ │ │ │ ├── database │ │ │ │ ├── FanDAO.java │ │ │ │ ├── SubsDAO.java │ │ │ │ └── DBHelper.java │ │ │ │ ├── ui │ │ │ │ ├── team │ │ │ │ │ ├── TeamBean.java │ │ │ │ │ ├── def │ │ │ │ │ │ ├── TeamDefaultFragment.java │ │ │ │ │ │ ├── TeamDefaultAdapter.java │ │ │ │ │ │ └── TeamDefaultViewHolder.java │ │ │ │ │ ├── rss │ │ │ │ │ │ ├── TeamRSSFragment.java │ │ │ │ │ │ ├── TeamRSSAdapter.java │ │ │ │ │ │ └── TeamRSSViewHolder.java │ │ │ │ │ ├── TeamPresenter.java │ │ │ │ │ └── TeamFragment.java │ │ │ │ ├── post │ │ │ │ │ ├── SubBean.java │ │ │ │ │ ├── PostAdapter.java │ │ │ │ │ ├── PostBean.java │ │ │ │ │ └── PostPresenter.java │ │ │ │ ├── index │ │ │ │ │ ├── IndexPresenter.java │ │ │ │ │ ├── IndexBean.java │ │ │ │ │ ├── IndexFragment.java │ │ │ │ │ └── IndexAdapter.java │ │ │ │ ├── fans │ │ │ │ │ ├── oldfans │ │ │ │ │ │ ├── FansBean.java │ │ │ │ │ │ ├── FansAdapter.java │ │ │ │ │ │ ├── FanAdapter.java │ │ │ │ │ │ ├── SeasonBean.java │ │ │ │ │ │ ├── FanViewHolder.java │ │ │ │ │ │ ├── FansViewHolder.java │ │ │ │ │ │ ├── FansPresenter.java │ │ │ │ │ │ └── FansFragment.java │ │ │ │ │ ├── newfans │ │ │ │ │ │ ├── NewFansBean.java │ │ │ │ │ │ ├── NewFansAdapter.java │ │ │ │ │ │ ├── NewFanAdapter.java │ │ │ │ │ │ ├── NewFansViewHolder.java │ │ │ │ │ │ ├── NewFanViewHolder.java │ │ │ │ │ │ ├── NewFansFragment.java │ │ │ │ │ │ └── NewFansPresenter.java │ │ │ │ │ ├── SubBean.java │ │ │ │ │ └── FanBean.java │ │ │ │ ├── rss │ │ │ │ │ ├── RSSPostAdapter.java │ │ │ │ │ ├── RSSPostBean.java │ │ │ │ │ ├── RSSPostPresenter.java │ │ │ │ │ ├── NoCoverViewHolder.java │ │ │ │ │ └── RSSPostFragment.java │ │ │ │ ├── about │ │ │ │ │ └── AboutFragment.java │ │ │ │ └── local │ │ │ │ │ └── subs │ │ │ │ │ └── LocalSubsAdapter.java │ │ │ │ ├── WeekIcon.java │ │ │ │ ├── glide │ │ │ │ ├── MyGlideModule.java │ │ │ │ └── integration │ │ │ │ │ ├── OkHttpLibraryGlideModule.java │ │ │ │ │ ├── OkHttpUrlLoader.java │ │ │ │ │ └── OkHttpStreamFetcher.java │ │ │ │ ├── widget │ │ │ │ └── BoldFontCollapsingToolbarLayout.java │ │ │ │ ├── utils │ │ │ │ ├── SimpleUtils.java │ │ │ │ ├── DateUtils.java │ │ │ │ └── MessageBar.java │ │ │ │ ├── Url.java │ │ │ │ ├── MyApp.java │ │ │ │ └── Menus.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── star │ │ │ └── iota │ │ │ └── sakura │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── star │ │ └── iota │ │ └── sakura │ │ └── ExampleInstrumentedTest.java ├── fabric.properties ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── .idea ├── copyright │ └── profiles_settings.xml ├── vcs.xml ├── smartfox_info.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml └── compiler.xml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── gradle.properties ├── README.md └── gradlew.bat /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_flower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/bg_flower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_sakura.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/bg_sakura.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_autumn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/ic_autumn.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_spring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/ic_spring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_summer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/ic_summer.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_winter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/ic_winter.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/mipmap-xhdpi/app_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_flower_sakura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/bg_flower_sakura.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_google_paly_store.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iota9star/sakura-dmhy/HEAD/app/src/main/res/drawable/ic_google_paly_store.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 2 | org.gradle.parallel=true 3 | org.gradle.daemon=true 4 | kotlin.incremental=true 5 | -------------------------------------------------------------------------------- /.idea/smartfox_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /app/fabric.properties: -------------------------------------------------------------------------------- 1 | #Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public. 2 | #Tue Jan 30 21:16:07 CST 2018 3 | apiSecret=787f8b5b6decc8115145c7593061f95140ce5a5e513720412d254f9c8366081a 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jul 18 13:24:12 CST 2017 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.5-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/xml/searchable.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_no_cover.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_drawer_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 64dp 3 | 128dp 4 | 256dp 5 | 24dp 6 | 8dp 7 | 56dp 8 | 96dp 9 | 10 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/PVContract.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | 4 | public interface PVContract { 5 | interface Presenter { 6 | void unsubscribe(); 7 | 8 | void get(String url); 9 | } 10 | 11 | interface View { 12 | 13 | void success(T result); 14 | 15 | void error(String error); 16 | 17 | void isCache(); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/database/FanDAO.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.database; 2 | 3 | 4 | import java.util.List; 5 | 6 | import star.iota.sakura.ui.fans.FanBean; 7 | 8 | public interface FanDAO { 9 | boolean save(FanBean bean); 10 | 11 | boolean save(List beans); 12 | 13 | boolean delete(FanBean bean); 14 | 15 | boolean deleteAll(); 16 | 17 | boolean exist(FanBean bean); 18 | 19 | List query(); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/TeamBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team; 2 | 3 | public class TeamBean { 4 | private final String id; 5 | private final String name; 6 | 7 | TeamBean(String id, String name) { 8 | this.id = id; 9 | this.name = name; 10 | } 11 | 12 | public String getId() { 13 | return id; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/database/SubsDAO.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.database; 2 | 3 | 4 | import java.util.List; 5 | 6 | import star.iota.sakura.ui.post.PostBean; 7 | 8 | public interface SubsDAO { 9 | boolean save(PostBean bean); 10 | 11 | boolean save(List beans); 12 | 13 | boolean delete(Integer id); 14 | 15 | boolean deleteAll(); 16 | 17 | boolean exist(String url); 18 | 19 | List query(); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_clear_all_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/def/TeamDefaultFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team.def; 2 | 3 | import star.iota.sakura.Menus; 4 | import star.iota.sakura.base.BaseAdapter; 5 | import star.iota.sakura.ui.team.TeamFragment; 6 | 7 | 8 | public class TeamDefaultFragment extends TeamFragment { 9 | @Override 10 | protected BaseAdapter getAdapter() { 11 | setToolbarTitle(Menus.TEAM_DEFAULT); 12 | return new TeamDefaultAdapter(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/rss/TeamRSSFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team.rss; 2 | 3 | import star.iota.sakura.Menus; 4 | import star.iota.sakura.base.BaseAdapter; 5 | import star.iota.sakura.ui.team.TeamFragment; 6 | 7 | 8 | public class TeamRSSFragment extends TeamFragment { 9 | @Override 10 | protected BaseAdapter getAdapter() { 11 | setToolbarTitle(Menus.RSS + " * " + Menus.RSS_SUBS); 12 | return new TeamRSSAdapter(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_music_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/post/SubBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.post; 2 | 3 | public class SubBean { 4 | private String name; 5 | private String url; 6 | 7 | public String getName() { 8 | return name; 9 | } 10 | 11 | public void setName(String name) { 12 | this.name = name; 13 | } 14 | 15 | public String getUrl() { 16 | return url; 17 | } 18 | 19 | public void setUrl(String url) { 20 | this.url = url; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/test/java/star/iota/sakura/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_game_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_manga_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_subs_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_index_season.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/index/IndexPresenter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.index; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import star.iota.sakura.base.PVContract; 6 | import star.iota.sakura.base.StringPresenter; 7 | 8 | 9 | class IndexPresenter extends StringPresenter { 10 | 11 | IndexPresenter(PVContract.View view) { 12 | super(view); 13 | } 14 | 15 | @Override 16 | protected IndexBean dealResponse(String s) { 17 | return new Gson().fromJson(s, IndexBean.class); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_news_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_raw_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_fan_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_category_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_anime_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favorite_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_weekly_fans_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/FansBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | 4 | import java.util.List; 5 | 6 | import star.iota.sakura.ui.fans.FanBean; 7 | 8 | class FansBean { 9 | private String week; 10 | private List fans; 11 | 12 | String getWeek() { 13 | return week; 14 | } 15 | 16 | void setWeek(String week) { 17 | this.week = week; 18 | } 19 | 20 | public List getFans() { 21 | return fans; 22 | } 23 | 24 | public void setFans(List fans) { 25 | this.fans = fans; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ffffff 4 | #ff5384 5 | #ff5384 6 | #ff5384 7 | #00000000 8 | #f0f0f0 9 | #252525 10 | #ffffff 11 | #ffffff 12 | #000000 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/BaseViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | import butterknife.ButterKnife; 8 | 9 | 10 | public abstract class BaseViewHolder extends RecyclerView.ViewHolder { 11 | protected final Context mContext; 12 | 13 | protected BaseViewHolder(View itemView) { 14 | super(itemView); 15 | mContext = itemView.getContext(); 16 | ButterKnife.bind(this, itemView); 17 | } 18 | 19 | public abstract void bindView(B beans); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFansBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.newfans; 2 | 3 | 4 | import java.util.List; 5 | 6 | import star.iota.sakura.ui.fans.FanBean; 7 | 8 | 9 | class NewFansBean { 10 | private String week; 11 | private List fans; 12 | 13 | String getWeek() { 14 | return week; 15 | } 16 | 17 | void setWeek(String week) { 18 | this.week = week; 19 | } 20 | 21 | public List getFans() { 22 | return fans; 23 | } 24 | 25 | public void setFans(List fans) { 26 | this.fans = fans; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_jp_tv_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_perm_contact_calendar_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_export_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_import_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_other_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_collection_list_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_rss_feed_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_group_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tokusatsu_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_sub.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_category_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_recycler_view_with_refresh_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favorite_border_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_new_post_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/animator/touch_floating.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 11 | 12 | 13 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/WeekIcon.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura; 2 | 3 | public class WeekIcon { 4 | public static final String MON = "https://share.dmhy.org/images/weekly/share_weekly_mon.gif"; 5 | public static final String TUE = "https://share.dmhy.org/images/weekly/share_weekly_tue.gif"; 6 | public static final String WED = "https://share.dmhy.org/images/weekly/share_weekly_wed.gif"; 7 | public static final String THU = "https://share.dmhy.org/images/weekly/share_weekly_thu.gif"; 8 | public static final String FRI = "https://share.dmhy.org/images/weekly/share_weekly_fri.gif"; 9 | public static final String SAT = "https://share.dmhy.org/images/weekly/share_weekly_sat.gif"; 10 | public static final String SUN = "https://share.dmhy.org/images/weekly/share_weekly_sun.gif"; 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/post/PostAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.post; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | 10 | 11 | class PostAdapter extends BaseAdapter { 12 | 13 | @Override 14 | public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 15 | return new PostViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_post, parent, false)); 16 | } 17 | 18 | @Override 19 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 20 | ((PostViewHolder) holder).bindView(mBeans.get(position)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/FansAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | 10 | 11 | class FansAdapter extends BaseAdapter { 12 | 13 | @Override 14 | public FansViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 15 | return new FansViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fans, parent, false)); 16 | } 17 | 18 | @Override 19 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 20 | ((FansViewHolder) holder).bindView(mBeans.get(position)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFansAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.newfans; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | 10 | 11 | class NewFansAdapter extends BaseAdapter { 12 | 13 | @Override 14 | public NewFansViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 15 | return new NewFansViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fans, parent, false)); 16 | } 17 | 18 | @Override 19 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 20 | ((NewFansViewHolder) holder).bindView(mBeans.get(position)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/FanAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | import star.iota.sakura.ui.fans.FanBean; 10 | 11 | 12 | class FanAdapter extends BaseAdapter { 13 | 14 | @Override 15 | public FanViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 16 | return new FanViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fan, parent, false)); 17 | } 18 | 19 | @Override 20 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 21 | ((FanViewHolder) holder).bindView(mBeans.get(position)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/glide/MyGlideModule.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.glide; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.bumptech.glide.GlideBuilder; 7 | import com.bumptech.glide.annotation.GlideModule; 8 | import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; 9 | import com.bumptech.glide.module.AppGlideModule; 10 | 11 | @GlideModule 12 | public class MyGlideModule extends AppGlideModule { 13 | 14 | @Override 15 | public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { 16 | long diskCacheSizeBytes = Long.MAX_VALUE; 17 | builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes)); 18 | } 19 | 20 | @Override 21 | public boolean isManifestParsingEnabled() { 22 | return false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFanAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.newfans; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | import star.iota.sakura.ui.fans.FanBean; 10 | 11 | 12 | class NewFanAdapter extends BaseAdapter { 13 | 14 | @Override 15 | public NewFanViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 16 | return new NewFanViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fan, parent, false)); 17 | } 18 | 19 | @Override 20 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 21 | ((NewFanViewHolder) holder).bindView(mBeans.get(position)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/rss/TeamRSSAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team.rss; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | import star.iota.sakura.ui.team.TeamBean; 10 | 11 | 12 | class TeamRSSAdapter extends BaseAdapter { 13 | 14 | @Override 15 | public TeamRSSViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 16 | return new TeamRSSViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_team, parent, false)); 17 | } 18 | 19 | @Override 20 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 21 | ((TeamRSSViewHolder) holder).bindView(mBeans.get(position)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_local.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/androidTest/java/star/iota/sakura/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("star.iota.dmhy", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_item_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/def/TeamDefaultAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team.def; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import star.iota.sakura.R; 8 | import star.iota.sakura.base.BaseAdapter; 9 | import star.iota.sakura.ui.team.TeamBean; 10 | 11 | 12 | class TeamDefaultAdapter extends BaseAdapter { 13 | 14 | @Override 15 | public TeamDefaultViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 16 | return new TeamDefaultViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_team, parent, false)); 17 | } 18 | 19 | @Override 20 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 21 | ((TeamDefaultViewHolder) holder).bindView(mBeans.get(position)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_history_fans_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/glide/integration/OkHttpLibraryGlideModule.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.glide.integration; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.bumptech.glide.Glide; 7 | import com.bumptech.glide.Registry; 8 | import com.bumptech.glide.annotation.GlideModule; 9 | import com.bumptech.glide.load.model.GlideUrl; 10 | import com.bumptech.glide.module.LibraryGlideModule; 11 | 12 | import java.io.InputStream; 13 | 14 | import star.iota.sakura.MyApp; 15 | 16 | @GlideModule 17 | public final class OkHttpLibraryGlideModule extends LibraryGlideModule { 18 | @Override 19 | public void registerComponents(@NonNull Context context, @NonNull Glide glide, 20 | @NonNull Registry registry) { 21 | registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(MyApp.makeOkHttpClient())); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_info.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/widget/BoldFontCollapsingToolbarLayout.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.widget; 2 | 3 | import android.content.Context; 4 | import android.graphics.Typeface; 5 | import android.support.design.widget.CollapsingToolbarLayout; 6 | import android.util.AttributeSet; 7 | 8 | 9 | public class BoldFontCollapsingToolbarLayout extends CollapsingToolbarLayout { 10 | public BoldFontCollapsingToolbarLayout(Context context) { 11 | super(context); 12 | init(); 13 | } 14 | 15 | 16 | public BoldFontCollapsingToolbarLayout(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | init(); 19 | } 20 | 21 | public BoldFontCollapsingToolbarLayout(Context context, AttributeSet attrs, int defStyleAttr) { 22 | super(context, attrs, defStyleAttr); 23 | init(); 24 | } 25 | 26 | private void init() { 27 | setExpandedTitleTypeface(Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/PagerAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.List; 8 | 9 | public class PagerAdapter extends FragmentPagerAdapter { 10 | private final List fragments; 11 | private final List titles; 12 | 13 | public PagerAdapter(FragmentManager fm, List fragments, List titles) { 14 | super(fm); 15 | this.fragments = fragments; 16 | this.titles = titles; 17 | } 18 | 19 | @Override 20 | public Fragment getItem(int position) { 21 | return fragments.get(position); 22 | } 23 | 24 | @Override 25 | public int getCount() { 26 | return fragments.size(); 27 | } 28 | 29 | @Override 30 | public CharSequence getPageTitle(int position) { 31 | return titles.get(position); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/TeamPresenter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team; 2 | 3 | import org.jsoup.Jsoup; 4 | import org.jsoup.nodes.Element; 5 | import org.jsoup.select.Elements; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import star.iota.sakura.base.PVContract; 11 | import star.iota.sakura.base.StringPresenter; 12 | 13 | 14 | class TeamPresenter extends StringPresenter> { 15 | 16 | TeamPresenter(PVContract.View view) { 17 | super(view); 18 | } 19 | 20 | @Override 21 | protected List dealResponse(String s) { 22 | List beans = new ArrayList<>(); 23 | Elements elements = Jsoup.parse(s).select("#AdvSearchTeam > option"); 24 | for (Element ele : elements) { 25 | String name = ele.text(); 26 | String id = ele.attr("value"); 27 | if (name.contains("全部") && id.equals("0")) continue; 28 | beans.add(new TeamBean(id, name)); 29 | } 30 | return beans; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_action_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/BaseAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.ViewGroup; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | 10 | public class BaseAdapter extends RecyclerView.Adapter { 11 | 12 | protected final List mBeans; 13 | 14 | protected BaseAdapter() { 15 | mBeans = new ArrayList<>(); 16 | } 17 | 18 | @Override 19 | public V onCreateViewHolder(ViewGroup parent, int viewType) { 20 | return null; 21 | } 22 | 23 | @Override 24 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 25 | 26 | } 27 | 28 | @Override 29 | public int getItemCount() { 30 | return mBeans.size(); 31 | } 32 | 33 | public void add(List beans) { 34 | int size = mBeans.size(); 35 | mBeans.addAll(beans); 36 | notifyItemRangeInserted(size, beans.size()); 37 | } 38 | 39 | 40 | public void clear() { 41 | int size = mBeans.size(); 42 | mBeans.clear(); 43 | notifyItemRangeRemoved(0, size); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/def/TeamDefaultViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team.def; 2 | 3 | import android.support.v7.widget.CardView; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import butterknife.BindView; 8 | import star.iota.sakura.R; 9 | import star.iota.sakura.Url; 10 | import star.iota.sakura.base.BaseActivity; 11 | import star.iota.sakura.base.BaseViewHolder; 12 | import star.iota.sakura.ui.post.PostFragment; 13 | import star.iota.sakura.ui.team.TeamBean; 14 | 15 | 16 | class TeamDefaultViewHolder extends BaseViewHolder { 17 | @BindView(R.id.card_view_container) 18 | CardView mCardViewContainer; 19 | @BindView(R.id.text_view_team_name) 20 | TextView mTextViewTeamName; 21 | 22 | TeamDefaultViewHolder(View itemView) { 23 | super(itemView); 24 | } 25 | 26 | @Override 27 | public void bindView(final TeamBean bean) { 28 | mTextViewTeamName.setText(bean.getName()); 29 | mCardViewContainer.setOnClickListener(view -> ((BaseActivity) mContext).addFragment( 30 | PostFragment.newInstance(Url.TEAM_DEFAULT + bean.getId() + "/page/", 31 | "", 32 | bean.getName()))); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/rss/TeamRSSViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team.rss; 2 | 3 | import android.support.v7.widget.CardView; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import butterknife.BindView; 8 | import star.iota.sakura.R; 9 | import star.iota.sakura.Url; 10 | import star.iota.sakura.base.BaseActivity; 11 | import star.iota.sakura.base.BaseViewHolder; 12 | import star.iota.sakura.ui.rss.RSSPostFragment; 13 | import star.iota.sakura.ui.team.TeamBean; 14 | 15 | 16 | class TeamRSSViewHolder extends BaseViewHolder { 17 | @BindView(R.id.card_view_container) 18 | CardView mCardViewContainer; 19 | @BindView(R.id.text_view_team_name) 20 | TextView mTextViewTeamName; 21 | 22 | TeamRSSViewHolder(View itemView) { 23 | super(itemView); 24 | } 25 | 26 | @Override 27 | public void bindView(final TeamBean bean) { 28 | mTextViewTeamName.setText(bean.getName()); 29 | mCardViewContainer.setOnClickListener(view -> ((BaseActivity) mContext).addFragment( 30 | RSSPostFragment.newInstance(Url.TEAM_RSS + bean.getId() + "/page/", 31 | "/rss.xml", 32 | bean.getName()))); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/SeasonBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | import java.util.List; 7 | 8 | import star.iota.sakura.ui.fans.FanBean; 9 | 10 | class SeasonBean { 11 | @SerializedName("Sun") 12 | private List Sun; 13 | @SerializedName("Mon") 14 | private List Mon; 15 | @SerializedName("Tue") 16 | private List Tue; 17 | @SerializedName("Wed") 18 | private List Wed; 19 | @SerializedName("Thu") 20 | private List Thu; 21 | @SerializedName("Fri") 22 | private List Fri; 23 | @SerializedName("Sat") 24 | private List Sat; 25 | 26 | List getSun() { 27 | return Sun; 28 | } 29 | 30 | 31 | List getMon() { 32 | return Mon; 33 | } 34 | 35 | 36 | List getTue() { 37 | return Tue; 38 | } 39 | 40 | 41 | List getWed() { 42 | return Wed; 43 | } 44 | 45 | 46 | List getThu() { 47 | return Thu; 48 | } 49 | 50 | 51 | List getFri() { 52 | return Fri; 53 | } 54 | 55 | 56 | List getSat() { 57 | return Sat; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/utils/SimpleUtils.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.utils; 2 | 3 | 4 | import android.content.ClipData; 5 | import android.content.ClipboardManager; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.net.Uri; 9 | 10 | public class SimpleUtils { 11 | public static void copy(Context context, String content) { 12 | try { 13 | ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 14 | //noinspection ConstantConditions 15 | cm.setPrimaryClip(ClipData.newPlainText("content", content)); 16 | MessageBar.create(context, "內容已複製到剪切板,同时尝试打开磁链"); 17 | Intent intent = new Intent(Intent.ACTION_VIEW); 18 | intent.setData(Uri.parse(content)); 19 | context.startActivity(intent); 20 | } catch (Exception e) { 21 | MessageBar.create(context, "發生錯誤:" + e.getMessage()); 22 | } 23 | } 24 | 25 | public static void openUrl(Context context, String url) { 26 | try { 27 | Intent intent = new Intent(Intent.ACTION_VIEW); 28 | intent.setData(Uri.parse(url)); 29 | context.startActivity(intent); 30 | } catch (Exception e) { 31 | MessageBar.create(context, "發生錯誤:" + e.getMessage()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/index/IndexBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.index; 2 | 3 | 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | import java.util.List; 7 | 8 | class IndexBean { 9 | @SerializedName("years") 10 | private List years; 11 | 12 | List getYears() { 13 | return years; 14 | } 15 | 16 | static class YearBean { 17 | @SerializedName("n") 18 | private int year; 19 | @SerializedName("seasons") 20 | private List seasons; 21 | 22 | int getYear() { 23 | return year; 24 | } 25 | 26 | List getSeasons() { 27 | return seasons; 28 | } 29 | 30 | static class SeasonBean { 31 | @SerializedName("text") 32 | private String text; 33 | @SerializedName("index") 34 | private String index; 35 | 36 | public String getText() { 37 | return text; 38 | } 39 | 40 | public void setText(String text) { 41 | this.text = text; 42 | } 43 | 44 | public String getIndex() { 45 | return index; 46 | } 47 | 48 | public void setIndex(String index) { 49 | this.index = index; 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SAKURA 3 | 搜索 4 | 感謝 5 | 1.感謝動漫花園以及所有的發佈組,可以的話,請前往@動漫花園點擊廣告支持其發展\n\n2.向開源致敬,感謝所有無私的開源貢獻者\n\n3.感谢酷安@Delsart的櫻花素材\n\n4.本軟件素材大多來自網絡,如有侵權,請聯繫我刪除 6 | 覺得還不錯的話 7 | 給我評分 8 | 來源 9 | 動漫花園 10 | 信息 11 | 字幕組 12 | 鏈接 13 | 磁鏈 14 | http://r.photo.store.qq.com/psb?/a97e084f-86ae-45db-a2e4-e63a3cb987b3/C2BKemHnKqek5Qym0GbtLtUmxMEXjz0FNMH5j3nTgi0!/r/dD8BAAAAAAAA 15 | http://r.photo.store.qq.com/psb?/a97e084f-86ae-45db-a2e4-e63a3cb987b3/P6Wmqmq3nW1DotpXhuLhwTaThhBM.t44pAPMIv.lTL8!/r/dGkBAAAAAAAA 16 | 收藏 17 | 刪除 18 | 導入 19 | 導出 20 | 分類 21 | All rights reserved 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_index.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 18 | 19 | 24 | 25 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 17 | 18 | 26 | 27 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/item_index.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 25 | 26 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/SubBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | 9 | public class SubBean implements Parcelable { 10 | public static final Creator CREATOR = new Creator() { 11 | @Override 12 | public SubBean createFromParcel(Parcel in) { 13 | return new SubBean(in); 14 | } 15 | 16 | @Override 17 | public SubBean[] newArray(int size) { 18 | return new SubBean[size]; 19 | } 20 | }; 21 | @SerializedName("name") 22 | private String name; 23 | @SerializedName("id") 24 | private String url; 25 | 26 | public SubBean() { 27 | } 28 | 29 | private SubBean(Parcel in) { 30 | name = in.readString(); 31 | url = in.readString(); 32 | } 33 | 34 | @Override 35 | public void writeToParcel(Parcel dest, int flags) { 36 | dest.writeString(name); 37 | dest.writeString(url); 38 | } 39 | 40 | @Override 41 | public int describeContents() { 42 | return 0; 43 | } 44 | 45 | public String getName() { 46 | return name; 47 | } 48 | 49 | public void setName(String name) { 50 | this.name = name; 51 | } 52 | 53 | public String getUrl() { 54 | return url; 55 | } 56 | 57 | public void setUrl(String url) { 58 | this.url = url; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFansViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.newfans; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import butterknife.BindView; 9 | import jp.wasabeef.recyclerview.animators.LandingAnimator; 10 | import star.iota.sakura.R; 11 | import star.iota.sakura.base.BaseViewHolder; 12 | import star.iota.sakura.glide.GlideApp; 13 | 14 | 15 | class NewFansViewHolder extends BaseViewHolder { 16 | 17 | @BindView(R.id.recycler_view) 18 | RecyclerView mRecyclerView; 19 | @BindView(R.id.image_view_week) 20 | ImageView mImageViewWeek; 21 | 22 | NewFansViewHolder(View itemView) { 23 | super(itemView); 24 | } 25 | 26 | @Override 27 | public void bindView(NewFansBean bean) { 28 | GlideApp.with(mContext) 29 | .load(bean.getWeek().replace("http://", "https://")) 30 | .placeholder(R.drawable.bg_sakura) 31 | .fallback(R.drawable.bg_sakura) 32 | .error(R.drawable.bg_sakura) 33 | .into(mImageViewWeek); 34 | NewFanAdapter adapter = new NewFanAdapter(); 35 | mRecyclerView.setHasFixedSize(true); 36 | mRecyclerView.setItemAnimator(new LandingAnimator()); 37 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false)); 38 | mRecyclerView.setAdapter(adapter); 39 | adapter.add(bean.getFans()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_info_with_progressbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 29 | 30 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/FanViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.widget.CardView; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import butterknife.BindView; 10 | import star.iota.sakura.R; 11 | import star.iota.sakura.base.BaseViewHolder; 12 | import star.iota.sakura.glide.GlideApp; 13 | import star.iota.sakura.ui.fans.FanBean; 14 | import star.iota.sakura.ui.more.MoreActivity; 15 | 16 | 17 | class FanViewHolder extends BaseViewHolder { 18 | 19 | @BindView(R.id.card_view_container) 20 | CardView mCardViewContainer; 21 | @BindView(R.id.text_view_name) 22 | TextView mTextViewName; 23 | @BindView(R.id.image_view_cover) 24 | ImageView mImageViewCover; 25 | 26 | FanViewHolder(View itemView) { 27 | super(itemView); 28 | } 29 | 30 | @Override 31 | public void bindView(final FanBean bean) { 32 | GlideApp.with(mContext) 33 | .load(bean.getCover().replace("http://", "https://")) 34 | .placeholder(R.drawable.bg_sakura) 35 | .error(R.drawable.bg_sakura) 36 | .fallback(R.drawable.bg_sakura) 37 | .into(mImageViewCover); 38 | mTextViewName.setText(bean.getName()); 39 | mCardViewContainer.setOnClickListener(view -> { 40 | Intent intent = new Intent(mContext, MoreActivity.class); 41 | intent.putExtra("bean", bean); 42 | mContext.startActivity(intent); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFanViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.newfans; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.widget.CardView; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import butterknife.BindView; 10 | import star.iota.sakura.R; 11 | import star.iota.sakura.base.BaseViewHolder; 12 | import star.iota.sakura.glide.GlideApp; 13 | import star.iota.sakura.ui.fans.FanBean; 14 | import star.iota.sakura.ui.more.MoreActivity; 15 | 16 | 17 | class NewFanViewHolder extends BaseViewHolder { 18 | 19 | @BindView(R.id.card_view_container) 20 | CardView mCardViewContainer; 21 | @BindView(R.id.text_view_name) 22 | TextView mTextViewName; 23 | @BindView(R.id.image_view_cover) 24 | ImageView mImageViewCover; 25 | 26 | NewFanViewHolder(View itemView) { 27 | super(itemView); 28 | } 29 | 30 | @Override 31 | public void bindView(final FanBean bean) { 32 | GlideApp.with(mContext) 33 | .load(bean.getCover().replace("http://", "https://")) 34 | .placeholder(R.drawable.bg_sakura) 35 | .fallback(R.drawable.bg_sakura) 36 | .error(R.drawable.bg_sakura) 37 | .into(mImageViewCover); 38 | mTextViewName.setText(bean.getName()); 39 | mCardViewContainer.setOnClickListener(view -> { 40 | Intent intent = new Intent(mContext, MoreActivity.class); 41 | intent.putExtra("bean", bean); 42 | mContext.startActivity(intent); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/rss/RSSPostAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.rss; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.text.TextUtils; 5 | import android.view.LayoutInflater; 6 | import android.view.ViewGroup; 7 | 8 | import star.iota.sakura.R; 9 | import star.iota.sakura.base.BaseAdapter; 10 | import star.iota.sakura.base.BaseViewHolder; 11 | 12 | class RSSPostAdapter extends BaseAdapter { 13 | 14 | private static final int WITH_COVER = 1; 15 | private static final int NO_COVER = 2; 16 | 17 | @Override 18 | public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 19 | if (viewType == WITH_COVER) { 20 | return new WithCoverViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rss_post_with_cover, parent, false)); 21 | } else { 22 | return new NoCoverViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_rss_post_no_cover, parent, false)); 23 | } 24 | } 25 | 26 | @Override 27 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 28 | if (mBeans.get(position).getCover() == null || TextUtils.isEmpty(mBeans.get(position).getCover())) { 29 | ((NoCoverViewHolder) holder).bindView(mBeans.get(position)); 30 | } else { 31 | ((WithCoverViewHolder) holder).bindView(mBeans.get(position)); 32 | } 33 | 34 | } 35 | 36 | @Override 37 | public int getItemViewType(int position) { 38 | return mBeans.get(position).getCover() != null ? WITH_COVER : NO_COVER; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/post/PostBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.post; 2 | 3 | 4 | public class PostBean { 5 | private int id; 6 | private String date; 7 | private String category; 8 | private SubBean sub; 9 | private String title; 10 | private String magnet; 11 | private String size; 12 | private String url; 13 | 14 | public int getId() { 15 | return id; 16 | } 17 | 18 | public void setId(int id) { 19 | this.id = id; 20 | } 21 | 22 | public String getDate() { 23 | return date; 24 | } 25 | 26 | public void setDate(String date) { 27 | this.date = date; 28 | } 29 | 30 | public String getCategory() { 31 | return category; 32 | } 33 | 34 | public void setCategory(String category) { 35 | this.category = category; 36 | } 37 | 38 | public SubBean getSub() { 39 | return sub; 40 | } 41 | 42 | public void setSub(SubBean sub) { 43 | this.sub = sub; 44 | } 45 | 46 | public String getTitle() { 47 | return title; 48 | } 49 | 50 | public void setTitle(String title) { 51 | this.title = title; 52 | } 53 | 54 | public String getMagnet() { 55 | return magnet; 56 | } 57 | 58 | public void setMagnet(String magnet) { 59 | this.magnet = magnet; 60 | } 61 | 62 | public String getSize() { 63 | return size; 64 | } 65 | 66 | public void setSize(String size) { 67 | this.size = size; 68 | } 69 | 70 | public String getUrl() { 71 | return url; 72 | } 73 | 74 | public void setUrl(String url) { 75 | this.url = url; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fan.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 26 | 27 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/StringPresenter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | 4 | import com.lzy.okgo.OkGo; 5 | import com.lzy.okgo.convert.StringConvert; 6 | import com.lzy.okrx2.adapter.ObservableResponse; 7 | 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | import io.reactivex.disposables.CompositeDisposable; 10 | import io.reactivex.schedulers.Schedulers; 11 | 12 | public abstract class StringPresenter implements PVContract.Presenter { 13 | 14 | private final PVContract.View view; 15 | 16 | private final CompositeDisposable mCompositeDisposable; 17 | 18 | @SuppressWarnings("unchecked") 19 | protected StringPresenter(PVContract.View view) { 20 | this.view = view; 21 | mCompositeDisposable = new CompositeDisposable(); 22 | } 23 | 24 | @Override 25 | public void unsubscribe() { 26 | mCompositeDisposable.clear(); 27 | } 28 | 29 | @Override 30 | public void get(String url) { 31 | mCompositeDisposable.add( 32 | OkGo.get(url) 33 | .converter(new StringConvert()) 34 | .adapt(new ObservableResponse<>()) 35 | .subscribeOn(Schedulers.io()) 36 | .map(s -> { 37 | if (s.isFromCache()) { 38 | view.isCache(); 39 | } 40 | return dealResponse(s.body()); 41 | }) 42 | .observeOn(AndroidSchedulers.mainThread()) 43 | .subscribe(view::success, throwable -> view.error(throwable.getMessage())) 44 | ); 45 | } 46 | 47 | protected abstract T dealResponse(String s); 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/item_fan.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 20 | 21 | 27 | 28 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/about/AboutFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.about; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.text.method.LinkMovementMethod; 6 | import android.view.View; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import butterknife.BindView; 11 | import butterknife.OnClick; 12 | import star.iota.sakura.R; 13 | import star.iota.sakura.Url; 14 | import star.iota.sakura.base.BaseFragment; 15 | import star.iota.sakura.glide.GlideApp; 16 | 17 | public class AboutFragment extends BaseFragment { 18 | @BindView(R.id.image_view_banner) 19 | ImageView mImageViewBanner; 20 | @BindView(R.id.text_view_thx) 21 | TextView mTextViewTHX; 22 | 23 | @OnClick({R.id.text_view_dmhy, R.id.linear_layout_grade}) 24 | public void onClick(View view) { 25 | Intent intent = new Intent(Intent.ACTION_VIEW); 26 | switch (view.getId()) { 27 | case R.id.text_view_dmhy: 28 | intent.setData(Uri.parse(Url.BASE)); 29 | break; 30 | case R.id.linear_layout_grade: 31 | intent.setData(Uri.parse("market://details?id=" + mContext.getPackageName())); 32 | break; 33 | } 34 | if (intent.getData() != null) { 35 | startActivity(intent); 36 | } 37 | } 38 | 39 | @Override 40 | protected void init() { 41 | setToolbarTitle("關於本軟"); 42 | GlideApp.with(mContext) 43 | .load(getResources().getString(R.string.sakura)) 44 | .into(mImageViewBanner); 45 | mTextViewTHX.setMovementMethod(LinkMovementMethod.getInstance()); 46 | } 47 | 48 | @Override 49 | protected int getLayoutId() { 50 | return R.layout.fragment_about; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 19 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/post/PostPresenter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.post; 2 | 3 | import org.jsoup.Jsoup; 4 | import org.jsoup.nodes.Element; 5 | import org.jsoup.select.Elements; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import star.iota.sakura.Url; 11 | import star.iota.sakura.base.PVContract; 12 | import star.iota.sakura.base.StringPresenter; 13 | 14 | 15 | class PostPresenter extends StringPresenter> { 16 | 17 | PostPresenter(PVContract.View view) { 18 | super(view); 19 | } 20 | 21 | @Override 22 | protected List dealResponse(String s) { 23 | List beans = new ArrayList<>(); 24 | Elements elements = Jsoup.parse(s).select("#topic_list > tbody > tr"); 25 | for (Element ele : elements) { 26 | PostBean bean = new PostBean(); 27 | ele.select("td:nth-child(1) > span").remove(); 28 | bean.setDate(ele.select("td:nth-child(1)").text()); 29 | bean.setCategory(ele.select("td:nth-child(2)").text()); 30 | bean.setMagnet(ele.select("td:nth-child(4) > a").attr("href")); 31 | bean.setTitle(ele.select("td.title > a").text()); 32 | Element tag = ele.select("td.title > span.tag > a").first(); 33 | if (tag != null) { 34 | String url = Url.BASE + tag.attr("href"); 35 | String text = tag.text(); 36 | SubBean subBean = new SubBean(); 37 | subBean.setUrl(url); 38 | subBean.setName(text); 39 | bean.setSub(subBean); 40 | } 41 | bean.setSize(ele.select("td:nth-child(5)").text()); 42 | bean.setUrl(Url.BASE + ele.select("td.title > a").attr("href")); 43 | beans.add(bean); 44 | } 45 | return beans; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/rss/RSSPostBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.rss; 2 | 3 | 4 | class RSSPostBean { 5 | private int id; 6 | private String title; 7 | private String link; 8 | private String pubDate; 9 | private String cover; 10 | private String description; 11 | private String url; 12 | private String category; 13 | private String categoryUrl; 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 getTitle() { 24 | return title; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | public String getLink() { 32 | return link; 33 | } 34 | 35 | public void setLink(String link) { 36 | this.link = link; 37 | } 38 | 39 | String getPubDate() { 40 | return pubDate; 41 | } 42 | 43 | void setPubDate(String pubDate) { 44 | this.pubDate = pubDate; 45 | } 46 | 47 | String getCover() { 48 | return cover; 49 | } 50 | 51 | void setCover(String cover) { 52 | this.cover = cover; 53 | } 54 | 55 | String getDescription() { 56 | return description; 57 | } 58 | 59 | void setDescription(String description) { 60 | this.description = description; 61 | } 62 | 63 | public String getUrl() { 64 | return url; 65 | } 66 | 67 | public void setUrl(String url) { 68 | this.url = url; 69 | } 70 | 71 | public String getCategory() { 72 | return category; 73 | } 74 | 75 | public void setCategory(String category) { 76 | this.category = category; 77 | } 78 | 79 | public String getCategoryUrl() { 80 | return categoryUrl; 81 | } 82 | 83 | void setCategoryUrl(String categoryUrl) { 84 | this.categoryUrl = categoryUrl; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/utils/DateUtils.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.Locale; 6 | 7 | public class DateUtils { 8 | 9 | public static String getBefore(String timestamp) { 10 | try { 11 | SimpleDateFormat formatter = new SimpleDateFormat( 12 | "EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH); 13 | Date date = formatter.parse(timestamp); 14 | long before = date.getTime(); 15 | long delta = System.currentTimeMillis() - before; 16 | long day = 24 * 60 * 60 * 1000; 17 | if (delta >= 3 * day) { 18 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm", Locale.ENGLISH); 19 | return sdf.format(before); 20 | } else if (delta >= 2 * day) { 21 | SimpleDateFormat sdf = new SimpleDateFormat("前天 HH:mm", Locale.ENGLISH); 22 | return sdf.format(before); 23 | } else if (delta >= day) { 24 | SimpleDateFormat sdf = new SimpleDateFormat("昨天 HH:mm", Locale.ENGLISH); 25 | return sdf.format(before); 26 | } 27 | String sb = ""; 28 | long[] times = new long[]{60 * 60 * 1000L, 60 * 1000, 1000L}; 29 | String[] units = new String[]{"小时前", "分钟前", "秒前"}; 30 | for (int i = 0, len = times.length; i < len; i++) { 31 | long time = times[i]; 32 | if (delta < time) { 33 | continue; 34 | } 35 | long temp = delta / time; 36 | if (temp > 0) { 37 | sb = temp + units[i]; 38 | break; 39 | } 40 | } 41 | return sb; 42 | } catch (Exception e) { 43 | e.printStackTrace(); 44 | } 45 | return ""; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](http://r.photo.store.qq.com/psb?/a97e084f-86ae-45db-a2e4-e63a3cb987b3/88Qq8LalxPS57wvG4w*HY2CD46yItoW*CJKbVbW6dLM!/r/dGsBAAAAAAAA) 2 | 3 | # Sakura - 『さくら さくら 会いたいよ いやだ,いやだ 君に今すぐ会いたいよ』 4 | 5 | ### 感谢 6 | 7 | + [动漫花园](https://share.dmhy.org/) 8 | + 酷安[@Delsart](http://www.coolapk.com/u/473036) 的樱花素材 9 | + 开发中使用到的各种库的作者们 10 | 11 | ### 版权 12 | 13 | + 软件中所使用的素材大多来自网络,如有侵权,请联系我删除 14 | 15 | ### 预览图效果 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
RSS 订阅完结番组番组详情
每周番组收藏番组联盟成员
菜单最新分类搜索
34 | 35 | ### 下载 36 | 37 | + 酷市场 - [Sakura](https://www.coolapk.com/apk/152628) 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_team.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | 29 | 30 | 36 | 37 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/database/DBHelper.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.database; 2 | 3 | import android.content.Context; 4 | import android.database.sqlite.SQLiteDatabase; 5 | import android.database.sqlite.SQLiteOpenHelper; 6 | 7 | 8 | class DBHelper extends SQLiteOpenHelper { 9 | static final String TABLE_NAME_FANS = "fans"; 10 | static final String TABLE_NAME_FAN = "fan"; 11 | private static final String DB_NAME = "collection.db"; 12 | private static final String CREATE_FANS_TABLE = "create table if not exists " + TABLE_NAME_FANS + "(" + 13 | "id integer primary key autoincrement," + 14 | "title text," + 15 | "category text," + 16 | "sub text," + 17 | "magnet text," + 18 | "size text," + 19 | "url text," + 20 | "date text" + 21 | ")"; 22 | private static final String CREATE_FAN_TABLE = "create table if not exists " + TABLE_NAME_FAN + "(" + 23 | "id integer primary key autoincrement," + 24 | "cover text," + 25 | "name text," + 26 | "keyword text," + 27 | "official text," + 28 | "subs text" + 29 | ")"; 30 | 31 | private static DBHelper mHelper; 32 | 33 | private DBHelper(Context context) { 34 | super(context, DB_NAME, null, 1); 35 | } 36 | 37 | static DBHelper getInstance(Context context) { 38 | if (mHelper == null) { 39 | synchronized (DBHelper.class) { 40 | if (mHelper == null) { 41 | mHelper = new DBHelper(context); 42 | } 43 | } 44 | } 45 | return mHelper; 46 | } 47 | 48 | @Override 49 | public void onCreate(SQLiteDatabase db) { 50 | db.execSQL(CREATE_FANS_TABLE); 51 | db.execSQL(CREATE_FAN_TABLE); 52 | } 53 | 54 | @Override 55 | public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/item_team.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 20 | 21 | 29 | 30 | 36 | 37 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/FansViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import java.util.Iterator; 9 | import java.util.List; 10 | 11 | import butterknife.BindView; 12 | import jp.wasabeef.recyclerview.animators.LandingAnimator; 13 | import star.iota.sakura.R; 14 | import star.iota.sakura.base.BaseViewHolder; 15 | import star.iota.sakura.glide.GlideApp; 16 | import star.iota.sakura.ui.fans.FanBean; 17 | 18 | 19 | class FansViewHolder extends BaseViewHolder { 20 | 21 | @BindView(R.id.recycler_view) 22 | RecyclerView mRecyclerView; 23 | @BindView(R.id.image_view_week) 24 | ImageView mImageViewWeek; 25 | 26 | FansViewHolder(View itemView) { 27 | super(itemView); 28 | } 29 | 30 | @Override 31 | public void bindView(FansBean bean) { 32 | GlideApp.with(mContext) 33 | .load(bean.getWeek().replace("http://", "https://")) 34 | .placeholder(R.drawable.bg_sakura) 35 | .fallback(R.drawable.bg_sakura) 36 | .error(R.drawable.bg_sakura) 37 | .into(mImageViewWeek); 38 | FanAdapter adapter = new FanAdapter(); 39 | mRecyclerView.setHasFixedSize(true); 40 | mRecyclerView.setItemAnimator(new LandingAnimator()); 41 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false)); 42 | mRecyclerView.setAdapter(adapter); 43 | List fans = bean.getFans(); 44 | Iterator iterator = fans.iterator(); 45 | while (iterator.hasNext()) { 46 | FanBean next = iterator.next(); 47 | if (next.getName().equals(" ")) { 48 | iterator.remove(); 49 | } 50 | } 51 | adapter.add(fans); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_fans.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 29 | 30 | 37 | 38 | 39 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout-v21/item_fans.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 20 | 21 | 31 | 32 | 39 | 40 | 41 | 42 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/rss/RSSPostPresenter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.rss; 2 | 3 | import org.jsoup.Jsoup; 4 | import org.jsoup.nodes.Element; 5 | import org.jsoup.select.Elements; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import star.iota.sakura.base.PVContract; 11 | import star.iota.sakura.base.StringPresenter; 12 | 13 | 14 | class RSSPostPresenter extends StringPresenter> { 15 | 16 | RSSPostPresenter(PVContract.View view) { 17 | super(view); 18 | } 19 | 20 | @Override 21 | protected List dealResponse(String s) { 22 | List beans = new ArrayList<>(); 23 | Elements elements = Jsoup.parseBodyFragment(s).select("item"); 24 | for (Element ele : elements) { 25 | RSSPostBean bean = new RSSPostBean(); 26 | String title = ele.select("title").text().replace("", ""); 27 | bean.setTitle(title); 28 | String link = ele.select("guid").text(); 29 | bean.setLink(link); 30 | String description = ele.select("description").text().replace("", ""); 31 | bean.setDescription(description); 32 | Element img = Jsoup.parseBodyFragment(description).select("img").first(); 33 | if (img != null) { 34 | String cover = img.attr("src"); 35 | bean.setCover(cover); 36 | } 37 | String url = ele.select("enclosure").attr("url"); 38 | bean.setUrl(url); 39 | String category = ele.select("category").text().replace("", ""); 40 | bean.setCategory(category); 41 | String categoryUrl = ele.select("category").attr("domain"); 42 | bean.setCategoryUrl(categoryUrl); 43 | ele.select("description").remove(); 44 | ele.select("author").remove(); 45 | ele.select("enclosure").remove(); 46 | ele.select("guid").remove(); 47 | ele.select("category").remove(); 48 | String pubDate = ele.select("pubDate").text(); 49 | bean.setPubDate(pubDate); 50 | beans.add(bean); 51 | } 52 | return beans; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/utils/MessageBar.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | 6 | import com.liuguangqiang.cookie.CookieBar; 7 | import com.liuguangqiang.cookie.OnActionClickListener; 8 | 9 | import java.util.Random; 10 | 11 | 12 | public class MessageBar { 13 | public static final String[] FACES = { 14 | "ヽ(✿゚▽゚)ノ", "━━( ̄ー ̄*|||━━", "┗|*`0′*|┛", "o(*^▽^*)┛", 15 | "( σ'ω')σ", "✧(≖ ◡ ≖✿)", "|(•_•) |•_•) |_•) |•) | )", "(゚ー゚)", 16 | "´・∀・)乂(・∀・`", "(。・∀・)ノ", "(o゚v゚)ノ", "(*゚ー゚)", 17 | "ʅ(´◔౪◔)ʃ", "(‾◡◝)", "(☆-v-)", "*(੭*ˊᵕˋ)੭*ଘ", 18 | "(>▽<)", "┗|`O′|┛ 嗷~~", "<( ̄3 ̄)> 表!", "不>( ̄ε ̄ =  ̄3 ̄)<要", 19 | "(≧∇≦)ノ", "~( TロT)σ", "n(*≧▽≦*)n", "(*^-^*)", 20 | "(○` 3′○)", "(○` 3′○)", "( * ̄▽ ̄)((≧︶≦*)", "(っ*´Д`)っ", 21 | "ο(=•ω<=)ρ⌒☆", "ヾ(´・ω・`)ノ", "ヾ(^▽^*)))", "m(o・ω・o)m", 22 | "ε = = (づ′▽`)づ", "(ノω<。)ノ))☆.。", "(。・・)ノ", "(/ω\*)……… (/ω•\*)", 23 | "┬┴┤_•)", "(o´・ェ・`o)", "(#`O′)", "o(〃'▽'〃)o", 24 | "( ╯▽╰)", "(~o ̄3 ̄)~", "(* ̄3 ̄)╭", "(づ ̄3 ̄)づ╭❤~", 25 | "(。﹏。)", "(/▽\)", "(′▽`〃)", "◕ฺ‿◕ฺ✿ฺ)", 26 | "(*/ω\*)", "(๑•̀ㅂ•́)و✧", "ヾ(≧▽≦*)o", "o(*≧▽≦)ツ", 27 | "<( ̄︶ ̄)>", "︿( ̄︶ ̄)︿", "嗯~ o(* ̄▽ ̄*)o", "╰( ̄▽ ̄)╭", 28 | "(。・∀・)ノ゙", "ヾ(≧∇≦*)ゝ", "(*^▽^*)", "╰( ̄▽ ̄)╭", 29 | "(゜▽^*))", "ヽ(✿゚▽゚)ノ", "(( へ(へ´∀`)へ", "╰(*°▽°*)╯", 30 | "^O^", "♪(^∇^*)", "(≧∀≦)ゞ", "(๑´ㅂ`๑)", 31 | "(๑¯∀¯๑)", "(/≧▽≦)/", "ヽ(゚∀゚*)ノ━━━ゥ♪", "o(*≧▽≦)ツ┏━┓", 32 | "ε(*´・∀・`)з゙", "~(~ ̄▽ ̄)~", "(o゜▽゜)o☆", "o(* ̄▽ ̄*)o", "(〃ノωノ)" 33 | }; 34 | 35 | public static void create(Context context, String content) { 36 | new CookieBar.Builder((Activity) context) 37 | .setTitle(FACES[new Random().nextInt(FACES.length)]) 38 | .setMessage(content) 39 | .show(); 40 | } 41 | 42 | public static void create(Context context, String content, String action, OnActionClickListener onActionClickListener) { 43 | new CookieBar.Builder((Activity) context) 44 | .setTitle(FACES[new Random().nextInt(FACES.length)]) 45 | .setMessage(content) 46 | .setAction(action, onActionClickListener) 47 | .show(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/Url.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura; 2 | 3 | 4 | public interface Url { 5 | 6 | String RSS_NEWS = "https://share.dmhy.org/topics/rss/page/"; 7 | 8 | String TEAM = "https://share.dmhy.org/topics/advanced-search"; 9 | String TEAM_DEFAULT = "https://share.dmhy.org/topics/list/team_id/"; 10 | String TEAM_RSS = "https://share.dmhy.org/topics/rss/team_id/"; 11 | String INDEX = "https://share.dmhy.org/json/index.json"; 12 | String FANS = "https://share.dmhy.org/json/"; 13 | String NEW_FANS = "https://share.dmhy.org/cms/page/name/programme.html"; 14 | String BASE = "https://share.dmhy.org"; 15 | 16 | String NEWS = "https://share.dmhy.org/topics/list/page/"; 17 | 18 | String SEARCH = "https://share.dmhy.org/topics/list/page/"; 19 | 20 | String ANIME = "https://share.dmhy.org/topics/list/sort_id/2/page/"; 21 | 22 | String ANIME_SEASON = "https://share.dmhy.org/topics/list/sort_id/31/page/"; 23 | 24 | String MANGA = "https://share.dmhy.org/topics/list/sort_id/3/page/"; 25 | 26 | String MANGA_GT_ORIGINAL = "https://share.dmhy.org/topics/list/sort_id/41/page/"; 27 | 28 | String MANGA_JP_ORIGINAL = "https://share.dmhy.org/topics/list/sort_id/42/page/"; 29 | 30 | String MUSIC = "https://share.dmhy.org/topics/list/sort_id/4/page/"; 31 | 32 | String MUSIC_ANIME = "https://share.dmhy.org/topics/list/sort_id/43/page/"; 33 | 34 | String MUSIC_TR = "https://share.dmhy.org/topics/list/sort_id/44/page/"; 35 | 36 | String MUSIC_POP = "https://share.dmhy.org/topics/list/sort_id/15/page/"; 37 | 38 | String JP_TV = "https://share.dmhy.org/topics/list/sort_id/6/page/"; 39 | 40 | String RAW = "https://share.dmhy.org/topics/list/sort_id/7/page/"; 41 | 42 | String GAME = "https://share.dmhy.org/topics/list/sort_id/9/page/"; 43 | 44 | String GAME_PC = "https://share.dmhy.org/topics/list/sort_id/17/page/"; 45 | 46 | String GAME_TV = "https://share.dmhy.org/topics/list/sort_id/18/page/"; 47 | 48 | String GAME_PSP = "https://share.dmhy.org/topics/list/sort_id/19/page/"; 49 | 50 | String GAME_ONLINE = "https://share.dmhy.org/topics/list/sort_id/20/page/"; 51 | 52 | String GAME_ACCESSORIES = "https://share.dmhy.org/topics/list/sort_id/21/page/"; 53 | 54 | String TOKUSATSU = "https://share.dmhy.org/topics/list/sort_id/12/page/"; 55 | 56 | String OTHER = "https://share.dmhy.org/topics/list/sort_id/1/page/"; 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/glide/integration/OkHttpUrlLoader.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.glide.integration; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import com.bumptech.glide.load.Options; 6 | import com.bumptech.glide.load.model.GlideUrl; 7 | import com.bumptech.glide.load.model.ModelLoader; 8 | import com.bumptech.glide.load.model.ModelLoaderFactory; 9 | import com.bumptech.glide.load.model.MultiModelLoaderFactory; 10 | 11 | import java.io.InputStream; 12 | 13 | import okhttp3.Call; 14 | import okhttp3.OkHttpClient; 15 | 16 | public class OkHttpUrlLoader implements ModelLoader { 17 | 18 | private final Call.Factory client; 19 | 20 | @SuppressWarnings("WeakerAccess") 21 | public OkHttpUrlLoader(@NonNull Call.Factory client) { 22 | this.client = client; 23 | } 24 | 25 | @Override 26 | public boolean handles(@NonNull GlideUrl url) { 27 | return true; 28 | } 29 | 30 | @Override 31 | public LoadData buildLoadData(@NonNull GlideUrl model, int width, int height, 32 | @NonNull Options options) { 33 | return new LoadData<>(model, new OkHttpStreamFetcher(client, model)); 34 | } 35 | 36 | 37 | @SuppressWarnings("WeakerAccess") 38 | public static class Factory implements ModelLoaderFactory { 39 | private static volatile Call.Factory internalClient; 40 | private final Call.Factory client; 41 | 42 | private static Call.Factory getInternalClient() { 43 | if (internalClient == null) { 44 | synchronized (Factory.class) { 45 | if (internalClient == null) { 46 | internalClient = new OkHttpClient(); 47 | } 48 | } 49 | } 50 | return internalClient; 51 | } 52 | 53 | public Factory() { 54 | this(getInternalClient()); 55 | } 56 | 57 | public Factory(@NonNull Call.Factory client) { 58 | this.client = client; 59 | } 60 | 61 | @NonNull 62 | @Override 63 | public ModelLoader build(@NonNull MultiModelLoaderFactory multiFactory) { 64 | return new OkHttpUrlLoader(client); 65 | } 66 | 67 | @Override 68 | public void teardown() { 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/oldfans/FansPresenter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.oldfans; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import star.iota.sakura.WeekIcon; 9 | import star.iota.sakura.base.PVContract; 10 | import star.iota.sakura.base.StringPresenter; 11 | 12 | 13 | class FansPresenter extends StringPresenter> { 14 | FansPresenter(PVContract.View view) { 15 | super(view); 16 | } 17 | 18 | @Override 19 | protected List dealResponse(String s) { 20 | SeasonBean result = new Gson().fromJson(s, SeasonBean.class); 21 | List fans = new ArrayList<>(); 22 | if (result.getSun() != null && result.getSun().size() > 0) { 23 | FansBean bean = new FansBean(); 24 | bean.setWeek(WeekIcon.SUN); 25 | bean.setFans(result.getSun()); 26 | fans.add(bean); 27 | } 28 | if (result.getMon() != null && result.getMon().size() > 0) { 29 | FansBean bean = new FansBean(); 30 | bean.setWeek(WeekIcon.MON); 31 | bean.setFans(result.getMon()); 32 | fans.add(bean); 33 | } 34 | if (result.getTue() != null && result.getTue().size() > 0) { 35 | FansBean bean = new FansBean(); 36 | bean.setWeek(WeekIcon.TUE); 37 | bean.setFans(result.getTue()); 38 | fans.add(bean); 39 | } 40 | if (result.getWed() != null && result.getWed().size() > 0) { 41 | FansBean bean = new FansBean(); 42 | bean.setWeek(WeekIcon.WED); 43 | bean.setFans(result.getWed()); 44 | fans.add(bean); 45 | } 46 | if (result.getThu() != null && result.getThu().size() > 0) { 47 | FansBean bean = new FansBean(); 48 | bean.setWeek(WeekIcon.THU); 49 | bean.setFans(result.getThu()); 50 | fans.add(bean); 51 | } 52 | if (result.getFri() != null && result.getFri().size() > 0) { 53 | FansBean bean = new FansBean(); 54 | bean.setWeek(WeekIcon.FRI); 55 | bean.setFans(result.getFri()); 56 | fans.add(bean); 57 | } 58 | if (result.getSat() != null && result.getSat().size() > 0) { 59 | FansBean bean = new FansBean(); 60 | bean.setWeek(WeekIcon.SAT); 61 | bean.setFans(result.getSat()); 62 | fans.add(bean); 63 | } 64 | return fans; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/rss/NoCoverViewHolder.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.rss; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.support.v7.app.AlertDialog; 5 | import android.support.v7.widget.CardView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.TextView; 10 | 11 | import com.zzhoujay.richtext.RichText; 12 | 13 | import butterknife.BindView; 14 | import star.iota.sakura.R; 15 | import star.iota.sakura.base.BaseViewHolder; 16 | import star.iota.sakura.utils.DateUtils; 17 | import star.iota.sakura.utils.SimpleUtils; 18 | 19 | 20 | public class NoCoverViewHolder extends BaseViewHolder { 21 | @BindView(R.id.text_view_title) 22 | TextView textViewTitle; 23 | @BindView(R.id.text_view_category) 24 | TextView textViewCategory; 25 | @BindView(R.id.text_view_date) 26 | TextView textViewDate; 27 | @BindView(R.id.button_link) 28 | Button buttonLink; 29 | @BindView(R.id.button_magnet) 30 | Button buttonMagnet; 31 | @BindView(R.id.card_view_container) 32 | CardView cardViewContainer; 33 | 34 | NoCoverViewHolder(View itemView) { 35 | super(itemView); 36 | } 37 | 38 | @Override 39 | public void bindView(final RSSPostBean bean) { 40 | textViewTitle.setText(("/" + bean.getTitle().replaceAll("]\\s*\\[|\\[|]|】\\s*【|】|【", "/") + "/").replaceAll("(/\\s*/+)+", "/")); 41 | textViewCategory.setText(bean.getCategory()); 42 | textViewDate.setText(DateUtils.getBefore(bean.getPubDate())); 43 | buttonMagnet.setOnClickListener(view -> SimpleUtils.copy(mContext, bean.getUrl())); 44 | buttonLink.setOnClickListener(view -> SimpleUtils.openUrl(mContext, bean.getLink().replace("http:", "https:"))); 45 | cardViewContainer.setOnClickListener(view -> showInfo(bean)); 46 | } 47 | 48 | private void showInfo(final RSSPostBean bean) { 49 | @SuppressLint("InflateParams") View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_info, null); 50 | TextView info = view.findViewById(R.id.text_view_info); 51 | RichText.fromHtml(bean.getDescription()) 52 | .clickable(true) 53 | .into(info); 54 | new AlertDialog.Builder(mContext) 55 | .setView(view) 56 | .setTitle(mContext.getString(R.string.app_name)) 57 | .setIcon(R.mipmap.app_icon) 58 | .setNegativeButton("瀏覽器打開", (dialogInterface, i) -> SimpleUtils.openUrl(mContext, bean.getLink().replace("http:", "https:"))) 59 | .show(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/FanBean.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import com.google.gson.annotations.SerializedName; 7 | 8 | import java.util.List; 9 | 10 | public class FanBean implements Parcelable { 11 | public static final Creator CREATOR = new Creator() { 12 | @Override 13 | public FanBean createFromParcel(Parcel in) { 14 | return new FanBean(in); 15 | } 16 | 17 | @Override 18 | public FanBean[] newArray(int size) { 19 | return new FanBean[size]; 20 | } 21 | }; 22 | private int id; 23 | @SerializedName("img") 24 | private String cover; 25 | @SerializedName("name") 26 | private String name; 27 | @SerializedName("kw") 28 | private String keyword; 29 | @SerializedName("hp") 30 | private String official; 31 | @SerializedName("sub") 32 | private List subs; 33 | 34 | public FanBean() { 35 | } 36 | 37 | protected FanBean(Parcel in) { 38 | id = in.readInt(); 39 | cover = in.readString(); 40 | name = in.readString(); 41 | keyword = in.readString(); 42 | official = in.readString(); 43 | subs = in.createTypedArrayList(SubBean.CREATOR); 44 | } 45 | 46 | @Override 47 | public void writeToParcel(Parcel dest, int flags) { 48 | dest.writeInt(id); 49 | dest.writeString(cover); 50 | dest.writeString(name); 51 | dest.writeString(keyword); 52 | dest.writeString(official); 53 | dest.writeTypedList(subs); 54 | } 55 | 56 | @Override 57 | public int describeContents() { 58 | return 0; 59 | } 60 | 61 | public int getId() { 62 | return id; 63 | } 64 | 65 | public void setId(int id) { 66 | this.id = id; 67 | } 68 | 69 | public String getCover() { 70 | return cover; 71 | } 72 | 73 | public void setCover(String cover) { 74 | this.cover = cover; 75 | } 76 | 77 | public String getName() { 78 | return name; 79 | } 80 | 81 | public void setName(String name) { 82 | this.name = name; 83 | } 84 | 85 | public String getKeyword() { 86 | return keyword; 87 | } 88 | 89 | public void setKeyword(String keyword) { 90 | this.keyword = keyword; 91 | } 92 | 93 | public String getOfficial() { 94 | return official; 95 | } 96 | 97 | public void setOfficial(String official) { 98 | this.official = official; 99 | } 100 | 101 | public List getSubs() { 102 | return subs; 103 | } 104 | 105 | public void setSubs(List subs) { 106 | this.subs = subs; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontskipnonpubliclibraryclassmembers 5 | -dontpreverify 6 | -verbose 7 | -printmapping proguardMapping.txt 8 | -optimizations !code/simplification/cast,!field/*,!class/merging/* 9 | -keepattributes *Annotation*,InnerClasses 10 | -keepattributes Signature 11 | -keepattributes SourceFile,LineNumberTable 12 | 13 | -ignorewarnings 14 | 15 | # okhttp3 16 | -dontwarn okhttp3.** 17 | -dontwarn okio.** 18 | -dontwarn javax.annotation.** 19 | -keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase 20 | 21 | # glide 22 | -keep public class * implements com.bumptech.glide.module.GlideModule 23 | -keep public class * extends com.bumptech.glide.AppGlideModule 24 | -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { 25 | **[] $VALUES; 26 | public *; 27 | } 28 | # jsoup 29 | -keep class org.jsoup.** { *; } 30 | 31 | 32 | -keep public class * extends android.app.Activity 33 | -keep public class * extends android.app.Application 34 | -keep public class * extends android.app.Service 35 | -keep public class * extends android.content.BroadcastReceiver 36 | -keep public class * extends android.content.ContentProvider 37 | -keep public class * extends android.app.backup.BackupAgentHelper 38 | -keep public class * extends android.preference.Preference 39 | -keep public class * extends android.view.View 40 | -keep public class com.android.vending.licensing.ILicensingService 41 | -keep class android.support.** {*;} 42 | 43 | -keepclasseswithmembernames class * { 44 | native ; 45 | } 46 | -keepclassmembers class * extends android.app.Activity{ 47 | public void *(android.view.View); 48 | } 49 | -keepclassmembers enum * { 50 | public static **[] values(); 51 | public static ** valueOf(java.lang.String); 52 | } 53 | -keep public class * extends android.view.View{ 54 | *** get*(); 55 | void set*(***); 56 | public (android.content.Context); 57 | public (android.content.Context, android.util.AttributeSet); 58 | public (android.content.Context, android.util.AttributeSet, int); 59 | } 60 | -keepclasseswithmembers class * { 61 | public (android.content.Context, android.util.AttributeSet); 62 | public (android.content.Context, android.util.AttributeSet, int); 63 | } 64 | -keep class * implements android.os.Parcelable { 65 | public static final android.os.Parcelable$Creator *; 66 | } 67 | -keepclassmembers class * implements java.io.Serializable { 68 | static final long serialVersionUID; 69 | private static final java.io.ObjectStreamField[] serialPersistentFields; 70 | private void writeObject(java.io.ObjectOutputStream); 71 | private void readObject(java.io.ObjectInputStream); 72 | java.lang.Object writeReplace(); 73 | java.lang.Object readResolve(); 74 | } 75 | -keep class **.R$* { 76 | *; 77 | } 78 | -keepclassmembers class * { 79 | void *(**On*Event); 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.design.widget.FloatingActionButton; 7 | import android.support.v4.app.Fragment; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import com.github.rubensousa.floatingtoolbar.FloatingToolbar; 14 | 15 | import butterknife.ButterKnife; 16 | import butterknife.Unbinder; 17 | import star.iota.sakura.R; 18 | import star.iota.sakura.ui.main.MainActivity; 19 | 20 | public abstract class BaseFragment extends Fragment { 21 | 22 | protected Context mContext; 23 | private View mContainerView; 24 | private Unbinder unbinder; 25 | private CharSequence mPreTitle; 26 | 27 | protected abstract void init(); 28 | 29 | protected abstract int getLayoutId(); 30 | 31 | protected void setToolbarTitle(CharSequence title) { 32 | AppCompatActivity activity = (AppCompatActivity) getActivity(); 33 | if (activity != null && activity instanceof MainActivity) { 34 | ((MainActivity) activity).getCollapsingToolbarLayout().setTitle(title); 35 | } 36 | } 37 | 38 | protected boolean isHideFab() { 39 | return true; 40 | } 41 | 42 | protected FloatingActionButton getFab() { 43 | //noinspection ConstantConditions 44 | return ButterKnife.findById(getActivity(), R.id.floating_action_button); 45 | } 46 | 47 | protected FloatingToolbar getFloatingToolbar() { 48 | //noinspection ConstantConditions 49 | return ButterKnife.findById(getActivity(), R.id.floating_toolbar); 50 | } 51 | 52 | @Override 53 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 54 | if (mContainerView == null) { 55 | mContainerView = inflater.inflate(getLayoutId(), container, false); 56 | } 57 | AppCompatActivity activity = (AppCompatActivity) getActivity(); 58 | mContext = activity; 59 | if (activity instanceof MainActivity) { 60 | mPreTitle = ((MainActivity) activity).getCollapsingToolbarLayout().getTitle(); 61 | } 62 | FloatingActionButton fab = getFab(); 63 | if (isHideFab()) { 64 | fab.setVisibility(View.GONE); 65 | } else { 66 | fab.setVisibility(View.VISIBLE); 67 | } 68 | unbinder = ButterKnife.bind(this, mContainerView); 69 | init(); 70 | return mContainerView; 71 | } 72 | 73 | @Override 74 | public void onDestroyView() { 75 | super.onDestroyView(); 76 | if (unbinder != null) { 77 | unbinder.unbind(); 78 | } 79 | if (mPreTitle != null) { 80 | setToolbarTitle(mPreTitle); 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 23 | 24 | 27 | 28 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 50 | 51 | 57 | 58 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFansFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.fans.newfans; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 7 | 8 | import java.util.List; 9 | 10 | import butterknife.BindView; 11 | import jp.wasabeef.recyclerview.animators.LandingAnimator; 12 | import star.iota.sakura.R; 13 | import star.iota.sakura.Url; 14 | import star.iota.sakura.base.BaseFragment; 15 | import star.iota.sakura.base.PVContract; 16 | import star.iota.sakura.utils.MessageBar; 17 | 18 | 19 | public class NewFansFragment extends BaseFragment implements PVContract.View> { 20 | 21 | @BindView(R.id.recycler_view) 22 | RecyclerView mRecyclerView; 23 | @BindView(R.id.refresh_layout) 24 | SmartRefreshLayout mRefreshLayout; 25 | private NewFansAdapter mAdapter; 26 | 27 | private NewFansPresenter mPresenter; 28 | private boolean isRunning; 29 | 30 | @Override 31 | protected void init() { 32 | setToolbarTitle("每週番組"); 33 | initPresenter(); 34 | initRecyclerView(); 35 | initRefreshLayout(); 36 | } 37 | 38 | private void initPresenter() { 39 | isRunning = false; 40 | mPresenter = new NewFansPresenter(this); 41 | } 42 | 43 | private void initRefreshLayout() { 44 | mRefreshLayout.autoRefresh(); 45 | mRefreshLayout.setEnableLoadmore(false); 46 | mRefreshLayout.setOnRefreshListener(refreshLayout -> { 47 | if (isRunning) { 48 | MessageBar.create(mContext, "正在加载中..."); 49 | return; 50 | } 51 | isRunning = true; 52 | mAdapter.clear(); 53 | mPresenter.get(Url.NEW_FANS); 54 | }); 55 | } 56 | 57 | private void initRecyclerView() { 58 | mAdapter = new NewFansAdapter(); 59 | mRecyclerView.setItemAnimator(new LandingAnimator()); 60 | mRecyclerView.setHasFixedSize(true); 61 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)); 62 | mRecyclerView.setAdapter(mAdapter); 63 | } 64 | 65 | @Override 66 | protected int getLayoutId() { 67 | return R.layout.fragment_recycler_view_with_refresh_layout; 68 | } 69 | 70 | @Override 71 | public void success(final List result) { 72 | mRefreshLayout.finishRefresh(true); 73 | mAdapter.add(result); 74 | isRunning = false; 75 | } 76 | 77 | @Override 78 | public void error(String error) { 79 | MessageBar.create(mContext, "可能發生錯誤:" + error); 80 | isRunning = false; 81 | mRefreshLayout.finishRefresh(false); 82 | } 83 | 84 | @Override 85 | public void isCache() { 86 | MessageBar.create(getActivity(),"请注意,以下内容来自缓存"); 87 | } 88 | 89 | @Override 90 | public void onDestroy() { 91 | super.onDestroy(); 92 | if (mPresenter != null) { 93 | mPresenter.unsubscribe(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/index/IndexFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.index; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 7 | 8 | import butterknife.BindView; 9 | import jp.wasabeef.recyclerview.animators.LandingAnimator; 10 | import star.iota.sakura.R; 11 | import star.iota.sakura.Url; 12 | import star.iota.sakura.base.BaseActivity; 13 | import star.iota.sakura.base.BaseFragment; 14 | import star.iota.sakura.base.PVContract; 15 | import star.iota.sakura.utils.MessageBar; 16 | 17 | 18 | public class IndexFragment extends BaseFragment implements PVContract.View { 19 | @BindView(R.id.recycler_view) 20 | RecyclerView mRecyclerView; 21 | @BindView(R.id.refresh_layout) 22 | SmartRefreshLayout mRefreshLayout; 23 | private IndexAdapter mAdapter; 24 | 25 | private IndexPresenter mPresenter; 26 | private boolean isRunning; 27 | 28 | @Override 29 | protected void init() { 30 | setToolbarTitle("完結番組"); 31 | initPresenter(); 32 | initRecyclerView(); 33 | initRefreshLayout(); 34 | } 35 | 36 | private void initPresenter() { 37 | isRunning = false; 38 | mPresenter = new IndexPresenter(this); 39 | } 40 | 41 | private void initRefreshLayout() { 42 | mRefreshLayout.autoRefresh(); 43 | mRefreshLayout.setEnableLoadmore(false); 44 | mRefreshLayout.setOnRefreshListener(refreshLayout -> { 45 | if (isRunning) { 46 | MessageBar.create(mContext, "还在加载中..."); 47 | return; 48 | } 49 | isRunning = true; 50 | mAdapter.clear(); 51 | mPresenter.get(Url.INDEX); 52 | }); 53 | } 54 | 55 | private void initRecyclerView() { 56 | mAdapter = new IndexAdapter((BaseActivity) getActivity()); 57 | mRecyclerView.setHasFixedSize(true); 58 | mRecyclerView.setItemAnimator(new LandingAnimator()); 59 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)); 60 | mRecyclerView.setAdapter(mAdapter); 61 | } 62 | 63 | @Override 64 | protected int getLayoutId() { 65 | return R.layout.fragment_recycler_view_with_refresh_layout; 66 | } 67 | 68 | @Override 69 | public void success(final IndexBean result) { 70 | mRefreshLayout.finishRefresh(true); 71 | mAdapter.add(result.getYears()); 72 | isRunning = false; 73 | } 74 | 75 | @Override 76 | public void error(String error) { 77 | MessageBar.create(mContext, "可能發生錯誤:" + error); 78 | isRunning = false; 79 | mRefreshLayout.finishRefresh(false); 80 | } 81 | 82 | @Override 83 | public void isCache() { 84 | MessageBar.create(getActivity(),"请注意,以下内容来自缓存"); 85 | } 86 | 87 | @Override 88 | public void onDestroy() { 89 | super.onDestroy(); 90 | if (mPresenter != null) { 91 | mPresenter.unsubscribe(); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_header_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 26 | 27 | 31 | 32 | 40 | 41 | 47 | 48 | 55 | 56 | 66 | 67 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/team/TeamFragment.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.team; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.support.v7.widget.StaggeredGridLayoutManager; 6 | 7 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 8 | 9 | import java.util.List; 10 | 11 | import butterknife.BindView; 12 | import jp.wasabeef.recyclerview.animators.LandingAnimator; 13 | import star.iota.sakura.R; 14 | import star.iota.sakura.Url; 15 | import star.iota.sakura.base.BaseAdapter; 16 | import star.iota.sakura.base.BaseFragment; 17 | import star.iota.sakura.base.PVContract; 18 | import star.iota.sakura.utils.MessageBar; 19 | 20 | 21 | public abstract class TeamFragment extends BaseFragment implements PVContract.View> { 22 | 23 | @BindView(R.id.recycler_view) 24 | RecyclerView mRecyclerView; 25 | @BindView(R.id.refresh_layout) 26 | SmartRefreshLayout mRefreshLayout; 27 | private BaseAdapter mAdapter; 28 | 29 | private TeamPresenter mPresenter; 30 | private boolean isRunning; 31 | 32 | @Override 33 | protected void init() { 34 | initPresenter(); 35 | initRecyclerView(); 36 | initRefreshLayout(); 37 | } 38 | 39 | private void initPresenter() { 40 | isRunning = false; 41 | mPresenter = new TeamPresenter(this); 42 | } 43 | 44 | private void initRefreshLayout() { 45 | mRefreshLayout.autoRefresh(); 46 | mRefreshLayout.setEnableLoadmore(false); 47 | mRefreshLayout.setOnRefreshListener(refreshLayout -> { 48 | if (isRunning) { 49 | MessageBar.create(mContext, "正在加载中..."); 50 | return; 51 | } 52 | isRunning = true; 53 | mAdapter.clear(); 54 | mPresenter.get(Url.TEAM); 55 | }); 56 | } 57 | 58 | private void initRecyclerView() { 59 | mAdapter = getAdapter(); 60 | mRecyclerView.setHasFixedSize(true); 61 | mRecyclerView.setItemAnimator(new LandingAnimator()); 62 | mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, LinearLayoutManager.VERTICAL)); 63 | mRecyclerView.setAdapter(mAdapter); 64 | } 65 | 66 | protected abstract BaseAdapter getAdapter(); 67 | 68 | @Override 69 | protected int getLayoutId() { 70 | return R.layout.fragment_recycler_view_with_refresh_layout; 71 | } 72 | 73 | 74 | @Override 75 | public void success(final List result) { 76 | mRefreshLayout.finishRefresh(true); 77 | mAdapter.add(result); 78 | isRunning = false; 79 | } 80 | 81 | @Override 82 | public void error(String error) { 83 | MessageBar.create(mContext, error); 84 | isRunning = false; 85 | mRefreshLayout.finishRefresh(false); 86 | } 87 | 88 | @Override 89 | public void onDestroy() { 90 | super.onDestroy(); 91 | if (mPresenter != null) { 92 | mPresenter.unsubscribe(); 93 | } 94 | } 95 | 96 | @Override 97 | public void isCache() { 98 | MessageBar.create(getActivity(),"请注意,以下内容来自缓存"); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.base; 2 | 3 | 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.os.SystemClock; 7 | import android.support.design.widget.Snackbar; 8 | import android.support.v4.app.FragmentManager; 9 | import android.support.v4.app.FragmentTransaction; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.view.ViewGroup; 12 | 13 | import java.util.Random; 14 | 15 | import butterknife.ButterKnife; 16 | import butterknife.Unbinder; 17 | import star.iota.sakura.utils.MessageBar; 18 | 19 | public abstract class BaseActivity extends AppCompatActivity { 20 | 21 | 22 | private final long[] mHints = new long[2]; 23 | protected Context mContext; 24 | private Unbinder unbinder; 25 | 26 | protected abstract void init(); 27 | 28 | @Override 29 | protected void onCreate(Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(getContentViewId()); 32 | mContext = this; 33 | unbinder = ButterKnife.bind(this); 34 | init(); 35 | setFirstFragment(); 36 | } 37 | 38 | @Override 39 | protected void onDestroy() { 40 | super.onDestroy(); 41 | if (unbinder != null) { 42 | unbinder.unbind(); 43 | } 44 | } 45 | 46 | protected abstract int getContentViewId(); 47 | 48 | protected int getFragmentContainerId() { 49 | return 0; 50 | } 51 | 52 | protected void setFirstFragment() { 53 | 54 | } 55 | 56 | protected void showFragment(BaseFragment fragment) { 57 | if (fragment != null) { 58 | FragmentManager fm = getSupportFragmentManager(); 59 | FragmentTransaction tx = fm.beginTransaction(); 60 | tx.replace(getFragmentContainerId(), fragment); 61 | tx.commit(); 62 | } 63 | } 64 | 65 | 66 | public void addFragment(BaseFragment fragment) { 67 | if (fragment != null) { 68 | getSupportFragmentManager().beginTransaction() 69 | .add(getFragmentContainerId(), fragment, fragment.getClass().getSimpleName()) 70 | .addToBackStack(fragment.getClass().getSimpleName()) 71 | .commitAllowingStateLoss(); 72 | } 73 | } 74 | 75 | protected void exit() { 76 | if (getSupportFragmentManager().getBackStackEntryCount() > 0) { 77 | getSupportFragmentManager().popBackStack(); 78 | } else { 79 | String hi[] = {"期待与你下一次的相遇", "要经常来看看我哦", "今天也要努力呢", "与你相伴的时光使我快乐", "我是多么盼望你能早点回来"}; 80 | System.arraycopy(mHints, 1, mHints, 0, mHints.length - 1); 81 | mHints[mHints.length - 1] = SystemClock.uptimeMillis(); 82 | String[] faces = MessageBar.FACES; 83 | Snackbar.make(findViewById(android.R.id.content), hi[new Random().nextInt(hi.length)], Snackbar.LENGTH_SHORT).setAction(faces[new Random().nextInt(faces.length)], view -> System.exit(0)).show(); 84 | if (SystemClock.uptimeMillis() - mHints[0] <= 1600) { 85 | System.exit(0); 86 | } 87 | } 88 | } 89 | 90 | protected void removeFragmentContainerChildrenViews() { 91 | ((ViewGroup) findViewById(getFragmentContainerId())).removeAllViews(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/star/iota/sakura/ui/index/IndexAdapter.java: -------------------------------------------------------------------------------- 1 | package star.iota.sakura.ui.index; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | import butterknife.BindView; 14 | import butterknife.ButterKnife; 15 | import cn.lankton.flowlayout.FlowLayout; 16 | import star.iota.sakura.R; 17 | import star.iota.sakura.base.BaseActivity; 18 | import star.iota.sakura.ui.fans.oldfans.FansFragment; 19 | 20 | 21 | class IndexAdapter extends RecyclerView.Adapter { 22 | private final List mBeans; 23 | private final LayoutInflater mInflater; 24 | private final BaseActivity mActivity; 25 | 26 | IndexAdapter(BaseActivity activity) { 27 | this.mActivity = activity; 28 | mInflater = LayoutInflater.from(activity); 29 | mBeans = new ArrayList<>(); 30 | } 31 | 32 | @Override 33 | public IndexViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 34 | return new IndexViewHolder(mInflater.inflate(R.layout.item_index, parent, false)); 35 | } 36 | 37 | @Override 38 | public void onBindViewHolder(IndexViewHolder holder, int position) { 39 | final IndexBean.YearBean bean = mBeans.get(position); 40 | holder.mTextViewYear.setText(String.valueOf(bean.getYear())); 41 | holder.mFlowLayout.removeAllViews(); 42 | holder.mFlowLayout.relayoutToAlign(); 43 | for (final IndexBean.YearBean.SeasonBean season : bean.getSeasons()) { 44 | ImageView tag = (ImageView) mInflater.inflate(R.layout.item_index_season, holder.mFlowLayout, false); 45 | if (season.getText().contains("春")) { 46 | tag.setImageResource(R.drawable.ic_spring); 47 | } else if (season.getText().contains("夏")) { 48 | tag.setImageResource(R.drawable.ic_summer); 49 | } else if (season.getText().contains("秋")) { 50 | tag.setImageResource(R.drawable.ic_autumn); 51 | } else if (season.getText().contains("冬")) { 52 | tag.setImageResource(R.drawable.ic_winter); 53 | } 54 | tag.setOnClickListener(view -> mActivity.addFragment(FansFragment.newInstance(season.getIndex()))); 55 | holder.mFlowLayout.addView(tag); 56 | } 57 | } 58 | 59 | public void add(List beans) { 60 | mBeans.addAll(beans); 61 | notifyItemRangeInserted(0, beans.size()); 62 | } 63 | 64 | public void clear() { 65 | int size = mBeans.size(); 66 | mBeans.clear(); 67 | notifyItemRangeRemoved(0, size); 68 | } 69 | 70 | @Override 71 | public int getItemCount() { 72 | return mBeans.size(); 73 | } 74 | 75 | static class IndexViewHolder extends RecyclerView.ViewHolder { 76 | @BindView(R.id.text_view_year) 77 | TextView mTextViewYear; 78 | @BindView(R.id.flow_layout) 79 | FlowLayout mFlowLayout; 80 | 81 | IndexViewHolder(View itemView) { 82 | super(itemView); 83 | ButterKnife.bind(this, itemView); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_rss_post_no_cover.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 21 | 22 | 30 | 31 | 32 | 37 | 38 | 49 | 50 | 61 | 62 |