├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ │ └── ml │ │ │ └── melun │ │ │ └── mangaview │ │ │ ├── CheckInfo.java │ │ │ ├── CustomJSONObject.java │ │ │ ├── Downloader.java │ │ │ ├── MainApplication.java │ │ │ ├── Migrator.java │ │ │ ├── Notice.java │ │ │ ├── Preference.java │ │ │ ├── UrlUpdater.java │ │ │ ├── Utils.java │ │ │ ├── activity │ │ │ ├── AdvSearchActivity.java │ │ │ ├── CaptchaActivity.java │ │ │ ├── CommentsActivity.java │ │ │ ├── DebugActivity.java │ │ │ ├── DownloadActivity.java │ │ │ ├── EpisodeActivity.java │ │ │ ├── FirstTimeActivity.java │ │ │ ├── FolderSelectActivity.java │ │ │ ├── LayoutEditActivity.java │ │ │ ├── LicenseActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── NoticesActivity.java │ │ │ ├── SettingsActivity.java │ │ │ ├── TagSearchActivity.java │ │ │ ├── ViewerActivity.java │ │ │ ├── ViewerActivity2.java │ │ │ └── ViewerActivity3.java │ │ │ ├── adapter │ │ │ ├── CommentsAdapter.java │ │ │ ├── CustomSpinnerAdapter.java │ │ │ ├── EpisodeAdapter.java │ │ │ ├── MainAdapter.java │ │ │ ├── MainTagAdapter.java │ │ │ ├── MainUpdatedAdapter.java │ │ │ ├── MainWebtoonAdapter.java │ │ │ ├── SelectEpisodeAdapter.java │ │ │ ├── StripAdapter.java │ │ │ ├── TagAdapter.java │ │ │ ├── TitleAdapter.java │ │ │ ├── UpdatedAdapter.java │ │ │ └── ViewerPagerAdapter.java │ │ │ ├── fragment │ │ │ ├── CommentsTabFragment.java │ │ │ ├── MainMain.java │ │ │ ├── MainSearch.java │ │ │ ├── RecyclerFragment.java │ │ │ └── ViewerPageFragment.java │ │ │ ├── glide │ │ │ └── CustomGlideModule.java │ │ │ ├── interfaces │ │ │ ├── IntegerCallback.java │ │ │ ├── MainActivityCallback.java │ │ │ ├── PageInterface.java │ │ │ └── StringCallback.java │ │ │ ├── mangaview │ │ │ ├── Bookmark.java │ │ │ ├── Comment.java │ │ │ ├── CustomHttpClient.java │ │ │ ├── Decoder.java │ │ │ ├── DownloadTitle.java │ │ │ ├── Login.java │ │ │ ├── MTitle.java │ │ │ ├── MainPage.java │ │ │ ├── MainPageWebtoon.java │ │ │ ├── Manga.java │ │ │ ├── Ranking.java │ │ │ ├── Search.java │ │ │ ├── Title.java │ │ │ ├── UpdatedList.java │ │ │ └── UpdatedManga.java │ │ │ ├── model │ │ │ └── PageItem.java │ │ │ └── ui │ │ │ ├── CustomSpinner.java │ │ │ ├── MarqueeToolbar.java │ │ │ ├── NpaFlexboxLayoutManager.java │ │ │ ├── NpaLinearLayoutManager.java │ │ │ └── StripLayoutManager.java │ └── res │ │ ├── anim │ │ ├── fade_in.xml │ │ └── fade_out.xml │ │ ├── drawable-hdpi │ │ └── notification_logo.png │ │ ├── drawable-mdpi │ │ └── notification_logo.png │ │ ├── drawable-v21 │ │ └── ic_menu_send.xml │ │ ├── drawable-xhdpi │ │ └── notification_logo.png │ │ ├── drawable-xxhdpi │ │ └── notification_logo.png │ │ ├── drawable-xxxhdpi │ │ ├── logo_static.png │ │ └── notification_logo.png │ │ ├── drawable │ │ ├── blank.xml │ │ ├── button_bg.xml │ │ ├── button_bg_light.xml │ │ ├── button_bg_on.xml │ │ ├── button_bg_white.xml │ │ ├── down_arrow.xml │ │ ├── download.xml │ │ ├── first_page.xml │ │ ├── ic_adv_search.xml │ │ ├── ic_arrow_left.xml │ │ ├── ic_arrow_right.xml │ │ ├── ic_baseline_close_24.xml │ │ ├── ic_baseline_fullscreen_24.xml │ │ ├── ic_baseline_fullscreen_exit_24.xml │ │ ├── ic_baseline_library_books_24.xml │ │ ├── ic_baseline_more_vert_24px.xml │ │ ├── ic_baseline_open_in_new_24.xml │ │ ├── ic_bookmark.xml │ │ ├── ic_bookmark_border.xml │ │ ├── ic_comment.xml │ │ ├── ic_comments.xml │ │ ├── ic_favorite.xml │ │ ├── ic_favorite_border.xml │ │ ├── ic_history.xml │ │ ├── ic_info_black.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_list.xml │ │ ├── ic_logo.xml │ │ ├── ic_menu_open_24px.xml │ │ ├── ic_refresh.xml │ │ ├── ic_search.xml │ │ ├── ic_smile.xml │ │ ├── ic_tag.xml │ │ ├── ic_thumb.xml │ │ ├── launch_screen.xml │ │ ├── placeholder.xml │ │ ├── play.xml │ │ ├── refresh_button_bg.xml │ │ ├── side_nav_bar.xml │ │ ├── up_arrow.xml │ │ └── user.png │ │ ├── layout │ │ ├── activity_adv_search.xml │ │ ├── activity_captcha.xml │ │ ├── activity_comments.xml │ │ ├── activity_debug.xml │ │ ├── activity_download.xml │ │ ├── activity_episode.xml │ │ ├── activity_first_time.xml │ │ ├── activity_folder_select.xml │ │ ├── activity_layout_edit.xml │ │ ├── activity_license.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_notices.xml │ │ ├── activity_settings.xml │ │ ├── activity_tag_search.xml │ │ ├── activity_viewer.xml │ │ ├── activity_viewer2.xml │ │ ├── activity_viewer3.xml │ │ ├── app_bar_main.xml │ │ ├── content_comments.xml │ │ ├── content_favorite.xml │ │ ├── content_kakao_popup.xml │ │ ├── content_key_set_popup.xml │ │ ├── content_main.xml │ │ ├── content_notification.xml │ │ ├── content_recent.xml │ │ ├── content_recycler.xml │ │ ├── content_search.xml │ │ ├── content_toki_captcha_popup.xml │ │ ├── fragment_test.xml │ │ ├── fragment_viewer.xml │ │ ├── item_comment.xml │ │ ├── item_custom_spinner.xml │ │ ├── item_custom_spinner_dropdown.xml │ │ ├── item_episode.xml │ │ ├── item_header.xml │ │ ├── item_main_header.xml │ │ ├── item_main_name.xml │ │ ├── item_main_tag.xml │ │ ├── item_main_updated_list.xml │ │ ├── item_spinner.xml │ │ ├── item_strip.xml │ │ ├── item_strip_info.xml │ │ ├── item_tag.xml │ │ ├── item_title.xml │ │ ├── item_updated.xml │ │ ├── item_updated_list.xml │ │ ├── main_item_ranking.xml │ │ ├── nav_header_main.xml │ │ ├── progress_panel.xml │ │ ├── viewer_toolbar.xml │ │ └── viewer_toolbar_bottom.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ ├── debug_menu.xml │ │ ├── episode_menu.xml │ │ ├── main.xml │ │ ├── search_menu.xml │ │ └── title_options.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── file_paths.xml │ │ ├── pref_data_sync.xml │ │ ├── pref_general.xml │ │ ├── pref_headers.xml │ │ └── pref_notification.xml │ └── test │ └── java │ └── ml │ └── melun │ └── mangaview │ └── ExampleUnitTest.java ├── build.gradle ├── etc ├── notice.json └── notices.json ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── index.html ├── releases.html ├── settings.gradle ├── version.json └── web ├── favicon.png ├── logo.svg ├── logo_static.svg └── style.css /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.war 15 | *.nar 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | 21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 22 | hs_err_pid* 23 | 24 | local.properties 25 | .gradle/ 26 | .idea/ 27 | .DS_Store 28 | build/ 29 | app/build/ 30 | release/ 31 | app/release/ 32 | 33 | *.iml 34 | *.p12 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 junheah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![logo](/web/logo_static.svg "MangaView")](https://junheah.github.io/MangaViewAndroid/) 2 | # 마나토끼 전용 뷰어/다운로더 앱 # 3 | 4 | [![GitHub All Releases](https://img.shields.io/github/downloads/junheah/MangaViewAndroid/total?color=db49de&label=다운로드)](https://junheah.github.io/MangaViewAndroid/) 5 | ### [최신 버전 다운로드 (apk)](https://junheah.github.io/MangaViewAndroid/) ### 6 | 7 | # 8 | [모든 릴리즈 한번에 보기](https://github.com/junheah/MangaViewAndroid/tree/master/releases_old) 9 | 10 | 버그 제보는 [이슈](https://github.com/junheah/MangaViewAndroid/issues)를 통해서 해주세요 11 | 12 | ## License ## 13 | [MIT License](/LICENSE) 14 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | android { 3 | compileOptions { 4 | sourceCompatibility JavaVersion.VERSION_1_8 5 | targetCompatibility JavaVersion.VERSION_1_8 6 | } 7 | 8 | signingConfigs { 9 | // debug { 10 | // Properties properties = new Properties() 11 | // properties.load(project.rootProject.file('local.properties').newDataInputStream()) 12 | // storeFile file(properties.getProperty('storeFile')) 13 | // keyAlias properties.getProperty('keyAlias') 14 | // storePassword properties.getProperty('storePassword') 15 | // keyPassword properties.getProperty('keyPassword') 16 | // } 17 | } 18 | 19 | compileSdkVersion 33 20 | def date = new Date() 21 | def formattedDate = date.format('YYMMdd') 22 | // integer max value is 2147483647 23 | def code = formattedDate.toInteger() + 2112000000 24 | defaultConfig { 25 | applicationId "ml.melun.mangaview" 26 | minSdkVersion 21 27 | targetSdkVersion 33 28 | versionName "4.6-" + code 29 | versionCode code 30 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 31 | vectorDrawables.useSupportLibrary = true 32 | multiDexEnabled true 33 | 34 | setProperty("archivesBaseName", "mangaViewer_" + code) 35 | } 36 | buildTypes { 37 | release { 38 | minifyEnabled false 39 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 40 | } 41 | debug { 42 | signingConfig signingConfigs.debug 43 | } 44 | } 45 | namespace 'ml.melun.mangaview' 46 | } 47 | repositories { 48 | mavenCentral() 49 | maven { url "https://jitpack.io" } 50 | google() 51 | } 52 | 53 | 54 | dependencies { 55 | implementation 'com.google.android.flexbox:flexbox:3.0.0' 56 | implementation 'androidx.documentfile:documentfile:1.0.1' 57 | implementation 'androidx.appcompat:appcompat:1.5.1' 58 | 59 | implementation("com.github.bumptech.glide:glide:4.14.0") { 60 | exclude group: "com.android.support" 61 | } 62 | implementation 'com.github.bumptech.glide:annotations:4.14.0' 63 | annotationProcessor 'com.github.bumptech.glide:compiler:4.14.0' 64 | implementation 'com.github.bumptech.glide:okhttp3-integration:4.14.0' 65 | implementation('com.github.bumptech.glide:recyclerview-integration:4.14.0') { 66 | transitive = false 67 | } 68 | 69 | implementation 'com.android.support:multidex:1.0.3' 70 | implementation 'androidx.fragment:fragment:1.5.5' 71 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 72 | implementation 'androidx.vectordrawable:vectordrawable:1.1.0' 73 | implementation 'com.google.android.material:material:1.7.0' 74 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 75 | testImplementation 'junit:junit:4.13.2' 76 | androidTestImplementation 'androidx.test.ext:junit:1.1.5' 77 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' 78 | implementation 'com.google.code.gson:gson:2.10' 79 | implementation 'androidx.cardview:cardview:1.0.0' 80 | implementation 'com.github.omadahealth:swipy:1.2.3@aar' 81 | implementation 'org.jsoup:jsoup:1.15.3' 82 | implementation 'com.squareup.okhttp3:okhttp:4.12.0' 83 | implementation 'org.apache.commons:commons-text:1.7' 84 | def acraVersion = '5.9.7' 85 | implementation "ch.acra:acra-mail:$acraVersion" 86 | implementation "ch.acra:acra-dialog:$acraVersion" 87 | 88 | } 89 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/CustomJSONObject.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | import org.json.JSONTokener; 7 | 8 | import java.util.Map; 9 | 10 | /* 11 | getters return default value instead of throwing exceptions 12 | */ 13 | 14 | public class CustomJSONObject extends JSONObject { 15 | public CustomJSONObject() { 16 | super(); 17 | } 18 | 19 | public CustomJSONObject(Map copyFrom) { 20 | super(copyFrom); 21 | } 22 | 23 | public CustomJSONObject(JSONTokener readFrom) throws JSONException { 24 | super(readFrom); 25 | } 26 | 27 | public CustomJSONObject(String json) throws JSONException { 28 | super(json); 29 | } 30 | 31 | public CustomJSONObject(JSONObject copyFrom, String[] names) throws JSONException { 32 | super(copyFrom, names); 33 | } 34 | 35 | 36 | 37 | public Object get(String name, Object def){ 38 | try { 39 | return super.get(name); 40 | }catch (JSONException e){ 41 | return def; 42 | } 43 | } 44 | 45 | public boolean getBoolean(String name, boolean def){ 46 | try { 47 | return super.getBoolean(name); 48 | }catch (JSONException e){ 49 | return def; 50 | } 51 | } 52 | 53 | public double getDouble(String name, double def){ 54 | try { 55 | return super.getDouble(name); 56 | }catch (JSONException e){ 57 | return def; 58 | } 59 | } 60 | 61 | public int getInt(String name, int def){ 62 | try { 63 | return super.getInt(name); 64 | }catch (JSONException e){ 65 | return def; 66 | } 67 | } 68 | 69 | public long getLong(String name, long def){ 70 | try { 71 | return super.getLong(name); 72 | }catch (JSONException e){ 73 | return def; 74 | } 75 | } 76 | 77 | public String getString(String name, String def){ 78 | try { 79 | return super.getString(name); 80 | }catch (JSONException e){ 81 | return def; 82 | } 83 | } 84 | 85 | public JSONArray getJSONArray(String name, JSONArray def){ 86 | try { 87 | return super.getJSONArray(name); 88 | }catch (JSONException e){ 89 | return def; 90 | } 91 | } 92 | 93 | public JSONObject getJSONObject(String name, JSONObject def){ 94 | try { 95 | return super.getJSONObject(name); 96 | }catch (JSONException e){ 97 | return def; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/MainApplication.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.appcompat.app.AppCompatDelegate; 6 | import androidx.multidex.MultiDexApplication; 7 | 8 | import org.acra.ACRA; 9 | import org.acra.config.CoreConfigurationBuilder; 10 | import org.acra.config.DialogConfigurationBuilder; 11 | import org.acra.config.MailSenderConfigurationBuilder; 12 | import org.acra.data.StringFormat; 13 | 14 | import ml.melun.mangaview.mangaview.CustomHttpClient; 15 | 16 | 17 | 18 | //@AcraCore(reportContent = { APP_VERSION_NAME, ANDROID_VERSION, PHONE_MODEL, STACK_TRACE, REPORT_ID}) 19 | 20 | 21 | public class MainApplication extends MultiDexApplication { 22 | public static CustomHttpClient httpClient; 23 | public static Preference p; 24 | @Override 25 | protected void attachBaseContext(Context base) { 26 | super.attachBaseContext(base); 27 | System.out.println("main app start"); 28 | ACRA.init(this, new CoreConfigurationBuilder() 29 | .withBuildConfigClass(BuildConfig.class) 30 | .withReportFormat(StringFormat.JSON) 31 | .withPluginConfigurations( 32 | new MailSenderConfigurationBuilder().withMailTo("mangaview@protonmail.com").build(), 33 | new DialogConfigurationBuilder() 34 | .withTitle("MangaView") 35 | .withText(getResources().getText(R.string.acra_dialog_text).toString()) 36 | .withPositiveButtonText("확인") 37 | .withNegativeButtonText("취소") 38 | .build() 39 | )); 40 | } 41 | 42 | @Override 43 | public void onCreate() { 44 | AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); 45 | p = new Preference(this); 46 | httpClient = new CustomHttpClient(); 47 | super.onCreate(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/Notice.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview; 2 | 3 | public class Notice{ 4 | int id = -1; 5 | String title, date, content; 6 | 7 | Notice(int id, String title, String date, String content){ 8 | this.id = id; 9 | this.title = title; 10 | this.date = date; 11 | this.content = content; 12 | } 13 | 14 | @Override 15 | public boolean equals(Object obj) { 16 | return this.id == ((Notice)obj).getId(); 17 | } 18 | 19 | @Override 20 | public int hashCode() { 21 | return id; 22 | } 23 | 24 | public int getId() { 25 | return id; 26 | } 27 | 28 | public String getContent() { 29 | return content; 30 | } 31 | 32 | public String getDate() { 33 | return date; 34 | } 35 | 36 | public String getTitle() { 37 | return title; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/UrlUpdater.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.widget.Toast; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import okhttp3.Response; 11 | 12 | import static ml.melun.mangaview.MainApplication.httpClient; 13 | import static ml.melun.mangaview.MainApplication.p; 14 | 15 | public class UrlUpdater extends AsyncTask { 16 | String result; 17 | String fetchUrl; 18 | boolean silent = false; 19 | Context c; 20 | UrlUpdaterCallback callback; 21 | public UrlUpdater(Context c){ 22 | this.c = c; 23 | this.fetchUrl = p.getDefUrl(); 24 | } 25 | public UrlUpdater(Context c, boolean silent, UrlUpdaterCallback callback, String defUrl){ 26 | this.c = c; 27 | this.silent = silent; 28 | this.callback = callback; 29 | this.fetchUrl = defUrl; 30 | } 31 | protected void onPreExecute() { 32 | if(!silent) Toast.makeText(c, "자동 URL 설정중...", Toast.LENGTH_SHORT).show(); 33 | } 34 | protected Boolean doInBackground(Void... params) { 35 | return fetch(); 36 | } 37 | 38 | protected Boolean fetch(){ 39 | try { 40 | Map headers = new HashMap<>(); 41 | headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"); 42 | Response r = httpClient.get(fetchUrl, headers); 43 | if (r.code() == 302) { 44 | result = r.header("Location"); 45 | r.close(); 46 | return true; 47 | } else{ 48 | r.close(); 49 | return false; 50 | } 51 | 52 | }catch (Exception e){ 53 | e.printStackTrace(); 54 | return false; 55 | } 56 | } 57 | 58 | protected void onPostExecute(Boolean r) { 59 | if(r && result !=null){ 60 | p.setUrl(result); 61 | if(!silent)Toast.makeText(c, "자동 URL 설정 완료!", Toast.LENGTH_SHORT).show(); 62 | if(callback!=null) callback.callback(true); 63 | }else{ 64 | if(!silent)Toast.makeText(c, "자동 URL 설정 실패, 잠시후 다시 시도해 주세요", Toast.LENGTH_LONG).show(); 65 | if(callback!=null) callback.callback(false); 66 | } 67 | 68 | 69 | } 70 | 71 | 72 | public interface UrlUpdaterCallback{ 73 | void callback(boolean success); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/activity/LayoutEditActivity.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.activity; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Context; 6 | import android.content.res.Configuration; 7 | import android.os.Bundle; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.Button; 11 | import android.widget.SeekBar; 12 | import android.widget.Toast; 13 | 14 | import ml.melun.mangaview.R; 15 | 16 | import static ml.melun.mangaview.MainApplication.p; 17 | import static ml.melun.mangaview.Utils.getScreenWidth; 18 | 19 | public class LayoutEditActivity extends AppCompatActivity { 20 | Button left; 21 | Button right; 22 | boolean leftRight; 23 | SeekBar seekBar; 24 | ViewGroup.LayoutParams params; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | if(p.getDarkTheme()) setTheme(R.style.AppThemeDark); 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_layout_edit); 31 | 32 | Context context = this; 33 | 34 | left = this.findViewById(R.id.layoutLeftButton); 35 | right = this.findViewById(R.id.layoutRightButton); 36 | leftRight = p.getLeftRight(); 37 | setButtonText(); 38 | 39 | seekBar = this.findViewById(R.id.seekBar); 40 | params = left.getLayoutParams(); 41 | refreshSeekbar(); 42 | 43 | seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 44 | @Override 45 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) { 46 | params.width = i; 47 | left.setLayoutParams(params); 48 | } 49 | 50 | @Override 51 | public void onStartTrackingTouch(SeekBar seekBar) { 52 | 53 | } 54 | 55 | @Override 56 | public void onStopTrackingTouch(SeekBar seekBar) { 57 | 58 | } 59 | }); 60 | 61 | this.findViewById(R.id.layout_save).setOnClickListener(view -> { 62 | p.setPageControlButtonOffset((float)seekBar.getProgress() / (float)seekBar.getMax()); 63 | p.setLeftRight(leftRight); 64 | Toast.makeText(context, "설정 완료", Toast.LENGTH_SHORT).show(); 65 | finish(); 66 | }); 67 | 68 | this.findViewById(R.id.layout_reset).setOnClickListener(view -> { 69 | p.setPageControlButtonOffset(-1); 70 | p.setLeftRight(false); 71 | Toast.makeText(context, "기본값으로 설정됨", Toast.LENGTH_SHORT).show(); 72 | finish(); 73 | }); 74 | 75 | this.findViewById(R.id.layout_cancel).setOnClickListener(view -> finish()); 76 | 77 | this.findViewById(R.id.layout_reverse).setOnClickListener(view -> { 78 | leftRight = !leftRight; 79 | setButtonText(); 80 | }); 81 | } 82 | 83 | private void refreshSeekbar(){ 84 | // set seekbar max to current screen width 85 | int max = getScreenWidth(getWindowManager().getDefaultDisplay()); 86 | seekBar.setMax(max); 87 | 88 | // set button width to saved value 89 | float percentage = p.getPageControlButtonOffset(); 90 | if(percentage != -1){ 91 | params.width = (int)((float)max * percentage); 92 | left.setLayoutParams(params); 93 | } 94 | // set seekbar progress to current button width 95 | seekBar.setProgress(params.width); 96 | } 97 | 98 | private void setButtonText(){ 99 | if(leftRight){ 100 | left.setText(R.string.next_page); 101 | right.setText(R.string.prev_page); 102 | }else{ 103 | right.setText(R.string.next_page); 104 | left.setText(R.string.prev_page); 105 | } 106 | } 107 | 108 | @Override 109 | public void onConfigurationChanged(Configuration newConfig) { 110 | super.onConfigurationChanged(newConfig); 111 | refreshSeekbar(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/activity/LicenseActivity.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.activity; 2 | 3 | import androidx.appcompat.app.ActionBar; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.view.MenuItem; 7 | 8 | import ml.melun.mangaview.R; 9 | 10 | public class LicenseActivity extends AppCompatActivity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_license); 16 | ActionBar ab = getSupportActionBar(); 17 | ab.setTitle("오픈소스 라이선스"); 18 | ab.setDisplayHomeAsUpEnabled(true); 19 | } 20 | public boolean onOptionsItemSelected(MenuItem item){ 21 | if (item.getItemId() == android.R.id.home) { 22 | finish(); 23 | return true; 24 | } 25 | return super.onOptionsItemSelected(item); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/adapter/CommentsAdapter.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.adapter; 2 | 3 | import android.content.Context; 4 | import androidx.constraintlayout.widget.ConstraintLayout; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.ImageView; 10 | import android.widget.TextView; 11 | 12 | import com.bumptech.glide.Glide; 13 | 14 | 15 | import java.util.ArrayList; 16 | 17 | import ml.melun.mangaview.R; 18 | import ml.melun.mangaview.mangaview.Comment; 19 | 20 | import static ml.melun.mangaview.MainApplication.p; 21 | 22 | public class CommentsAdapter extends BaseAdapter { 23 | Context context; 24 | ArrayList data; 25 | LayoutInflater inflater; 26 | boolean dark; 27 | boolean save; 28 | public CommentsAdapter(Context context, ArrayList data) { 29 | super(); 30 | this.dark = p.getDarkTheme(); 31 | this.save = p.getDataSave(); 32 | this.context = context; 33 | this.data = data; 34 | this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return data.size(); 40 | } 41 | 42 | @Override 43 | public View getView(int position, View convertView, ViewGroup parent) { 44 | if(convertView==null){ 45 | convertView = inflater.inflate(R.layout.item_comment,parent,false); 46 | } 47 | Comment c = data.get(position); 48 | ConstraintLayout layout = convertView.findViewById(R.id.comment_layout); 49 | ImageView icon = convertView.findViewById(R.id.comment_icon); 50 | TextView content = convertView.findViewById(R.id.comment_content); 51 | TextView timeStamp = convertView.findViewById(R.id.comment_time); 52 | TextView user = convertView.findViewById(R.id.comment_user); 53 | TextView likes = convertView.findViewById(R.id.comment_likes); 54 | TextView level = convertView.findViewById(R.id.comment_level); 55 | 56 | layout.setPadding(60*c.getIndent(),0,0,0); 57 | if(c.getIcon().length()>1 && !save) Glide.with(icon).load(c.getIcon()).into(icon); 58 | else icon.setImageResource(R.drawable.user); 59 | content.setText(c.getContent()); 60 | timeStamp.setText(c.getTimestamp()); 61 | user.setText(c.getUser()); 62 | level.setText(String.valueOf(c.getLevel())); 63 | if(c.getLikes()>0) likes.setText(String.valueOf(c.getLikes())); 64 | else likes.setText(""); 65 | return convertView; 66 | } 67 | 68 | @Override 69 | public Comment getItem(int position) { 70 | return data.get(position); 71 | } 72 | 73 | 74 | @Override 75 | public long getItemId(int position) { 76 | return 0; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/adapter/CustomSpinnerAdapter.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.adapter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.BaseAdapter; 9 | import android.widget.SpinnerAdapter; 10 | import android.widget.TextView; 11 | 12 | import java.util.List; 13 | 14 | import ml.melun.mangaview.R; 15 | import ml.melun.mangaview.mangaview.Manga; 16 | 17 | public class CustomSpinnerAdapter extends BaseAdapter implements SpinnerAdapter { 18 | 19 | private List data; 20 | private static LayoutInflater inflater = null; 21 | private CustomSpinnerListener listener; 22 | private int selected = -1; 23 | 24 | public CustomSpinnerAdapter(Context context) { 25 | this.selected = -1; 26 | inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 27 | } 28 | 29 | public int getCount() { 30 | if(data != null) 31 | return data.size(); 32 | return 0; 33 | } 34 | 35 | public void setData(List data, Manga m){ 36 | this.data = data; 37 | setSelection(m); 38 | notifyDataSetChanged(); 39 | } 40 | 41 | public void setSelection(int position){ 42 | if(position != selected) 43 | this.selected = position; 44 | } 45 | 46 | public void setSelection(Manga m){ 47 | for(int i=0; i< data.size(); i++){ 48 | if(m.equals(data.get(i))) 49 | setSelection(i); 50 | } 51 | } 52 | public int getSelected(){ 53 | return selected; 54 | } 55 | public Object getItem(int position) { 56 | return data.get(position); 57 | } 58 | 59 | public long getItemId(int position) { 60 | return data.get(position).getId(); 61 | } 62 | 63 | public View getView(int position, View convertView, ViewGroup parent) { 64 | if (convertView == null) { 65 | convertView = inflater.inflate(R.layout.item_custom_spinner, parent, false); 66 | } 67 | return convertView; 68 | } 69 | 70 | @Override 71 | public View getDropDownView(int position, View convertView, ViewGroup parent) { 72 | ViewHolder holder = null; 73 | try { 74 | if (convertView == null) { 75 | convertView = inflater.inflate(R.layout.item_custom_spinner_dropdown, null); 76 | holder = new ViewHolder(); 77 | holder.name = (TextView) convertView.findViewById(R.id.spinner_text); 78 | convertView.setTag(holder); 79 | } else { 80 | holder = (ViewHolder) convertView.getTag(); 81 | } 82 | 83 | if(position == selected){ 84 | holder.name.setTextColor(Color.argb(255,230,160,220)); 85 | }else{ 86 | holder.name.setTextColor(Color.WHITE); 87 | } 88 | 89 | holder.name.setText(data.get(position).getName()); 90 | holder.name.setSelected(true); 91 | 92 | convertView.setOnClickListener(view -> { 93 | if(listener != null && selected != position) { 94 | listener.onClick(data.get(position), position); 95 | setSelection(position); 96 | } 97 | }); 98 | 99 | } catch (Exception e) { 100 | // TODO Auto-generated catch block 101 | e.printStackTrace(); 102 | } 103 | return convertView; 104 | } 105 | 106 | public void setListener(CustomSpinnerListener listener){ 107 | this.listener = listener; 108 | } 109 | 110 | private static class ViewHolder { 111 | private TextView name; 112 | } 113 | 114 | public interface CustomSpinnerListener{ 115 | void onClick(Manga m, int i); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/adapter/TagAdapter.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.adapter; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | import androidx.cardview.widget.CardView; 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.TextView; 11 | 12 | import java.util.List; 13 | 14 | import ml.melun.mangaview.R; 15 | import static ml.melun.mangaview.MainApplication.p; 16 | 17 | public class TagAdapter extends RecyclerView.Adapter{ 18 | 19 | Context mcontext; 20 | List tags; 21 | LayoutInflater mInflater; 22 | private tagOnclick mClickListener; 23 | boolean dark; 24 | 25 | public TagAdapter(Context m, List t) { 26 | mcontext = m; 27 | tags = t; 28 | this.mInflater = LayoutInflater.from(m); 29 | dark = p.getDarkTheme(); 30 | setHasStableIds(true); 31 | } 32 | 33 | @Override 34 | public long getItemId(int position) { 35 | return position; 36 | } 37 | 38 | @NonNull 39 | @Override 40 | public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 41 | View view = mInflater.inflate(R.layout.item_tag, parent, false); 42 | return new tagHolder(view); 43 | } 44 | 45 | @Override 46 | public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { 47 | tagHolder h = (tagHolder) holder; 48 | h.tag.setText(tags.get(position)); 49 | } 50 | 51 | @Override 52 | public int getItemCount() { 53 | return tags.size(); 54 | } 55 | 56 | public void setClickListener(tagOnclick t){ 57 | this.mClickListener = t; 58 | } 59 | 60 | class tagHolder extends RecyclerView.ViewHolder{ 61 | TextView tag; 62 | CardView card; 63 | public tagHolder(View itemView) { 64 | super(itemView); 65 | card = itemView.findViewById(R.id.tagCard); 66 | tag = itemView.findViewById(R.id.tag); 67 | card.setOnClickListener(v -> mClickListener.onClick(tags.get(getAdapterPosition()))); 68 | } 69 | } 70 | public interface tagOnclick{ 71 | void onClick(String tag); 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/adapter/ViewerPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.adapter; 2 | 3 | import android.content.Context; 4 | import android.os.Parcelable; 5 | 6 | import androidx.fragment.app.Fragment; 7 | import androidx.fragment.app.FragmentManager; 8 | import androidx.fragment.app.FragmentStatePagerAdapter; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | import ml.melun.mangaview.fragment.ViewerPageFragment; 15 | import ml.melun.mangaview.interfaces.PageInterface; 16 | import ml.melun.mangaview.mangaview.Decoder; 17 | import ml.melun.mangaview.mangaview.Manga; 18 | 19 | import static ml.melun.mangaview.MainApplication.p; 20 | 21 | public class ViewerPagerAdapter extends FragmentStatePagerAdapter 22 | { 23 | List fragments; 24 | FragmentManager fm; 25 | int width; 26 | Context context; 27 | PageInterface itf; 28 | public ViewerPagerAdapter(FragmentManager fm, int width, Context context, PageInterface i) { 29 | super(fm); 30 | this.fm = fm; 31 | this.width = width; 32 | this.context = context; 33 | this.itf = i; 34 | fragments = new ArrayList<>(); 35 | } 36 | 37 | public void setManga(Manga m){ 38 | fragments.clear(); 39 | List imgs = m.getImgs(context); 40 | if (p.getPageRtl()) Collections.reverse(imgs); 41 | for(int i = 0; i itf.onPageClick())); 45 | } 46 | notifyDataSetChanged(); 47 | } 48 | @Override 49 | public int getItemPosition(Object object) { 50 | return POSITION_NONE; 51 | } 52 | @Override 53 | public Fragment getItem(int position) 54 | { 55 | return fragments.get(position); 56 | } 57 | @Override 58 | public int getCount() 59 | { 60 | return fragments.size(); 61 | } 62 | 63 | @Override 64 | public Parcelable saveState() 65 | { 66 | return null; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/fragment/CommentsTabFragment.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.fragment; 2 | 3 | import android.os.Bundle; 4 | import androidx.fragment.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ListView; 9 | 10 | import ml.melun.mangaview.R; 11 | import ml.melun.mangaview.adapter.CommentsAdapter; 12 | 13 | public class CommentsTabFragment extends Fragment { 14 | CommentsAdapter madapter; 15 | public CommentsTabFragment() { 16 | } 17 | public void setAdapter(CommentsAdapter adapter){ 18 | madapter = adapter; 19 | } 20 | @Override 21 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 22 | Bundle savedInstanceState) { 23 | View rootView = inflater.inflate(R.layout.fragment_test, container, false); 24 | ListView list = rootView.findViewById(R.id.section_list); 25 | list.setAdapter(madapter); 26 | return rootView; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/fragment/ViewerPageFragment.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.fragment; 2 | 3 | import static ml.melun.mangaview.Utils.getGlideUrl; 4 | 5 | import android.content.Context; 6 | import android.graphics.Bitmap; 7 | import android.graphics.drawable.Drawable; 8 | 9 | import androidx.fragment.app.Fragment; 10 | import android.os.Bundle; 11 | import androidx.annotation.Nullable; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.ImageButton; 16 | import android.widget.ImageView; 17 | 18 | import com.bumptech.glide.Glide; 19 | import com.bumptech.glide.load.model.GlideUrl; 20 | import com.bumptech.glide.request.target.CustomTarget; 21 | import com.bumptech.glide.request.transition.Transition; 22 | 23 | import ml.melun.mangaview.R; 24 | import ml.melun.mangaview.interfaces.PageInterface; 25 | import ml.melun.mangaview.mangaview.Decoder; 26 | 27 | public class ViewerPageFragment extends Fragment { 28 | String image; 29 | Decoder decoder; 30 | Context context; 31 | PageInterface i; 32 | int width; 33 | 34 | public ViewerPageFragment(){ 35 | 36 | } 37 | public ViewerPageFragment(String image, Decoder decoder, int width, Context context, PageInterface i){ 38 | this.image = image; 39 | this.decoder = decoder; 40 | this.width = width; 41 | this.context = context; 42 | this.i = i; 43 | } 44 | public static Fragment create(String image, Decoder decoder, int width, Context context, PageInterface i){ 45 | return new ViewerPageFragment(image, decoder, width, context, i); 46 | } 47 | 48 | public void updatePageFragment(Context context){ 49 | this.context = context; 50 | } 51 | 52 | @Nullable 53 | @Override 54 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { 55 | View rootView = inflater.inflate(R.layout.fragment_viewer, container, false); 56 | ImageView frame = rootView.findViewById(R.id.page); 57 | ImageButton refresh = rootView.findViewById(R.id.refreshButton); 58 | //glide 59 | frame.setImageResource(R.drawable.placeholder); 60 | refresh.setVisibility(View.VISIBLE); 61 | 62 | if(context != null) 63 | loadImage(frame, refresh); 64 | 65 | refresh.setOnClickListener(v -> { 66 | if(context != null) { 67 | loadImage(frame, refresh); 68 | } 69 | }); 70 | rootView.setOnClickListener(v -> i.onPageClick()); 71 | 72 | return rootView; 73 | } 74 | 75 | void loadImage(ImageView frame, ImageButton refresh){ 76 | Object target = image.startsWith("http") ? getGlideUrl(image) : image; 77 | Glide.with(frame) 78 | .asBitmap() 79 | .load(target) 80 | .into(new CustomTarget() { 81 | @Override 82 | public void onResourceReady(Bitmap bitmap, Transition transition) { 83 | refresh.setVisibility(View.GONE); 84 | bitmap = decoder.decode(bitmap,width); 85 | frame.setImageBitmap(bitmap); 86 | } 87 | 88 | @Override 89 | public void onLoadCleared(@Nullable Drawable placeholder) { 90 | // 91 | } 92 | 93 | @Override 94 | public void onLoadFailed(@Nullable Drawable errorDrawable) { 95 | if(image.length()>0) { 96 | frame.setImageResource(R.drawable.placeholder); 97 | refresh.setVisibility(View.VISIBLE); 98 | } 99 | } 100 | }); 101 | } 102 | 103 | public void setOnClick(PageInterface i){ 104 | this.i = i; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/glide/CustomGlideModule.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.glide; 2 | 3 | import android.content.Context; 4 | import androidx.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.integration.okhttp3.OkHttpUrlLoader; 10 | import com.bumptech.glide.load.model.GlideUrl; 11 | import com.bumptech.glide.module.AppGlideModule; 12 | import static ml.melun.mangaview.MainApplication.httpClient; 13 | import static ml.melun.mangaview.MainApplication.p; 14 | 15 | import java.io.InputStream; 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | import okhttp3.OkHttpClient; 20 | 21 | @GlideModule 22 | public class CustomGlideModule extends AppGlideModule { 23 | @Override 24 | public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { 25 | System.out.println("glide module create"); 26 | registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(httpClient.client)); 27 | } 28 | 29 | @Override 30 | public boolean isManifestParsingEnabled() { 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/interfaces/IntegerCallback.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.interfaces; 2 | 3 | public interface IntegerCallback { 4 | void callback(int i); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/interfaces/MainActivityCallback.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.interfaces; 2 | 3 | public interface MainActivityCallback{ 4 | void search(String query); 5 | } -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/interfaces/PageInterface.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.interfaces; 2 | 3 | public interface PageInterface { 4 | void onPageClick(); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/interfaces/StringCallback.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.interfaces; 2 | 3 | public interface StringCallback { 4 | void callback(String data); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/Bookmark.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import ml.melun.mangaview.Preference; 7 | 8 | public class Bookmark { 9 | List result; 10 | int page = -1; 11 | boolean last = false; 12 | 13 | public Bookmark(){ 14 | 15 | } 16 | 17 | public int fetch(CustomHttpClient client){ 18 | result = new ArrayList<>(); 19 | //todo implement this 20 | return 0; 21 | } 22 | 23 | public boolean isLast() { 24 | return !last; 25 | } 26 | 27 | public List getResult(){ 28 | return this.result; 29 | } 30 | 31 | public static int importBookmark(Preference p, CustomHttpClient client){ 32 | try { 33 | Bookmark b = new Bookmark(); 34 | List bookmarks = new ArrayList<>(); 35 | while (b.isLast()) { 36 | if (b.fetch(client) == 0) 37 | bookmarks.addAll(b.getResult()); 38 | else 39 | return 1; 40 | } 41 | 42 | for (MTitle t : bookmarks) { 43 | if (p.findFavorite(t) < 0) 44 | p.toggleFavorite(t, 0); 45 | } 46 | }catch (Exception e){ 47 | return 1; 48 | } 49 | return 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/Comment.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | public class Comment { 4 | 5 | public Comment(String user, String ts, String icon, String content, int indent, int likes, int level) { 6 | this.user = user; 7 | this.icon = icon; 8 | this.content = content; 9 | this.timestamp = ts; 10 | this.indent = indent; 11 | this.likes = likes; 12 | this.level = level; 13 | } 14 | public String getContent() {return content;} 15 | public String getUser() {return user;} 16 | public String getIcon() {return icon;} 17 | public String getTimestamp() { return timestamp;} 18 | public int getIndent() { return indent; } 19 | public int getLikes() { return likes; } 20 | public int getLevel() { return level; } 21 | 22 | String content, user, icon, timestamp; 23 | int indent = 0; 24 | int likes = 0; 25 | int level = 0; 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/Decoder.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Canvas; 6 | 7 | import java.io.ByteArrayInputStream; 8 | import java.io.ByteArrayOutputStream; 9 | 10 | import static ml.melun.mangaview.Utils.getSample; 11 | 12 | 13 | public class Decoder { 14 | int __seed=0; 15 | int id=0; 16 | int view_cnt; 17 | int cx=5, cy=5; 18 | 19 | public int getCnt(){ 20 | return view_cnt; 21 | } 22 | 23 | public Decoder(int seed, int id){ 24 | view_cnt = seed; 25 | __seed = seed/10; 26 | this.id = id; 27 | if(__seed>30000){ 28 | cx = 1; 29 | cy = 6; 30 | }else if(__seed>20000){ 31 | cx = 1; 32 | } else if (__seed>10000) { 33 | cy = 1; 34 | } 35 | } 36 | 37 | public Bitmap decode(Bitmap input, int width){ 38 | input = getSample(input,width); 39 | return decode(input); 40 | } 41 | public Bitmap downSample(final Bitmap input, int maxBytes) { 42 | if(input.getByteCount() > maxBytes) { 43 | Float ratio = (maxBytes*1.0f/input.getByteCount()); 44 | return downSize(input, ratio); 45 | } 46 | return input; 47 | } 48 | public Bitmap downSize(final Bitmap input, Float ratio) { 49 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); 50 | Bitmap bitmap = Bitmap.createScaledBitmap(input, ((Float)(input.getWidth()*ratio)).intValue(), ((Float)(input.getHeight()*ratio)).intValue(), true); 51 | return bitmap; 52 | } 53 | 54 | public Bitmap decode(Bitmap input){ 55 | input = downSample(input, 100000000); 56 | if(view_cnt==0) return input; 57 | int[][] order = new int[cx*cy][2]; 58 | for (int i = 0; i < cx*cy; i++) { 59 | order[i][0] = i; 60 | if (id < 554714) order[i][1] = _random(i); 61 | else order[i][1] = newRandom(i); 62 | } 63 | java.util.Arrays.sort(order, (a, b) -> { 64 | //return Double.compare(a[1], b[1]); 65 | return a[1] != b[1] ? a[1] - b[1] : a[0] - b[0]; 66 | }); 67 | //create new bitmap 68 | Bitmap output = Bitmap.createBitmap(input.getWidth(), input.getHeight(), Bitmap.Config.ARGB_8888); 69 | 70 | Canvas canvas = new Canvas(output); 71 | 72 | int row_w = input.getWidth() / cx; 73 | int row_h = input.getHeight() / cy; 74 | for (int i = 0; i < cx*cy; i++) { 75 | int[] o = order[i]; 76 | int ox = i % cx; 77 | int oy = i / cx; 78 | int tx = o[0] % cx; 79 | int ty = o[0] / cx; 80 | Bitmap cropped = Bitmap.createBitmap(input, ox * row_w, oy * row_h, row_w, row_h); 81 | canvas.drawBitmap(cropped, tx * row_w, ty * row_h, null); 82 | } 83 | return output; 84 | } 85 | 86 | private int _random(int index){ 87 | double x = Math.sin(__seed+index) * 10000; 88 | return (int) Math.floor((x - Math.floor(x)) * 100000); 89 | } 90 | 91 | private int newRandom(int index){ 92 | index++; 93 | double t = 100 * Math.sin(10 * (__seed+index)) 94 | , n = 1000 * Math.cos(13 * (__seed+index)) 95 | , a = 10000 * Math.tan(14 * (__seed+index)); 96 | t = Math.floor(100 * (t - Math.floor(t))); 97 | n = Math.floor(1000 * (n - Math.floor(n))); 98 | a = Math.floor(10000 * (a - Math.floor(a))); 99 | return (int)(t + n + a); 100 | } 101 | } -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/DownloadTitle.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import java.util.List; 4 | 5 | public class DownloadTitle extends MTitle { 6 | private List eps; 7 | 8 | public DownloadTitle(Title t){ 9 | super(t.getName(), t.getId(), t.getThumb(), t.getAuthor(), t.getTags(), t.getRelease(), t.getBaseMode()); 10 | eps = t.getEps(); 11 | } 12 | 13 | public List getEps() { 14 | return eps; 15 | } 16 | 17 | public void setEps(List eps) { 18 | this.eps = eps; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/Login.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import ml.melun.mangaview.Preference; 8 | import okhttp3.FormBody; 9 | import okhttp3.RequestBody; 10 | import okhttp3.Response; 11 | 12 | import static java.lang.System.currentTimeMillis; 13 | import static ml.melun.mangaview.MainApplication.p; 14 | 15 | public class Login { 16 | private String user; 17 | private String pass; 18 | String cookie = ""; 19 | long currentTime = 0; 20 | 21 | public Login(){ 22 | } 23 | 24 | public void set(String id, String pass){ 25 | this.user = id; 26 | this.pass = pass; 27 | } 28 | 29 | public byte[] prepare(CustomHttpClient client, Preference p){ 30 | Response r; 31 | int tries = 3; 32 | while(tries > 0) { 33 | r = client.post(p.getUrl() + "/plugin/kcaptcha/kcaptcha_session.php", new FormBody.Builder().build(), new HashMap<>(),false); 34 | if(r.code() == 200) { 35 | List setcookie = r.headers("Set-Cookie"); 36 | for (String c : setcookie) { 37 | if (c.contains("PHPSESSID=")) { 38 | cookie = c.substring(c.indexOf("=") + 1, c.indexOf(";")); 39 | client.setCookie("PHPSESSID",cookie); 40 | } 41 | } 42 | break; 43 | }else { 44 | r.close(); 45 | tries--; 46 | } 47 | } 48 | currentTime = currentTimeMillis(); 49 | r = client.mget("/plugin/kcaptcha/kcaptcha_image.php?t=" + currentTime, false); 50 | try { 51 | return r.body().bytes(); 52 | }catch (Exception e){ 53 | e.printStackTrace(); 54 | return null; 55 | } 56 | } 57 | 58 | public Boolean submit(CustomHttpClient client, String answer){ 59 | try{ 60 | RequestBody requestBody = new FormBody.Builder() 61 | .addEncoded("auto_login", "on") 62 | .addEncoded("mb_id",user) 63 | .addEncoded("mb_password",pass) 64 | .addEncoded("captcha_key", answer) 65 | .build(); 66 | Map headers = new HashMap<>(); 67 | headers.put("Cookie", "PHPSESSID="+cookie+";"); 68 | 69 | Response response = client.post(p.getUrl() + "/bbs/login_check.php", requestBody, headers); 70 | int responseCode = response.code(); 71 | 72 | if(responseCode == 302) { 73 | //follow redirect 74 | Map cookies = new HashMap<>(); 75 | cookies.put("PHPSESSID", cookie); 76 | client.mget("/?captcha_key="+answer+"&auto_login=on",false, cookies); 77 | response.close(); 78 | return true; 79 | } 80 | else{ 81 | response.close(); 82 | return false; 83 | } 84 | }catch (Exception e){ 85 | e.printStackTrace(); 86 | } 87 | return false; 88 | } 89 | public void buildCookie(Map map){ 90 | //java always passes by reference 91 | map.put("PHPSESSID", cookie); 92 | } 93 | 94 | public boolean isValid(){ 95 | return cookie !=null && cookie.length()>0; 96 | } 97 | 98 | public String getCookie(Boolean format){ 99 | if(format) return "PHPSESSID=" +cookie +';'; 100 | return cookie; 101 | } 102 | 103 | public String getCookie() { 104 | return cookie; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/MTitle.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class MTitle{ 9 | String name; 10 | int id; 11 | String thumb; 12 | String author; 13 | List tags; 14 | String release; 15 | String path; 16 | int baseMode = base_comic; // default is comic 17 | //public static final String[] releases = {"미분류","주간","격주","월간","격월/비정기","단편","단행본","완결"}; 18 | public MTitle(){ 19 | 20 | } 21 | public MTitle(String name, int id, String thumb, String author, List tags, String release, int baseMode) { 22 | this.name = name.replace("\"", ""); 23 | this.id = id; 24 | this.thumb = thumb; 25 | this.tags = tags; 26 | this.release = release; 27 | this.author = author; 28 | this.baseMode = baseMode; 29 | } 30 | 31 | public String getPath() { 32 | return path; 33 | } 34 | 35 | public void setPath(String path) { 36 | this.path = path; 37 | } 38 | 39 | public int getBaseMode() { 40 | if(baseMode == base_auto) 41 | baseMode = base_comic; 42 | return baseMode; 43 | } 44 | 45 | public String getBaseModeStr(){ 46 | return baseModeKorStr(baseMode); 47 | } 48 | 49 | public void setBaseMode(int baseMode) { 50 | this.baseMode = baseMode; 51 | } 52 | 53 | public String getName() { 54 | return name; 55 | } 56 | 57 | public int getId() { 58 | return id; 59 | } 60 | 61 | public String getThumb() { 62 | return thumb; 63 | } 64 | 65 | public String getAuthor() { 66 | if(author == null) return ""; 67 | return author; 68 | } 69 | 70 | public List getTags(){ 71 | if(tags==null) return new ArrayList<>(); 72 | return tags; 73 | } 74 | 75 | public String getRelease() { 76 | return release; 77 | } 78 | 79 | public void setId(int id) { 80 | this.id = id; 81 | } 82 | 83 | public void setName(String name) { 84 | this.name = name.replace("\"", ""); 85 | } 86 | 87 | public void setThumb(String thumb) { 88 | this.thumb = thumb; 89 | } 90 | 91 | public void setAuthor(String author) { 92 | this.author = author; 93 | } 94 | 95 | public void setTags(List tags) { 96 | this.tags = tags; 97 | } 98 | 99 | public void setRelease(String release) { 100 | this.release = release; 101 | } 102 | 103 | @Override 104 | public MTitle clone() { 105 | return new MTitle(name, id, thumb, author, tags, release, baseMode); 106 | } 107 | 108 | public static final int base_auto = 0; 109 | public static final int base_comic = 1; 110 | public static final int base_webtoon = 2; 111 | 112 | public static String baseModeStr(int mode){ 113 | switch(mode){ 114 | case base_comic: 115 | return "comic"; 116 | case base_webtoon: 117 | return "webtoon"; 118 | default: 119 | return "comic"; 120 | } 121 | } 122 | public static String baseModeKorStr(int mode){ 123 | switch(mode){ 124 | case base_comic: 125 | return "만화"; 126 | case base_webtoon: 127 | return "웹툰"; 128 | default: 129 | return "만화"; 130 | } 131 | } 132 | 133 | @NonNull 134 | @Override 135 | public String toString() { 136 | return name + " . " + id + " . " + thumb + " . " + author + " . " + baseMode; 137 | } 138 | 139 | @Override 140 | public boolean equals(Object obj) { 141 | return ((MTitle)obj).getBaseMode() == this.baseMode && ((MTitle)obj).getId() == this.id ; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/Ranking.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | 6 | public class Ranking extends ArrayList { 7 | String name; 8 | public Ranking(String name){ 9 | super(); 10 | this.name = name; 11 | } 12 | public Ranking(Collection c, String name) { 13 | super(c); 14 | this.name = name; 15 | } 16 | public String getName(){ 17 | return this.name; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/UpdatedList.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import org.jsoup.Jsoup; 4 | import org.jsoup.nodes.Document; 5 | import org.jsoup.nodes.Element; 6 | import org.jsoup.select.Elements; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | 12 | import okhttp3.Response; 13 | 14 | 15 | public class UpdatedList { 16 | Boolean last = false; 17 | ArrayList result; 18 | int page = 1; 19 | int baseMode; 20 | 21 | public UpdatedList(int baseMode){ 22 | this.baseMode = baseMode; 23 | } 24 | 25 | public int getPage(){ 26 | return this.page; 27 | } 28 | 29 | public void fetch(CustomHttpClient client){ 30 | //50 items per page 31 | result = new ArrayList<>(); 32 | String url = "/bbs/page.php?hid=update&page="; 33 | if(!last) { 34 | try { 35 | Response response= client.mget(url + page++,true,null); 36 | String body = response.body().string(); 37 | if(body.contains("Connect Error: Connection timed out")){ 38 | //adblock : try again 39 | response.close(); 40 | fetch(client); 41 | return; 42 | } 43 | Document document = Jsoup.parse(body); 44 | Elements items = document.select("div.post-row"); 45 | if (items == null || items.size() < 70) last = true; 46 | for(Element item : items){ 47 | try { 48 | String img = item.selectFirst("img").attr("src"); 49 | String name = item.selectFirst("div.post-subject").selectFirst("a").ownText(); 50 | int id = Integer.parseInt(item 51 | .selectFirst("div.pull-left") 52 | .selectFirst("a") 53 | .attr("href") 54 | .split("comic/")[1]); 55 | 56 | Elements rightInfo = item.selectFirst("div.pull-right").select("p"); 57 | 58 | int tid = Integer.parseInt(rightInfo 59 | .get(0) 60 | .selectFirst("a") 61 | .attr("href") 62 | .split("comic/")[1]); 63 | 64 | String date = rightInfo.get(1).selectFirst("span").ownText(); 65 | 66 | 67 | String at = item.selectFirst("div.post-text").ownText(); 68 | //작가 작가 태그1,태그2,태그3 69 | String author = at.substring(0,at.lastIndexOf(' ')); 70 | 71 | List tags = Arrays.asList(at.substring(at.lastIndexOf(' ')).split(",")); 72 | 73 | UpdatedManga tmp = new UpdatedManga(id, name, date, baseMode,author,tags); 74 | tmp.setMode(0); 75 | tmp.setTitle(new Title(name, img, author, tags, "", tid, MTitle.base_comic)); 76 | tmp.addThumb(img); 77 | result.add(tmp); 78 | }catch(Exception e){ 79 | e.printStackTrace(); 80 | } 81 | } 82 | response.close(); 83 | } catch (Exception e) { 84 | e.printStackTrace(); 85 | page--; 86 | } 87 | } 88 | } 89 | 90 | public ArrayList getResult() { 91 | return result; 92 | } 93 | public boolean isLast(){return last;} 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/mangaview/UpdatedManga.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.mangaview; 2 | 3 | import java.util.List; 4 | 5 | public class UpdatedManga extends Manga{ 6 | String author; 7 | List tag; 8 | 9 | UpdatedManga(int i, String n, String d, int baseMode, String author, List tag){ 10 | super(i, n, d, baseMode); 11 | this.author = author; 12 | this.tag = tag; 13 | } 14 | 15 | public String getAuthor() { 16 | return author; 17 | } 18 | 19 | public List getTag() { 20 | return tag; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/model/PageItem.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.model; 2 | 3 | import androidx.annotation.Nullable; 4 | 5 | import ml.melun.mangaview.mangaview.Manga; 6 | 7 | public class PageItem{ 8 | public static final int FIRST = 0; 9 | public static final int SECOND = 1; 10 | public PageItem(int index, String img, Manga manga) { 11 | this.index = index; 12 | this.img = img; 13 | this.manga = manga; 14 | this.side = FIRST; 15 | } 16 | public PageItem(int index, String img, Manga manga, int side){ 17 | this.index = index; 18 | this.img = img; 19 | this.manga = manga; 20 | this.side = side; 21 | } 22 | 23 | @Override 24 | public int hashCode() { 25 | return manga.getId()*10000 + index*10 + this.side; 26 | } 27 | 28 | @Override 29 | public boolean equals(@Nullable Object obj) { 30 | if(obj instanceof PageItem){ 31 | PageItem p = (PageItem)obj; 32 | return p.index == this.index && p.manga.equals(this.manga); 33 | }else 34 | return false; 35 | } 36 | 37 | public int index; 38 | public int side; 39 | public String img; 40 | public Manga manga; 41 | } -------------------------------------------------------------------------------- /app/src/main/java/ml/melun/mangaview/ui/CustomSpinner.java: -------------------------------------------------------------------------------- 1 | package ml.melun.mangaview.ui; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | 6 | import ml.melun.mangaview.adapter.CustomSpinnerAdapter; 7 | import ml.melun.mangaview.mangaview.Manga; 8 | 9 | public class CustomSpinner extends androidx.appcompat.widget.AppCompatSpinner { 10 | 11 | public CustomSpinner(Context context) { 12 | super(context); 13 | } 14 | 15 | public CustomSpinner(Context context, AttributeSet attrs) { 16 | super(context, attrs); 17 | } 18 | 19 | public CustomSpinner(Context context, AttributeSet attrs, int defStyleAttr) { 20 | super(context, attrs, defStyleAttr); 21 | } 22 | 23 | @Override 24 | public void setSelection(int position) { 25 | super.setSelection(position); 26 | } 27 | 28 | public void setSelection(Manga m) { 29 | CustomSpinnerAdapter adapter = (CustomSpinnerAdapter) getAdapter(); 30 | for(int i=0; i items = adapter.getItems(); 44 | for(int i=0; i -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/notification_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable-hdpi/notification_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/notification_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable-mdpi/notification_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/notification_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable-xhdpi/notification_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notification_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable-xxhdpi/notification_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/logo_static.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable-xxxhdpi/logo_static.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/notification_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable-xxxhdpi/notification_logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/blank.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_bg_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_bg_on.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_bg_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/down_arrow.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/download.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/first_page.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_adv_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_left.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_right.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_close_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_fullscreen_24.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_fullscreen_exit_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_library_books_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_more_vert_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_open_in_new_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bookmark.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_bookmark_border.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_comment.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_comments.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favorite.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_favorite_border.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_history.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_black.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_list.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_logo.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_open_24px.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_smile.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tag.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_thumb.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/launch_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/play.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/refresh_button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/up_arrow.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junheah/MangaViewAndroid/0c9d985e106338346fa2228e4c3837a692ea0324/app/src/main/res/drawable/user.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_captcha.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 21 | 22 | 37 | 38 | 48 | 49 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_download.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 23 | 24 |