├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── github │ │ └── javiewer │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── io │ │ │ └── github │ │ │ └── javiewer │ │ │ ├── Configurations.java │ │ │ ├── JAViewer.java │ │ │ ├── Properties.java │ │ │ ├── activity │ │ │ ├── DownloadActivity.java │ │ │ ├── FavouriteActivity.java │ │ │ ├── GalleryActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MovieActivity.java │ │ │ ├── MovieListActivity.java │ │ │ ├── SecureActivity.java │ │ │ ├── StartActivity.java │ │ │ └── WebViewActivity.java │ │ │ ├── adapter │ │ │ ├── ActressAdapter.java │ │ │ ├── ActressPaletteAdapter.java │ │ │ ├── DownloadLinkAdapter.java │ │ │ ├── GenreAdapter.java │ │ │ ├── ItemAdapter.java │ │ │ ├── MovieAdapter.java │ │ │ ├── MovieHeaderAdapter.java │ │ │ ├── NavigationSpinnerAdapter.java │ │ │ ├── ScreenshotAdapter.java │ │ │ ├── ViewPagerAdapter.java │ │ │ └── item │ │ │ │ ├── Actress.java │ │ │ │ ├── DataSource.java │ │ │ │ ├── DownloadLink.java │ │ │ │ ├── Genre.java │ │ │ │ ├── Linkable.java │ │ │ │ ├── MagnetLink.java │ │ │ │ ├── Movie.java │ │ │ │ ├── MovieDetail.java │ │ │ │ └── Screenshot.java │ │ │ ├── fragment │ │ │ ├── ActressesFragment.java │ │ │ ├── DownloadFragment.java │ │ │ ├── ExtendedAppBarFragment.java │ │ │ ├── HomeFragment.java │ │ │ ├── MovieFragment.java │ │ │ ├── MovieListFragment.java │ │ │ ├── PopularFragment.java │ │ │ ├── RecyclerFragment.java │ │ │ ├── ReleasedFragment.java │ │ │ ├── favourite │ │ │ │ ├── FavouriteActressFragment.java │ │ │ │ ├── FavouriteFragment.java │ │ │ │ ├── FavouriteMovieFragment.java │ │ │ │ └── FavouriteTabsFragment.java │ │ │ └── genre │ │ │ │ ├── GenreFragment.java │ │ │ │ └── GenreTabsFragment.java │ │ │ ├── network │ │ │ ├── Avgle.java │ │ │ ├── BTSO.java │ │ │ ├── BasicService.java │ │ │ ├── PSVS.java │ │ │ ├── TorrentKitty.java │ │ │ ├── item │ │ │ │ └── AvgleSearchResult.java │ │ │ └── provider │ │ │ │ ├── AVMOProvider.java │ │ │ │ ├── BTSOLinkProvider.java │ │ │ │ ├── DownloadLinkProvider.java │ │ │ │ └── TorrentKittyLinkProvider.java │ │ │ ├── util │ │ │ ├── ExoPlayerImpl.java │ │ │ └── SimpleVideoPlayer.java │ │ │ └── view │ │ │ ├── CompactCollapsingToolbarLayout.java │ │ │ ├── PinchImageView.java │ │ │ ├── SimpleSearchView.java │ │ │ ├── SquareTopCrop.java │ │ │ ├── ViewUtil.java │ │ │ ├── decoration │ │ │ ├── ActressItemDecoration.java │ │ │ ├── DownloadItemDecoration.java │ │ │ ├── GridSpacingItemDecoration.java │ │ │ └── MovieItemDecoration.java │ │ │ └── listener │ │ │ ├── ActressClickListener.java │ │ │ ├── ActressLongClickListener.java │ │ │ ├── BasicOnScrollListener.java │ │ │ └── EndlessOnScrollListener.java │ └── res │ │ ├── drawable │ │ ├── actress_image_gradient.xml │ │ ├── coll_toolbar_image_gradient.xml │ │ ├── ic_arrow_back.xml │ │ ├── ic_general_movie.xml │ │ ├── ic_javiewer.xml │ │ ├── ic_logo.xml │ │ ├── ic_menu_actresses.xml │ │ ├── ic_menu_donate.xml │ │ ├── ic_menu_download.xml │ │ ├── ic_menu_genre.xml │ │ ├── ic_menu_github.xml │ │ ├── ic_menu_home.xml │ │ ├── ic_menu_popular.xml │ │ ├── ic_menu_released.xml │ │ ├── ic_menu_save.xml │ │ ├── ic_menu_share.xml │ │ ├── ic_menu_source.xml │ │ ├── ic_menu_star.xml │ │ ├── ic_menu_star_border.xml │ │ ├── ic_movie_actresses.xml │ │ ├── ic_movie_genre.xml │ │ ├── ic_movie_photo.xml │ │ ├── ic_movie_play.xml │ │ ├── ic_movie_preview.xml │ │ ├── ic_player_fast_forward.xml │ │ ├── ic_player_fast_rewind.xml │ │ ├── ic_player_pause.xml │ │ ├── ic_player_play.xml │ │ ├── ic_player_replay.xml │ │ ├── ic_player_volume_down.xml │ │ ├── ic_player_volume_off.xml │ │ ├── ic_player_volume_up.xml │ │ ├── ic_toolbar_search.xml │ │ ├── nav_bg.png │ │ ├── pic_start.xml │ │ ├── progress_seek_bar.xml │ │ ├── selector_pause.xml │ │ ├── selector_play.xml │ │ ├── selector_replay.xml │ │ └── shadow.xml │ │ ├── layout │ │ ├── activity_download.xml │ │ ├── activity_favourite.xml │ │ ├── activity_favourite_bak.xml │ │ ├── activity_gallery.xml │ │ ├── activity_main.xml │ │ ├── activity_movie.xml │ │ ├── activity_movie_list.xml │ │ ├── activity_start.xml │ │ ├── activity_web_view.xml │ │ ├── app_bar_main.xml │ │ ├── card_actress.xml │ │ ├── card_actress_palette.xml │ │ ├── card_download.xml │ │ ├── card_genre.xml │ │ ├── card_movie.xml │ │ ├── chip_genre.xml │ │ ├── content_gallery.xml │ │ ├── content_movie.xml │ │ ├── content_movie_actresses.xml │ │ ├── content_movie_genre.xml │ │ ├── content_movie_headers.xml │ │ ├── content_movie_new.xml │ │ ├── content_movie_preview.xml │ │ ├── content_movie_screenshots.xml │ │ ├── dialog_player_progress.xml │ │ ├── dialog_player_volume.xml │ │ ├── drawer_header.xml │ │ ├── fragment_favourite.xml │ │ ├── fragment_genre.xml │ │ ├── fragment_genre_list.xml │ │ ├── fragment_recycler.xml │ │ ├── layout_actress.xml │ │ ├── layout_divider.xml │ │ ├── layout_divider_margin.xml │ │ ├── layout_download.xml │ │ ├── layout_fade_app_bar_layout.xml │ │ ├── layout_header.xml │ │ ├── layout_screenshot.xml │ │ ├── layout_video_player.xml │ │ ├── nav_header_main.xml │ │ ├── nav_spinner_item.xml │ │ └── view_drop_down.xml │ │ ├── menu │ │ ├── gallery.xml │ │ ├── main.xml │ │ ├── main_drawer.xml │ │ ├── movie.xml │ │ └── nav_favourite.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── bottombar_favourite_tabs.xml │ │ ├── file_paths.xml │ │ └── network_security_config.xml │ └── test │ └── java │ └── io │ └── github │ └── javiewer │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradlew ├── gradlew.bat ├── properties.json └── settings.gradle /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 提交问题前请务必先查看[已知问题](https://github.com/SeanChengN/JAViewer/blob/fuck/README.md#%E5%B7%B2%E7%9F%A5%E9%97%AE%E9%A2%98),若仍无法解决再提交请求! 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | /gradle/wrapper 10 | /.idea 11 | /JAViewer.iml 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## JAViewer 2 | 质感设计 更优雅的驾车体验 3 | 4 | ### 官方Telegram交流群 5 | 点击加入 [JAViewer 官方步行街](https://t.me/joinchat/Bp7eL0ehwp4WI-GxWxitQg) 【禁止车辆通行】 6 | 7 | ## 变更内容 8 | 基于原版 2.0.0-Alpha-1 修改了指向地址,增加欧美区,修复了其他BUG。 9 | 10 | > 由于签名不同,需要卸载原版再安装,收藏不会丢。通常情况下无需手动修改properties.json,即装即用。 11 | 12 | 下载地址:https://github.com/SeanChengN/JAViewer/releases 13 | 14 | ## 已知问题 15 | #### Q1. 无法在线播放(由于原作者搭建的源 api.rekonquer.com 失效,导致无法在线播放) 16 | A1. 考虑使用 Avgle API,但官方不允许嵌入式播放器,只能打开网页播放以保证其广告收入。 17 | > 建议直接在[Avgle](https://avgle.com/)上看,打开app多此一举。 18 | #### Q2. 无法保存收藏(由于 Androd Q 的文件权限变更,导致无法保存配置文件) 19 | A2. 已修复,如果仍然无法保存的,请卸载后重新安装并再次赋予权限。 20 | #### Q3. 界面白屏(由于在线网站的网址变更,也可能是梯子的问题) 21 | A3. 切换无码再切回有码,应用将自动更新网址。搭梯子/换线路,网站被墙,所以要搭梯子。 22 | #### Q4. 卡在启动页(卡logo,应用在启动时会联网检查数据,如果无法获取则卡在启动页) 23 | A4. 必定与网络有关,搭梯子/换线路/换梯子,参考[issues](https://github.com/SeanChengN/JAViewer/issues/9) 24 | #### Q5. 无法打开旧收藏(由于在线网站的网址变更,而旧收藏的网址不会同步更新,导致无法打开收藏) 25 | A5. 用带有文本查找替换功能的应用(比如MT管理器)打开 properties.json 文件(通常在根目录 JAViewer 文件夹内),查找 avmoo.asia 全部替换为 avmask.com 并保存,然后重启应用。**以后网址再改变的话,也是同样操作,我会在此处标注需要替换的内容。** 26 | > 嫌麻烦的话,删掉旧收藏再重新收藏也行。 27 | 28 | `avmoo.cyou > avmoo.casa` 2021/06/09 29 | 30 | `avsox.cyou > avsox.website` 2020/11/27 31 | 32 | `avmoo.host > avmoo.cyou` 2020/11/27 33 | 34 | `avmoo.host > avmoo.site` 2020/10/4 35 | 36 | `avsox.icu > avsox.cyou` 2020/8/24 37 | 38 | `avsox.host > avsox.icu` 2020/8/12 39 | 40 | `avmask.com > avmoo.host` 2020/4/16 41 | 42 | `avsox.asia > avsox.host` 2020/1/26 43 | 44 | `avmoo.asia > avmask.com` 2019/9/19 45 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'io.fabric' 3 | 4 | android { 5 | compileSdkVersion 29 6 | buildToolsVersion '28.0.3' 7 | 8 | defaultConfig { 9 | applicationId "io.github.javiewer" 10 | minSdkVersion 16 11 | targetSdkVersion 29 12 | versionCode 22 13 | versionName "2.0.0-fuck-0812" 14 | 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | compileOptions { 23 | sourceCompatibility = '1.8' 24 | targetCompatibility = '1.8' 25 | } 26 | } 27 | 28 | allprojects { 29 | repositories { 30 | maven { url "https://jitpack.io" } 31 | maven { url 'https://maven.fabric.io/public' } 32 | } 33 | } 34 | 35 | dependencies { 36 | //compile fileTree(include: ['*.jar'], dir: 'libs') 37 | 38 | //Support 39 | implementation 'androidx.appcompat:appcompat:1.0.2' 40 | implementation 'androidx.cardview:cardview:1.0.0' 41 | implementation 'com.google.android.material:material:1.0.0' 42 | implementation 'androidx.palette:palette:1.0.0' 43 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 44 | implementation 'androidx.percentlayout:percentlayout:1.0.0' 45 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' 46 | //View 47 | implementation "com.mikepenz:materialdrawer:6.1.1" 48 | implementation 'com.aurelhubert:ahbottomnavigation:2.2.0' 49 | implementation 'com.wefika:flowlayout:0.4.1' 50 | implementation 'com.robertlevonyan.view:MaterialChipView:1.0.1' 51 | implementation 'com.miguelcatalan:materialsearchview:1.4.0' 52 | implementation 'de.hdodenhof:circleimageview:2.2.0' 53 | implementation 'com.flaviofaria:kenburnsview:1.0.7' 54 | //Utility 55 | implementation 'cat.ereza:customactivityoncrash:2.2.0' 56 | implementation 'com.github.bumptech.glide:glide:3.7.0' 57 | implementation 'com.google.code.gson:gson:2.8.5' 58 | implementation 'com.squareup.retrofit2:converter-gson:2.6.0' 59 | implementation 'com.squareup.retrofit2:retrofit:2.6.0' 60 | implementation 'org.jsoup:jsoup:1.12.1' 61 | implementation 'com.karumi:dexter:5.0.0' 62 | implementation 'jp.wasabeef:recyclerview-animators:2.2.6' 63 | 64 | //Player 65 | implementation 'cn.jzvd:jiaozivideoplayer:6.2.12' 66 | implementation 'com.google.android.exoplayer:exoplayer:2.8.2' 67 | //Firebase 68 | implementation 'com.google.firebase:firebase-auth:19.0.0' 69 | 70 | testImplementation 'junit:junit:4.12' 71 | implementation 'com.jakewharton:butterknife:10.1.0' 72 | annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' 73 | 74 | implementation('com.crashlytics.sdk.android:crashlytics:2.9.4@aar') { 75 | transitive = true; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Development\Runtime\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/io/github/javiewer/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laojichao/JAViewer/f5a272112db5b115ea5aeda27dcd9c845c7b8a57/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/Configurations.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.stream.JsonReader; 5 | 6 | import java.io.File; 7 | import java.io.FileReader; 8 | import java.io.FileWriter; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | 12 | import io.github.javiewer.adapter.item.Actress; 13 | import io.github.javiewer.adapter.item.DataSource; 14 | import io.github.javiewer.adapter.item.Movie; 15 | 16 | /** 17 | * Project: JAViewer 18 | */ 19 | 20 | public class Configurations { 21 | 22 | private static File file; 23 | 24 | private ArrayList starred_movies; 25 | 26 | private ArrayList starred_actresses; 27 | 28 | private DataSource data_source; 29 | 30 | private boolean show_ads; 31 | 32 | private long download_counter; 33 | 34 | public static Configurations load(File file) { 35 | Configurations.file = file; 36 | Configurations config = null; 37 | try { 38 | config = JAViewer.parseJson(Configurations.class, new JsonReader(new FileReader(file))); 39 | } catch (Exception ignored) { 40 | } 41 | 42 | if (config == null) { 43 | config = new Configurations(); 44 | } 45 | 46 | return config; 47 | } 48 | 49 | public ArrayList getStarredMovies() { 50 | if (starred_movies == null) { 51 | starred_movies = new ArrayList<>(); 52 | } 53 | return starred_movies; 54 | } 55 | 56 | public ArrayList getStarredActresses() { 57 | if (starred_actresses == null) { 58 | starred_actresses = new ArrayList<>(); 59 | } 60 | return starred_actresses; 61 | } 62 | 63 | public DataSource getDataSource() { 64 | if (data_source == null) { 65 | data_source = JAViewer.DATA_SOURCES.get(0); 66 | } 67 | return data_source; 68 | } 69 | 70 | public void setDataSource(DataSource source) { 71 | this.data_source = source; 72 | } 73 | 74 | public void save() { 75 | try { 76 | FileWriter writer = new FileWriter(file); 77 | new Gson().toJson(this, writer); 78 | writer.flush(); 79 | writer.close(); 80 | } catch (IOException e) { 81 | e.printStackTrace(); 82 | } 83 | } 84 | 85 | public void setShowAds(boolean show_ads) { 86 | this.show_ads = show_ads; 87 | } 88 | 89 | public boolean showAds() { 90 | return show_ads; 91 | } 92 | 93 | public long getDownloadCounter() { 94 | return download_counter; 95 | } 96 | 97 | public void setDownloadCounter(long download_counter) { 98 | this.download_counter = download_counter; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/Properties.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer; 2 | 3 | import java.util.List; 4 | 5 | import io.github.javiewer.adapter.item.DataSource; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | 11 | public class Properties { 12 | 13 | private String latest_version; 14 | private int latest_version_code; 15 | 16 | private String changelog; 17 | private List data_sources; 18 | 19 | public Properties() { 20 | } 21 | 22 | public String getLatestVersion() { 23 | return latest_version; 24 | } 25 | 26 | public int getLatestVersionCode() { 27 | return latest_version_code; 28 | } 29 | 30 | public List getDataSources() { 31 | return data_sources; 32 | } 33 | 34 | public String getChangelog() { 35 | return changelog; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/activity/FavouriteActivity.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.activity; 2 | 3 | import android.os.Bundle; 4 | import com.google.android.material.appbar.AppBarLayout; 5 | import androidx.viewpager.widget.ViewPager; 6 | import androidx.appcompat.widget.Toolbar; 7 | 8 | import com.aurelhubert.ahbottomnavigation.AHBottomNavigation; 9 | import com.aurelhubert.ahbottomnavigation.AHBottomNavigationAdapter; 10 | import com.aurelhubert.ahbottomnavigation.AHBottomNavigationViewPager; 11 | 12 | import butterknife.BindColor; 13 | import butterknife.BindView; 14 | import butterknife.ButterKnife; 15 | import io.github.javiewer.R; 16 | import io.github.javiewer.adapter.ViewPagerAdapter; 17 | import io.github.javiewer.fragment.favourite.FavouriteActressFragment; 18 | import io.github.javiewer.fragment.favourite.FavouriteFragment; 19 | import io.github.javiewer.fragment.favourite.FavouriteMovieFragment; 20 | 21 | public class FavouriteActivity extends SecureActivity { 22 | 23 | public static ViewPagerAdapter mAdapter; 24 | @BindView(R.id.favourite_view_pager) 25 | AHBottomNavigationViewPager mViewPager; 26 | @BindView(R.id.app_bar_fav) 27 | AppBarLayout mAppBarLayout; 28 | @BindView(R.id.bottom_navigation) 29 | AHBottomNavigation mBottomNav; 30 | @BindView(R.id.toolbar_fav) 31 | Toolbar mToolbar; 32 | @BindColor(R.color.colorPrimary) 33 | int mColorPrimary; 34 | private ViewPager.OnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() { 35 | @Override 36 | public void onPageSelected(int position) { 37 | mBottomNav.setCurrentItem(position); 38 | mBottomNav.restoreBottomNavigation(); 39 | } 40 | }; 41 | 42 | public static void update() { 43 | if (mAdapter != null) { 44 | for (int i = 0; i < mAdapter.getCount(); i++) { 45 | ((FavouriteFragment) mAdapter.getItem(i)).update(); 46 | } 47 | } 48 | } 49 | 50 | @Override 51 | protected void onCreate(Bundle savedInstanceState) { 52 | super.onCreate(savedInstanceState); 53 | setContentView(R.layout.activity_favourite); 54 | 55 | ButterKnife.bind(this); 56 | 57 | setSupportActionBar(mToolbar); 58 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 59 | 60 | mAdapter = new ViewPagerAdapter(getSupportFragmentManager()); 61 | mViewPager.setAdapter(mAdapter); 62 | mViewPager.setPagingEnabled(true); 63 | mViewPager.addOnPageChangeListener(mOnPageChangeListener); 64 | 65 | FavouriteFragment fragment = new FavouriteMovieFragment(); 66 | mAdapter.addFragment(fragment, "作品"); 67 | fragment = new FavouriteActressFragment(); 68 | mAdapter.addFragment(fragment, "女优"); 69 | mAdapter.notifyDataSetChanged(); 70 | 71 | AHBottomNavigationAdapter navigationAdapter = new AHBottomNavigationAdapter(this, R.menu.nav_favourite); 72 | navigationAdapter.setupWithBottomNavigation(mBottomNav); 73 | mBottomNav.setTranslucentNavigationEnabled(true); 74 | mBottomNav.setAccentColor(mColorPrimary); 75 | mBottomNav.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW); 76 | 77 | mBottomNav.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() { 78 | @Override 79 | public boolean onTabSelected(int position, boolean wasSelected) { 80 | if (!wasSelected) { 81 | mViewPager.setCurrentItem(position); 82 | return true; 83 | } 84 | 85 | return false; 86 | } 87 | }); 88 | } 89 | 90 | @Override 91 | public boolean onSupportNavigateUp() { 92 | onBackPressed(); 93 | return true; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/activity/MovieListActivity.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.activity; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import androidx.fragment.app.FragmentTransaction; 7 | import androidx.appcompat.widget.Toolbar; 8 | 9 | import io.github.javiewer.R; 10 | import io.github.javiewer.fragment.MovieListFragment; 11 | import io.github.javiewer.view.ViewUtil; 12 | 13 | public class MovieListActivity extends SecureActivity { 14 | 15 | public static Intent newIntent(Context context, String title, String link) { 16 | Intent intent = new Intent(context, MovieListActivity.class); 17 | Bundle bundle = new Bundle(); 18 | bundle.putString("title", title); 19 | bundle.putString("link", link); 20 | intent.putExtras(bundle); 21 | return intent; 22 | } 23 | 24 | @Override 25 | @SuppressWarnings("ConstantConditions") 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_movie_list); 29 | 30 | Bundle bundle = this.getIntent().getExtras(); 31 | 32 | setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); 33 | getSupportActionBar().setTitle(bundle.getString("title")); 34 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 35 | getSupportActionBar().setElevation(ViewUtil.dpToPx(4)); 36 | 37 | if (savedInstanceState == null) { 38 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 39 | 40 | MovieListFragment fragment = new MovieListFragment(); 41 | fragment.setArguments(bundle); 42 | transaction.replace(R.id.content_query, fragment); 43 | transaction.commit(); 44 | } 45 | } 46 | 47 | @Override 48 | public boolean onSupportNavigateUp() { 49 | onBackPressed(); 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/activity/SecureActivity.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.activity; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import android.view.WindowManager; 5 | 6 | public class SecureActivity extends AppCompatActivity { 7 | 8 | @Override 9 | protected void onPause() { 10 | super.onPause(); 11 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); 12 | } 13 | 14 | @Override 15 | protected void onResume() { 16 | super.onResume(); 17 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/ActressAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import android.app.Activity; 4 | import androidx.recyclerview.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.bumptech.glide.Glide; 12 | 13 | import java.util.List; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | import io.github.javiewer.R; 18 | import io.github.javiewer.adapter.item.Actress; 19 | import io.github.javiewer.view.SquareTopCrop; 20 | import io.github.javiewer.view.listener.ActressClickListener; 21 | import io.github.javiewer.view.listener.ActressLongClickListener; 22 | 23 | import static com.bumptech.glide.load.engine.DiskCacheStrategy.SOURCE; 24 | 25 | /** 26 | * Project: JAViewer 27 | */ 28 | public class ActressAdapter extends ItemAdapter { 29 | 30 | private Activity mParentActivity; 31 | 32 | public ActressAdapter(List actresses, Activity mParentActivity) { 33 | super(actresses); 34 | this.mParentActivity = mParentActivity; 35 | } 36 | 37 | @Override 38 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_actress, parent, false); 40 | 41 | return new ViewHolder(v); 42 | } 43 | 44 | @Override 45 | public void onBindViewHolder(final ViewHolder holder, int position) { 46 | 47 | final Actress actress = getItems().get(position); 48 | 49 | holder.parse(actress); 50 | 51 | holder.mLayout.setOnClickListener(new ActressClickListener(actress, mParentActivity)); 52 | holder.mLayout.setOnLongClickListener(new ActressLongClickListener(actress, mParentActivity)); 53 | 54 | holder.mImage.setImageDrawable(null); 55 | Glide.with(holder.mImage.getContext().getApplicationContext()) 56 | .load(actress.getImageUrl()) 57 | .placeholder(R.drawable.ic_movie_actresses) 58 | .diskCacheStrategy(SOURCE) // override default RESULT cache and apply transform always 59 | .skipMemoryCache(true) // do not reuse the transformed result while running 60 | .transform(new SquareTopCrop(holder.mImage.getContext())) 61 | .dontAnimate() 62 | .into(holder.mImage); 63 | } 64 | 65 | public static class ViewHolder extends RecyclerView.ViewHolder { 66 | 67 | @BindView(R.id.actress_name) 68 | public TextView mTextName; 69 | 70 | @BindView(R.id.actress_img) 71 | public ImageView mImage; 72 | 73 | @BindView(R.id.layout_actress) 74 | public View mLayout; 75 | 76 | public ViewHolder(View view) { 77 | super(view); 78 | 79 | ButterKnife.bind(this, view); 80 | } 81 | 82 | public void parse(Actress actress) { 83 | mTextName.setText(actress.getName()); 84 | mTextName.setSelected(true); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/GenreAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import androidx.cardview.widget.CardView; 7 | import androidx.recyclerview.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | 13 | import java.util.List; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | import io.github.javiewer.R; 18 | import io.github.javiewer.activity.MovieListActivity; 19 | import io.github.javiewer.adapter.item.Genre; 20 | 21 | /** 22 | * Project: JAViewer 23 | */ 24 | public class GenreAdapter extends RecyclerView.Adapter { 25 | 26 | private List genres; 27 | 28 | private Activity mParentActivity; 29 | 30 | public GenreAdapter(List genres, Activity mParentActivity) { 31 | this.genres = genres; 32 | this.mParentActivity = mParentActivity; 33 | } 34 | 35 | @Override 36 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 37 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_genre, parent, false); 38 | 39 | return new ViewHolder(v); 40 | } 41 | 42 | @Override 43 | public void onBindViewHolder(final ViewHolder holder, int position) { 44 | 45 | final Genre genre = genres.get(position); 46 | holder.parse(genre); 47 | 48 | holder.mCard.setOnClickListener(new View.OnClickListener() { 49 | @Override 50 | public void onClick(View v) { 51 | if (genre.getLink() != null) { 52 | Intent intent = new Intent(mParentActivity, MovieListActivity.class); 53 | Bundle bundle = new Bundle(); 54 | bundle.putString("title", genre.getName()); 55 | bundle.putString("link", genre.getLink()); 56 | 57 | intent.putExtras(bundle); 58 | 59 | mParentActivity.startActivity(intent); 60 | } 61 | } 62 | }); 63 | 64 | 65 | } 66 | 67 | @Override 68 | public int getItemCount() { 69 | return genres == null ? 0 : genres.size(); 70 | } 71 | 72 | public static class ViewHolder extends RecyclerView.ViewHolder { 73 | 74 | @BindView(R.id.genre_name) 75 | public TextView mTextName; 76 | 77 | @BindView(R.id.card_genre) 78 | public CardView mCard; 79 | 80 | public ViewHolder(View view) { 81 | super(view); 82 | 83 | ButterKnife.bind(this, view); 84 | } 85 | 86 | public void parse(Genre genre) { 87 | mTextName.setText(genre.getName()); 88 | /*int lineCount = mTextName.getLineCount(); 89 | 90 | if (lineCount > 1) { 91 | mTextName.setSingleLine(true); 92 | StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(itemView.getLayoutParams()); 93 | layoutParams.setFullSpan(true); 94 | itemView.setLayoutParams(layoutParams); 95 | }*/ 96 | 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/ItemAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import androidx.recyclerview.widget.RecyclerView; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | 11 | public abstract class ItemAdapter extends RecyclerView.Adapter { 12 | 13 | private List items; 14 | 15 | public ItemAdapter(List items) { 16 | this.items = items; 17 | } 18 | 19 | public List getItems() { 20 | return items; 21 | } 22 | 23 | public void setItems(List items) { 24 | int size = this.getItems().size(); 25 | if (size > 0) { 26 | this.getItems().clear(); 27 | notifyItemRangeRemoved(0, size); 28 | } 29 | this.getItems().addAll(items); 30 | notifyItemRangeInserted(0, items.size()); 31 | } 32 | 33 | @Override 34 | public int getItemCount() { 35 | return getItems().size(); 36 | } 37 | 38 | @Override 39 | public void onViewDetachedFromWindow(VH holder) { 40 | holder.itemView.clearAnimation(); 41 | super.onViewDetachedFromWindow(holder); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/MovieAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import androidx.cardview.widget.CardView; 7 | import androidx.recyclerview.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | 14 | import com.bumptech.glide.Glide; 15 | 16 | import java.util.List; 17 | 18 | import butterknife.BindView; 19 | import butterknife.ButterKnife; 20 | import io.github.javiewer.R; 21 | import io.github.javiewer.activity.MovieActivity; 22 | import io.github.javiewer.adapter.item.Movie; 23 | 24 | /** 25 | * Project: JAViewer 26 | */ 27 | public class MovieAdapter extends ItemAdapter { 28 | 29 | protected boolean showIfHot = true; 30 | private Activity mParentActivity; 31 | 32 | public MovieAdapter(List movies, Activity mParentActivity) { 33 | super(movies); 34 | this.mParentActivity = mParentActivity; 35 | } 36 | 37 | @Override 38 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_movie, parent, false); 40 | 41 | return new ViewHolder(v); 42 | } 43 | 44 | @Override 45 | public void onBindViewHolder(final ViewHolder holder, int position) { 46 | final Movie movie = getItems().get(position); 47 | 48 | holder.parse(movie); 49 | 50 | holder.mCard.setOnClickListener(new View.OnClickListener() { 51 | @Override 52 | public void onClick(View v) { 53 | Intent intent = new Intent(mParentActivity, MovieActivity.class); 54 | Bundle bundle = new Bundle(); 55 | bundle.putSerializable("movie", movie); 56 | intent.putExtras(bundle); 57 | 58 | mParentActivity.startActivity(intent); 59 | } 60 | }); 61 | 62 | holder.mImageCover.setImageDrawable(null); 63 | Glide.with(holder.mImageCover.getContext().getApplicationContext()) 64 | .load(movie.getCoverUrl()) 65 | .into(holder.mImageCover); 66 | 67 | holder.mImageHot.setVisibility(movie.isHot() && showIfHot ? View.VISIBLE : View.GONE); 68 | } 69 | 70 | public static class ViewHolder extends RecyclerView.ViewHolder { 71 | 72 | @BindView(R.id.movie_title) 73 | public TextView mTextTitle; 74 | 75 | @BindView(R.id.movie_size) 76 | public TextView mTextCode; 77 | 78 | @BindView(R.id.movie_date) 79 | public TextView mTextDate; 80 | 81 | @BindView(R.id.movie_cover) 82 | public ImageView mImageCover; 83 | 84 | @BindView(R.id.movie_hot) 85 | public ImageView mImageHot; 86 | 87 | @BindView(R.id.card_movie) 88 | public CardView mCard; 89 | 90 | public ViewHolder(View view) { 91 | super(view); 92 | 93 | ButterKnife.bind(this, view); 94 | } 95 | 96 | public void parse(Movie movie) { 97 | mTextCode.setText(movie.getCode()); 98 | mTextTitle.setText(movie.getTitle()); 99 | mTextDate.setText(movie.getDate()); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/NavigationSpinnerAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.IdRes; 5 | import androidx.annotation.LayoutRes; 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ArrayAdapter; 12 | import android.widget.TextView; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | import io.github.javiewer.R; 19 | 20 | /** 21 | * Project: JAViewer 22 | */ 23 | 24 | public class NavigationSpinnerAdapter extends ArrayAdapter { 25 | 26 | private final LayoutInflater mLayoutInflater; 27 | 28 | public NavigationSpinnerAdapter(@NonNull Context context, @LayoutRes int resource) { 29 | this(context, resource, 0, new ArrayList()); 30 | } 31 | 32 | public NavigationSpinnerAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId) { 33 | this(context, resource, textViewResourceId, new ArrayList()); 34 | } 35 | 36 | public NavigationSpinnerAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull T[] objects) { 37 | this(context, resource, 0, Arrays.asList(objects)); 38 | } 39 | 40 | public NavigationSpinnerAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull T[] objects) { 41 | this(context, resource, textViewResourceId, Arrays.asList(objects)); 42 | } 43 | 44 | public NavigationSpinnerAdapter(@NonNull Context context, @LayoutRes int resource, @NonNull List objects) { 45 | this(context, resource, 0, objects); 46 | } 47 | 48 | public NavigationSpinnerAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull List objects) { 49 | super(context, resource, textViewResourceId, objects); 50 | mLayoutInflater = LayoutInflater.from(context); 51 | } 52 | 53 | @Override 54 | public View getDropDownView(int position, @Nullable View view, @NonNull ViewGroup parent) { 55 | if (view == null || !view.getTag().toString().equals("DROPDOWN")) { 56 | view = mLayoutInflater.inflate(R.layout.view_drop_down, parent, false); 57 | view.setTag("DROPDOWN"); 58 | } 59 | 60 | TextView textView = (TextView) view.findViewById(R.id.dropdown_text); 61 | textView.setText(getItem(position).toString()); 62 | 63 | return view; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/ScreenshotAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import androidx.recyclerview.widget.RecyclerView; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | import com.bumptech.glide.Glide; 13 | 14 | import java.util.List; 15 | 16 | import butterknife.BindView; 17 | import butterknife.ButterKnife; 18 | import io.github.javiewer.R; 19 | import io.github.javiewer.activity.GalleryActivity; 20 | import io.github.javiewer.adapter.item.Movie; 21 | import io.github.javiewer.adapter.item.Screenshot; 22 | import io.github.javiewer.view.ViewUtil; 23 | 24 | /** 25 | * Project: JAViewer 26 | */ 27 | 28 | public class ScreenshotAdapter extends RecyclerView.Adapter { 29 | 30 | private List screenshots; 31 | 32 | private Activity mParentActivity; 33 | 34 | private ImageView mIcon; 35 | 36 | private Movie movie; 37 | 38 | public ScreenshotAdapter(List screenshots, Activity mParentActivity, ImageView mIcon, Movie movie) { 39 | this.screenshots = screenshots; 40 | this.mParentActivity = mParentActivity; 41 | this.mIcon = mIcon; 42 | this.movie = movie; 43 | } 44 | 45 | @Override 46 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 47 | View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_screenshot, parent, false); 48 | 49 | return new ViewHolder(v); 50 | } 51 | 52 | @Override 53 | public void onBindViewHolder(final ViewHolder holder, int position) { 54 | Screenshot screenshot = screenshots.get(position); 55 | 56 | holder.mImage.setImageDrawable(null); 57 | Glide.with(holder.mImage.getContext().getApplicationContext()) 58 | .load(screenshot.getThumbnailUrl()) 59 | .into(holder.mImage); 60 | 61 | holder.mImage.setOnClickListener(new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | Intent i = new Intent(mParentActivity, GalleryActivity.class); 65 | Bundle bundle = new Bundle(); 66 | 67 | String[] urls = new String[screenshots.size()]; 68 | for (int k = 0; k < screenshots.size(); k++) { 69 | urls[k] = screenshots.get(k).getImageUrl(); 70 | } 71 | bundle.putStringArray("urls", urls); 72 | bundle.putSerializable("movie", movie); 73 | bundle.putInt("position", holder.getAdapterPosition()); 74 | i.putExtras(bundle); 75 | mParentActivity.startActivity(i); 76 | 77 | } 78 | }); 79 | 80 | if (position == 0) { 81 | ViewUtil.alignIconToView(mIcon, holder.mImage); 82 | } 83 | } 84 | 85 | @Override 86 | public int getItemCount() { 87 | return screenshots == null ? 0 : screenshots.size(); 88 | } 89 | 90 | public class ViewHolder extends RecyclerView.ViewHolder { 91 | 92 | @BindView(R.id.screenshot_image_view) 93 | public ImageView mImage; 94 | 95 | public ViewHolder(View view) { 96 | super(view); 97 | ButterKnife.bind(this, view); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/ViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter; 2 | 3 | import androidx.fragment.app.Fragment; 4 | import androidx.fragment.app.FragmentManager; 5 | import androidx.fragment.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ViewPagerAdapter extends FragmentPagerAdapter { 11 | private final List mFragmentList = new ArrayList<>(); 12 | private final List mFragmentTitleList = new ArrayList<>(); 13 | 14 | public ViewPagerAdapter(FragmentManager manager) { 15 | super(manager); 16 | } 17 | 18 | @Override 19 | public Fragment getItem(int position) { 20 | return mFragmentList.get(position); 21 | } 22 | 23 | @Override 24 | public int getCount() { 25 | return mFragmentList.size(); 26 | } 27 | 28 | public void addFragment(Fragment fragment, String title) { 29 | mFragmentList.add(fragment); 30 | mFragmentTitleList.add(title); 31 | } 32 | 33 | @Override 34 | public CharSequence getPageTitle(int position) { 35 | return mFragmentTitleList.get(position); 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/Actress.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | /** 4 | * Project: JAViewer 5 | */ 6 | public class Actress extends Linkable { 7 | 8 | protected String name; 9 | protected String imageUrl; 10 | 11 | public static Actress create(String name, String imageUrl, String detailUrl) { 12 | Actress actress = new Actress(); 13 | actress.name = name; 14 | actress.imageUrl = imageUrl; 15 | actress.link = detailUrl; 16 | return actress; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public String getImageUrl() { 24 | return imageUrl; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object obj) { 29 | if (super.equals(obj)) { 30 | return true; 31 | } 32 | 33 | if (obj instanceof Actress) { 34 | return this.name.equals(((Actress) obj).getName()); 35 | } 36 | 37 | return false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/DataSource.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Project: JAViewer 7 | */ 8 | 9 | public class DataSource extends Linkable { 10 | 11 | public static DataSource AVMO = new DataSource("AVMOO 日本", "https://avos.pw"); 12 | public static DataSource AVSO = new DataSource("AVSOX 日本无码", "https://avso.club"); 13 | public static DataSource AVXO = new DataSource("AVMEMO 欧美", "https://avxo.pw"); 14 | 15 | 16 | public String name; 17 | public List legacies; 18 | 19 | public DataSource(String name, String baseUrl) { 20 | this.name = name; 21 | this.link = baseUrl; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return name; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/DownloadLink.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | /** 4 | * Project: JAViewer 5 | */ 6 | public class DownloadLink extends Linkable { 7 | protected String title; 8 | protected String size; 9 | protected String date; 10 | protected MagnetLink magnetLink; 11 | 12 | public static DownloadLink create(String title, String size, String date, String link, String magnetLink) { 13 | DownloadLink download = new DownloadLink(); 14 | download.title = title; 15 | download.size = size; 16 | download.date = date; 17 | download.link = link; 18 | download.magnetLink = MagnetLink.create(magnetLink); 19 | return download; 20 | } 21 | 22 | public String getTitle() { 23 | return title; 24 | } 25 | 26 | public String getSize() { 27 | return size; 28 | } 29 | 30 | public String getDate() { 31 | return date; 32 | } 33 | 34 | public boolean hasMagnetLink() { 35 | return magnetLink.getMagnetLink() != null; 36 | } 37 | 38 | public String getMagnetLink() { 39 | return magnetLink.getMagnetLink(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/Genre.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | /** 4 | * Project: JAViewer 5 | */ 6 | public class Genre extends Linkable { 7 | public String name; 8 | 9 | public static Genre create(String name, String link) { 10 | Genre genre = new Genre(); 11 | genre.name = name; 12 | genre.link = link; 13 | return genre; 14 | } 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return name + ":" + link; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/Linkable.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | import java.io.Serializable; 4 | 5 | import static io.github.javiewer.JAViewer.Objects_equals; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | public class Linkable implements Serializable { 11 | 12 | public String link; 13 | 14 | public String getLink() { 15 | return link; 16 | } 17 | 18 | @Override 19 | public boolean equals(Object linkable) { 20 | if (!(linkable instanceof Linkable)) { 21 | return false; 22 | } 23 | 24 | return Objects_equals(link, ((Linkable) linkable).link); 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "Linkable{" + 30 | "link='" + link + '\'' + 31 | '}'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/MagnetLink.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Project: JAViewer 7 | */ 8 | public class MagnetLink implements Serializable { 9 | 10 | protected String magnetLink; 11 | 12 | public static MagnetLink create(String magnetLink) { 13 | MagnetLink magnet = new MagnetLink(); 14 | if (magnetLink != null) { 15 | magnet.magnetLink = magnetLink.substring(0, magnetLink.indexOf("&")); 16 | } 17 | return magnet; 18 | } 19 | 20 | public String getMagnetLink() { 21 | return magnetLink; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/Movie.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | /** 4 | * Project: JAViewer 5 | */ 6 | public class Movie extends Linkable { 7 | 8 | public String title; 9 | public String code; 10 | public String coverUrl; 11 | public String date; 12 | public boolean hot; 13 | 14 | public static Movie create(String title, String code, String date, String coverUrl, String detailUrl, boolean hot) { 15 | Movie movie = new Movie(); 16 | movie.title = title; 17 | movie.date = date; 18 | movie.code = code; 19 | movie.coverUrl = coverUrl; 20 | movie.hot = hot; 21 | movie.link = detailUrl; 22 | return movie; 23 | } 24 | 25 | public String getTitle() { 26 | return title; 27 | } 28 | 29 | public String getDate() { 30 | return date; 31 | } 32 | 33 | public String getCode() { 34 | return code; 35 | } 36 | 37 | public String getCoverUrl() { 38 | return coverUrl; 39 | } 40 | 41 | public boolean isHot() { 42 | return hot; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "Movie{" + 48 | "title='" + title + '\'' + 49 | ", code='" + code + '\'' + 50 | ", coverUrl='" + coverUrl + '\'' + 51 | ", date='" + date + '\'' + 52 | ", hot=" + hot + 53 | '}'; 54 | } 55 | 56 | @Override 57 | public boolean equals(Object obj) { 58 | if (super.equals(obj)) { 59 | return true; 60 | } 61 | 62 | if (obj instanceof Movie) { 63 | return this.code.equals(((Movie) obj).code); 64 | } 65 | 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/MovieDetail.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Project: JAViewer 8 | */ 9 | public class MovieDetail { 10 | 11 | public final List screenshots = new ArrayList<>(); 12 | public String title; 13 | public String coverUrl; 14 | public List
headers = new ArrayList<>(); 15 | 16 | public List genres = new ArrayList<>(); 17 | 18 | public List actresses = new ArrayList<>(); 19 | 20 | public static class Header extends Linkable { 21 | public String name; 22 | public String value; 23 | 24 | public static Header create(String name, String value, String link) { 25 | Header header = new Header(); 26 | header.name = name; 27 | header.value = value; 28 | header.link = link; 29 | return header; 30 | } 31 | 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public String getValue() { 37 | return value; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "Header{" + 43 | "name='" + name + '\'' + 44 | ", value='" + value + '\'' + 45 | '}'; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/adapter/item/Screenshot.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.adapter.item; 2 | 3 | /** 4 | * Project: JAViewer 5 | */ 6 | public class Screenshot extends Linkable { 7 | 8 | protected String thumbnailUrl; 9 | 10 | public static Screenshot create(String thumbnailUrl, String imageUrl) { 11 | Screenshot screenshot = new Screenshot(); 12 | screenshot.thumbnailUrl = thumbnailUrl; 13 | screenshot.link = imageUrl; 14 | return screenshot; 15 | } 16 | 17 | public String getThumbnailUrl() { 18 | return thumbnailUrl; 19 | } 20 | 21 | public String getImageUrl() { 22 | return getLink(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/ActressesFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | 4 | import android.os.Bundle; 5 | import androidx.annotation.Nullable; 6 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; 7 | import androidx.recyclerview.widget.LinearLayoutManager; 8 | import androidx.recyclerview.widget.RecyclerView; 9 | 10 | import java.util.List; 11 | 12 | import io.github.javiewer.JAViewer; 13 | import io.github.javiewer.adapter.ActressAdapter; 14 | import io.github.javiewer.adapter.item.Actress; 15 | import io.github.javiewer.network.provider.AVMOProvider; 16 | import io.github.javiewer.view.decoration.ActressItemDecoration; 17 | import io.github.javiewer.view.listener.EndlessOnScrollListener; 18 | import okhttp3.ResponseBody; 19 | import retrofit2.Call; 20 | 21 | public class ActressesFragment extends RecyclerFragment { 22 | 23 | public ActressesFragment() { 24 | // Required empty public constructor 25 | } 26 | 27 | @Override 28 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 29 | this.setLayoutManager(new LinearLayoutManager(this.getContext())); 30 | //this.setAdapter(new SlideInBottomAnimationAdapter(new ActressAdapter(getItems(), this.getActivity()))); 31 | this.setAdapter(new ActressAdapter(getItems(), this.getActivity())); 32 | 33 | mRecyclerView.addItemDecoration(new ActressItemDecoration()); 34 | 35 | /*RecyclerView.ItemAnimator animator = new SlideInUpAnimator(); 36 | animator.setAddDuration(300); 37 | mRecyclerView.setItemAnimator(animator);*/ 38 | 39 | this.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 40 | @Override 41 | public void onRefresh() { 42 | getOnScrollListener().refresh(); 43 | } 44 | }); 45 | 46 | this.addOnScrollListener(new EndlessOnScrollListener() { 47 | @Override 48 | public Call newCall(int page) { 49 | return ActressesFragment.this.newCall(page); 50 | } 51 | 52 | @Override 53 | public RecyclerView.LayoutManager getLayoutManager() { 54 | return ActressesFragment.this.getLayoutManager(); 55 | } 56 | 57 | @Override 58 | public SwipeRefreshLayout getRefreshLayout() { 59 | return ActressesFragment.this.mRefreshLayout; 60 | } 61 | 62 | @Override 63 | public RecyclerView.Adapter getAdapter() { 64 | return ActressesFragment.this.getAdapter(); 65 | } 66 | 67 | @Override 68 | public List getItems() { 69 | return ActressesFragment.this.getItems(); 70 | } 71 | 72 | @Override 73 | public void onResult(ResponseBody response) throws Exception { 74 | super.onResult(response); 75 | List wrappers = AVMOProvider.parseActresses(response.string()); 76 | 77 | int pos = getItems().size(); 78 | 79 | getItems().addAll(wrappers); 80 | getAdapter().notifyItemRangeInserted(pos, wrappers.size()); 81 | } 82 | }); 83 | 84 | mRefreshLayout.post(new Runnable() { 85 | @Override 86 | public void run() { 87 | mRefreshLayout.setRefreshing(true); 88 | getOnRefreshListener().onRefresh(); 89 | } 90 | }); 91 | 92 | super.onActivityCreated(savedInstanceState); 93 | } 94 | 95 | public Call newCall(int page) { 96 | return JAViewer.SERVICE.getActresses(page); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/ExtendedAppBarFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | import com.google.android.material.appbar.AppBarLayout; 4 | import androidx.fragment.app.Fragment; 5 | 6 | /** 7 | * Project: JAViewer 8 | */ 9 | public class ExtendedAppBarFragment extends Fragment { 10 | private AppBarLayout mAppBarLayout; 11 | 12 | public AppBarLayout getAppBarLayout() { 13 | return mAppBarLayout; 14 | } 15 | 16 | public void setAppBarLayout(AppBarLayout mAppBarLayout) { 17 | this.mAppBarLayout = mAppBarLayout; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/HomeFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.Call; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | public class HomeFragment extends MovieFragment { 11 | @Override 12 | public Call newCall(int page) { 13 | return JAViewer.SERVICE.getHomePage(page); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/MovieFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | 4 | import android.os.Bundle; 5 | import androidx.annotation.Nullable; 6 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; 7 | import androidx.recyclerview.widget.LinearLayoutManager; 8 | import androidx.recyclerview.widget.RecyclerView; 9 | 10 | import java.util.List; 11 | 12 | import io.github.javiewer.adapter.MovieAdapter; 13 | import io.github.javiewer.adapter.item.Movie; 14 | import io.github.javiewer.network.provider.AVMOProvider; 15 | import io.github.javiewer.view.decoration.MovieItemDecoration; 16 | import io.github.javiewer.view.listener.EndlessOnScrollListener; 17 | import jp.wasabeef.recyclerview.adapters.SlideInBottomAnimationAdapter; 18 | import jp.wasabeef.recyclerview.animators.SlideInUpAnimator; 19 | import okhttp3.ResponseBody; 20 | import retrofit2.Call; 21 | 22 | public abstract class MovieFragment extends RecyclerFragment { 23 | 24 | public MovieFragment() { 25 | // Required empty public constructor 26 | } 27 | 28 | @Override 29 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 30 | this.setLayoutManager(new LinearLayoutManager(this.getContext())); 31 | mRecyclerView.addItemDecoration(new MovieItemDecoration()); 32 | this.setAdapter(new SlideInBottomAnimationAdapter(new MovieAdapter(getItems(), this.getActivity()))); 33 | RecyclerView.ItemAnimator animator = new SlideInUpAnimator(); 34 | animator.setAddDuration(300); 35 | mRecyclerView.setItemAnimator(animator); 36 | 37 | this.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 38 | @Override 39 | public void onRefresh() { 40 | getOnScrollListener().refresh(); 41 | } 42 | }); 43 | 44 | this.addOnScrollListener(new EndlessOnScrollListener() { 45 | @Override 46 | public Call newCall(int page) { 47 | return MovieFragment.this.newCall(page); 48 | } 49 | 50 | @Override 51 | public RecyclerView.LayoutManager getLayoutManager() { 52 | return MovieFragment.this.getLayoutManager(); 53 | } 54 | 55 | @Override 56 | public SwipeRefreshLayout getRefreshLayout() { 57 | return MovieFragment.this.mRefreshLayout; 58 | } 59 | 60 | @Override 61 | public List getItems() { 62 | return MovieFragment.this.getItems(); 63 | } 64 | 65 | @Override 66 | public RecyclerView.Adapter getAdapter() { 67 | return MovieFragment.this.getAdapter(); 68 | } 69 | 70 | @Override 71 | public void onResult(ResponseBody response) throws Exception { 72 | super.onResult(response); 73 | List wrappers = AVMOProvider.parseMovies(response.string()); 74 | 75 | int pos = getItems().size(); 76 | 77 | getItems().addAll(wrappers); 78 | getAdapter().notifyItemRangeInserted(pos, wrappers.size()); 79 | } 80 | }); 81 | 82 | mRefreshLayout.post(new Runnable() { 83 | @Override 84 | public void run() { 85 | mRefreshLayout.setRefreshing(true); 86 | getOnRefreshListener().onRefresh(); 87 | } 88 | }); 89 | 90 | super.onActivityCreated(savedInstanceState); 91 | } 92 | 93 | public abstract Call newCall(int page); 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/MovieListFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | import android.os.Bundle; 4 | import androidx.annotation.Nullable; 5 | 6 | import io.github.javiewer.JAViewer; 7 | import okhttp3.ResponseBody; 8 | import retrofit2.Call; 9 | 10 | /** 11 | * Project: JAViewer 12 | */ 13 | public class MovieListFragment extends MovieFragment { 14 | 15 | public String link; 16 | 17 | @Override 18 | public void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | 21 | Bundle bundle = getArguments(); 22 | this.link = bundle.getString("link"); 23 | } 24 | 25 | @Override 26 | public Call newCall(int page) { 27 | return JAViewer.SERVICE.get(this.link + "/page/" + page); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/PopularFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.Call; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | public class PopularFragment extends MovieFragment { 11 | @Override 12 | public Call newCall(int page) { 13 | return JAViewer.SERVICE.getPopular(page); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/ReleasedFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.Call; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | public class ReleasedFragment extends MovieFragment { 11 | @Override 12 | public Call newCall(int page) { 13 | return JAViewer.SERVICE.getReleased(page); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/favourite/FavouriteActressFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment.favourite; 2 | 3 | import androidx.recyclerview.widget.RecyclerView; 4 | 5 | import io.github.javiewer.JAViewer; 6 | import io.github.javiewer.adapter.ActressAdapter; 7 | import io.github.javiewer.adapter.ItemAdapter; 8 | import io.github.javiewer.view.decoration.ActressItemDecoration; 9 | 10 | /** 11 | * Project: JAViewer 12 | */ 13 | 14 | public class FavouriteActressFragment extends FavouriteFragment { 15 | @Override 16 | public ItemAdapter adapter() { 17 | return new ActressAdapter(JAViewer.CONFIGURATIONS.getStarredActresses(), this.getActivity()); 18 | } 19 | 20 | @Override 21 | public RecyclerView.ItemDecoration decoration() { 22 | return new ActressItemDecoration(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/favourite/FavouriteFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment.favourite; 2 | 3 | import android.os.Bundle; 4 | import androidx.annotation.Nullable; 5 | import androidx.recyclerview.widget.LinearLayoutManager; 6 | import androidx.recyclerview.widget.RecyclerView; 7 | 8 | import io.github.javiewer.adapter.ItemAdapter; 9 | import io.github.javiewer.adapter.item.Movie; 10 | import io.github.javiewer.fragment.RecyclerFragment; 11 | 12 | /** 13 | * Project: JAViewer 14 | */ 15 | 16 | public abstract class FavouriteFragment extends RecyclerFragment { 17 | 18 | public void update() { 19 | RecyclerView.Adapter adapter = getAdapter(); 20 | if (adapter != null) { 21 | adapter.notifyDataSetChanged(); 22 | } 23 | } 24 | 25 | @Override 26 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 27 | this.setLayoutManager(new LinearLayoutManager(this.getContext())); 28 | this.setAdapter(adapter()); 29 | //this.setAdapter(adapter = 30 | mRefreshLayout.setEnabled(false); 31 | 32 | if (decoration() != null) { 33 | mRecyclerView.addItemDecoration(decoration()); 34 | } 35 | 36 | super.onActivityCreated(savedInstanceState); 37 | } 38 | 39 | @Override 40 | public void onDestroy() { 41 | super.onDestroy(); 42 | } 43 | 44 | public abstract ItemAdapter adapter(); 45 | 46 | public RecyclerView.ItemDecoration decoration() { 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/favourite/FavouriteMovieFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment.favourite; 2 | 3 | import androidx.recyclerview.widget.RecyclerView; 4 | 5 | import io.github.javiewer.JAViewer; 6 | import io.github.javiewer.adapter.ItemAdapter; 7 | import io.github.javiewer.adapter.MovieAdapter; 8 | import io.github.javiewer.view.decoration.MovieItemDecoration; 9 | 10 | /** 11 | * Project: JAViewer 12 | */ 13 | 14 | public class FavouriteMovieFragment extends FavouriteFragment { 15 | @Override 16 | public ItemAdapter adapter() { 17 | return new MovieAdapter(JAViewer.CONFIGURATIONS.getStarredMovies(), this.getActivity()) {{ 18 | showIfHot = false; 19 | }}; 20 | } 21 | 22 | @Override 23 | public RecyclerView.ItemDecoration decoration() { 24 | return new MovieItemDecoration(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/favourite/FavouriteTabsFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment.favourite; 2 | 3 | 4 | import android.os.Bundle; 5 | import androidx.annotation.Nullable; 6 | import com.google.android.material.tabs.TabLayout; 7 | import androidx.viewpager.widget.ViewPager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import butterknife.BindView; 13 | import butterknife.ButterKnife; 14 | import io.github.javiewer.R; 15 | import io.github.javiewer.adapter.ViewPagerAdapter; 16 | import io.github.javiewer.fragment.ExtendedAppBarFragment; 17 | 18 | public class FavouriteTabsFragment extends ExtendedAppBarFragment { 19 | 20 | public static ViewPagerAdapter mAdapter; 21 | @BindView(R.id.favourite_tabs) 22 | public TabLayout mTabLayout; 23 | @BindView(R.id.favourite_view_pager) 24 | public ViewPager mViewPager; 25 | 26 | public FavouriteTabsFragment() { 27 | // Required empty public constructor 28 | } 29 | 30 | public static void update() { 31 | if (mAdapter != null) { 32 | for (int i = 0; i < mAdapter.getCount(); i++) { 33 | ((FavouriteFragment) mAdapter.getItem(i)).update(); 34 | } 35 | } 36 | } 37 | 38 | @Override 39 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 40 | super.onActivityCreated(savedInstanceState); 41 | 42 | mAdapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager()); 43 | mViewPager.setAdapter(mAdapter); 44 | mTabLayout.setupWithViewPager(mViewPager); 45 | 46 | FavouriteFragment fragment = new FavouriteMovieFragment(); 47 | mAdapter.addFragment(fragment, "作品"); 48 | fragment = new FavouriteActressFragment(); 49 | mAdapter.addFragment(fragment, "女优"); 50 | 51 | mAdapter.notifyDataSetChanged(); 52 | } 53 | 54 | @Override 55 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 56 | View view = inflater.inflate(R.layout.fragment_favourite, container, false); 57 | ButterKnife.bind(this, view); 58 | return view; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/genre/GenreFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment.genre; 2 | 3 | 4 | import android.os.Bundle; 5 | import androidx.annotation.Nullable; 6 | import androidx.fragment.app.Fragment; 7 | import androidx.recyclerview.widget.RecyclerView; 8 | import androidx.recyclerview.widget.StaggeredGridLayoutManager; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import butterknife.BindView; 17 | import butterknife.ButterKnife; 18 | import io.github.javiewer.JAViewer; 19 | import io.github.javiewer.R; 20 | import io.github.javiewer.adapter.GenreAdapter; 21 | import io.github.javiewer.adapter.item.Genre; 22 | import io.github.javiewer.view.ViewUtil; 23 | import io.github.javiewer.view.decoration.GridSpacingItemDecoration; 24 | import jp.wasabeef.recyclerview.animators.SlideInUpAnimator; 25 | import okhttp3.ResponseBody; 26 | import retrofit2.Call; 27 | 28 | public class GenreFragment extends Fragment { 29 | 30 | @BindView(R.id.genre_recycler_view) 31 | public RecyclerView mRecyclerView; 32 | protected List genres = new ArrayList<>(); 33 | private RecyclerView.Adapter mAdapter; 34 | private StaggeredGridLayoutManager mLayoutManager; 35 | 36 | public GenreFragment() { 37 | // Required empty public constructor 38 | } 39 | 40 | @Override 41 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 42 | Bundle savedInstanceState) { 43 | View view = inflater.inflate(R.layout.fragment_genre_list, container, false); 44 | ButterKnife.bind(this, view); 45 | return view; 46 | } 47 | 48 | @Override 49 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 50 | super.onActivityCreated(savedInstanceState); 51 | 52 | mRecyclerView.setLayoutManager(mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); 53 | mRecyclerView.setAdapter(this.mAdapter = new GenreAdapter(genres, this.getActivity())); 54 | mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(2, ViewUtil.dpToPx(8), true)); 55 | 56 | RecyclerView.ItemAnimator animator = new SlideInUpAnimator(); 57 | animator.setAddDuration(300); 58 | mRecyclerView.setItemAnimator(animator); 59 | 60 | this.mAdapter.notifyItemRangeInserted(0, this.mAdapter.getItemCount()); 61 | } 62 | 63 | public Call getCall(int page) { 64 | return JAViewer.SERVICE.getActresses(page); 65 | } 66 | 67 | public List getGenres() { 68 | return genres; 69 | } 70 | 71 | public RecyclerView.Adapter getAdapter() { 72 | return mAdapter; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/fragment/genre/GenreTabsFragment.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.fragment.genre; 2 | 3 | 4 | import android.os.Bundle; 5 | import androidx.annotation.Nullable; 6 | import com.google.android.material.tabs.TabLayout; 7 | import androidx.viewpager.widget.ViewPager; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ProgressBar; 12 | 13 | import java.util.LinkedHashMap; 14 | import java.util.List; 15 | 16 | import butterknife.BindView; 17 | import butterknife.ButterKnife; 18 | import io.github.javiewer.JAViewer; 19 | import io.github.javiewer.R; 20 | import io.github.javiewer.adapter.ViewPagerAdapter; 21 | import io.github.javiewer.adapter.item.Genre; 22 | import io.github.javiewer.fragment.ExtendedAppBarFragment; 23 | import io.github.javiewer.network.provider.AVMOProvider; 24 | import okhttp3.ResponseBody; 25 | import retrofit2.Call; 26 | import retrofit2.Callback; 27 | import retrofit2.Response; 28 | 29 | public class GenreTabsFragment extends ExtendedAppBarFragment { 30 | 31 | @BindView(R.id.genre_tabs) 32 | public TabLayout mTabLayout; 33 | 34 | @BindView(R.id.genre_view_pager) 35 | public ViewPager mViewPager; 36 | 37 | @BindView(R.id.genre_progress_bar) 38 | public ProgressBar mProgressBar; 39 | 40 | public ViewPagerAdapter mAdapter; 41 | 42 | public GenreTabsFragment() { 43 | // Required empty public constructor 44 | } 45 | 46 | @Override 47 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 48 | super.onActivityCreated(savedInstanceState); 49 | 50 | mAdapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager()); 51 | mViewPager.setAdapter(mAdapter); 52 | mTabLayout.setupWithViewPager(mViewPager); 53 | 54 | Call call = JAViewer.SERVICE.getGenre(); 55 | call.enqueue(new Callback() { 56 | @Override 57 | public void onResponse(Call call, Response response) { 58 | mProgressBar.setVisibility(View.GONE); 59 | try { 60 | LinkedHashMap> genres = AVMOProvider.parseGenres(response.body().string()); 61 | 62 | GenreFragment fragment; 63 | for (String title : genres.keySet()) { 64 | fragment = new GenreFragment(); 65 | fragment.getGenres().addAll(genres.get(title)); 66 | mAdapter.addFragment(fragment, title); 67 | } 68 | 69 | mAdapter.notifyDataSetChanged(); 70 | 71 | mTabLayout.setVisibility(View.VISIBLE); 72 | } catch (Throwable e) { 73 | onFailure(call, e); 74 | } 75 | } 76 | 77 | @Override 78 | public void onFailure(Call call, Throwable t) { 79 | t.printStackTrace(); 80 | } 81 | }); 82 | } 83 | 84 | @Override 85 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 86 | View view = inflater.inflate(R.layout.fragment_genre, container, false); 87 | ButterKnife.bind(this, view); 88 | return view; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/network/Avgle.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.network; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import io.github.javiewer.network.item.AvgleSearchResult; 5 | import okhttp3.ResponseBody; 6 | import retrofit2.Call; 7 | import retrofit2.Retrofit; 8 | import retrofit2.converter.gson.GsonConverterFactory; 9 | import retrofit2.http.GET; 10 | import retrofit2.http.Headers; 11 | import retrofit2.http.Path; 12 | 13 | /** 14 | * Project: JAViewer 15 | */ 16 | public interface Avgle { 17 | 18 | String BASE_URL = "https://api.avgle.com"; 19 | Avgle INSTANCE = new Retrofit.Builder() 20 | .baseUrl(Avgle.BASE_URL) 21 | .client(JAViewer.HTTP_CLIENT) 22 | .addConverterFactory(GsonConverterFactory.create()) 23 | .build() 24 | .create(Avgle.class); 25 | 26 | @GET("/v1/search/{keyword}/0?limit=1") 27 | @Headers("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6") 28 | Call search(@Path(value = "keyword") String keyword); 29 | 30 | @GET("/{path}") 31 | Call get(@Path("path") String path); 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/network/BTSO.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.network; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.Call; 6 | import retrofit2.Retrofit; 7 | import retrofit2.http.GET; 8 | import retrofit2.http.Headers; 9 | import retrofit2.http.Path; 10 | import retrofit2.http.Url; 11 | 12 | /** 13 | * Project: JAViewer 14 | */ 15 | public interface BTSO { 16 | 17 | String BASE_URL = "https://btsow.monster"; 18 | BTSO INSTANCE = new Retrofit.Builder() 19 | .baseUrl(BTSO.BASE_URL) 20 | .client(JAViewer.HTTP_CLIENT) 21 | .build() 22 | .create(BTSO.class); 23 | 24 | @GET("/search/{keyword}/page/{page}") 25 | @Headers("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6") 26 | Call search(@Path(value = "keyword") String keyword, @Path("page") int page); 27 | 28 | @GET 29 | @Headers("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6") 30 | Call get(@Url String url); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/network/BasicService.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.network; 2 | 3 | import okhttp3.ResponseBody; 4 | import retrofit2.Call; 5 | import retrofit2.http.GET; 6 | import retrofit2.http.Path; 7 | import retrofit2.http.Url; 8 | 9 | /** 10 | * Project: JAViewer 11 | */ 12 | public interface BasicService { 13 | 14 | String LANGUAGE_NODE = "/cn"; 15 | 16 | @GET(BasicService.LANGUAGE_NODE + "/page/{page}") 17 | Call getHomePage(@Path("page") int page); 18 | 19 | @GET(BasicService.LANGUAGE_NODE + "/released/page/{page}") 20 | Call getReleased(@Path("page") int page); 21 | 22 | @GET(BasicService.LANGUAGE_NODE + "/popular/page/{page}") 23 | Call getPopular(@Path("page") int page); 24 | 25 | @GET(BasicService.LANGUAGE_NODE + "/actresses/page/{page}") 26 | Call getActresses(@Path("page") int page); 27 | 28 | @GET(BasicService.LANGUAGE_NODE + "/genre") 29 | Call getGenre(); 30 | 31 | @GET 32 | Call get(@Url String url); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/network/PSVS.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.network; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import io.github.javiewer.network.item.AvgleSearchResult; 5 | import retrofit2.Call; 6 | import retrofit2.Retrofit; 7 | import retrofit2.converter.gson.GsonConverterFactory; 8 | import retrofit2.http.GET; 9 | import retrofit2.http.Query; 10 | 11 | /** 12 | * Project: JAViewer 13 | */ 14 | public interface PSVS { 15 | 16 | String BASE_URL = "http://api.rekonquer.com"; 17 | PSVS INSTANCE = new Retrofit.Builder() 18 | .baseUrl(PSVS.BASE_URL) 19 | .client(JAViewer.HTTP_CLIENT) 20 | .addConverterFactory(GsonConverterFactory.create()) 21 | .build() 22 | .create(PSVS.class); 23 | 24 | @GET("/psvs/search.php") 25 | Call search(@Query(value = "kw") String keyword); 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/network/TorrentKitty.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.network; 2 | 3 | import io.github.javiewer.JAViewer; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.Call; 6 | import retrofit2.Retrofit; 7 | import retrofit2.http.GET; 8 | import retrofit2.http.Headers; 9 | import retrofit2.http.Path; 10 | import retrofit2.http.Url; 11 | 12 | /** 13 | * Project: JAViewer 14 | */ 15 | public interface TorrentKitty { 16 | 17 | String BASE_URL = "https://www.torrentkitty.tv"; 18 | TorrentKitty INSTANCE = new Retrofit.Builder() 19 | .baseUrl(TorrentKitty.BASE_URL) 20 | .client(JAViewer.HTTP_CLIENT) 21 | .build() 22 | .create(TorrentKitty.class); 23 | 24 | @GET("/search/{keyword}") 25 | @Headers("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6") 26 | Call search(@Path(value = "keyword") String keyword); 27 | 28 | @GET 29 | @Headers("Accept-Language: zh-CN,zh;q=0.8,en;q=0.6") 30 | Call get(@Url String url); 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/javiewer/network/item/AvgleSearchResult.java: -------------------------------------------------------------------------------- 1 | package io.github.javiewer.network.item; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Project: JAViewer 9 | */ 10 | public class AvgleSearchResult { 11 | 12 | public boolean success; 13 | public Response response; 14 | 15 | public static class Response { 16 | 17 | public boolean has_more; 18 | public int total_videos; 19 | public int current_offset; 20 | public int limit; 21 | public List