├── 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 |
5 |
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 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
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 |
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 |
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 |
19 |
20 |
21 |
22 |
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 | 
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 |
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 |
71 |
72 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/MyApp.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Application;
5 | import android.content.Context;
6 |
7 | import com.crashlytics.android.Crashlytics;
8 | import com.lzy.okgo.OkGo;
9 | import com.lzy.okgo.cache.CacheEntity;
10 | import com.lzy.okgo.cache.CacheMode;
11 | import com.lzy.okgo.cookie.CookieJarImpl;
12 | import com.lzy.okgo.cookie.store.SPCookieStore;
13 | import com.lzy.okgo.https.HttpsUtils;
14 | import com.lzy.okgo.model.HttpHeaders;
15 | import com.scwang.smartrefresh.header.StoreHouseHeader;
16 | import com.scwang.smartrefresh.layout.SmartRefreshLayout;
17 | import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
18 | import com.zzhoujay.richtext.RichText;
19 |
20 | import java.util.concurrent.TimeUnit;
21 |
22 | import io.fabric.sdk.android.Fabric;
23 | import okhttp3.OkHttpClient;
24 |
25 |
26 | public class MyApp extends Application {
27 |
28 | @SuppressLint("StaticFieldLeak")
29 | private static Context mContext;
30 |
31 | static {
32 | SmartRefreshLayout.setDefaultRefreshHeaderCreater((context, layout) -> {
33 | StoreHouseHeader storeHouseHeader = new StoreHouseHeader(context);
34 | storeHouseHeader.initWithString(context.getString(R.string.app_name), 28);
35 | storeHouseHeader.setLineWidth(4);
36 | storeHouseHeader.setTextColor(0xff5384);
37 | storeHouseHeader.setMinimumHeight(context.getResources().getDimensionPixelSize(R.dimen.v64dp));
38 | storeHouseHeader.setDropHeight(context.getResources().getDimensionPixelSize(R.dimen.v128dp));
39 | return storeHouseHeader;
40 | });
41 | SmartRefreshLayout.setDefaultRefreshFooterCreater((context, layout) -> new ClassicsFooter(context));
42 | }
43 |
44 | public static OkHttpClient makeOkHttpClient() {
45 | HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
46 | return new OkHttpClient.Builder()
47 | .readTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
48 | .writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
49 | .connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
50 | .cookieJar(new CookieJarImpl(new SPCookieStore(mContext)))
51 | .hostnameVerifier((s, sslSession) -> true)
52 | .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
53 | .build();
54 | }
55 |
56 | @Override
57 | public void onCreate() {
58 | super.onCreate();
59 | mContext = getApplicationContext();
60 | initOkGo();
61 | RichText.initCacheDir(mContext);
62 | Fabric.with(this, new Crashlytics());
63 | }
64 |
65 | private void initOkGo() {
66 | HttpHeaders headers = new HttpHeaders();
67 | headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.1.2716.5 Safari/537.36");
68 | OkGo.getInstance()
69 | .init(this)
70 | .setOkHttpClient(makeOkHttpClient())
71 | .setCacheMode(CacheMode.REQUEST_FAILED_READ_CACHE)
72 | .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE)
73 | .setRetryCount(3)
74 | .addCommonHeaders(headers);
75 | }
76 |
77 | @Override
78 | public void onTerminate() {
79 | super.onTerminate();
80 | RichText.recycle();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v21/item_rss_post_no_cover.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
22 |
23 |
31 |
32 |
33 |
38 |
39 |
50 |
51 |
62 |
63 |
72 |
73 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/base/ScrollAwareFABBehavior.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura.base;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.design.widget.CoordinatorLayout;
6 | import android.support.design.widget.FloatingActionButton;
7 | import android.support.v4.view.ViewCompat;
8 | import android.support.v4.view.ViewPropertyAnimatorListener;
9 | import android.support.v4.view.animation.FastOutSlowInInterpolator;
10 | import android.util.AttributeSet;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.view.animation.Interpolator;
14 |
15 | public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
16 | private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
17 | private boolean mIsAnimatingOut = false;
18 |
19 | public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
20 | super();
21 | }
22 |
23 | @Override
24 | public boolean onStartNestedScroll(@NonNull final CoordinatorLayout coordinatorLayout, @NonNull final FloatingActionButton child,
25 | @NonNull final View directTargetChild, @NonNull final View target, final int nestedScrollAxes) {
26 | return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
27 | || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
28 | }
29 |
30 | @Override
31 | public void onNestedScroll(@NonNull final CoordinatorLayout coordinatorLayout, @NonNull final FloatingActionButton child,
32 | @NonNull final View target, final int dxConsumed, final int dyConsumed,
33 | final int dxUnconsumed, final int dyUnconsumed) {
34 | super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
35 | if (dyConsumed > 0 && !this.mIsAnimatingOut && child.getVisibility() == View.VISIBLE) {
36 | animateOut(child);
37 | } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
38 | animateIn(child);
39 | }
40 | }
41 |
42 | private void animateOut(final FloatingActionButton button) {
43 | ViewCompat.animate(button).translationY(button.getHeight() + getMarginBottom(button)).setInterpolator(INTERPOLATOR).withLayer()
44 | .setListener(new ViewPropertyAnimatorListener() {
45 | public void onAnimationStart(View view) {
46 | ScrollAwareFABBehavior.this.mIsAnimatingOut = true;
47 | }
48 |
49 | public void onAnimationCancel(View view) {
50 | ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
51 | }
52 |
53 | public void onAnimationEnd(View view) {
54 | ScrollAwareFABBehavior.this.mIsAnimatingOut = false;
55 | view.setVisibility(View.INVISIBLE);
56 | }
57 | }).start();
58 | }
59 |
60 | private void animateIn(FloatingActionButton button) {
61 | button.setVisibility(View.VISIBLE);
62 | ViewCompat.animate(button).translationY(0)
63 | .setInterpolator(INTERPOLATOR).withLayer().setListener(null)
64 | .start();
65 | }
66 |
67 | private int getMarginBottom(View v) {
68 | int marginBottom = 0;
69 | final ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
70 | if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
71 | marginBottom = ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin;
72 | }
73 | return marginBottom;
74 | }
75 | }
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/glide/integration/OkHttpStreamFetcher.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura.glide.integration;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.util.Log;
5 |
6 | import com.bumptech.glide.Priority;
7 | import com.bumptech.glide.load.DataSource;
8 | import com.bumptech.glide.load.HttpException;
9 | import com.bumptech.glide.load.data.DataFetcher;
10 | import com.bumptech.glide.load.model.GlideUrl;
11 | import com.bumptech.glide.util.ContentLengthInputStream;
12 | import com.bumptech.glide.util.Preconditions;
13 |
14 | import java.io.IOException;
15 | import java.io.InputStream;
16 | import java.util.Map;
17 |
18 | import okhttp3.Call;
19 | import okhttp3.Request;
20 | import okhttp3.Response;
21 | import okhttp3.ResponseBody;
22 |
23 |
24 | public class OkHttpStreamFetcher implements DataFetcher, okhttp3.Callback {
25 | private static final String TAG = "OkHttpFetcher";
26 | private final Call.Factory client;
27 | private final GlideUrl url;
28 | private InputStream stream;
29 | private ResponseBody responseBody;
30 | private DataCallback super InputStream> callback;
31 | private volatile Call call;
32 |
33 | @SuppressWarnings("WeakerAccess")
34 | public OkHttpStreamFetcher(Call.Factory client, GlideUrl url) {
35 | this.client = client;
36 | this.url = url;
37 | }
38 |
39 | @Override
40 | public void loadData(@NonNull Priority priority,
41 | @NonNull final DataCallback super InputStream> callback) {
42 | Request.Builder requestBuilder = new Request.Builder().url(url.toStringUrl());
43 | for (Map.Entry headerEntry : url.getHeaders().entrySet()) {
44 | String key = headerEntry.getKey();
45 | requestBuilder.addHeader(key, headerEntry.getValue());
46 | }
47 | Request request = requestBuilder.build();
48 | this.callback = callback;
49 |
50 | call = client.newCall(request);
51 | call.enqueue(this);
52 | }
53 |
54 | @Override
55 | public void onFailure(@NonNull Call call, @NonNull IOException e) {
56 | if (Log.isLoggable(TAG, Log.DEBUG)) {
57 | Log.d(TAG, "OkHttp failed to obtain result", e);
58 | }
59 |
60 | callback.onLoadFailed(e);
61 | }
62 |
63 | @Override
64 | public void onResponse(@NonNull Call call, @NonNull Response response) {
65 | responseBody = response.body();
66 | if (response.isSuccessful()) {
67 | long contentLength = Preconditions.checkNotNull(responseBody).contentLength();
68 | stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength);
69 | callback.onDataReady(stream);
70 | } else {
71 | callback.onLoadFailed(new HttpException(response.message(), response.code()));
72 | }
73 | }
74 |
75 | @Override
76 | public void cleanup() {
77 | try {
78 | if (stream != null) {
79 | stream.close();
80 | }
81 | } catch (IOException ignored) {
82 | }
83 | if (responseBody != null) {
84 | responseBody.close();
85 | }
86 | callback = null;
87 | }
88 |
89 | @Override
90 | public void cancel() {
91 | Call local = call;
92 | if (local != null) {
93 | local.cancel();
94 | }
95 | }
96 |
97 | @NonNull
98 | @Override
99 | public Class getDataClass() {
100 | return InputStream.class;
101 | }
102 |
103 | @NonNull
104 | @Override
105 | public DataSource getDataSource() {
106 | return DataSource.REMOTE;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/ui/fans/oldfans/FansFragment.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura.ui.fans.oldfans;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.widget.LinearLayoutManager;
5 | import android.support.v7.widget.RecyclerView;
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.BaseFragment;
16 | import star.iota.sakura.base.PVContract;
17 | import star.iota.sakura.utils.MessageBar;
18 |
19 |
20 | public class FansFragment extends BaseFragment implements PVContract.View> {
21 |
22 |
23 | @BindView(R.id.recycler_view)
24 | RecyclerView mRecyclerView;
25 | @BindView(R.id.refresh_layout)
26 | SmartRefreshLayout mRefreshLayout;
27 | private FansAdapter mAdapter;
28 |
29 | private FansPresenter mPresenter;
30 | private boolean isRunning;
31 | private String index;
32 |
33 | public static FansFragment newInstance(String index) {
34 | FansFragment fragment = new FansFragment();
35 | Bundle bundle = new Bundle();
36 | bundle.putString("index", index);
37 | fragment.setArguments(bundle);
38 | return fragment;
39 | }
40 |
41 | @Override
42 | protected void init() {
43 | //noinspection ConstantConditions
44 | index = getArguments().getString("index");
45 | if (index == null) {
46 | MessageBar.create(mContext, "获取数据错误,请返回重试");
47 | return;
48 | }
49 | setToolbarTitle(index + "番组");
50 | initPresenter();
51 | initRecyclerView();
52 | initRefreshLayout();
53 | }
54 |
55 | private void initPresenter() {
56 | isRunning = false;
57 | mPresenter = new FansPresenter(this);
58 | }
59 |
60 | private void initRefreshLayout() {
61 | mRefreshLayout.autoRefresh();
62 | mRefreshLayout.setEnableLoadmore(false);
63 | mRefreshLayout.setOnRefreshListener(refreshLayout -> {
64 | if (isRunning) {
65 | MessageBar.create(mContext, "正在加载中...");
66 | return;
67 | }
68 | isRunning = true;
69 | mAdapter.clear();
70 | mPresenter.get(Url.FANS + index + ".json");
71 | });
72 | }
73 |
74 | private void initRecyclerView() {
75 | mAdapter = new FansAdapter();
76 | mRecyclerView.setHasFixedSize(true);
77 | mRecyclerView.setItemAnimator(new LandingAnimator());
78 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
79 | mRecyclerView.setAdapter(mAdapter);
80 | }
81 |
82 | @Override
83 | protected int getLayoutId() {
84 | return R.layout.fragment_recycler_view_with_refresh_layout;
85 | }
86 |
87 | @Override
88 | public void success(final List result) {
89 | mRefreshLayout.finishRefresh(true);
90 | mAdapter.add(result);
91 | isRunning = false;
92 | }
93 |
94 | @Override
95 | public void error(String error) {
96 | MessageBar.create(mContext, "可能發生錯誤:" + error);
97 | isRunning = false;
98 | mRefreshLayout.finishRefresh(false);
99 | }
100 |
101 | @Override
102 | public void isCache() {
103 | MessageBar.create(getActivity(),"请注意,以下内容来自缓存");
104 | }
105 |
106 | @Override
107 | public void onDestroy() {
108 | super.onDestroy();
109 | if (mPresenter != null) {
110 | mPresenter.unsubscribe();
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/Menus.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura;
2 |
3 |
4 | public interface Menus {
5 |
6 | String ALL = "全部";
7 | int ALL_ID = 0;
8 |
9 | String ANIME = "動畫";
10 | int ANIME_ID = 2;
11 | int ANIME_ICON = R.drawable.ic_anime_black_24dp;
12 |
13 | String ANIME_SEASON = "季度全集";
14 | int ANIME_SEASON_ID = 31;
15 | int ANIME_SEASON_ICON = R.drawable.ic_anime_black_24dp;
16 |
17 | String MANGA = "漫畫";
18 | int MANGA_ID = 3;
19 | int MANGA_ICON = R.drawable.ic_manga_black_24dp;
20 |
21 | String MANGA_GT_ORIGINAL = "港台原版";
22 | int MANGA_GT_ORIGINAL_ID = 41;
23 | int MANGA_GT_ORIGINAL_ICON = R.drawable.ic_manga_black_24dp;
24 |
25 | String MANGA_JP_ORIGINAL = "日文原版";
26 | int MANGA_JP_ORIGINAL_ID = 42;
27 | int MANGA_JP_ORIGINAL_ICON = R.drawable.ic_manga_black_24dp;
28 |
29 | String MUSIC = "音樂";
30 | int MUSIC_ID = 4;
31 | int MUSIC_ICON = R.drawable.ic_music_black_24dp;
32 |
33 | String MUSIC_ANIME = "動漫音樂";
34 | int MUSIC_ANIME_ID = 43;
35 | int MUSIC_ANIME_ICON = R.drawable.ic_music_black_24dp;
36 |
37 | String MUSIC_TR = "同人音樂";
38 | int MUSIC_TR_ID = 44;
39 | int MUSIC_TR_ICON = R.drawable.ic_music_black_24dp;
40 |
41 | String MUSIC_POP = "流行音樂";
42 | int MUSIC_POP_ID = 15;
43 | int MUSIC_POP_ICON = R.drawable.ic_music_black_24dp;
44 |
45 | String JP_TV = "日劇";
46 | int JP_TV_ID = 6;
47 | int JP_TV_ICON = R.drawable.ic_jp_tv_black_24dp;
48 |
49 | String RAW = "RAW";
50 | int RAW_ID = 7;
51 | int RAW_ICON = R.drawable.ic_raw_black_24dp;
52 |
53 | String GAME = "遊戲";
54 | int GAME_ID = 9;
55 | int GAME_ICON = R.drawable.ic_game_black_24dp;
56 |
57 | String GAME_PC = "電腦遊戲";
58 | int GAME_PC_ID = 17;
59 | int GAME_PC_ICON = R.drawable.ic_game_black_24dp;
60 |
61 | String GAME_TV = "電視遊戲";
62 | int GAME_TV_ID = 18;
63 | int GAME_TV_ICON = R.drawable.ic_game_black_24dp;
64 |
65 | String GAME_PSP = "掌機遊戲";
66 | int GAME_PSP_ID = 19;
67 | int GAME_PSP_ICON = R.drawable.ic_game_black_24dp;
68 |
69 | String GAME_ONLINE = "網絡遊戲";
70 | int GAME_ONLINE_ID = 20;
71 | int GAME_ONLINE_ICON = R.drawable.ic_game_black_24dp;
72 |
73 | String GAME_ACCESSORIES = "遊戲周邊";
74 | int GAME_ACCESSORIES_ID = 21;
75 | int GAME_ACCESSORIES_ICON = R.drawable.ic_game_black_24dp;
76 |
77 | String TOKUSATSU = "特攝";
78 | int TOKUSATSU_ID = 12;
79 | int TOKUSATSU_ICON = R.drawable.ic_tokusatsu_black_24dp;
80 |
81 | String OTHER = "其他";
82 | int OTHER_ID = 1;
83 | int OTHER_ICON = R.drawable.ic_other_black_24dp;
84 |
85 | String TEAM_DEFAULT = "聯盟成員";
86 | int TEAM_DEFAULT_ID = 999;
87 | int TEAM_DEFAULT_ICON = R.drawable.ic_group_black_24dp;
88 |
89 | String NEW_FANS = "每週番組";
90 | int NEW_FANS_ID = 998;
91 | int NEW_FANS_ICON = R.drawable.ic_weekly_fans_black_24dp;
92 |
93 | String INDEX = "完結番組";
94 | int INDEX_ID = 997;
95 | int INDEX_ICON = R.drawable.ic_history_fans_black_24dp;
96 |
97 | String ABOUT = "關於本軟";
98 | int ABOUT_ID = 996;
99 | int ABOUT_ICON = R.drawable.ic_perm_contact_calendar_black_24dp;
100 |
101 | String NEWS = "最新張貼";
102 | int NEWS_ID = 995;
103 | int NEWS_ICON = R.drawable.ic_new_post_black_24dp;
104 |
105 | String COLLECTION_SUBS = "單項";
106 | int COLLECTION_SUBS_ID = 994;
107 | int COLLECTION_SUBS_ICON = R.drawable.ic_item_black_24dp;
108 |
109 | String COLLECTION_FAN = "番組";
110 | int COLLECTION_FAN_ID = 993;
111 | int COLLECTION_FAN_ICON = R.drawable.ic_fan_black_24dp;
112 |
113 | String RSS_NEWS = "最新";
114 | int RSS_NEWS_ID = 992;
115 | int RSS_NEWS_ICON = R.drawable.ic_news_black_24dp;
116 |
117 | String RSS_SUBS = "字幕組";
118 | int RSS_SUBS_ID = 991;
119 | int RSS_SUBS_ICON = R.drawable.ic_subs_black_24dp;
120 |
121 | String COLLECTION = "收藏列表";
122 | int COLLECTION_ID = 990;
123 | int COLLECTION_ICON = R.drawable.ic_collection_list_black_24dp;
124 |
125 | String CATEGORY = "分類列表";
126 | int CATEGORY_ID = 989;
127 | int CATEGORY_ICON = R.drawable.ic_category_black_24dp;
128 |
129 | String RSS = "RSS訂閱";
130 | int RSS_ID = 987;
131 | int RSS_ICON = R.drawable.ic_rss_feed_black_24dp;
132 | }
133 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/ui/fans/newfans/NewFansPresenter.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura.ui.fans.newfans;
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 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 |
12 | import star.iota.sakura.Url;
13 | import star.iota.sakura.WeekIcon;
14 | import star.iota.sakura.base.PVContract;
15 | import star.iota.sakura.base.StringPresenter;
16 | import star.iota.sakura.ui.fans.FanBean;
17 | import star.iota.sakura.ui.fans.SubBean;
18 |
19 | class NewFansPresenter extends StringPresenter> {
20 |
21 | NewFansPresenter(PVContract.View view) {
22 | super(view);
23 | }
24 |
25 | @Override
26 | protected List dealResponse(String s) {
27 | String regex = "[a-z]{3}array\\.push\\(\\[(.*)]\\);";
28 | Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
29 | Matcher matcher = pattern.matcher(s);
30 | List list = new ArrayList<>();
31 | NewFansBean fansSun = new NewFansBean();
32 | NewFansBean fansMon = new NewFansBean();
33 | NewFansBean fansTue = new NewFansBean();
34 | NewFansBean fansWed = new NewFansBean();
35 | NewFansBean fansThu = new NewFansBean();
36 | NewFansBean fansFri = new NewFansBean();
37 | NewFansBean fansSat = new NewFansBean();
38 | List Sun = new ArrayList<>();
39 | List Mon = new ArrayList<>();
40 | List Tue = new ArrayList<>();
41 | List Wed = new ArrayList<>();
42 | List Thu = new ArrayList<>();
43 | List Fri = new ArrayList<>();
44 | List Sat = new ArrayList<>();
45 | while (matcher.find()) {
46 | String group = matcher.group();
47 | String[] arr = matcher.group(1).replaceAll("'", "").split(",");
48 | if (arr.length != 5) return list;
49 | FanBean fan = new FanBean();
50 | fan.setCover(arr[0]);
51 | fan.setName(arr[1]);
52 | fan.setKeyword(arr[2]);
53 | List subs = new ArrayList<>();
54 | Elements elements = Jsoup.parseBodyFragment(arr[3]).select("a");
55 | for (Element ele : elements) {
56 | SubBean sub = new SubBean();
57 | sub.setName(ele.text());
58 | sub.setUrl(Url.BASE + ele.attr("href"));
59 | subs.add(sub);
60 | }
61 | fan.setSubs(subs);
62 | fan.setOfficial(arr[4]);
63 | if (group.startsWith("sun")) {
64 | Sun.add(fan);
65 | fansSun.setWeek(WeekIcon.SUN);
66 | } else if (group.startsWith("mon")) {
67 | Mon.add(fan);
68 | fansMon.setWeek(WeekIcon.MON);
69 | } else if (group.startsWith("tue")) {
70 | Tue.add(fan);
71 | fansTue.setWeek(WeekIcon.TUE);
72 | } else if (group.startsWith("wed")) {
73 | Wed.add(fan);
74 | fansWed.setWeek(WeekIcon.WED);
75 | } else if (group.startsWith("thu")) {
76 | Thu.add(fan);
77 | fansThu.setWeek(WeekIcon.THU);
78 | } else if (group.startsWith("fri")) {
79 | Fri.add(fan);
80 | fansFri.setWeek(WeekIcon.FRI);
81 | } else if (group.startsWith("sat")) {
82 | Sat.add(fan);
83 | fansSat.setWeek(WeekIcon.SAT);
84 | }
85 | }
86 | if (Sun.size() > 0) {
87 | fansSun.setFans(Sun);
88 | list.add(fansSun);
89 | }
90 | if (Mon.size() > 0) {
91 | fansMon.setFans(Mon);
92 | list.add(fansMon);
93 | }
94 | if (Tue.size() > 0) {
95 | fansTue.setFans(Tue);
96 | list.add(fansTue);
97 | }
98 | if (Wed.size() > 0) {
99 | fansWed.setFans(Wed);
100 | list.add(fansWed);
101 | }
102 | if (Thu.size() > 0) {
103 | fansThu.setFans(Thu);
104 | list.add(fansThu);
105 | }
106 | if (Fri.size() > 0) {
107 | fansFri.setFans(Fri);
108 | list.add(fansFri);
109 | }
110 | if (Sat.size() > 0) {
111 | fansSat.setFans(Sat);
112 | list.add(fansSat);
113 | }
114 | return list;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_local_fan.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
19 |
20 |
26 |
27 |
36 |
37 |
43 |
44 |
48 |
49 |
60 |
61 |
67 |
68 |
69 |
70 |
75 |
76 |
86 |
87 |
100 |
101 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v21/item_local_fan.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
20 |
21 |
27 |
28 |
37 |
38 |
44 |
45 |
49 |
50 |
62 |
63 |
69 |
70 |
71 |
72 |
77 |
78 |
88 |
89 |
102 |
103 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/ui/local/subs/LocalSubsAdapter.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura.ui.local.subs;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.Button;
9 | import android.widget.TextView;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | import butterknife.BindView;
15 | import butterknife.ButterKnife;
16 | import io.reactivex.Observable;
17 | import io.reactivex.android.schedulers.AndroidSchedulers;
18 | import io.reactivex.schedulers.Schedulers;
19 | import star.iota.sakura.R;
20 | import star.iota.sakura.base.BaseActivity;
21 | import star.iota.sakura.database.SubsDAOImpl;
22 | import star.iota.sakura.ui.post.PostBean;
23 | import star.iota.sakura.ui.post.PostFragment;
24 | import star.iota.sakura.utils.MessageBar;
25 | import star.iota.sakura.utils.SimpleUtils;
26 |
27 |
28 | class LocalSubsAdapter extends RecyclerView.Adapter {
29 |
30 | private final List list;
31 |
32 | LocalSubsAdapter() {
33 | list = new ArrayList<>();
34 | }
35 |
36 | @Override
37 | public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
38 | return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_local_subs, parent, false));
39 | }
40 |
41 | @Override
42 | public void onBindViewHolder(final MyViewHolder holder, int pos) {
43 | final PostBean bean = list.get(pos);
44 | holder.mTextViewCategory.setText(bean.getCategory());
45 | holder.mTextViewTitle.setText(("/" + bean.getTitle().replaceAll("]\\s*\\[|\\[|]|】\\s*【|】|【", "/") + "/").replaceAll("(/\\s*/+)+", "/"));
46 | holder.mTextViewDate.setText(bean.getDate());
47 | holder.mTextViewSize.setText(bean.getSize());
48 | if (bean.getSub() != null) {
49 | holder.mButtonSub.setOnClickListener(view -> ((BaseActivity) holder.context).addFragment(
50 | PostFragment.newInstance(bean.getSub().getUrl() + "/page/",
51 | "",
52 | bean.getSub().getName())));
53 | } else {
54 | holder.mButtonSub.setOnClickListener(view -> MessageBar.create(holder.context, "該發佈者無鏈接"));
55 | }
56 | holder.mButtonMagnet.setOnClickListener(view -> SimpleUtils.copy(holder.context, bean.getMagnet()));
57 | holder.mButtonLink.setOnClickListener(view -> SimpleUtils.openUrl(holder.context, bean.getUrl()));
58 | holder.mButtonDelete.setOnClickListener(view -> Observable.just(new SubsDAOImpl(holder.context))
59 | .map(subsDAO -> subsDAO.delete(bean.getId()))
60 | .subscribeOn(Schedulers.io())
61 | .observeOn(AndroidSchedulers.mainThread())
62 | .subscribe(aBoolean -> {
63 | if (aBoolean) {
64 | MessageBar.create(holder.context, "刪除成功:" + ("/" + bean.getTitle().replaceAll("]\\s*\\[|\\[|]|】\\s*【|】|【", "/") + "/").replaceAll("(/\\s*/+)+", "/"));
65 | remove(holder.getAdapterPosition());
66 | } else {
67 | MessageBar.create(holder.context, "刪除過程可能出現錯誤");
68 | }
69 | }, throwable -> MessageBar.create(holder.context, "刪除過程可能出現錯誤:" + throwable.getMessage())));
70 | }
71 |
72 | @Override
73 | public int getItemCount() {
74 | return list.size();
75 | }
76 |
77 | public void add(List beans) {
78 | int size = list.size();
79 | list.addAll(beans);
80 | notifyItemRangeInserted(size, beans.size());
81 | }
82 |
83 | private void remove(int pos) {
84 | list.remove(pos);
85 | notifyItemRemoved(pos);
86 | }
87 |
88 | public void clear() {
89 | int size = list.size();
90 | list.clear();
91 | notifyItemRangeRemoved(0, size);
92 | }
93 |
94 | class MyViewHolder extends RecyclerView.ViewHolder {
95 | private final Context context;
96 | @BindView(R.id.text_view_title)
97 | TextView mTextViewTitle;
98 | @BindView(R.id.text_view_category)
99 | TextView mTextViewCategory;
100 | @BindView(R.id.text_view_date)
101 | TextView mTextViewDate;
102 | @BindView(R.id.text_view_size)
103 | TextView mTextViewSize;
104 | @BindView(R.id.button_link)
105 | Button mButtonLink;
106 | @BindView(R.id.button_magnet)
107 | Button mButtonMagnet;
108 | @BindView(R.id.button_sub)
109 | Button mButtonSub;
110 | @BindView(R.id.button_delete)
111 | Button mButtonDelete;
112 |
113 | MyViewHolder(View itemView) {
114 | super(itemView);
115 | context = itemView.getContext();
116 | ButterKnife.bind(this, itemView);
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.jakewharton.butterknife'
3 | apply plugin: 'io.fabric'
4 | android {
5 | compileSdkVersion 27
6 | buildToolsVersion "27.0.3"
7 | defaultConfig {
8 | applicationId "star.iota.sakura"
9 | minSdkVersion 16
10 | targetSdkVersion 27
11 | versionCode 20
12 | versionName " グッ!(๑•̀ㅂ•́)و✧ ,dadada..."
13 | resConfigs "zh"
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled true
19 | shrinkResources true
20 | zipAlignEnabled true
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | compileOptions {
25 | sourceCompatibility JavaVersion.VERSION_1_8
26 | targetCompatibility JavaVersion.VERSION_1_8
27 | }
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(include: ['*.jar'], dir: 'libs')
32 | testImplementation 'junit:junit:4.12'
33 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
35 | implementation 'com.android.support:appcompat-v7:27.0.2'
36 | implementation 'com.android.support:design:27.0.2'
37 | implementation 'com.android.support:recyclerview-v7:27.0.2'
38 | implementation 'com.android.support:cardview-v7:27.0.2'
39 | implementation 'com.android.support:palette-v7:27.0.2'
40 |
41 | //fabric
42 |
43 | //noinspection GradleDependency
44 | implementation('com.crashlytics.sdk.android:crashlytics:latest.release') {
45 | transitive = true
46 | }
47 |
48 | //glide
49 |
50 | //noinspection GradleDependency
51 | implementation 'com.github.bumptech.glide:glide:latest.release'
52 |
53 | //noinspection GradleDependency
54 | annotationProcessor 'com.github.bumptech.glide:compiler:latest.release'
55 |
56 | //blurry
57 |
58 | //noinspection GradleDependency
59 | implementation 'jp.wasabeef:blurry:latest.release'
60 |
61 | //flowlayout
62 |
63 | //noinspection GradleDependency
64 | implementation 'cn.lankton:flowlayout:latest.release'
65 |
66 | //OkHttp
67 |
68 | //noinspection GradleDependency
69 | implementation 'com.squareup.okhttp3:okhttp:latest.release'
70 |
71 | //okio
72 |
73 | //noinspection GradleDependency
74 | implementation 'com.squareup.okio:okio:latest.release'
75 |
76 | //RxJava
77 |
78 | //noinspection GradleDependency
79 | implementation 'io.reactivex.rxjava2:rxjava:latest.release'
80 |
81 | //RxAndroid
82 |
83 | //noinspection GradleDependency
84 | implementation 'io.reactivex.rxjava2:rxandroid:latest.release'
85 |
86 | //ButterKnife
87 |
88 | //noinspection GradleDependency
89 | implementation 'com.jakewharton:butterknife:8.5.1'
90 |
91 | //noinspection GradleDependency
92 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
93 |
94 | //material drawer
95 |
96 | //noinspection GradleDependency
97 | implementation('com.mikepenz:materialdrawer:latest.release') {
98 | transitive = true
99 | }
100 |
101 | //recyclerview-animators
102 |
103 | //noinspection GradleDependency
104 | implementation 'jp.wasabeef:recyclerview-animators:latest.release'
105 |
106 | //RxPermission
107 |
108 | //noinspection GradleDependency
109 | implementation 'com.tbruyelle.rxpermissions2:rxpermissions:latest.release'
110 |
111 | //circle image view
112 |
113 | //noinspection GradleDependency
114 | implementation 'de.hdodenhof:circleimageview:latest.release'
115 |
116 | //floating toolbar
117 |
118 | //noinspection GradleDependency
119 | implementation 'com.github.rubensousa:floatingtoolbar:latest.release'
120 |
121 | //jsoup
122 |
123 | //noinspection GradleDependency
124 | implementation 'org.jsoup:jsoup:latest.release'
125 |
126 | //okgo
127 |
128 | //noinspection GradleDependency
129 | implementation 'com.lzy.net:okgo:latest.release'
130 |
131 | //noinspection GradleDependency
132 | implementation 'com.lzy.net:okrx2:latest.release'
133 |
134 | //gson
135 |
136 | //noinspection GradleDependency
137 | implementation 'com.google.code.gson:gson:latest.release'
138 |
139 | //richtext
140 |
141 | //noinspection GradleDependency
142 | implementation 'com.zzhoujay.richtext:richtext:latest.release'
143 |
144 | //SmartRefreshLayout
145 |
146 | //noinspection GradleDependency
147 | implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4-7'
148 |
149 | //noinspection GradleDependency
150 | implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.0.4-7'
151 |
152 | //cookiebar
153 |
154 | //noinspection GradleDependency
155 | implementation 'com.liuguangqiang.cookie:library:latest.release'
156 | }
157 |
--------------------------------------------------------------------------------
/app/src/main/java/star/iota/sakura/ui/rss/RSSPostFragment.java:
--------------------------------------------------------------------------------
1 | package star.iota.sakura.ui.rss;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 |
8 | import com.scwang.smartrefresh.layout.SmartRefreshLayout;
9 |
10 | import java.util.List;
11 |
12 | import butterknife.BindView;
13 | import jp.wasabeef.recyclerview.animators.LandingAnimator;
14 | import star.iota.sakura.R;
15 | import star.iota.sakura.base.BaseFragment;
16 | import star.iota.sakura.base.PVContract;
17 | import star.iota.sakura.utils.MessageBar;
18 |
19 |
20 | public class RSSPostFragment extends BaseFragment implements PVContract.View> {
21 |
22 | @BindView(R.id.recycler_view)
23 | RecyclerView mRecyclerView;
24 | @BindView(R.id.refresh_layout)
25 | SmartRefreshLayout mRefreshLayout;
26 | private RSSPostAdapter mAdapter;
27 | private RSSPostPresenter mPresenter;
28 | private boolean isRunning;
29 | private boolean isLoadMore;
30 | private int mPage;
31 | private String mUrl;
32 | private String mParameter;
33 | private String mTitle;
34 |
35 | public static RSSPostFragment newInstance(String url, String parameter, String title) {
36 | RSSPostFragment fragment = new RSSPostFragment();
37 | Bundle bundle = new Bundle();
38 | bundle.putString("url", url);
39 | bundle.putString("parameter", parameter);
40 | bundle.putString("title", title);
41 | fragment.setArguments(bundle);
42 | return fragment;
43 | }
44 |
45 | @Override
46 | public void onCreate(@Nullable Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | //noinspection ConstantConditions
49 | mUrl = getArguments().getString("url");
50 | mParameter = getArguments().getString("parameter");
51 | mTitle = getArguments().getString("title");
52 | }
53 |
54 | @Override
55 | protected void init() {
56 | setToolbarTitle(mTitle);
57 | initPresenter();
58 | initRecyclerView();
59 | initRefreshLayout();
60 | }
61 |
62 | private void initPresenter() {
63 | isRunning = false;
64 | isLoadMore = false;
65 | mPage = 1;
66 | mPresenter = new RSSPostPresenter(this);
67 | }
68 |
69 | private void initRefreshLayout() {
70 | mRefreshLayout.autoRefresh();
71 | mRefreshLayout.setOnLoadmoreListener(refreshlayout -> {
72 | if (isRunning) {
73 | MessageBar.create(mContext, "正在加载中...");
74 | return;
75 | }
76 | isRunning = true;
77 | isLoadMore = true;
78 | String url = mUrl + mPage + mParameter;
79 | if (url.contains("+team_id%3A")) {
80 | url = url.replace("+team_id%3A", "&team_id=");
81 | }
82 | mPresenter.get(url);
83 | });
84 | mRefreshLayout.setOnRefreshListener(refreshlayout -> {
85 | if (isRunning) {
86 | MessageBar.create(mContext, "正在加载中...");
87 | return;
88 | }
89 | mPage = 1;
90 | isRunning = true;
91 | isLoadMore = false;
92 | mAdapter.clear();
93 | mPresenter.get(mUrl + mPage + mParameter);
94 | });
95 | }
96 |
97 | private void initRecyclerView() {
98 | mAdapter = new RSSPostAdapter();
99 | mRecyclerView.setItemAnimator(new LandingAnimator());
100 | mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
101 | mRecyclerView.setAdapter(mAdapter);
102 | }
103 |
104 | @Override
105 | protected int getLayoutId() {
106 | return R.layout.fragment_recycler_view_with_refresh_layout;
107 | }
108 |
109 | @Override
110 | public void success(final List result) {
111 | if (isLoadMore) {
112 | mRefreshLayout.finishLoadmore(true);
113 | } else {
114 | mPage = 1;
115 | mRefreshLayout.finishRefresh(true);
116 | }
117 | mAdapter.add(result);
118 | isRunning = false;
119 | if (result.size() < 1) {
120 | MessageBar.create(mContext, "未檢索到更多數據...");
121 | } else {
122 | mPage++;
123 | }
124 | }
125 |
126 | @Override
127 | public void error(String error) {
128 | MessageBar.create(mContext, error);
129 | isRunning = false;
130 | if (isLoadMore) {
131 | mRefreshLayout.finishLoadmore(false);
132 | } else {
133 | mRefreshLayout.finishRefresh(false);
134 | }
135 | }
136 |
137 | @Override
138 | public void isCache() {
139 | MessageBar.create(getActivity(), "请注意,以下内容来自缓存");
140 | }
141 |
142 | @Override
143 | public void onDestroy() {
144 | super.onDestroy();
145 | if (mPresenter != null) {
146 | mPresenter.unsubscribe();
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------