Compare commits
32 Commits
Author | SHA1 | Date |
---|---|---|
Z | afd769d194 | 3 years ago |
Z | 07492bc003 | 4 years ago |
Z | 7e4b7daa41 | 4 years ago |
Z | 4f34c3637c | 4 years ago |
Z | 0d4eb3cb38 | 4 years ago |
Z | 2dd625aea1 | 4 years ago |
Z | fcc39378a4 | 4 years ago |
Z | 4178ba6b7e | 4 years ago |
Z | bdb67bdf34 | 4 years ago |
Z | 379375cb38 | 4 years ago |
Z | e64af72698 | 4 years ago |
Z | af217ea769 | 4 years ago |
Z | cd85e330ff | 4 years ago |
Z | 16a88c11d6 | 4 years ago |
Z | 11c0cc5391 | 4 years ago |
Z | 7d142b4491 | 4 years ago |
Z | ffb620a3cf | 4 years ago |
Z | b5a59fd8fd | 4 years ago |
Z | ec0bdb643b | 4 years ago |
Z | fb107c7318 | 4 years ago |
Z | feca1a1c3d | 4 years ago |
Z | f57a981cc0 | 4 years ago |
Z | 14c40c159e | 4 years ago |
Z | e13acb46ff | 4 years ago |
Z | 7c82e5dcfe | 4 years ago |
Z | e9eae50925 | 4 years ago |
Z | c15e394c40 | 4 years ago |
Z | 517ca3016e | 4 years ago |
Z | 8ae61b4085 | 4 years ago |
Z | f837ce60e9 | 4 years ago |
Z | 1050a30856 | 4 years ago |
Z | 9c632d4a05 | 4 years ago |
@ -0,0 +1,3 @@ |
|||||||
|
# Default ignored files |
||||||
|
/shelf/ |
||||||
|
/workspace.xml |
@ -0,0 +1,6 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="CompilerConfiguration"> |
||||||
|
<bytecodeTargetLevel target="1.8" /> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,7 @@ |
|||||||
|
<component name="ProjectDictionaryState"> |
||||||
|
<dictionary name="Administrator"> |
||||||
|
<words> |
||||||
|
<w>umeng</w> |
||||||
|
</words> |
||||||
|
</dictionary> |
||||||
|
</component> |
@ -1,4 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project version="4"> |
|
||||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" /> |
|
||||||
</project> |
|
@ -1,86 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project version="4"> |
|
||||||
<component name="MarkdownProjectSettings" wasCopied="false"> |
|
||||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true" replaceUnicodeEmoji="false" lastLayoutSetsDefault="false"> |
|
||||||
<PanelProvider> |
|
||||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" /> |
|
||||||
</PanelProvider> |
|
||||||
</PreviewSettings> |
|
||||||
<ParserSettings gitHubSyntaxChange="false" emojiShortcuts="1" emojiImages="0"> |
|
||||||
<PegdownExtensions> |
|
||||||
<option name="ABBREVIATIONS" value="false" /> |
|
||||||
<option name="ANCHORLINKS" value="true" /> |
|
||||||
<option name="ASIDE" value="false" /> |
|
||||||
<option name="ATXHEADERSPACE" value="true" /> |
|
||||||
<option name="AUTOLINKS" value="false" /> |
|
||||||
<option name="DEFINITIONS" value="false" /> |
|
||||||
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" /> |
|
||||||
<option name="FENCED_CODE_BLOCKS" value="true" /> |
|
||||||
<option name="FOOTNOTES" value="false" /> |
|
||||||
<option name="HARDWRAPS" value="false" /> |
|
||||||
<option name="HTML_DEEP_PARSER" value="false" /> |
|
||||||
<option name="INSERTED" value="false" /> |
|
||||||
<option name="QUOTES" value="false" /> |
|
||||||
<option name="RELAXEDHRULES" value="true" /> |
|
||||||
<option name="SMARTS" value="false" /> |
|
||||||
<option name="STRIKETHROUGH" value="true" /> |
|
||||||
<option name="SUBSCRIPT" value="false" /> |
|
||||||
<option name="SUPERSCRIPT" value="false" /> |
|
||||||
<option name="SUPPRESS_HTML_BLOCKS" value="false" /> |
|
||||||
<option name="SUPPRESS_INLINE_HTML" value="false" /> |
|
||||||
<option name="TABLES" value="true" /> |
|
||||||
<option name="TASKLISTITEMS" value="true" /> |
|
||||||
<option name="TOC" value="false" /> |
|
||||||
<option name="WIKILINKS" value="false" /> |
|
||||||
</PegdownExtensions> |
|
||||||
<ParserOptions> |
|
||||||
<option name="ADMONITION_EXT" value="false" /> |
|
||||||
<option name="ATTRIBUTES_EXT" value="false" /> |
|
||||||
<option name="COMMONMARK_LISTS" value="true" /> |
|
||||||
<option name="DUMMY" value="false" /> |
|
||||||
<option name="EMOJI_SHORTCUTS" value="true" /> |
|
||||||
<option name="ENUMERATED_REFERENCES_EXT" value="false" /> |
|
||||||
<option name="FLEXMARK_FRONT_MATTER" value="false" /> |
|
||||||
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" /> |
|
||||||
<option name="GFM_TABLE_RENDERING" value="true" /> |
|
||||||
<option name="GITBOOK_URL_ENCODING" value="false" /> |
|
||||||
<option name="GITHUB_LISTS" value="false" /> |
|
||||||
<option name="GITHUB_WIKI_LINKS" value="false" /> |
|
||||||
<option name="GITLAB_EXT" value="false" /> |
|
||||||
<option name="GITLAB_MATH_EXT" value="false" /> |
|
||||||
<option name="GITLAB_MERMAID_EXT" value="false" /> |
|
||||||
<option name="HEADER_ID_NON_ASCII_TO_LOWERCASE" value="false" /> |
|
||||||
<option name="HEADER_ID_NO_DUPED_DASHES" value="false" /> |
|
||||||
<option name="JEKYLL_FRONT_MATTER" value="false" /> |
|
||||||
<option name="MACROS_EXT" value="false" /> |
|
||||||
<option name="NO_TEXT_ATTRIBUTES" value="false" /> |
|
||||||
<option name="PARSE_HTML_ANCHOR_ID" value="false" /> |
|
||||||
<option name="PLANTUML_FENCED_CODE" value="false" /> |
|
||||||
<option name="PUML_FENCED_CODE" value="false" /> |
|
||||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" /> |
|
||||||
</ParserOptions> |
|
||||||
</ParserSettings> |
|
||||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false" imageUriSerials="false" addDocTypeHtml="true" noParaTags="false" plantUmlConversion="0" mathConversion="0"> |
|
||||||
<GeneratorProvider> |
|
||||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" /> |
|
||||||
</GeneratorProvider> |
|
||||||
<headerTop /> |
|
||||||
<headerBottom /> |
|
||||||
<bodyTop /> |
|
||||||
<bodyBottom /> |
|
||||||
</HtmlSettings> |
|
||||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="true" isCssTextEnabled="false" isDynamicPageWidth="true"> |
|
||||||
<StylesheetProvider> |
|
||||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" /> |
|
||||||
</StylesheetProvider> |
|
||||||
<ScriptProviders /> |
|
||||||
<cssText /> |
|
||||||
<cssUriHistory /> |
|
||||||
</CssSettings> |
|
||||||
<AnnotatorSettings targetHasSpaces="true" linkCaseMismatch="true" wikiCaseMismatch="true" wikiLinkHasDashes="true" notUnderWikiHome="true" targetNotWikiPageExt="true" notUnderSourceWikiHome="true" targetNameHasAnchor="true" targetPathHasAnchor="true" wikiLinkHasSlash="true" wikiLinkHasSubdir="true" wikiLinkHasOnlyAnchor="true" linkTargetsWikiHasExt="true" linkTargetsWikiHasBadExt="true" notUnderSameRepo="true" targetNotUnderVcs="false" linkNeedsExt="true" linkHasBadExt="true" linkTargetNeedsExt="true" linkTargetHasBadExt="true" wikiLinkNotInWiki="true" imageTargetNotInRaw="true" repoRelativeAcrossVcsRoots="true" multipleWikiTargetsMatch="true" unresolvedLinkReference="true" linkIsIgnored="true" anchorIsIgnored="true" anchorIsUnresolved="true" anchorLineReferenceIsUnresolved="true" anchorLineReferenceFormat="true" anchorHasDuplicates="true" abbreviationDuplicates="true" abbreviationNotUsed="true" attributeIdDuplicateDefinition="true" attributeIdNotUsed="true" footnoteDuplicateDefinition="true" footnoteUnresolved="true" footnoteDuplicates="true" footnoteNotUsed="true" macroDuplicateDefinition="true" macroUnresolved="true" macroDuplicates="true" macroNotUsed="true" referenceDuplicateDefinition="true" referenceUnresolved="true" referenceDuplicates="true" referenceNotUsed="true" referenceUnresolvedNumericId="true" enumRefDuplicateDefinition="true" enumRefUnresolved="true" enumRefDuplicates="true" enumRefNotUsed="true" enumRefLinkUnresolved="true" enumRefLinkDuplicates="true" simTocUpdateNeeded="true" simTocTitleSpaceNeeded="true" /> |
|
||||||
<HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="css" scriptDir="js" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetPathType="2" targetExt="" useTargetExt="false" noCssNoScripts="false" useElementStyleAttribute="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" /> |
|
||||||
<LinkMapSettings> |
|
||||||
<textMaps /> |
|
||||||
</LinkMapSettings> |
|
||||||
</component> |
|
||||||
</project> |
|
@ -1,3 +0,0 @@ |
|||||||
<component name="MarkdownNavigator.ProfileManager"> |
|
||||||
<settings default="" pdf-export="" plain-text-search-scope="Project Files" /> |
|
||||||
</component> |
|
@ -1,12 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<project version="4"> |
|
||||||
<component name="RunConfigurationProducerService"> |
|
||||||
<option name="ignoredProducers"> |
|
||||||
<set> |
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" /> |
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" /> |
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" /> |
|
||||||
</set> |
|
||||||
</option> |
|
||||||
</component> |
|
||||||
</project> |
|
@ -1,7 +1,6 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||||||
<project version="4"> |
<project version="4"> |
||||||
<component name="VcsDirectoryMappings"> |
<component name="VcsDirectoryMappings"> |
||||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" /> |
<mapping directory="" vcs="Git" /> |
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" /> |
|
||||||
</component> |
</component> |
||||||
</project> |
</project> |
@ -1,38 +1,160 @@ |
|||||||
apply plugin: 'com.android.application' |
plugins { |
||||||
|
id 'com.android.application' |
||||||
apply plugin: 'kotlin-android' |
id 'kotlin-android' |
||||||
|
id 'kotlin-parcelize' |
||||||
|
} |
||||||
|
|
||||||
apply plugin: 'kotlin-android-extensions' |
def name = "reader" |
||||||
|
def code = 1 |
||||||
|
def version = "1.0.0" |
||||||
|
|
||||||
android { |
android { |
||||||
compileSdkVersion rootProject.ext.android.compileSdkVersion |
compileSdkVersion 30 |
||||||
|
buildToolsVersion "29.0.3" |
||||||
|
|
||||||
defaultConfig { |
defaultConfig { |
||||||
applicationId rootProject.ext.android.applicationId |
applicationId "com.novel.read" |
||||||
minSdkVersion rootProject.ext.android.minSdkVersion |
minSdkVersion 21 |
||||||
targetSdkVersion rootProject.ext.android.targetSdkVersion |
targetSdkVersion 30 |
||||||
versionCode rootProject.ext.android.versionCode |
versionCode code |
||||||
versionName rootProject.ext.android.versionName |
versionName version |
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" |
||||||
|
|
||||||
|
ndk { |
||||||
|
abiFilters "armeabi" |
||||||
|
} |
||||||
|
multiDexEnabled true |
||||||
|
resConfigs "zh", "zh-rCN" |
||||||
|
resConfigs "zh", "zh-rTW" |
||||||
|
resConfigs "zh", "zh-rHK" |
||||||
|
} |
||||||
|
|
||||||
|
signingConfigs { |
||||||
|
release { |
||||||
|
keyAlias 'key0' |
||||||
|
keyPassword '1qaz@WSX' |
||||||
|
storeFile file('reader.jks') |
||||||
|
storePassword '1qaz@WSX' |
||||||
|
} |
||||||
|
} |
||||||
|
buildFeatures { |
||||||
|
viewBinding true |
||||||
} |
} |
||||||
buildTypes { |
buildTypes { |
||||||
|
debug { |
||||||
|
minifyEnabled true |
||||||
|
shrinkResources true |
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
||||||
|
signingConfig signingConfigs.release |
||||||
|
} |
||||||
release { |
release { |
||||||
minifyEnabled false |
buildConfigField "boolean", "LOG_DEBUG", "false" //不显示log |
||||||
|
minifyEnabled true |
||||||
|
shrinkResources true |
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' |
||||||
|
signingConfig signingConfigs.release |
||||||
|
} |
||||||
|
|
||||||
|
android.applicationVariants.all { variant -> |
||||||
|
variant.outputs.all { |
||||||
|
def flavor = variant.productFlavors[0].name |
||||||
|
outputFileName = "${name}_${flavor}_${defaultConfig.versionName}.apk" |
||||||
|
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
|
flavorDimensions "mode" |
||||||
|
productFlavors { |
||||||
|
app { |
||||||
|
dimension "mode" |
||||||
|
manifestPlaceholders = [APP_CHANNEL_VALUE: "app"] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
compileOptions { |
compileOptions { |
||||||
sourceCompatibility JavaVersion.VERSION_1_8 |
sourceCompatibility JavaVersion.VERSION_1_8 |
||||||
targetCompatibility JavaVersion.VERSION_1_8 |
targetCompatibility JavaVersion.VERSION_1_8 |
||||||
} |
} |
||||||
|
kotlinOptions { |
||||||
|
jvmTarget = '1.8' |
||||||
|
} |
||||||
|
|
||||||
} |
} |
||||||
|
|
||||||
dependencies { |
dependencies { |
||||||
implementation fileTree(dir: 'libs', include: ['*.jar']) |
implementation fileTree(dir: 'libs', include: ['*.aar']) |
||||||
testImplementation rootProject.ext.dependencies["junit"] |
testImplementation 'junit:junit:4.13.1' |
||||||
androidTestImplementation rootProject.ext.dependencies["runner"] |
androidTestImplementation 'androidx.test:runner:1.3.0' |
||||||
androidTestImplementation rootProject.ext.dependencies["espresso_core"] |
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' |
||||||
implementation project(path: ':net_serivce') |
implementation "com.android.support:multidex:1.0.3" |
||||||
implementation project(path: ':common_lib') |
|
||||||
|
//kotlin |
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" |
||||||
|
|
||||||
|
//androidX |
||||||
|
implementation 'androidx.core:core-ktx:1.3.2' |
||||||
|
implementation 'androidx.appcompat:appcompat:1.2.0' |
||||||
|
implementation 'androidx.media:media:1.2.1' |
||||||
|
implementation 'androidx.preference:preference-ktx:1.1.1' |
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' |
||||||
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' |
||||||
|
implementation 'androidx.viewpager2:viewpager2:1.0.0' |
||||||
|
implementation 'com.google.android.material:material:1.2.1' |
||||||
|
implementation 'com.google.android:flexbox:1.1.0' |
||||||
|
implementation 'com.google.code.gson:gson:2.8.6' |
||||||
|
|
||||||
|
//基本的网络框架 |
||||||
|
implementation 'com.squareup.okhttp3:okhttp:3.14.9' |
||||||
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0' |
||||||
|
implementation 'com.squareup.retrofit2:converter-gson:2.7.2' |
||||||
|
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' |
||||||
|
|
||||||
|
//anko |
||||||
|
def anko_version = '0.10.8' |
||||||
|
implementation "org.jetbrains.anko:anko-sdk27:$anko_version" |
||||||
|
implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version" |
||||||
|
|
||||||
|
//sql |
||||||
|
implementation 'org.litepal.android:kotlin:3.0.0' |
||||||
|
|
||||||
|
//协程 |
||||||
|
def coroutines_version = '1.3.7' |
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" |
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" |
||||||
|
|
||||||
|
//liveEventBus |
||||||
|
implementation 'com.jeremyliao:live-event-bus-x:1.7.2' |
||||||
|
|
||||||
|
//lifecycle |
||||||
|
def lifecycle_version = '2.2.0' |
||||||
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" |
||||||
|
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" |
||||||
|
|
||||||
|
//Glide |
||||||
|
implementation 'com.github.bumptech.glide:glide:4.11.0' |
||||||
|
|
||||||
|
//MarkDown |
||||||
|
implementation 'io.noties.markwon:core:4.6.0' |
||||||
|
implementation 'io.noties.markwon:image-glide:4.6.0' |
||||||
|
//转换繁体 |
||||||
|
implementation files('libs/ZHConverter.jar') |
||||||
|
//brvah |
||||||
|
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6' |
||||||
|
|
||||||
|
//字符串比较 |
||||||
|
implementation 'net.ricecode:string-similarity:1.0.0' |
||||||
|
|
||||||
|
//epub |
||||||
|
implementation('com.positiondev.epublib:epublib-core:3.1') { |
||||||
|
exclude group: 'org.slf4j' |
||||||
|
exclude group: 'xmlpull' |
||||||
|
} |
||||||
|
|
||||||
|
//flex |
||||||
|
implementation 'com.google.android:flexbox:1.1.0' |
||||||
|
|
||||||
implementation 'com.allenliu.versionchecklib:library:2.2.0' |
implementation 'com.allenliu.versionchecklib:library:2.2.0' |
||||||
} |
|
||||||
|
implementation 'com.permissionx.guolindev:permissionx:1.4.0' |
||||||
|
} |
Binary file not shown.
@ -0,0 +1,18 @@ |
|||||||
|
{ |
||||||
|
"version": 2, |
||||||
|
"artifactType": { |
||||||
|
"type": "APK", |
||||||
|
"kind": "Directory" |
||||||
|
}, |
||||||
|
"applicationId": "com.novel.read", |
||||||
|
"variantName": "processAppReleaseResources", |
||||||
|
"elements": [ |
||||||
|
{ |
||||||
|
"type": "SINGLE", |
||||||
|
"filters": [], |
||||||
|
"versionCode": 1, |
||||||
|
"versionName": "1.0.0", |
||||||
|
"outputFile": "reader_app_1.0.0.apk" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
Binary file not shown.
After Width: | Height: | Size: 246 KiB |
@ -0,0 +1,62 @@ |
|||||||
|
[ |
||||||
|
{ |
||||||
|
"id": 1598233029304, |
||||||
|
"name": "度小美", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=0&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029305, |
||||||
|
"name": "度小宇", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=1&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029306, |
||||||
|
"name": "度逍遥", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5003&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029307, |
||||||
|
"name": "度丫丫", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=4&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029308, |
||||||
|
"name": "度小娇", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=5&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029309, |
||||||
|
"name": "度米朵", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=103&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029310, |
||||||
|
"name": "度博文", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=106&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029311, |
||||||
|
"name": "度小童", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=110&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029312, |
||||||
|
"name": "度小萌", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=111&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029313, |
||||||
|
"name": "百度骚男", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=11&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029314, |
||||||
|
"name": "百度评书", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=6&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"id": 1598233029315, |
||||||
|
"name": "百度主持", |
||||||
|
"url": "http://tts.baidu.com/text2audio,{\n \"method\": \"POST\",\n \"body\": \"tex={{java.encodeURI(java.encodeURI(speakText))}}&spd={{String((speakSpeed + 5) / 10 + 4)}}&per=9&cuid=baidu_speech_demo&idx=1&cod=2&lan=zh&ctp=1&pdt=1&vol=5&pit=5&_res_tag_=audio\"\n}" |
||||||
|
} |
||||||
|
] |
@ -0,0 +1,52 @@ |
|||||||
|
[ |
||||||
|
{ |
||||||
|
"bgStr": "#EFEFF7", |
||||||
|
"bgStrNight": "#212021", |
||||||
|
"textColor": "#383429", |
||||||
|
"textColorNight": "#94969C", |
||||||
|
"bgType": 0, |
||||||
|
"bgTypeNight": 0, |
||||||
|
"darkStatusIcon": true, |
||||||
|
"darkStatusIconNight": false |
||||||
|
}, |
||||||
|
{ |
||||||
|
"bgStr": "#DDC090", |
||||||
|
"bgStrNight": "#3C3F43", |
||||||
|
"textColor": "#3E3422", |
||||||
|
"textColorNight": "#DCDFE1", |
||||||
|
"bgType": 0, |
||||||
|
"bgTypeNight": 0, |
||||||
|
"darkStatusIcon": true, |
||||||
|
"darkStatusIconNight": false |
||||||
|
}, |
||||||
|
{ |
||||||
|
"bgStr": "#C2D8AA", |
||||||
|
"bgStrNight": "#3C3F43", |
||||||
|
"textColor": "#596C44", |
||||||
|
"textColorNight": "#88C16F", |
||||||
|
"bgType": 0, |
||||||
|
"bgTypeNight": 0, |
||||||
|
"darkStatusIcon": false, |
||||||
|
"darkStatusIconNight": false |
||||||
|
}, |
||||||
|
{ |
||||||
|
"bgStr": "#DBB8E2", |
||||||
|
"bgStrNight": "#3C3F43", |
||||||
|
"textColor": "#68516C", |
||||||
|
"textColorNight": "#F6AEAE", |
||||||
|
"bgType": 0, |
||||||
|
"bgTypeNight": 0, |
||||||
|
"darkStatusIcon": false, |
||||||
|
"darkStatusIconNight": false |
||||||
|
}, |
||||||
|
{ |
||||||
|
"bgStr": "#ABCEE0", |
||||||
|
"bgStrNight": "#3C3F43", |
||||||
|
"textColor": "#3D4C54", |
||||||
|
"textColorNight": "#90BFF5", |
||||||
|
"bgType": 0, |
||||||
|
"bgTypeNight": 0, |
||||||
|
"darkStatusIcon": false, |
||||||
|
"darkStatusIconNight": false |
||||||
|
} |
||||||
|
] |
@ -0,0 +1,26 @@ |
|||||||
|
[ |
||||||
|
{ |
||||||
|
"themeName": "典雅蓝", |
||||||
|
"isNightTheme": false, |
||||||
|
"primaryColor": "#03A9F4", |
||||||
|
"accentColor": "#AD1457", |
||||||
|
"backgroundColor": "#F5F5F5", |
||||||
|
"bottomBackground": "#EEEEEE" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"themeName": "黑白", |
||||||
|
"isNightTheme": true, |
||||||
|
"primaryColor": "#303030", |
||||||
|
"accentColor": "#E0E0E0", |
||||||
|
"backgroundColor": "#424242", |
||||||
|
"bottomBackground": "#424242" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"themeName": "A屏黑", |
||||||
|
"isNightTheme": true, |
||||||
|
"primaryColor": "#000000", |
||||||
|
"accentColor": "#FFFFFF", |
||||||
|
"backgroundColor": "#000000", |
||||||
|
"bottomBackground": "#000000" |
||||||
|
} |
||||||
|
] |
Binary file not shown.
@ -1,23 +1,12 @@ |
|||||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||||
<litepal> |
<litepal> |
||||||
<dbname value="readDb" /> |
<dbname value="light_book" /> |
||||||
|
<version value="1" /> |
||||||
<version value="9" /> |
|
||||||
|
|
||||||
<list> |
<list> |
||||||
<!--搜索记录表--> |
<mapping class="com.novel.read.data.db.entity.Book" /> |
||||||
<mapping class="com.novel.read.model.db.SearchListTable"/> |
<mapping class="com.novel.read.data.db.entity.BookChapter" /> |
||||||
<!--收藏书籍表--> |
<mapping class="com.novel.read.data.db.entity.Bookmark" /> |
||||||
<mapping class="com.novel.read.model.db.CollBookBean"/> |
<mapping class="com.novel.read.data.db.entity.ReadRecord" /> |
||||||
<!--章节表--> |
<mapping class="com.novel.read.data.db.entity.SearchHistory" /> |
||||||
<mapping class="com.novel.read.model.db.BookChapterBean"/> |
|
||||||
<!--阅读记录表--> |
|
||||||
<mapping class="com.novel.read.model.db.BookRecordBean"/> |
|
||||||
<!--章节详情表--> |
|
||||||
<mapping class="com.novel.read.model.db.ChapterInfoBean" /> |
|
||||||
<!--章节详情表--> |
|
||||||
<mapping class="com.novel.read.model.db.DownloadTaskBean" /> |
|
||||||
<!--书签表--> |
|
||||||
<mapping class="com.novel.read.model.db.BookSignTable" /> |
|
||||||
</list> |
</list> |
||||||
|
<storage value="external" /> |
||||||
</litepal> |
</litepal> |
@ -0,0 +1,138 @@ |
|||||||
|
package com.novel.read |
||||||
|
|
||||||
|
import android.app.NotificationChannel |
||||||
|
import android.app.NotificationManager |
||||||
|
import android.content.Context |
||||||
|
import android.content.res.Configuration |
||||||
|
import android.os.Build |
||||||
|
import android.provider.Settings |
||||||
|
import androidx.annotation.RequiresApi |
||||||
|
import androidx.appcompat.app.AppCompatDelegate |
||||||
|
import androidx.multidex.MultiDexApplication |
||||||
|
import com.bumptech.glide.Glide |
||||||
|
import com.jeremyliao.liveeventbus.LiveEventBus |
||||||
|
import com.novel.read.constant.AppConst.channelIdDownload |
||||||
|
import com.novel.read.constant.AppConst.channelIdReadAloud |
||||||
|
import com.novel.read.constant.EventBus |
||||||
|
import com.novel.read.data.db.BookDatabase |
||||||
|
import com.novel.read.help.ActivityHelp |
||||||
|
import com.novel.read.help.AppConfig |
||||||
|
import com.novel.read.help.ReadBookConfig |
||||||
|
import com.novel.read.help.ThemeConfig |
||||||
|
import com.novel.read.utils.LanguageUtils |
||||||
|
import com.novel.read.utils.ext.postEvent |
||||||
|
import org.litepal.LitePal |
||||||
|
|
||||||
|
@Suppress("DEPRECATION") |
||||||
|
class App : MultiDexApplication() { |
||||||
|
|
||||||
|
companion object { |
||||||
|
@JvmStatic |
||||||
|
lateinit var INSTANCE: App |
||||||
|
private set |
||||||
|
|
||||||
|
@JvmStatic |
||||||
|
lateinit var db: BookDatabase |
||||||
|
private set |
||||||
|
|
||||||
|
lateinit var androidId: String |
||||||
|
var versionCode = 0 |
||||||
|
var versionName = "" |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreate() { |
||||||
|
super.onCreate() |
||||||
|
INSTANCE = this |
||||||
|
androidId = Settings.System.getString(contentResolver, Settings.Secure.ANDROID_ID) |
||||||
|
LanguageUtils.setConfiguration(this) |
||||||
|
LitePal.initialize(this) |
||||||
|
db = BookDatabase.get() |
||||||
|
packageManager.getPackageInfo(packageName, 0)?.let { |
||||||
|
versionCode = it.versionCode |
||||||
|
versionName = it.versionName |
||||||
|
} |
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createChannelId() |
||||||
|
applyDayNight() |
||||||
|
LiveEventBus |
||||||
|
.config() |
||||||
|
.lifecycleObserverAlwaysActive(true) |
||||||
|
.autoClear(false) |
||||||
|
registerActivityLifecycleCallbacks(ActivityHelp) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) { |
||||||
|
super.onConfigurationChanged(newConfig) |
||||||
|
when (newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK) { |
||||||
|
Configuration.UI_MODE_NIGHT_YES, |
||||||
|
Configuration.UI_MODE_NIGHT_NO -> applyDayNight() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
fun applyDayNight() { |
||||||
|
AppConfig.upEInkMode() |
||||||
|
ReadBookConfig.upBg() |
||||||
|
ThemeConfig.applyTheme(this) |
||||||
|
initNightMode() |
||||||
|
postEvent(EventBus.RECREATE, "") |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private fun initNightMode() { |
||||||
|
val targetMode = |
||||||
|
if (AppConfig.isNightTheme) { |
||||||
|
AppCompatDelegate.MODE_NIGHT_YES |
||||||
|
} else { |
||||||
|
AppCompatDelegate.MODE_NIGHT_NO |
||||||
|
} |
||||||
|
AppCompatDelegate.setDefaultNightMode(targetMode) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建通知ID |
||||||
|
*/ |
||||||
|
@RequiresApi(Build.VERSION_CODES.O) |
||||||
|
private fun createChannelId() { |
||||||
|
(getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager)?.let { |
||||||
|
//用唯一的ID创建渠道对象 |
||||||
|
val downloadChannel = NotificationChannel( |
||||||
|
channelIdDownload, |
||||||
|
getString(R.string.action_download), |
||||||
|
NotificationManager.IMPORTANCE_LOW |
||||||
|
) |
||||||
|
//初始化channel |
||||||
|
downloadChannel.enableLights(false) |
||||||
|
downloadChannel.enableVibration(false) |
||||||
|
downloadChannel.setSound(null, null) |
||||||
|
|
||||||
|
//用唯一的ID创建渠道对象 |
||||||
|
val readAloudChannel = NotificationChannel( |
||||||
|
channelIdReadAloud, |
||||||
|
getString(R.string.read_aloud), |
||||||
|
NotificationManager.IMPORTANCE_LOW |
||||||
|
) |
||||||
|
//初始化channel |
||||||
|
readAloudChannel.enableLights(false) |
||||||
|
readAloudChannel.enableVibration(false) |
||||||
|
readAloudChannel.setSound(null, null) |
||||||
|
|
||||||
|
//向notification manager 提交channel |
||||||
|
it.createNotificationChannels(listOf(downloadChannel, readAloudChannel)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
override fun onLowMemory() { |
||||||
|
super.onLowMemory() |
||||||
|
Glide.get(this).clearMemory() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onTrimMemory(level: Int) { |
||||||
|
super.onTrimMemory(level) |
||||||
|
if (level == TRIM_MEMORY_UI_HIDDEN) { |
||||||
|
Glide.get(this).clearMemory() |
||||||
|
} |
||||||
|
Glide.get(this).trimMemory(level) |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,22 +0,0 @@ |
|||||||
package com.novel.read |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.Toast |
|
||||||
|
|
||||||
fun Context.showToast(msg:String){ |
|
||||||
Toast.makeText(this,msg,Toast.LENGTH_SHORT).show() |
|
||||||
} |
|
||||||
|
|
||||||
fun Context.getScreenContentWidth(): Int { |
|
||||||
val displayMetrics = this.resources.displayMetrics |
|
||||||
return displayMetrics.widthPixels |
|
||||||
} |
|
||||||
|
|
||||||
fun Context.dp2px(dps: Int): Int { |
|
||||||
return Math.round(dps.toFloat() * getDensityDpiScale(this)) |
|
||||||
} |
|
||||||
|
|
||||||
fun getDensityDpiScale(context: Context): Float { |
|
||||||
return context.resources.displayMetrics.xdpi / 160.0f |
|
||||||
} |
|
@ -1,205 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.annotation.SuppressLint |
|
||||||
import android.app.ProgressDialog |
|
||||||
import android.content.Intent |
|
||||||
import android.util.Log |
|
||||||
import android.view.View |
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.adapter.LoveLyAdapter |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.constants.Constant.RequestCode.Companion.REQUEST_READ |
|
||||||
import com.novel.read.constants.Constant.ResultCode.Companion.RESULT_IS_COLLECTED |
|
||||||
import com.novel.read.event.BookArticleEvent |
|
||||||
import com.novel.read.event.GetBookDetailEvent |
|
||||||
import com.novel.read.event.GetRecommendBookEvent |
|
||||||
import com.novel.read.event.UpdateBookEvent |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.model.db.CollBookBean |
|
||||||
import com.novel.read.model.db.dbManage.BookRepository |
|
||||||
import com.novel.read.model.protocol.RecommendBookResp |
|
||||||
import com.novel.read.showToast |
|
||||||
import com.novel.read.utlis.DateUtli |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
import com.squareup.otto.Subscribe |
|
||||||
import kotlinx.android.synthetic.main.activity_book_detail.* |
|
||||||
import org.litepal.LitePal |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
class NovelBookDetailActivity(override val layoutId: Int = R.layout.activity_book_detail) : NovelBaseActivity(), View.OnClickListener { |
|
||||||
|
|
||||||
private lateinit var mAdapter: LoveLyAdapter |
|
||||||
private val mList = ArrayList<RecommendBookResp.BookBean>() |
|
||||||
private var mBookId: Int = 0 |
|
||||||
private var isCollected = false |
|
||||||
private var mCollBookBean: CollBookBean? = null |
|
||||||
private lateinit var mProgressDialog: ProgressDialog |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
mBookId = intent.getIntExtra(Constant.Bundle.BookId, 0) |
|
||||||
rlv_lovely.layoutManager = LinearLayoutManager(this) |
|
||||||
mAdapter = LoveLyAdapter(mList) |
|
||||||
rlv_lovely.adapter = mAdapter |
|
||||||
mProgressDialog = ProgressDialog(this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
refresh.showLoading() |
|
||||||
refresh.setOnReloadingListener { getData() } |
|
||||||
getData() |
|
||||||
toolbar.setNavigationOnClickListener { finish() } |
|
||||||
tv_add_book.setOnClickListener(this) |
|
||||||
tv_start_read.setOnClickListener(this) |
|
||||||
} |
|
||||||
|
|
||||||
private fun getData() { |
|
||||||
AccountManager.getInstance().getRecommendBook(mBookId.toString(), "10") |
|
||||||
AccountManager.getInstance().getBookDetail(mBookId.toString()) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onClick(v: View?) { |
|
||||||
when (v?.id) { |
|
||||||
R.id.tv_add_book -> |
|
||||||
//点击存储 |
|
||||||
if (isCollected) { |
|
||||||
//放弃点击 |
|
||||||
BookRepository.getInstance().deleteCollBookInRx(mCollBookBean) |
|
||||||
tv_add_book.text = resources.getString(R.string.add_book) |
|
||||||
isCollected = false |
|
||||||
} else { |
|
||||||
mProgressDialog.setTitle("正在添加到书架中") |
|
||||||
mProgressDialog.show() |
|
||||||
AccountManager.getInstance().getBookArticle(mBookId.toString()) |
|
||||||
|
|
||||||
} |
|
||||||
R.id.tv_start_read -> |
|
||||||
startActivityForResult( |
|
||||||
Intent(this, NovelReadActivity::class.java) |
|
||||||
.putExtra(NovelReadActivity.EXTRA_IS_COLLECTED, isCollected) |
|
||||||
.putExtra(NovelReadActivity.EXTRA_COLL_BOOK, mCollBookBean), REQUEST_READ |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n") |
|
||||||
@Subscribe |
|
||||||
fun getBookDetail(event: GetBookDetailEvent) { |
|
||||||
refresh.showFinish() |
|
||||||
if (event.isFail) { |
|
||||||
refresh.showError() |
|
||||||
} else { |
|
||||||
val bookBean = event.result!!.book |
|
||||||
GlideImageLoader.displayCornerImage(this, bookBean.cover, iv_book) |
|
||||||
tv_book_name.text = bookBean.title |
|
||||||
|
|
||||||
tv_book_author.text = bookBean.author + " | " |
|
||||||
tv_book_length.text = getString(R.string.book_word, bookBean.words / 10000) |
|
||||||
|
|
||||||
if (event.result!!.last_article != null) { |
|
||||||
tv_new_title.text = |
|
||||||
getString(R.string.new_chapter, event.result!!.last_article.title) |
|
||||||
tv_update_time.text = |
|
||||||
DateUtli.dateConvert(event.result!!.last_article.create_time, 0) |
|
||||||
} |
|
||||||
|
|
||||||
tv_human_num.text = bookBean.hot.toString() + "" |
|
||||||
tv_love_look_num.text = bookBean.like |
|
||||||
tv_Intro.text = bookBean.description |
|
||||||
mCollBookBean = BookRepository.getInstance().getCollBook(bookBean.id.toString()) |
|
||||||
//判断是否收藏 |
|
||||||
if (mCollBookBean != null) { |
|
||||||
isCollected = true |
|
||||||
tv_add_book.text = resources.getString(R.string.already_add) |
|
||||||
tv_start_read.text = resources.getString(R.string.go_read) |
|
||||||
} else { |
|
||||||
mCollBookBean = event.result!!.collBookBean |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun getRecommendBook(event: GetRecommendBookEvent) { |
|
||||||
if (event.isFail) { |
|
||||||
Log.e("getRecommendBook", event.er?.msg) |
|
||||||
} else { |
|
||||||
mList.clear() |
|
||||||
mList.addAll(event.result!!.book) |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onResume() { |
|
||||||
super.onResume() |
|
||||||
EventManager.instance.registerSubscriber(this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPause() { |
|
||||||
super.onPause() |
|
||||||
EventManager.instance.unregisterSubscriber(this) |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun getArticle(event: BookArticleEvent) { |
|
||||||
if (event.isFail) { |
|
||||||
dismiss() |
|
||||||
showToast(getString(R.string.net_error)) |
|
||||||
} else { |
|
||||||
//存储收藏 |
|
||||||
var success = false |
|
||||||
if (mCollBookBean != null) { |
|
||||||
success = mCollBookBean!!.saveOrUpdate("bookId=?", mCollBookBean!!.id) |
|
||||||
} |
|
||||||
if (success) { |
|
||||||
val bookChapterBean = event.result!!.chapterBean |
|
||||||
for (i in bookChapterBean.indices) { |
|
||||||
bookChapterBean[i].collBookBean = mCollBookBean |
|
||||||
} |
|
||||||
LitePal.saveAllAsync(bookChapterBean).listen { success1 -> |
|
||||||
if (success1) { |
|
||||||
if (tv_add_book != null) { |
|
||||||
tv_add_book.text = resources.getString(R.string.already_add) |
|
||||||
} |
|
||||||
isCollected = true |
|
||||||
} else { |
|
||||||
LitePal.deleteAll(CollBookBean::class.java, "bookId =?", mCollBookBean!!.id) |
|
||||||
showToast(getString(R.string.net_error)) |
|
||||||
} |
|
||||||
dismiss() |
|
||||||
} |
|
||||||
} else { |
|
||||||
showToast(getString(R.string.net_error)) |
|
||||||
dismiss() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private fun dismiss() { |
|
||||||
mProgressDialog.dismiss() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { |
|
||||||
super.onActivityResult(requestCode, resultCode, data) |
|
||||||
//如果进入阅读页面收藏了,页面结束的时候,就需要返回改变收藏按钮 |
|
||||||
if (requestCode == REQUEST_READ) { |
|
||||||
if (data == null) { |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
isCollected = data.getBooleanExtra(RESULT_IS_COLLECTED, false) |
|
||||||
|
|
||||||
if (isCollected) { |
|
||||||
tv_add_book.text = resources.getString(R.string.already_add) |
|
||||||
tv_start_read.text = resources.getString(R.string.go_read) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
EventManager.instance.postEvent(UpdateBookEvent()) |
|
||||||
} |
|
||||||
} |
|
@ -1,89 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.adapter.BookListAdapter |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.constants.Constant.COMMENT_SIZE |
|
||||||
import com.novel.read.event.SearchListEvent |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.inter.OnLoadMoreListener |
|
||||||
import com.novel.read.model.protocol.SearchResp |
|
||||||
import com.squareup.otto.Subscribe |
|
||||||
import kotlinx.android.synthetic.main.activity_book_type_list.* |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
class NovelBookTypeListActivity(override val layoutId: Int = R.layout.activity_book_type_list) : NovelBaseActivity() { |
|
||||||
|
|
||||||
private var mList: MutableList<SearchResp.BookBean> = ArrayList() |
|
||||||
private lateinit var mAdapter: BookListAdapter |
|
||||||
private var mCategoryId: String? = null |
|
||||||
private var mTitle: String? = null |
|
||||||
private var page: Int = 1 |
|
||||||
private var loadSize: Int = 0 |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
EventManager.instance.registerSubscriber(this) |
|
||||||
|
|
||||||
mCategoryId = intent.getStringExtra(Constant.Bundle.CategoryId) |
|
||||||
mTitle = intent.getStringExtra(Constant.Bundle.mTitle) |
|
||||||
|
|
||||||
rlv_type_list.layoutManager = LinearLayoutManager(this) |
|
||||||
mAdapter = BookListAdapter(mList, rlv_type_list) |
|
||||||
rlv_type_list.adapter = mAdapter |
|
||||||
|
|
||||||
mAdapter.setOnLoadMoreListener(object : OnLoadMoreListener { |
|
||||||
override fun onLoadMore() { |
|
||||||
if (mAdapter.isLoadingMore) { |
|
||||||
rlv_type_list.stopScroll() |
|
||||||
} else { |
|
||||||
if (loadSize >= COMMENT_SIZE) { |
|
||||||
mAdapter.isLoadingMore = true |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
page++ |
|
||||||
getData() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
refresh.showLoading() |
|
||||||
refresh.setOnReloadingListener { this.getData() } |
|
||||||
getData() |
|
||||||
toolbar.title = mTitle |
|
||||||
toolbar.setNavigationOnClickListener { finish() } |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private fun getData() { |
|
||||||
mCategoryId?.let { AccountManager.getInstance().getSearchBookList(it, "", page) } |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun getSearchList(event: SearchListEvent) { |
|
||||||
refresh.showFinish() |
|
||||||
if (event.isFail) { |
|
||||||
refresh.showError() |
|
||||||
} else { |
|
||||||
loadSize = event.result!!.book.size |
|
||||||
if (mAdapter.isLoadingMore) { |
|
||||||
mAdapter.isLoadingMore = false |
|
||||||
mList.addAll(event.result!!.book) |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
} else { |
|
||||||
mList.clear() |
|
||||||
mList.addAll(event.result!!.book) |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
EventManager.instance.unregisterSubscriber(this) |
|
||||||
} |
|
||||||
} |
|
@ -1,148 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.annotation.SuppressLint |
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.os.Bundle |
|
||||||
import android.util.Log |
|
||||||
import android.view.KeyEvent |
|
||||||
import android.view.View |
|
||||||
import androidx.fragment.app.Fragment |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.event.* |
|
||||||
import com.novel.read.fragment.BookFragment |
|
||||||
import com.novel.read.fragment.MoreFragment |
|
||||||
import com.novel.read.fragment.RecommendFragment |
|
||||||
import com.novel.read.fragment.StackFragment |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.model.db.dbManage.BookRepository |
|
||||||
import com.novel.read.showToast |
|
||||||
import com.novel.read.utlis.SpUtil |
|
||||||
import com.squareup.otto.Subscribe |
|
||||||
import kotlinx.android.synthetic.main.activity_main.* |
|
||||||
|
|
||||||
class NovelMainActivity(override val layoutId: Int = R.layout.activity_main) : NovelBaseActivity() { |
|
||||||
|
|
||||||
private lateinit var mCurrentFrag: Fragment |
|
||||||
private lateinit var mMainFragment: BookFragment |
|
||||||
private lateinit var mRecommendFragment: RecommendFragment |
|
||||||
private lateinit var mStackFragment: StackFragment |
|
||||||
private lateinit var mMoreFragment: MoreFragment |
|
||||||
|
|
||||||
//记录用户首次点击返回键的时间 |
|
||||||
private var firstTime: Long = 0 |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
mCurrentFrag = Fragment() |
|
||||||
mMainFragment = BookFragment.newInstance() |
|
||||||
mRecommendFragment = RecommendFragment.newInstance() |
|
||||||
mStackFragment = StackFragment.newInstance() |
|
||||||
mMoreFragment = MoreFragment.newInstance() |
|
||||||
AccountManager.getInstance().login(this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
bottom_bar.setOnNavigationItemSelectedListener { menuItem -> |
|
||||||
when (menuItem.itemId) { |
|
||||||
R.id.tab_one -> { |
|
||||||
switchFragment(mMainFragment) |
|
||||||
return@setOnNavigationItemSelectedListener true |
|
||||||
} |
|
||||||
R.id.tab_two -> { |
|
||||||
switchFragment(mRecommendFragment) |
|
||||||
return@setOnNavigationItemSelectedListener true |
|
||||||
} |
|
||||||
R.id.tab_three -> { |
|
||||||
switchFragment(mStackFragment) |
|
||||||
return@setOnNavigationItemSelectedListener true |
|
||||||
} |
|
||||||
R.id.tab_four -> { |
|
||||||
switchFragment(mMoreFragment) |
|
||||||
return@setOnNavigationItemSelectedListener true |
|
||||||
} |
|
||||||
} |
|
||||||
false |
|
||||||
} |
|
||||||
|
|
||||||
if (BookRepository.getInstance().collBooks.size > 0) { |
|
||||||
switchFragment(mMainFragment) |
|
||||||
} else { |
|
||||||
bottom_bar.selectedItemId = R.id.tab_two |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private fun switchFragment(targetFragment: Fragment) { |
|
||||||
val transaction = supportFragmentManager.beginTransaction() |
|
||||||
if (!targetFragment.isAdded) { |
|
||||||
transaction.hide(mCurrentFrag) |
|
||||||
transaction.add(R.id.fl_content, targetFragment, targetFragment.javaClass.name) |
|
||||||
} else { |
|
||||||
transaction.hide(mCurrentFrag).show(targetFragment) |
|
||||||
} |
|
||||||
mCurrentFrag = targetFragment |
|
||||||
transaction.commit() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onResume() { |
|
||||||
super.onResume() |
|
||||||
EventManager.instance.registerSubscriber(this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPause() { |
|
||||||
super.onPause() |
|
||||||
EventManager.instance.unregisterSubscriber(this) |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun login(event: LoginEvent) { |
|
||||||
if (event.isFail) { |
|
||||||
Log.e("NovelMainActivity", "login: " + event.er!!.msg) |
|
||||||
} else { |
|
||||||
SpUtil.setStringValue(Constant.Uid, event.result!!.uid.toString()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { |
|
||||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) { |
|
||||||
if (!isVisible(bottom_bar)) { |
|
||||||
bottom_bar.visibility = View.VISIBLE |
|
||||||
mMainFragment.updateBook(UpdateBookEvent()) |
|
||||||
} else { |
|
||||||
val secondTime = System.currentTimeMillis() |
|
||||||
if (secondTime - firstTime > 1000) { |
|
||||||
firstTime = secondTime |
|
||||||
showToast("再次点击退出界面") |
|
||||||
} else { |
|
||||||
finish() |
|
||||||
} |
|
||||||
} |
|
||||||
return true |
|
||||||
} |
|
||||||
return super.onKeyUp(keyCode, event) |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun setBottomBar(event: HideBottomBarEvent) { |
|
||||||
if (event.result!!) { |
|
||||||
bottom_bar.visibility = View.GONE |
|
||||||
} else { |
|
||||||
bottom_bar.visibility = View.VISIBLE |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun toRecommendFragment(event: SwitchFragmentEvent) { |
|
||||||
bottom_bar.selectedItemId = R.id.tab_two |
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
fun reStart(context: Context) { |
|
||||||
val intent = Intent(context, NovelMainActivity::class.java) |
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK |
|
||||||
context.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,91 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.adapter.RankListAdapter |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.constants.Constant.COMMENT_SIZE |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.inter.OnLoadMoreListener |
|
||||||
import com.novel.read.model.protocol.RankByUpdateResp |
|
||||||
import kotlinx.android.synthetic.main.activity_rank_list.* |
|
||||||
import retrofit2.Call |
|
||||||
import retrofit2.Callback |
|
||||||
import retrofit2.Response |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
/** |
|
||||||
* 推荐fragment中点击更多跳转来的。 |
|
||||||
*/ |
|
||||||
class NovelRankListActivity(override val layoutId: Int= R.layout.activity_rank_list) : NovelBaseActivity() { |
|
||||||
|
|
||||||
private lateinit var mAdapter: RankListAdapter |
|
||||||
private var mList: MutableList<RankByUpdateResp.BookBean> = ArrayList() |
|
||||||
private var page = 1 |
|
||||||
private var loadSize: Int = 0 |
|
||||||
private var type: String = "" |
|
||||||
private var sex: String = "" |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
rlv_book_list.layoutManager = LinearLayoutManager(this) |
|
||||||
mAdapter = RankListAdapter(mList, rlv_book_list) |
|
||||||
rlv_book_list.adapter = mAdapter |
|
||||||
sex = intent.getStringExtra(Constant.Sex) |
|
||||||
type = intent.getStringExtra(Constant.Type) |
|
||||||
when (type) { |
|
||||||
Constant.ListType.Human -> toolbar.title = getString(R.string.popular_selection) |
|
||||||
Constant.ListType.EditRecommend -> toolbar.title = getString(R.string.edit_recommend) |
|
||||||
Constant.ListType.HotSearch -> toolbar.title = getString(R.string.hot_search) |
|
||||||
} |
|
||||||
getData() |
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
toolbar.setNavigationOnClickListener { finish() } |
|
||||||
|
|
||||||
mAdapter.setOnLoadMoreListener(object : OnLoadMoreListener { |
|
||||||
override fun onLoadMore() { |
|
||||||
if (mAdapter.isLoadingMore) { |
|
||||||
|
|
||||||
} else { |
|
||||||
if (loadSize >= COMMENT_SIZE) { |
|
||||||
mAdapter.isLoadingMore = true |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
page++ |
|
||||||
getData() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
private fun getData() { |
|
||||||
AccountManager.getInstance().getRankList(type, sex, Constant.DateTyp.Week, page.toString(), RankCallBack()) |
|
||||||
} |
|
||||||
|
|
||||||
private inner class RankCallBack : Callback<RankByUpdateResp> { |
|
||||||
|
|
||||||
override fun onResponse(call: Call<RankByUpdateResp>, response: Response<RankByUpdateResp>) { |
|
||||||
if (response.isSuccessful) { |
|
||||||
if (response.body() != null) { |
|
||||||
loadSize = response.body()!!.book.size |
|
||||||
if (mAdapter.isLoadingMore) { |
|
||||||
mAdapter.isLoadingMore = false |
|
||||||
mList.addAll(response.body()!!.book) |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
} else { |
|
||||||
mList.clear() |
|
||||||
mList.addAll(response.body()!!.book) |
|
||||||
mAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onFailure(call: Call<RankByUpdateResp>, t: Throwable) { |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,655 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.annotation.SuppressLint |
|
||||||
import android.app.Activity |
|
||||||
import android.app.Service |
|
||||||
import android.content.* |
|
||||||
import android.os.Build |
|
||||||
import android.os.Handler |
|
||||||
import android.os.IBinder |
|
||||||
import android.os.Message |
|
||||||
import android.util.Log |
|
||||||
import android.view.KeyEvent |
|
||||||
import android.view.View.* |
|
||||||
import android.view.WindowManager |
|
||||||
import android.view.animation.Animation |
|
||||||
import android.view.animation.AnimationUtils |
|
||||||
import android.widget.SeekBar |
|
||||||
import androidx.appcompat.app.AlertDialog |
|
||||||
import androidx.core.content.ContextCompat |
|
||||||
import androidx.core.view.GravityCompat |
|
||||||
import androidx.drawerlayout.widget.DrawerLayout |
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.adapter.CategoryAdapter |
|
||||||
import com.novel.read.adapter.MarkAdapter |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.constants.Constant.ResultCode.Companion.RESULT_IS_COLLECTED |
|
||||||
import com.novel.read.event.BookArticleEvent |
|
||||||
import com.novel.read.event.ErrorChapterEvent |
|
||||||
import com.novel.read.event.FinishChapterEvent |
|
||||||
import com.novel.read.event.RxBus |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.model.db.BookChapterBean |
|
||||||
import com.novel.read.model.db.BookSignTable |
|
||||||
import com.novel.read.model.db.CollBookBean |
|
||||||
import com.novel.read.model.db.DownloadTaskBean |
|
||||||
import com.novel.read.model.db.dbManage.BookRepository |
|
||||||
import com.novel.read.service.DownloadMessage |
|
||||||
import com.novel.read.service.DownloadService |
|
||||||
import com.novel.read.showToast |
|
||||||
import com.novel.read.utlis.BrightnessUtils |
|
||||||
import com.novel.read.utlis.ScreenUtils |
|
||||||
import com.novel.read.utlis.SpUtil |
|
||||||
import com.novel.read.utlis.SystemBarUtils |
|
||||||
import com.novel.read.widget.dialog.ReadSettingDialog |
|
||||||
import com.novel.read.widget.page.PageLoader |
|
||||||
import com.novel.read.widget.page.PageView |
|
||||||
import com.novel.read.widget.page.ReadSettingManager |
|
||||||
import com.novel.read.widget.page.TxtChapter |
|
||||||
import com.squareup.otto.Subscribe |
|
||||||
import kotlinx.android.synthetic.main.activity_read.* |
|
||||||
import kotlinx.android.synthetic.main.layout_download.* |
|
||||||
import kotlinx.android.synthetic.main.layout_light.* |
|
||||||
import kotlinx.android.synthetic.main.layout_read_mark.* |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
/** |
|
||||||
* 阅读页📕 |
|
||||||
*/ |
|
||||||
class NovelReadActivity : NovelBaseActivity(), DownloadService.OnDownloadListener { |
|
||||||
|
|
||||||
private lateinit var mCategoryAdapter: CategoryAdapter |
|
||||||
private val mChapters = ArrayList<TxtChapter>() |
|
||||||
private lateinit var mCurrentChapter: TxtChapter //当前章节 |
|
||||||
private var currentChapter = 0 |
|
||||||
private lateinit var mMarkAdapter: MarkAdapter |
|
||||||
private val mMarks = ArrayList<BookSignTable>() |
|
||||||
private lateinit var mPageLoader: PageLoader |
|
||||||
private var mTopInAnim: Animation? = null |
|
||||||
private var mTopOutAnim: Animation? = null |
|
||||||
private var mBottomInAnim: Animation? = null |
|
||||||
private var mBottomOutAnim: Animation? = null |
|
||||||
|
|
||||||
private lateinit var mSettingDialog: ReadSettingDialog |
|
||||||
private var isCollected = false // isFromSDCard |
|
||||||
private var isNightMode = false |
|
||||||
private var isFullScreen = false |
|
||||||
private val isRegistered = false |
|
||||||
|
|
||||||
private lateinit var mCollBook: CollBookBean |
|
||||||
private lateinit var mBookId: String |
|
||||||
|
|
||||||
@SuppressLint("HandlerLeak") |
|
||||||
private val mHandler = object : Handler() { |
|
||||||
override fun handleMessage(msg: Message) { |
|
||||||
super.handleMessage(msg) |
|
||||||
when (msg.what) { |
|
||||||
WHAT_CATEGORY -> rlv_list.setSelection(mPageLoader.chapterPos) |
|
||||||
WHAT_CHAPTER -> mPageLoader.openChapter() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override val layoutId: Int get() = R.layout.activity_read |
|
||||||
|
|
||||||
// 接收电池信息和时间更新的广播 |
|
||||||
private val mReceiver = object : BroadcastReceiver() { |
|
||||||
override fun onReceive(context: Context, intent: Intent) { |
|
||||||
if (Objects.requireNonNull(intent.action) == Intent.ACTION_BATTERY_CHANGED) { |
|
||||||
val level = intent.getIntExtra("level", 0) |
|
||||||
mPageLoader.updateBattery(level) |
|
||||||
} else if (intent.action == Intent.ACTION_TIME_TICK) { |
|
||||||
mPageLoader.updateTime() |
|
||||||
}// 监听分钟的变化 |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private var mService: DownloadService.IDownloadManager? = null |
|
||||||
private var mConn: ServiceConnection? = null |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
EventManager.instance.registerSubscriber(this) |
|
||||||
mCollBook = intent.getSerializableExtra(EXTRA_COLL_BOOK) as CollBookBean |
|
||||||
isCollected = intent.getBooleanExtra(EXTRA_IS_COLLECTED, false) |
|
||||||
mBookId = mCollBook.id |
|
||||||
initService() |
|
||||||
// 如果 API < 18 取消硬件加速 |
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { |
|
||||||
read_pv_page.setLayerType(LAYER_TYPE_SOFTWARE, null) |
|
||||||
} |
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) |
|
||||||
|
|
||||||
//获取页面加载器 |
|
||||||
mPageLoader = read_pv_page.getPageLoader(mCollBook) |
|
||||||
|
|
||||||
mSettingDialog = ReadSettingDialog(this, mPageLoader) |
|
||||||
//禁止滑动展示DrawerLayout |
|
||||||
read_dl_slide.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) |
|
||||||
//侧边打开后,返回键能够起作用 |
|
||||||
read_dl_slide.isFocusableInTouchMode = false |
|
||||||
//半透明化StatusBar |
|
||||||
SystemBarUtils.transparentStatusBar(this) |
|
||||||
//隐藏StatusBar |
|
||||||
read_pv_page.post { this.hideSystemBar() } |
|
||||||
read_abl_top_menu.setPadding(0, ScreenUtils.statusBarHeight, 0, 0) |
|
||||||
ll_download.setPadding(0, ScreenUtils.statusBarHeight, 0, ScreenUtils.dpToPx(15)) |
|
||||||
|
|
||||||
val lp = window.attributes |
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { |
|
||||||
lp.layoutInDisplayCutoutMode = 1 |
|
||||||
} |
|
||||||
window.attributes = lp |
|
||||||
|
|
||||||
//设置当前Activity的Brightness |
|
||||||
if (ReadSettingManager.getInstance().isBrightnessAuto) { |
|
||||||
BrightnessUtils.setDefaultBrightness(this) |
|
||||||
} else { |
|
||||||
BrightnessUtils.setBrightness(this, ReadSettingManager.getInstance().brightness) |
|
||||||
} |
|
||||||
|
|
||||||
//注册广播 |
|
||||||
val intentFilter = IntentFilter() |
|
||||||
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED) |
|
||||||
intentFilter.addAction(Intent.ACTION_TIME_TICK) |
|
||||||
registerReceiver(mReceiver, intentFilter) |
|
||||||
|
|
||||||
if (!SpUtil.getBooleanValue(Constant.BookGuide, false)) { |
|
||||||
iv_guide.visibility = VISIBLE |
|
||||||
toggleMenu(false) |
|
||||||
} |
|
||||||
|
|
||||||
if (isCollected) { |
|
||||||
mPageLoader.collBook.bookChapters = BookRepository.getInstance().getBookChaptersInRx(mBookId) |
|
||||||
// 刷新章节列表 |
|
||||||
mPageLoader.refreshChapterList() |
|
||||||
// 如果是网络小说并被标记更新的,则从网络下载目录 |
|
||||||
if (mCollBook.isUpdate && !mCollBook.isLocal) { |
|
||||||
AccountManager.getInstance().getBookArticle(mBookId) |
|
||||||
} |
|
||||||
} else { |
|
||||||
AccountManager.getInstance().getBookArticle(mBookId) |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
tv_book_name.text = mCollBook.title |
|
||||||
mCategoryAdapter = CategoryAdapter() |
|
||||||
rlv_list.adapter = mCategoryAdapter |
|
||||||
rlv_list.isFastScrollEnabled = true |
|
||||||
rlv_mark.layoutManager = LinearLayoutManager(this) |
|
||||||
mMarkAdapter = MarkAdapter(mMarks) |
|
||||||
rlv_mark.adapter = mMarkAdapter |
|
||||||
isNightMode = ReadSettingManager.getInstance().isNightMode |
|
||||||
//夜间模式按钮的状态 |
|
||||||
toggleNightMode() |
|
||||||
isFullScreen = ReadSettingManager.getInstance().isFullScreen |
|
||||||
toolbar.setNavigationOnClickListener { finish() } |
|
||||||
read_setting_sb_brightness.progress = ReadSettingManager.getInstance().brightness |
|
||||||
mPageLoader.setOnPageChangeListener( |
|
||||||
object : PageLoader.OnPageChangeListener { |
|
||||||
|
|
||||||
override fun onChapterChange(pos: Int) { |
|
||||||
var index: Int = pos |
|
||||||
if (pos >= mChapters.size) { |
|
||||||
index = mChapters.size - 1 |
|
||||||
} |
|
||||||
mCategoryAdapter.setChapter(index) |
|
||||||
mCurrentChapter = mChapters[index] |
|
||||||
currentChapter = index |
|
||||||
} |
|
||||||
|
|
||||||
override fun requestChapters(requestChapters: List<TxtChapter>) { |
|
||||||
AccountManager.getInstance().getBookArticleDetail(mBookId, requestChapters) |
|
||||||
mHandler.sendEmptyMessage(WHAT_CATEGORY) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCategoryFinish(chapters: List<TxtChapter>) { |
|
||||||
mChapters.clear() |
|
||||||
mChapters.addAll(chapters) |
|
||||||
mCategoryAdapter.refreshItems(mChapters) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPageCountChange(count: Int) {} |
|
||||||
|
|
||||||
override fun onPageChange(pos: Int) { |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
) |
|
||||||
read_pv_page.setTouchListener(object : PageView.TouchListener { |
|
||||||
override fun onTouch(): Boolean { |
|
||||||
return !hideReadMenu() |
|
||||||
} |
|
||||||
|
|
||||||
override fun center() { |
|
||||||
toggleMenu(true) |
|
||||||
} |
|
||||||
|
|
||||||
override fun prePage() {} |
|
||||||
|
|
||||||
override fun nextPage() {} |
|
||||||
|
|
||||||
override fun cancel() {} |
|
||||||
}) |
|
||||||
read_tv_category.setOnClickListener { |
|
||||||
//移动到指定位置 |
|
||||||
if (mCategoryAdapter.count > 0) { |
|
||||||
rlv_list.setSelection(mPageLoader.chapterPos) |
|
||||||
} |
|
||||||
//切换菜单 |
|
||||||
toggleMenu(true) |
|
||||||
//打开侧滑动栏 |
|
||||||
read_dl_slide.openDrawer(GravityCompat.START) |
|
||||||
} |
|
||||||
tv_light.setOnClickListener { |
|
||||||
ll_light.visibility = GONE |
|
||||||
rlReadMark.visibility = GONE |
|
||||||
if (isVisible(ll_light)) { |
|
||||||
ll_light.visibility = GONE |
|
||||||
} else { |
|
||||||
ll_light.visibility = VISIBLE |
|
||||||
} |
|
||||||
} |
|
||||||
tv_setting.setOnClickListener { |
|
||||||
ll_light.visibility = GONE |
|
||||||
rlReadMark.visibility = GONE |
|
||||||
toggleMenu(false) |
|
||||||
mSettingDialog.show() |
|
||||||
} |
|
||||||
|
|
||||||
read_setting_sb_brightness.setOnSeekBarChangeListener(object : |
|
||||||
SeekBar.OnSeekBarChangeListener { |
|
||||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun onStartTrackingTouch(seekBar: SeekBar) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun onStopTrackingTouch(seekBar: SeekBar) { |
|
||||||
val progress = seekBar.progress |
|
||||||
//设置当前 Activity 的亮度 |
|
||||||
BrightnessUtils.setBrightness(this@NovelReadActivity, progress) |
|
||||||
//存储亮度的进度条 |
|
||||||
ReadSettingManager.getInstance().brightness = progress |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
tvBookReadMode.setOnClickListener { |
|
||||||
isNightMode = !isNightMode |
|
||||||
mPageLoader.setNightMode(isNightMode) |
|
||||||
toggleNightMode() |
|
||||||
} |
|
||||||
|
|
||||||
read_tv_brief.setOnClickListener { |
|
||||||
val intent = Intent(this, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, Integer.valueOf(mBookId)) |
|
||||||
startActivity(intent) |
|
||||||
} |
|
||||||
|
|
||||||
read_tv_community.setOnClickListener { |
|
||||||
if (isVisible(read_ll_bottom_menu)) { |
|
||||||
if (isVisible(rlReadMark)) { |
|
||||||
gone(rlReadMark) |
|
||||||
} else { |
|
||||||
gone(ll_light) |
|
||||||
updateMark() |
|
||||||
visible(rlReadMark) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
tvAddMark.setOnClickListener { |
|
||||||
mMarkAdapter.edit = false |
|
||||||
if (BookRepository.getInstance().getSignById(mCurrentChapter.chapterId)) { |
|
||||||
showToast(getString(R.string.sign_exist)) |
|
||||||
return@setOnClickListener |
|
||||||
} |
|
||||||
BookRepository.getInstance().addSign(mBookId, mCurrentChapter.chapterId, mCurrentChapter.title) |
|
||||||
updateMark() |
|
||||||
} |
|
||||||
|
|
||||||
tvClear.setOnClickListener { |
|
||||||
if (mMarkAdapter.edit) { |
|
||||||
val sign = mMarkAdapter.selectList |
|
||||||
if (sign != "") { |
|
||||||
BookRepository.getInstance().deleteSign(sign) |
|
||||||
updateMark() |
|
||||||
} |
|
||||||
mMarkAdapter.edit = false |
|
||||||
} else { |
|
||||||
mMarkAdapter.edit = true |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
tv_cache.setOnClickListener { |
|
||||||
if (!isCollected) { //没有收藏 先收藏 然后弹框 |
|
||||||
//设置为已收藏 |
|
||||||
isCollected = true |
|
||||||
//设置阅读时间 |
|
||||||
mCollBook.lastRead = System.currentTimeMillis().toString() |
|
||||||
BookRepository.getInstance().saveCollBookWithAsync(mCollBook) |
|
||||||
} |
|
||||||
showDownLoadDialog() |
|
||||||
|
|
||||||
} |
|
||||||
rlv_list.setOnItemClickListener { _, _, position, _ -> |
|
||||||
read_dl_slide.closeDrawer(GravityCompat.START) |
|
||||||
mPageLoader.skipToChapter(position) |
|
||||||
} |
|
||||||
iv_guide.setOnClickListener { |
|
||||||
iv_guide.visibility = GONE |
|
||||||
SpUtil.setBooleanValue(Constant.BookGuide, true) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private fun showDownLoadDialog() { |
|
||||||
val builder = AlertDialog.Builder(this) |
|
||||||
builder.setTitle(getString(R.string.d_cache_num)) |
|
||||||
.setItems( |
|
||||||
arrayOf( |
|
||||||
getString(R.string.d_cache_last_50), |
|
||||||
getString(R.string.d_cache_last_all), |
|
||||||
getString(R.string.d_cache_all) |
|
||||||
) |
|
||||||
) { _, which -> |
|
||||||
when (which) { |
|
||||||
0 -> { |
|
||||||
//50章 |
|
||||||
val last = currentChapter + 50 |
|
||||||
if (last > mCollBook.bookChapters.size) { |
|
||||||
downLoadCache(mCollBook.bookChapters, mCollBook.bookChapters.size) |
|
||||||
} else { |
|
||||||
downLoadCache(mCollBook.bookChapters, last) |
|
||||||
} |
|
||||||
} |
|
||||||
1 -> { |
|
||||||
//后面所有 |
|
||||||
val lastBeans = ArrayList<BookChapterBean>() |
|
||||||
for (i in currentChapter until mCollBook.bookChapters.size) { |
|
||||||
lastBeans.add(mCollBook.bookChapters[i]) |
|
||||||
} |
|
||||||
downLoadCache(lastBeans, mCollBook.bookChapters.size - currentChapter) |
|
||||||
} |
|
||||||
2 -> downLoadCache(mCollBook.bookChapters, mCollBook.bookChapters.size) //所有 |
|
||||||
else -> { |
|
||||||
} |
|
||||||
} |
|
||||||
toggleMenu(true) |
|
||||||
} |
|
||||||
builder.show() |
|
||||||
} |
|
||||||
|
|
||||||
private fun downLoadCache(beans: List<BookChapterBean>, size: Int) { |
|
||||||
val task = DownloadTaskBean() |
|
||||||
task.taskName = mCollBook.title |
|
||||||
task.bookId = mCollBook.id |
|
||||||
task.bookChapters = beans //计算要缓存的章节 |
|
||||||
task.currentChapter = currentChapter |
|
||||||
task.lastChapter = size |
|
||||||
|
|
||||||
RxBus.getInstance().post(task) |
|
||||||
startService(Intent(this, DownloadService::class.java)) |
|
||||||
} |
|
||||||
|
|
||||||
private fun toggleNightMode() { |
|
||||||
if (isNightMode) { |
|
||||||
tvBookReadMode.text = resources.getString(R.string.book_read_mode_day) |
|
||||||
val drawable = ContextCompat.getDrawable(this, R.drawable.ic_read_menu_moring) |
|
||||||
tvBookReadMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null) |
|
||||||
cl_layout.setBackgroundColor(ContextCompat.getColor(this, R.color.read_bg_night)) |
|
||||||
} else { |
|
||||||
tvBookReadMode.text = resources.getString(R.string.book_read_mode_day) |
|
||||||
val drawable = ContextCompat.getDrawable(this, R.drawable.ic_read_menu_night) |
|
||||||
tvBookReadMode.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null) |
|
||||||
cl_layout.setBackgroundColor( |
|
||||||
ContextCompat.getColor( |
|
||||||
this, |
|
||||||
ReadSettingManager.getInstance().pageStyle.bgColor |
|
||||||
) |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 隐藏阅读界面的菜单显示 |
|
||||||
* |
|
||||||
* @return 是否隐藏成功 |
|
||||||
*/ |
|
||||||
private fun hideReadMenu(): Boolean { |
|
||||||
hideSystemBar() |
|
||||||
if (read_abl_top_menu.visibility == VISIBLE) { |
|
||||||
toggleMenu(true) |
|
||||||
return true |
|
||||||
} else if (mSettingDialog.isShowing) { |
|
||||||
mSettingDialog.dismiss() |
|
||||||
return true |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
private fun showSystemBar() { |
|
||||||
//显示 |
|
||||||
SystemBarUtils.showUnStableStatusBar(this) |
|
||||||
if (isFullScreen) { |
|
||||||
SystemBarUtils.showUnStableNavBar(this) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private fun hideSystemBar() { |
|
||||||
//隐藏 |
|
||||||
SystemBarUtils.hideStableStatusBar(this) |
|
||||||
if (isFullScreen) { |
|
||||||
SystemBarUtils.hideStableNavBar(this) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 切换菜单栏的可视状态 |
|
||||||
* 默认是隐藏的 |
|
||||||
*/ |
|
||||||
private fun toggleMenu(hideStatusBar: Boolean) { |
|
||||||
initMenuAnim() |
|
||||||
gone(ll_light, rlReadMark) |
|
||||||
if (read_abl_top_menu.visibility == VISIBLE) { |
|
||||||
//关闭 |
|
||||||
read_abl_top_menu.startAnimation(mTopOutAnim) |
|
||||||
read_ll_bottom_menu.startAnimation(mBottomOutAnim) |
|
||||||
read_abl_top_menu.visibility = GONE |
|
||||||
read_ll_bottom_menu.visibility = GONE |
|
||||||
|
|
||||||
if (hideStatusBar) { |
|
||||||
hideSystemBar() |
|
||||||
} |
|
||||||
} else { |
|
||||||
read_abl_top_menu.visibility = VISIBLE |
|
||||||
read_ll_bottom_menu.visibility = VISIBLE |
|
||||||
read_abl_top_menu.startAnimation(mTopInAnim) |
|
||||||
read_ll_bottom_menu.startAnimation(mBottomInAnim) |
|
||||||
|
|
||||||
showSystemBar() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//初始化菜单动画 |
|
||||||
private fun initMenuAnim() { |
|
||||||
if (mTopInAnim != null) return |
|
||||||
mTopInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_in) |
|
||||||
mTopOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_top_out) |
|
||||||
mBottomInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_in) |
|
||||||
mBottomOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_out) |
|
||||||
//退出的速度要快 |
|
||||||
mTopOutAnim!!.duration = 200 |
|
||||||
mBottomOutAnim!!.duration = 200 |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun getBookArticle(event: BookArticleEvent) { |
|
||||||
if (event.isFail) { |
|
||||||
//获取章节失败处理 |
|
||||||
Log.e(TAG, event.er!!.msg) |
|
||||||
} else { |
|
||||||
val chapterBeans = event.result!!.chapterBean |
|
||||||
mPageLoader.collBook.bookChapters = chapterBeans |
|
||||||
mPageLoader.refreshChapterList() |
|
||||||
|
|
||||||
// 如果是目录更新的情况,那么就需要存储更新数据 |
|
||||||
if (mCollBook.isUpdate && isCollected) { |
|
||||||
BookRepository.getInstance().saveBookChaptersWithAsync(chapterBeans, mCollBook) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun finishChapter(event: FinishChapterEvent) { |
|
||||||
if (mPageLoader.pageStatus == PageLoader.STATUS_LOADING) { |
|
||||||
mHandler.sendEmptyMessage(WHAT_CHAPTER) |
|
||||||
} |
|
||||||
// 当完成章节的时候,刷新列表 |
|
||||||
mCategoryAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun errorChapter(event: ErrorChapterEvent) { |
|
||||||
if (mPageLoader.pageStatus == PageLoader.STATUS_LOADING) { |
|
||||||
mPageLoader.chapterError() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private fun updateMark() { |
|
||||||
mMarks.clear() |
|
||||||
mMarks.addAll(BookRepository.getInstance().getSign(mBookId)) |
|
||||||
mMarkAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { |
|
||||||
when (keyCode) { |
|
||||||
KeyEvent.KEYCODE_VOLUME_UP -> return mPageLoader.skipToPrePage() |
|
||||||
|
|
||||||
KeyEvent.KEYCODE_VOLUME_DOWN -> return mPageLoader.skipToNextPage() |
|
||||||
} |
|
||||||
return super.onKeyDown(keyCode, event) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBackPressed() { |
|
||||||
if (read_abl_top_menu.visibility == VISIBLE) { |
|
||||||
// 非全屏下才收缩,全屏下直接退出 |
|
||||||
if (!ReadSettingManager.getInstance().isFullScreen) { |
|
||||||
toggleMenu(true) |
|
||||||
return |
|
||||||
} |
|
||||||
} else if (mSettingDialog.isShowing) { |
|
||||||
mSettingDialog.dismiss() |
|
||||||
return |
|
||||||
} else if (read_dl_slide.isDrawerOpen(GravityCompat.START)) { |
|
||||||
read_dl_slide.closeDrawer(GravityCompat.START) |
|
||||||
return |
|
||||||
} |
|
||||||
Log.e(TAG, "onBackPressed: " + mCollBook.bookChapters.isEmpty()) |
|
||||||
|
|
||||||
if (!mCollBook.isLocal && !isCollected && mCollBook.bookChapters.isNotEmpty()) { |
|
||||||
val alertDialog = AlertDialog.Builder(this) |
|
||||||
.setTitle(getString(R.string.add_book)) |
|
||||||
.setMessage(getString(R.string.like_book)) |
|
||||||
.setPositiveButton(getString(R.string.sure)) { dialog, which -> |
|
||||||
//设置为已收藏 |
|
||||||
isCollected = true |
|
||||||
//设置阅读时间 |
|
||||||
mCollBook.lastRead = System.currentTimeMillis().toString() |
|
||||||
|
|
||||||
BookRepository.getInstance().saveCollBookWithAsync(mCollBook) |
|
||||||
|
|
||||||
exit() |
|
||||||
} |
|
||||||
.setNegativeButton(getString(R.string.cancel)) { dialog, which -> exit() }.create() |
|
||||||
alertDialog.show() |
|
||||||
} else { |
|
||||||
exit() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// 退出 |
|
||||||
private fun exit() { |
|
||||||
// 返回给BookDetail。 |
|
||||||
val result = Intent() |
|
||||||
result.putExtra(RESULT_IS_COLLECTED, isCollected) |
|
||||||
setResult(Activity.RESULT_OK, result) |
|
||||||
super.onBackPressed() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPause() { |
|
||||||
super.onPause() |
|
||||||
if (isCollected) { |
|
||||||
mPageLoader.saveRecord() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
EventManager.instance.unregisterSubscriber(this) |
|
||||||
mPageLoader.closeBook() |
|
||||||
unbindService(mConn) |
|
||||||
unregisterReceiver(mReceiver) |
|
||||||
} |
|
||||||
|
|
||||||
private fun initService() { |
|
||||||
|
|
||||||
mConn = object : ServiceConnection { |
|
||||||
override fun onServiceConnected(name: ComponentName, service: IBinder) { |
|
||||||
mService = service as DownloadService.IDownloadManager |
|
||||||
mService!!.setOnDownloadListener(this@NovelReadActivity) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onServiceDisconnected(name: ComponentName) {} |
|
||||||
} |
|
||||||
//绑定 |
|
||||||
bindService(Intent(this, DownloadService::class.java), mConn, Service.BIND_AUTO_CREATE) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDownloadChange(pos: Int, status: Int, msg: String) { |
|
||||||
Log.e(TAG, "onDownloadChange: $pos $status $msg") |
|
||||||
|
|
||||||
if (msg == getString(R.string.download_success) || msg == getString(R.string.download_error)) { |
|
||||||
//下载成功或失败后隐藏下载视图 |
|
||||||
if (ll_download != null) { |
|
||||||
ll_download.visibility = GONE |
|
||||||
showToast(msg) |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (ll_download != null) { |
|
||||||
ll_download.visibility = VISIBLE |
|
||||||
tv_progress.text = getString( |
|
||||||
R.string.download_loading, |
|
||||||
mService!!.downloadTaskList[pos].currentChapter, |
|
||||||
mService!!.downloadTaskList[pos].lastChapter |
|
||||||
) |
|
||||||
pb_loading.max = mService!!.downloadTaskList[pos].lastChapter |
|
||||||
pb_loading.progress = mService!!.downloadTaskList[pos].currentChapter |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
override fun onDownloadResponse(pos: Int, status: Int) { |
|
||||||
Log.e(TAG, "onDownloadResponse: $pos $status") |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun onDownLoadEvent(message: DownloadMessage) { |
|
||||||
showToast(message.message) |
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
|
|
||||||
private const val TAG = "NovelReadActivity" |
|
||||||
const val EXTRA_COLL_BOOK = "extra_coll_book" |
|
||||||
const val EXTRA_IS_COLLECTED = "extra_is_collected" |
|
||||||
private const val WHAT_CATEGORY = 1 |
|
||||||
private const val WHAT_CHAPTER = 2 |
|
||||||
} |
|
||||||
} |
|
@ -1,62 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.view.View |
|
||||||
import androidx.fragment.app.Fragment |
|
||||||
import androidx.viewpager.widget.ViewPager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.adapter.ViewPageAdapter |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.fragment.BookListFragment |
|
||||||
import com.novel.read.widget.VpTabLayout |
|
||||||
import kotlinx.android.synthetic.main.activity_recommend_book_list.* |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
class NovelRecommendBookListActivity(override val layoutId: Int= R.layout.activity_recommend_book_list) : NovelBaseActivity() { |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
val fragmentList = ArrayList<Fragment>() |
|
||||||
val sex = intent.getStringExtra(Constant.Sex) |
|
||||||
val type = intent.getStringExtra(Constant.Type) |
|
||||||
when (type) { |
|
||||||
Constant.ListType.Human -> toolbar.title = getString(R.string.popular_selection) |
|
||||||
Constant.ListType.EditRecommend -> toolbar.title = getString(R.string.edit_recommend) |
|
||||||
Constant.ListType.HotSearch -> toolbar.title = getString(R.string.hot_search) |
|
||||||
} |
|
||||||
val generalFragment = BookListFragment.newInstance(type, Constant.DateTyp.General, sex) |
|
||||||
val monthFragment = BookListFragment.newInstance(type, Constant.DateTyp.Month, sex) |
|
||||||
val weekFragment = BookListFragment.newInstance(type, Constant.DateTyp.Week, sex) |
|
||||||
fragmentList.add(generalFragment) |
|
||||||
fragmentList.add(monthFragment) |
|
||||||
fragmentList.add(weekFragment) |
|
||||||
val pageAdapter = ViewPageAdapter(supportFragmentManager, fragmentList) |
|
||||||
vp_recommend_type.adapter = pageAdapter |
|
||||||
vp_recommend_type.offscreenPageLimit = 2 |
|
||||||
vp_recommend_type.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { |
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun onPageSelected(position: Int) { |
|
||||||
vp_tab.setAnim(position, vp_recommend_type) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPageScrollStateChanged(state: Int) {} |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
toolbar!!.setNavigationOnClickListener { finish() } |
|
||||||
|
|
||||||
vp_tab.setOnTabBtnClickListener(object : VpTabLayout.OnTabClickListener { |
|
||||||
override fun onTabBtnClick(var1: VpTabLayout.CommonTabBtn, var2: View) { |
|
||||||
when (var1) { |
|
||||||
VpTabLayout.CommonTabBtn.ONE -> vp_tab.setAnim(0, vp_recommend_type) |
|
||||||
VpTabLayout.CommonTabBtn.TWO -> vp_tab.setAnim(1, vp_recommend_type) |
|
||||||
VpTabLayout.CommonTabBtn.THREE -> vp_tab.setAnim(2, vp_recommend_type) |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,255 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.content.DialogInterface |
|
||||||
import android.text.Editable |
|
||||||
import android.text.TextUtils |
|
||||||
import android.text.TextWatcher |
|
||||||
import android.view.KeyEvent |
|
||||||
import android.view.View |
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import com.google.android.flexbox.AlignItems |
|
||||||
import com.google.android.flexbox.FlexDirection |
|
||||||
import com.google.android.flexbox.FlexWrap |
|
||||||
import com.google.android.flexbox.FlexboxLayoutManager |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.adapter.HistoryAdapter |
|
||||||
import com.novel.read.adapter.HotAdapter |
|
||||||
import com.novel.read.adapter.SearchAdapter |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant.COMMENT_SIZE |
|
||||||
import com.novel.read.event.HotSearchEvent |
|
||||||
import com.novel.read.event.SearchListEvent |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.inter.OnLoadMoreListener |
|
||||||
import com.novel.read.model.db.SearchListTable |
|
||||||
import com.novel.read.model.protocol.SearchResp |
|
||||||
import com.novel.read.utlis.DialogUtils |
|
||||||
import com.spreada.utils.chinese.ZHConverter |
|
||||||
import com.squareup.otto.Subscribe |
|
||||||
import kotlinx.android.synthetic.main.activity_search.* |
|
||||||
import kotlinx.android.synthetic.main.title_search.* |
|
||||||
import org.litepal.LitePal |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
class NovelSearchActivity(override val layoutId: Int= R.layout.activity_search) : NovelBaseActivity() { |
|
||||||
|
|
||||||
private val mHotList = ArrayList<String>() |
|
||||||
private lateinit var mHotAdapter: HotAdapter |
|
||||||
|
|
||||||
private var mHisList: MutableList<SearchListTable> = ArrayList() |
|
||||||
private lateinit var mHisAdapter: HistoryAdapter |
|
||||||
|
|
||||||
private val mSearchList = ArrayList<SearchResp.BookBean>() |
|
||||||
private lateinit var mSearchAdapter: SearchAdapter |
|
||||||
|
|
||||||
private var page = 1 |
|
||||||
private var loadSize: Int = 0 |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
EventManager.instance.registerSubscriber(this) |
|
||||||
|
|
||||||
val manager = FlexboxLayoutManager(this) |
|
||||||
//设置主轴排列方式 |
|
||||||
manager.flexDirection = FlexDirection.ROW |
|
||||||
//设置是否换行 |
|
||||||
manager.flexWrap = FlexWrap.WRAP |
|
||||||
manager.alignItems = AlignItems.STRETCH |
|
||||||
rlv_hot.layoutManager = manager |
|
||||||
mHotAdapter = HotAdapter(mHotList) |
|
||||||
rlv_hot.adapter = mHotAdapter |
|
||||||
|
|
||||||
mHisList = LitePal.order("saveTime desc").limit(5).find(SearchListTable::class.java) |
|
||||||
val manager2 = FlexboxLayoutManager(this) |
|
||||||
//设置主轴排列方式 |
|
||||||
manager2.flexDirection = FlexDirection.ROW |
|
||||||
//设置是否换行 |
|
||||||
manager2.flexWrap = FlexWrap.WRAP |
|
||||||
manager2.alignItems = AlignItems.STRETCH |
|
||||||
mHisAdapter = HistoryAdapter(mHisList) |
|
||||||
rlv_history.layoutManager = manager2 |
|
||||||
rlv_history.adapter = mHisAdapter |
|
||||||
|
|
||||||
rlv_search.layoutManager = LinearLayoutManager(this) |
|
||||||
mSearchAdapter = SearchAdapter(mSearchList, rlv_search) |
|
||||||
rlv_search.adapter = mSearchAdapter |
|
||||||
|
|
||||||
mSearchAdapter.setOnLoadMoreListener(object : OnLoadMoreListener { |
|
||||||
override fun onLoadMore() { |
|
||||||
if (mSearchAdapter.isLoadingMore) { |
|
||||||
|
|
||||||
} else { |
|
||||||
if (loadSize >= COMMENT_SIZE) { |
|
||||||
mSearchAdapter.isLoadingMore = true |
|
||||||
mSearchAdapter.notifyDataSetChanged() |
|
||||||
page++ |
|
||||||
getData() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
AccountManager.getInstance().getHotSearch() |
|
||||||
} |
|
||||||
|
|
||||||
private fun getData() { |
|
||||||
val str = convertCC(tv_search.text.toString().trim { it <= ' ' }) |
|
||||||
AccountManager.getInstance().getSearchBookList("", str, page) |
|
||||||
} |
|
||||||
|
|
||||||
//繁簡轉換 |
|
||||||
fun convertCC(input: String): String { |
|
||||||
return if (TextUtils.isEmpty(input) || input.isEmpty()) "" else ZHConverter.getInstance( |
|
||||||
ZHConverter.SIMPLIFIED |
|
||||||
).convert(input) |
|
||||||
} |
|
||||||
|
|
||||||
override fun initData() { |
|
||||||
//输入框 |
|
||||||
tv_search.addTextChangedListener(object : TextWatcher { |
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { |
|
||||||
if (s.toString().trim { it <= ' ' } == "") { |
|
||||||
refresh.visibility = View.GONE |
|
||||||
head_hot.visibility = View.VISIBLE |
|
||||||
head_history.visibility = View.VISIBLE |
|
||||||
rlv_hot.visibility = View.VISIBLE |
|
||||||
rlv_history.visibility = View.VISIBLE |
|
||||||
} else { |
|
||||||
refresh.visibility = View.VISIBLE |
|
||||||
head_hot.visibility = View.GONE |
|
||||||
head_history.visibility = View.GONE |
|
||||||
rlv_hot.visibility = View.GONE |
|
||||||
rlv_history.visibility = View.GONE |
|
||||||
refresh.showLoading() |
|
||||||
page = 1 |
|
||||||
getData() |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable) { |
|
||||||
|
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
//键盘的搜索 |
|
||||||
tv_search.setOnKeyListener { v, keyCode, event -> |
|
||||||
//修改回车键功能 |
|
||||||
if (keyCode == KeyEvent.KEYCODE_ENTER) { |
|
||||||
mSearchAdapter.setHolderType(true) |
|
||||||
saveKey() |
|
||||||
return@setOnKeyListener true |
|
||||||
} |
|
||||||
false |
|
||||||
} |
|
||||||
|
|
||||||
mHotAdapter.setOnItemClickListener(object :HotAdapter.OnItemClickListener{ |
|
||||||
override fun onItemClick(view: View, pos: Int) { |
|
||||||
mSearchAdapter.setHolderType(true) |
|
||||||
refresh.visibility = View.VISIBLE |
|
||||||
tv_search.setText(mHotList[pos]) |
|
||||||
saveKey() |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
mHisAdapter.setOnItemClickListener(object :HistoryAdapter.OnItemClickListener{ |
|
||||||
override fun onItemClick(view: View, pos: Int) { |
|
||||||
mSearchAdapter.setHolderType(true) |
|
||||||
refresh.visibility = View.VISIBLE |
|
||||||
tv_search.setText(mHisList[pos].key) |
|
||||||
saveKey() |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
mSearchAdapter.setOnItemClickListener(object :SearchAdapter.OnItemClickListener{ |
|
||||||
override fun onItemClick(view: View, pos: Int) { |
|
||||||
mSearchAdapter.setHolderType(true) |
|
||||||
tv_search.setText(mSearchList[pos].title) |
|
||||||
saveKey() |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
head_history.setOnClickListener { view -> |
|
||||||
|
|
||||||
DialogUtils.getInstance().showAlertDialog( |
|
||||||
this, |
|
||||||
getString(R.string.clear_search), |
|
||||||
dialogListener = DialogInterface.OnClickListener { dialog, which -> |
|
||||||
LitePal.deleteAll(SearchListTable::class.java) |
|
||||||
mHisList.clear() |
|
||||||
mHisList.addAll(LitePal.order("saveTime desc").limit(5).find(SearchListTable::class.java)) |
|
||||||
mHisAdapter.notifyDataSetChanged() |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
tv_cancel.setOnClickListener { |
|
||||||
onBackPressed() |
|
||||||
} |
|
||||||
|
|
||||||
refresh.setOnReloadingListener { getData() } |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private fun saveKey() { |
|
||||||
if (tv_search.text.toString().trim { it <= ' ' } == "") { |
|
||||||
return |
|
||||||
} |
|
||||||
val searchListTable = SearchListTable() |
|
||||||
searchListTable.key = tv_search.text.toString().trim { it <= ' ' } |
|
||||||
searchListTable.saveTime = System.currentTimeMillis() |
|
||||||
searchListTable.saveOrUpdate("key=?", tv_search.text.toString().trim { it <= ' ' }) |
|
||||||
mHisList.clear() |
|
||||||
mHisList.addAll(LitePal.order("saveTime desc").limit(5).find(SearchListTable::class.java)) |
|
||||||
mHisAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBackPressed() { |
|
||||||
if (refresh.visibility == View.VISIBLE) { |
|
||||||
tv_search.setText("") |
|
||||||
mSearchAdapter.setHolderType(false) |
|
||||||
page = 1 |
|
||||||
} else { |
|
||||||
super.onBackPressed() |
|
||||||
overridePendingTransition(R.anim.message_fade_in, R.anim.message_fade_out) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun getHotSearch(event: HotSearchEvent) { |
|
||||||
if (event.isFail) { |
|
||||||
|
|
||||||
} else { |
|
||||||
mHotList.clear() |
|
||||||
mHotList.addAll(event.result!!.key) |
|
||||||
mHotAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun getSearchList(event: SearchListEvent) { |
|
||||||
refresh.showFinish() |
|
||||||
if (event.isFail) { |
|
||||||
refresh.showError() |
|
||||||
} else { |
|
||||||
loadSize = event.result!!.book.size |
|
||||||
if (mSearchAdapter.isLoadingMore) { |
|
||||||
mSearchAdapter.isLoadingMore = false |
|
||||||
mSearchList.addAll(event.result!!.book) |
|
||||||
mSearchAdapter.notifyDataSetChanged() |
|
||||||
} else { |
|
||||||
mSearchList.clear() |
|
||||||
mSearchList.addAll(event.result!!.book) |
|
||||||
mSearchAdapter.notifyDataSetChanged() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
EventManager.instance.unregisterSubscriber(this) |
|
||||||
} |
|
||||||
} |
|
@ -1,152 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.annotation.SuppressLint |
|
||||||
import android.app.AlertDialog |
|
||||||
import android.text.TextUtils |
|
||||||
import android.view.View |
|
||||||
import com.allenliu.versionchecklib.v2.AllenVersionChecker |
|
||||||
import com.allenliu.versionchecklib.v2.builder.UIData |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.base.NovelBaseActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.event.UpdateBookEvent |
|
||||||
import com.novel.read.event.VersionEvent |
|
||||||
import com.novel.read.http.AccountManager |
|
||||||
import com.novel.read.model.protocol.VersionResp |
|
||||||
import com.novel.read.utlis.CleanCacheUtils |
|
||||||
import com.novel.read.utlis.LocalManageUtil |
|
||||||
import com.novel.read.utlis.SpUtil |
|
||||||
import com.novel.read.utlis.VersionUtil |
|
||||||
import com.squareup.otto.Subscribe |
|
||||||
import kotlinx.android.synthetic.main.activity_setting.* |
|
||||||
|
|
||||||
class NovelSettingActivity(override val layoutId: Int = R.layout.activity_setting) : NovelBaseActivity(), View.OnClickListener { |
|
||||||
|
|
||||||
private var resp: VersionResp? = null |
|
||||||
|
|
||||||
override fun initView() { |
|
||||||
EventManager.instance.registerSubscriber(this) |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n") |
|
||||||
override fun initData() { |
|
||||||
tv_language.text = |
|
||||||
resources.getStringArray(R.array.setting_dialog_language_choice)[SpUtil.getIntValue( |
|
||||||
Constant.Language, |
|
||||||
1 |
|
||||||
)] |
|
||||||
tv_version.text = "V" + VersionUtil.getPackageName(this)!! |
|
||||||
try { |
|
||||||
val cacheSize = |
|
||||||
CleanCacheUtils.getInstance().getTotalCacheSize(this@NovelSettingActivity) |
|
||||||
tv_cache_num.text = cacheSize |
|
||||||
} catch (e: Exception) { |
|
||||||
e.printStackTrace() |
|
||||||
} |
|
||||||
toolbar.setNavigationOnClickListener { finish() } |
|
||||||
AccountManager.getInstance().checkVersion(VersionUtil.getPackageCode(this)) |
|
||||||
|
|
||||||
ll_choose_language.setOnClickListener(this) |
|
||||||
ll_clear_cache.setOnClickListener(this) |
|
||||||
tv_check.setOnClickListener(this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onClick(v: View?) { |
|
||||||
when (v?.id) { |
|
||||||
R.id.ll_choose_language -> showLanguageDialog() |
|
||||||
R.id.ll_clear_cache -> { |
|
||||||
//默认不勾选清空书架列表,防手抖!! |
|
||||||
val selected = booleanArrayOf(true, false) |
|
||||||
AlertDialog.Builder(this) |
|
||||||
.setTitle(getString(R.string.clear_cache)) |
|
||||||
.setCancelable(true) |
|
||||||
.setMultiChoiceItems(arrayOf(getString(R.string.clear_cache), getString(R.string.clear_book)), selected) { _, which, isChecked -> selected[which] = isChecked } |
|
||||||
.setPositiveButton(getString(R.string.sure)) { dialog, _ -> |
|
||||||
Thread { |
|
||||||
CleanCacheUtils.getInstance() |
|
||||||
.clearCache(selected[0], selected[1], this@NovelSettingActivity) |
|
||||||
var cacheSize = "" |
|
||||||
try { |
|
||||||
cacheSize = |
|
||||||
CleanCacheUtils.getInstance() |
|
||||||
.getTotalCacheSize(this@NovelSettingActivity) |
|
||||||
} catch (e: Exception) { |
|
||||||
e.printStackTrace() |
|
||||||
} |
|
||||||
val finalCacheSize = cacheSize |
|
||||||
runOnUiThread { |
|
||||||
EventManager.instance.postEvent(UpdateBookEvent()) |
|
||||||
tv_cache_num.text = finalCacheSize |
|
||||||
} |
|
||||||
}.start() |
|
||||||
dialog.dismiss() |
|
||||||
} |
|
||||||
.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> dialog.dismiss() } |
|
||||||
.create().show() |
|
||||||
} |
|
||||||
R.id.tv_check -> |
|
||||||
//版本大小不为空 去更新。 |
|
||||||
updateApk(resp!!) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private fun showLanguageDialog() { |
|
||||||
AlertDialog.Builder(this) |
|
||||||
.setTitle(getString(R.string.choose_language)) |
|
||||||
.setSingleChoiceItems( |
|
||||||
resources.getStringArray(R.array.setting_dialog_language_choice), |
|
||||||
SpUtil.getIntValue(Constant.Language, 1) |
|
||||||
) { dialog, which -> |
|
||||||
val language = |
|
||||||
resources.getStringArray(R.array.setting_dialog_language_choice)[which] |
|
||||||
tv_language.text = language |
|
||||||
SpUtil.setIntValue(Constant.Language, which) |
|
||||||
dialog.dismiss() |
|
||||||
|
|
||||||
if (which == 0) { |
|
||||||
selectLanguage(0) |
|
||||||
} else { |
|
||||||
selectLanguage(1) |
|
||||||
} |
|
||||||
} |
|
||||||
.create().show() |
|
||||||
} |
|
||||||
|
|
||||||
private fun selectLanguage(select: Int) { |
|
||||||
LocalManageUtil.saveSelectLanguage(this, select) |
|
||||||
NovelMainActivity.reStart(this) |
|
||||||
} |
|
||||||
|
|
||||||
@Subscribe |
|
||||||
fun checkVersion(event: VersionEvent) { |
|
||||||
if (event.isFail) { |
|
||||||
|
|
||||||
} else { |
|
||||||
if (TextUtils.isEmpty(event.result!!.version.size)) { |
|
||||||
return |
|
||||||
} |
|
||||||
resp = event.result |
|
||||||
tv_check.visibility = View.VISIBLE |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private fun updateApk(resp: VersionResp) { |
|
||||||
val versionBean = resp.version |
|
||||||
val builder = AllenVersionChecker |
|
||||||
.getInstance() |
|
||||||
.downloadOnly( |
|
||||||
UIData.create() |
|
||||||
.setTitle(getString(R.string.new_version, versionBean.version)) |
|
||||||
.setContent(versionBean.content) |
|
||||||
.setDownloadUrl(versionBean.download) |
|
||||||
) |
|
||||||
builder.executeMission(this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
EventManager.instance.unregisterSubscriber(this) |
|
||||||
} |
|
||||||
} |
|
@ -1,69 +0,0 @@ |
|||||||
package com.novel.read.activity |
|
||||||
|
|
||||||
import android.content.Intent |
|
||||||
import android.os.Bundle |
|
||||||
import androidx.appcompat.app.AppCompatActivity |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.utlis.PermissionUtil |
|
||||||
import com.novel.read.utlis.StatusBarUtil |
|
||||||
import kotlinx.android.synthetic.main.activity_splash.* |
|
||||||
|
|
||||||
class NovelSplashActivity : AppCompatActivity(), PermissionUtil.PermissionCallBack { |
|
||||||
|
|
||||||
private var flag = false |
|
||||||
private var runnable: Runnable? = null |
|
||||||
|
|
||||||
private var mPermissionUtil: PermissionUtil = PermissionUtil.getInstance() |
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) { |
|
||||||
super.onCreate(savedInstanceState) |
|
||||||
StatusBarUtil.setBarsStyle(this, R.color.colorPrimary, true) |
|
||||||
setContentView(R.layout.activity_splash) |
|
||||||
mPermissionUtil.requestPermissions(this, PERMISSION_CODE, this) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onRequestPermissionsResult( |
|
||||||
requestCode: Int, |
|
||||||
permissions: Array<String>, |
|
||||||
grantResults: IntArray |
|
||||||
) { |
|
||||||
mPermissionUtil.requestResult(this, permissions, grantResults, this) |
|
||||||
} |
|
||||||
|
|
||||||
private fun init() { |
|
||||||
runnable = Runnable { goHome() } |
|
||||||
tvSkip.postDelayed(runnable, 2000) |
|
||||||
tvSkip.setOnClickListener { goHome() } |
|
||||||
} |
|
||||||
|
|
||||||
@Synchronized |
|
||||||
private fun goHome() { |
|
||||||
if (!flag) { |
|
||||||
flag = true |
|
||||||
startActivity(Intent(this, NovelMainActivity::class.java)) |
|
||||||
finish() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
flag = true |
|
||||||
tvSkip.removeCallbacks(runnable) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPermissionSuccess() { |
|
||||||
init() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPermissionReject(strMessage: String) { |
|
||||||
finish() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onPermissionFail() { |
|
||||||
mPermissionUtil.requestPermissions(this, PERMISSION_CODE, this) |
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
private val PERMISSION_CODE = 999 |
|
||||||
} |
|
||||||
} |
|
@ -1,163 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.Button |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelReadActivity |
|
||||||
import com.novel.read.model.db.CollBookBean |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
|
|
||||||
import java.util.ArrayList |
|
||||||
|
|
||||||
class BookAdapter(private val mList: List<CollBookBean>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
private lateinit var mContext: Context |
|
||||||
|
|
||||||
private var mClickListener: OnItemClickListener? = null |
|
||||||
private var mEdit: Boolean = false |
|
||||||
|
|
||||||
val selectList: List<CollBookBean> |
|
||||||
get() { |
|
||||||
val collBookBeans = ArrayList<CollBookBean>() |
|
||||||
for (i in mList.indices) { |
|
||||||
if (mList[i].isSelect) { |
|
||||||
collBookBeans.add(mList[i]) |
|
||||||
} |
|
||||||
} |
|
||||||
return collBookBeans |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecyclerView.ViewHolder { |
|
||||||
mContext = viewGroup.context |
|
||||||
val view: View |
|
||||||
if (i == VALUE_ITEM) { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.rlv_item_book, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} else if (i == EMPTY_ITEM) { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.rlv_empty_add_book, viewGroup, false) |
|
||||||
return EmptyHolder(view) |
|
||||||
} |
|
||||||
throw IllegalArgumentException() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
if (viewHolder is ViewHolder) { |
|
||||||
if (mEdit) { //编辑模式 |
|
||||||
viewHolder.mIvCheck.isSelected = mList[i].isSelect |
|
||||||
viewHolder.mIvCheck.visibility = View.VISIBLE |
|
||||||
viewHolder.mTvBookName.text = mList[i].title |
|
||||||
viewHolder.mTvBookAuthor.text = mList[i].author |
|
||||||
if (mList[i].isUpdate) { |
|
||||||
viewHolder.mIvGeng.visibility = View.VISIBLE |
|
||||||
} else { |
|
||||||
viewHolder.mIvGeng.visibility = View.GONE |
|
||||||
} |
|
||||||
GlideImageLoader.displayCornerImage(mContext, mList[i].cover, viewHolder.mIvBook) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
viewHolder.mIvCheck.isSelected = !mList[i].isSelect |
|
||||||
mList[i].isSelect = !mList[i].isSelect |
|
||||||
} |
|
||||||
} else { //正常模式 |
|
||||||
viewHolder.mIvCheck.visibility = View.GONE |
|
||||||
if (mList.size == i) { //最后的条目 |
|
||||||
viewHolder.mTvBookName.text = "" |
|
||||||
viewHolder.mTvBookAuthor.text = "" |
|
||||||
viewHolder.mIvBook.setImageResource(R.drawable.ic_book_add) |
|
||||||
viewHolder.mIvGeng.visibility = View.GONE |
|
||||||
viewHolder.itemView.setOnClickListener { view -> |
|
||||||
mClickListener!!.onItemClick( |
|
||||||
view, |
|
||||||
i |
|
||||||
) |
|
||||||
} |
|
||||||
} else { |
|
||||||
viewHolder.mTvBookName.text = mList[i].title |
|
||||||
viewHolder.mTvBookAuthor.text = mList[i].author |
|
||||||
if (mList[i].isUpdate) { |
|
||||||
viewHolder.mIvGeng.visibility = View.VISIBLE |
|
||||||
} else { |
|
||||||
viewHolder.mIvGeng.visibility = View.GONE |
|
||||||
} |
|
||||||
GlideImageLoader.displayCornerImage( |
|
||||||
mContext, |
|
||||||
mList[i].cover, |
|
||||||
viewHolder.mIvBook |
|
||||||
) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelReadActivity::class.java) |
|
||||||
intent.putExtra(NovelReadActivity.EXTRA_IS_COLLECTED, true) |
|
||||||
intent.putExtra(NovelReadActivity.EXTRA_COLL_BOOK, mList[i]) |
|
||||||
mContext.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} else if (viewHolder is EmptyHolder) { //空条目 |
|
||||||
viewHolder.mBtnAdd.setOnClickListener { view -> mClickListener!!.onItemClick(view, i) } |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
if (mList.isEmpty()) { |
|
||||||
return 1 |
|
||||||
} |
|
||||||
return if (mEdit) { |
|
||||||
mList.size |
|
||||||
} else { |
|
||||||
mList.size + 1 |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int { |
|
||||||
return if (mList.isEmpty()) { |
|
||||||
EMPTY_ITEM |
|
||||||
} else { |
|
||||||
VALUE_ITEM |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mIvBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var mTvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var mTvBookAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
var mIvCheck: ImageView = itemView.findViewById(R.id.iv_check) |
|
||||||
var mIvGeng: ImageView = itemView.findViewById(R.id.iv_geng) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
internal class EmptyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mBtnAdd: Button = itemView.findViewById(R.id.btn_add) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
fun setOnItemClickListener(mListener: OnItemClickListener) { |
|
||||||
this.mClickListener = mListener |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
interface OnItemClickListener { |
|
||||||
fun onItemClick(view: View, pos: Int) |
|
||||||
} |
|
||||||
|
|
||||||
fun setEdit(edit: Boolean) { //开启编辑模式 |
|
||||||
mEdit = edit |
|
||||||
notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
companion object { |
|
||||||
|
|
||||||
private const val VALUE_ITEM = 100 //正常item |
|
||||||
|
|
||||||
private const val EMPTY_ITEM = 101 //空白item |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,126 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.adapter.holder.EmptyHolder |
|
||||||
import com.novel.read.adapter.holder.MoreHolder |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.constants.Constant.COMMENT_SIZE |
|
||||||
import com.novel.read.inter.OnLoadMoreListener |
|
||||||
import com.novel.read.model.protocol.SearchResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
|
|
||||||
class BookListAdapter(private val mList: List<SearchResp.BookBean>, recyclerView: RecyclerView) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
private var mContext: Context? = null |
|
||||||
|
|
||||||
var isLoadingMore: Boolean = false |
|
||||||
private var lastVisibleItem: Int = 0 |
|
||||||
private var totalItemCount: Int = 0 |
|
||||||
private val visibleThreshold = 1 |
|
||||||
private var mOnLoadMoreListener: OnLoadMoreListener? = null |
|
||||||
|
|
||||||
init { |
|
||||||
if (recyclerView.layoutManager is LinearLayoutManager) { |
|
||||||
val manager = recyclerView.layoutManager as LinearLayoutManager? |
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { |
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { |
|
||||||
super.onScrolled(recyclerView, dx, dy) |
|
||||||
totalItemCount = manager!!.itemCount |
|
||||||
lastVisibleItem = manager.findLastVisibleItemPosition() |
|
||||||
if (!isLoadingMore && totalItemCount == lastVisibleItem + visibleThreshold && totalItemCount >= COMMENT_SIZE) { |
|
||||||
if (mOnLoadMoreListener != null) { |
|
||||||
mOnLoadMoreListener!!.onLoadMore() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fun setOnLoadMoreListener(listener: OnLoadMoreListener) { |
|
||||||
this.mOnLoadMoreListener = listener |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view: View |
|
||||||
return when (viewType) { |
|
||||||
VALUE_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.rlv_item_book_list, viewGroup, false) |
|
||||||
ViewHolder(view) |
|
||||||
} |
|
||||||
EMPTY_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.rlv_empty_view, viewGroup, false) |
|
||||||
EmptyHolder(view) |
|
||||||
} |
|
||||||
PROCESS_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.load_more_layout, viewGroup, false) |
|
||||||
MoreHolder(view) |
|
||||||
} |
|
||||||
else -> throw IllegalArgumentException() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
if (viewHolder is ViewHolder) { |
|
||||||
val bookBean = mList[i] |
|
||||||
viewHolder.tvBookName.text = bookBean.title |
|
||||||
viewHolder.tvBookAuthor.text = bookBean.author |
|
||||||
viewHolder.tvBookDescription.text = bookBean.description |
|
||||||
GlideImageLoader.displayCornerImage(mContext!!, bookBean.cover!!, viewHolder.ivBook) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, bookBean.id) |
|
||||||
mContext!!.startActivity(intent) |
|
||||||
} |
|
||||||
}else if (viewHolder is MoreHolder){ |
|
||||||
viewHolder.bindModule(isLoadingMore) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return if (mList.isEmpty()) { |
|
||||||
1 |
|
||||||
} else mList.size + 1 |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int { |
|
||||||
if (mList.isNotEmpty() &&position == itemCount - 1) { |
|
||||||
return PROCESS_ITEM |
|
||||||
} |
|
||||||
return when { |
|
||||||
mList.isEmpty() -> EMPTY_ITEM |
|
||||||
else -> VALUE_ITEM |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var ivBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var tvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var tvBookAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
var tvBookDescription: TextView = itemView.findViewById(R.id.tv_book_description) |
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
|
|
||||||
private const val VALUE_ITEM = 100 //正常item |
|
||||||
|
|
||||||
private const val EMPTY_ITEM = 101 //空白item |
|
||||||
|
|
||||||
private const val PROCESS_ITEM = 102 |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,34 +0,0 @@ |
|||||||
package com.novel.read.adapter; |
|
||||||
|
|
||||||
import android.view.View; |
|
||||||
import android.view.ViewGroup; |
|
||||||
|
|
||||||
import com.novel.read.adapter.holder.CategoryHolder; |
|
||||||
import com.novel.read.widget.page.TxtChapter; |
|
||||||
|
|
||||||
public class CategoryAdapter extends EasyAdapter<TxtChapter> { |
|
||||||
private int currentSelected = 0; |
|
||||||
|
|
||||||
@Override |
|
||||||
public View getView(int position, View convertView, ViewGroup parent) { |
|
||||||
View view = super.getView(position, convertView, parent); |
|
||||||
CategoryHolder holder = (CategoryHolder) view.getTag(); |
|
||||||
|
|
||||||
if (position == currentSelected){ |
|
||||||
holder.setSelectedChapter(); |
|
||||||
} |
|
||||||
|
|
||||||
return view; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected IViewHolder<TxtChapter> onCreateViewHolder(int viewType) { |
|
||||||
return new CategoryHolder(); |
|
||||||
} |
|
||||||
|
|
||||||
public void setChapter(int pos){ |
|
||||||
currentSelected = pos; |
|
||||||
notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,87 +0,0 @@ |
|||||||
package com.novel.read.adapter; |
|
||||||
|
|
||||||
import android.view.View; |
|
||||||
import android.view.ViewGroup; |
|
||||||
import android.widget.BaseAdapter; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
public abstract class EasyAdapter<T> extends BaseAdapter { |
|
||||||
|
|
||||||
private List<T> mList = new ArrayList<T>(); |
|
||||||
|
|
||||||
@Override |
|
||||||
public int getCount() { |
|
||||||
return mList.size(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public T getItem(int position) { |
|
||||||
return mList.get(position); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public long getItemId(int position) { |
|
||||||
return position; |
|
||||||
} |
|
||||||
|
|
||||||
public void addItem(T value){ |
|
||||||
mList.add(value); |
|
||||||
notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
public void addItem(int index,T value){ |
|
||||||
mList.add(index, value); |
|
||||||
notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
public void addItems(List<T> values){ |
|
||||||
mList.addAll(values); |
|
||||||
notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
public void removeItem(T value){ |
|
||||||
mList.remove(value); |
|
||||||
notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
public List<T> getItems(){ |
|
||||||
return Collections.unmodifiableList(mList); |
|
||||||
} |
|
||||||
|
|
||||||
public int getItemSize(){ |
|
||||||
return mList.size(); |
|
||||||
} |
|
||||||
|
|
||||||
public void refreshItems(List<T> list){ |
|
||||||
mList.clear(); |
|
||||||
mList.addAll(list); |
|
||||||
notifyDataSetChanged(); |
|
||||||
} |
|
||||||
|
|
||||||
public void clear(){ |
|
||||||
mList.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public View getView(int position, View convertView, ViewGroup parent) { |
|
||||||
IViewHolder holder; |
|
||||||
if (convertView == null){ |
|
||||||
holder = onCreateViewHolder(getItemViewType(position)); |
|
||||||
convertView = holder.createItemView(parent); |
|
||||||
convertView.setTag(holder); |
|
||||||
//初始化
|
|
||||||
holder.initView(); |
|
||||||
} |
|
||||||
else { |
|
||||||
holder = (IViewHolder)convertView.getTag(); |
|
||||||
} |
|
||||||
//执行绑定
|
|
||||||
holder.onBind(getItem(position),position); |
|
||||||
return convertView; |
|
||||||
} |
|
||||||
|
|
||||||
protected abstract IViewHolder<T> onCreateViewHolder(int viewType); |
|
||||||
} |
|
@ -1,62 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.model.protocol.RecommendListResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
|
|
||||||
/** |
|
||||||
* create by zlj on 2019/6/19 |
|
||||||
* describe: |
|
||||||
*/ |
|
||||||
class EditRecommendAdapter(private val mList: List<RecommendListResp.ListBean>) : RecyclerView.Adapter<EditRecommendAdapter.ViewHolder>() { |
|
||||||
|
|
||||||
private var mContext: Context? = null |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view = LayoutInflater.from(mContext) |
|
||||||
.inflate(R.layout.rlv_edit_recommend_item, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { |
|
||||||
val listBean = mList[i] |
|
||||||
viewHolder.mTvBookName.text = listBean.book_title |
|
||||||
viewHolder.mTvAuthor.text = listBean.author |
|
||||||
viewHolder.mTvDescription.text = listBean.description |
|
||||||
viewHolder.mTvHumanNum.text = listBean.getHot() |
|
||||||
viewHolder.mTvLoveNum.text = listBean.getLike() |
|
||||||
GlideImageLoader.displayCornerImage(mContext!!, listBean.book_cover!!, viewHolder.mIvBook) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, listBean.book_id) |
|
||||||
mContext!!.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mIvBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var mTvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var mTvAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
var mTvDescription: TextView = itemView.findViewById(R.id.tv_book_description) |
|
||||||
var mTvHumanNum: TextView = itemView.findViewById(R.id.tv_human_num) |
|
||||||
var mTvLoveNum: TextView = itemView.findViewById(R.id.tv_love_look_num) |
|
||||||
} |
|
||||||
} |
|
@ -1,54 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.model.db.SearchListTable |
|
||||||
|
|
||||||
/** |
|
||||||
* create by zlj on 2019/6/17 |
|
||||||
* describe: |
|
||||||
*/ |
|
||||||
class HistoryAdapter(private val mList: List<SearchListTable>) : |
|
||||||
RecyclerView.Adapter<HistoryAdapter.ViewHolder>() { |
|
||||||
private var mContext: Context? = null |
|
||||||
|
|
||||||
private lateinit var mClickListener: OnItemClickListener |
|
||||||
|
|
||||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mTvLabel: TextView = itemView.findViewById(R.id.tv_label) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view = LayoutInflater.from(mContext).inflate(R.layout.item_label, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { |
|
||||||
viewHolder.mTvLabel.text = mList[i].key |
|
||||||
viewHolder.itemView.setOnClickListener { view -> mClickListener.onItemClick(view, i) } |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
fun setOnItemClickListener(mListener: OnItemClickListener) { |
|
||||||
this.mClickListener = mListener |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
interface OnItemClickListener { |
|
||||||
fun onItemClick(view: View, pos: Int) |
|
||||||
} |
|
||||||
} |
|
@ -1,54 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
|
|
||||||
/** |
|
||||||
* create by 赵利君 on 2019/6/17 |
|
||||||
* describe: |
|
||||||
*/ |
|
||||||
class HotAdapter(private val mList: List<String>) : RecyclerView.Adapter<HotAdapter.ViewHolder>() { |
|
||||||
private var mContext: Context? = null |
|
||||||
private lateinit var mClickListener: OnItemClickListener |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view = LayoutInflater.from(mContext).inflate(R.layout.item_label, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { |
|
||||||
viewHolder.mTvLabel.text = mList[i] |
|
||||||
viewHolder.mTvLabel.setBackgroundColor(Constant.tagColors[i]) |
|
||||||
viewHolder.itemView.setOnClickListener { view -> mClickListener.onItemClick(view, i) } |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return if (mList.size > 8) { |
|
||||||
8 |
|
||||||
} else mList.size |
|
||||||
} |
|
||||||
|
|
||||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mTvLabel: TextView = itemView.findViewById(R.id.tv_label) |
|
||||||
} |
|
||||||
|
|
||||||
fun setOnItemClickListener(mListener: OnItemClickListener) { |
|
||||||
this.mClickListener = mListener |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
interface OnItemClickListener { |
|
||||||
fun onItemClick(view: View, pos: Int) |
|
||||||
} |
|
||||||
} |
|
@ -1,58 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
|
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.dp2px |
|
||||||
import com.novel.read.getScreenContentWidth |
|
||||||
import com.novel.read.model.protocol.RecommendListResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
import kotlinx.android.synthetic.main.rlv_human_item.view.* |
|
||||||
|
|
||||||
/** |
|
||||||
* create by zlj on 2019/6/19 |
|
||||||
* describe: |
|
||||||
*/ |
|
||||||
class HumanAdapter(private val mList: List<RecommendListResp.ListBean>) : RecyclerView.Adapter<HumanAdapter.ViewHolder>() { |
|
||||||
private lateinit var mContext: Context |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder { |
|
||||||
mContext = viewGroup.context |
|
||||||
val view = LayoutInflater.from(mContext).inflate(R.layout.rlv_human_item, viewGroup, false) |
|
||||||
val ivSize = (mContext.getScreenContentWidth() - mContext.dp2px(10) * 4) / 3 |
|
||||||
view.cl_layout.layoutParams.width = ivSize |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { |
|
||||||
viewHolder.mTvBookName.text = mList[i].book_title |
|
||||||
viewHolder.mTvAuthor.text = mList[i].author |
|
||||||
GlideImageLoader.displayCornerImage(mContext, mList[i].book_cover!!, viewHolder.mIvBook) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, mList[i].book_id) |
|
||||||
mContext.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mIvBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var mTvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var mTvAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,15 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by zlj |
|
||||||
*/ |
|
||||||
|
|
||||||
interface IViewHolder<T> { |
|
||||||
fun createItemView(parent: ViewGroup): View |
|
||||||
fun initView() |
|
||||||
fun onBind(data: T, pos: Int) |
|
||||||
fun onClick() |
|
||||||
} |
|
@ -1,59 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.model.protocol.RecommendBookResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
|
|
||||||
/** |
|
||||||
* 猜你喜欢adapter |
|
||||||
*/ |
|
||||||
class LoveLyAdapter(private val mList: List<RecommendBookResp.BookBean>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
|
|
||||||
private var mContext: Context? = null |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecyclerView.ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view: View = LayoutInflater.from(mContext).inflate(R.layout.rlv_item_lovely, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
if (viewHolder is ViewHolder) { |
|
||||||
val bookBean = mList[i] |
|
||||||
GlideImageLoader.displayCornerImage(mContext!!, bookBean.cover!!, viewHolder.mIvBook) |
|
||||||
viewHolder.mTvBookName.text = bookBean.title |
|
||||||
viewHolder.mTvBookAuthor.text = |
|
||||||
mContext!!.getString(R.string.author_zhu, bookBean.author) |
|
||||||
viewHolder.mTvDescription.text = bookBean.description |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, bookBean.id) |
|
||||||
mContext!!.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mIvBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var mTvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var mTvBookAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
var mTvDescription: TextView = itemView.findViewById(R.id.tv_book_description) |
|
||||||
} |
|
||||||
} |
|
@ -1,71 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.CheckBox |
|
||||||
import android.widget.CompoundButton |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.model.db.BookSignTable |
|
||||||
import com.novel.read.model.protocol.MarkResp |
|
||||||
|
|
||||||
class MarkAdapter(private val mList: List<BookSignTable>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
|
|
||||||
private var mContext: Context? = null |
|
||||||
var edit: Boolean = false |
|
||||||
set(edit) { |
|
||||||
field = edit |
|
||||||
notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
val selectList: String |
|
||||||
get() { |
|
||||||
val signs = StringBuilder() |
|
||||||
for (i in mList.indices) { |
|
||||||
if (mList[i].edit) { |
|
||||||
if (signs.toString() == "") { |
|
||||||
signs.append(mList[i].articleId) |
|
||||||
} else { |
|
||||||
signs.append(",").append(mList[i].articleId) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return signs.toString() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecyclerView.ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view: View = LayoutInflater.from(mContext).inflate(R.layout.rlv_item_mark, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
if (viewHolder is ViewHolder) { |
|
||||||
if (this.edit) { |
|
||||||
viewHolder.mCheck.visibility = View.VISIBLE |
|
||||||
viewHolder.mCheck.setOnCheckedChangeListener { compoundButton, b -> |
|
||||||
mList[i].edit = b |
|
||||||
} |
|
||||||
} else { |
|
||||||
viewHolder.mCheck.visibility = View.GONE |
|
||||||
} |
|
||||||
viewHolder.mTvMark.text = mList[i].content |
|
||||||
viewHolder.mCheck.isChecked = mList[i].edit |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mTvMark: TextView = itemView.findViewById(R.id.tvMarkItem) |
|
||||||
var mCheck: CheckBox = itemView.findViewById(R.id.checkbox) |
|
||||||
} |
|
||||||
} |
|
@ -1,54 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.graphics.drawable.Drawable |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
import com.mango.mangolib.event.EventManager |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.widget.page.PageLoader |
|
||||||
import com.novel.read.widget.page.PageStyle |
|
||||||
|
|
||||||
class PageStyleAdapter(val mList: List<Drawable>, private val mPageLoader: PageLoader) : |
|
||||||
RecyclerView.Adapter<PageStyleAdapter.PageHolder>() { |
|
||||||
private var mContext: Context? = null |
|
||||||
private var currentChecked: Int = 0 |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): PageHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view = LayoutInflater.from(mContext).inflate(R.layout.item_read_bg, viewGroup, false) |
|
||||||
return PageHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(pageHolder: PageHolder, i: Int) { |
|
||||||
pageHolder.mReadBg.background = mList[i] |
|
||||||
pageHolder.mIvChecked.visibility = View.GONE |
|
||||||
if (currentChecked == i) { |
|
||||||
pageHolder.mIvChecked.visibility = View.VISIBLE |
|
||||||
} |
|
||||||
pageHolder.itemView.setOnClickListener { |
|
||||||
currentChecked = i |
|
||||||
notifyDataSetChanged() |
|
||||||
mPageLoader.setPageStyle(PageStyle.values()[i]) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fun setPageStyleChecked(pageStyle: PageStyle) { |
|
||||||
currentChecked = pageStyle.ordinal |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
class PageHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
val mReadBg: View = itemView.findViewById(R.id.read_bg_view) |
|
||||||
val mIvChecked: ImageView = itemView.findViewById(R.id.read_bg_iv_checked) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,59 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
|
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.dp2px |
|
||||||
import com.novel.read.getScreenContentWidth |
|
||||||
import com.novel.read.model.protocol.RecommendListResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
import kotlinx.android.synthetic.main.rlv_human_item.view.* |
|
||||||
|
|
||||||
/** |
|
||||||
* create by zlj on 2019/6/20 |
|
||||||
* describe: |
|
||||||
*/ |
|
||||||
class RankAdapter(private val mList: List<RecommendListResp.ListBean>) : |
|
||||||
RecyclerView.Adapter<RankAdapter.ViewHolder>() { |
|
||||||
private lateinit var mContext: Context |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): ViewHolder { |
|
||||||
mContext = viewGroup.context |
|
||||||
val view = LayoutInflater.from(mContext).inflate(R.layout.rlv_human_item, viewGroup, false) |
|
||||||
val ivSize = (mContext.getScreenContentWidth() - mContext.dp2px(10) * 4) / 3 |
|
||||||
view.cl_layout.layoutParams.width = ivSize |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { |
|
||||||
viewHolder.mTvBookName.text = mList[i].book_title |
|
||||||
viewHolder.mTvAuthor.text = mList[i].author |
|
||||||
GlideImageLoader.displayCornerImage(mContext, mList[i].book_cover!!, viewHolder.mIvBook) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, mList[i].book_id) |
|
||||||
mContext.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mIvBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var mTvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var mTvAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,125 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.adapter.holder.EmptyHolder |
|
||||||
import com.novel.read.adapter.holder.MoreHolder |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.inter.OnLoadMoreListener |
|
||||||
import com.novel.read.model.protocol.RankByUpdateResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
import com.novel.read.constants.Constant.COMMENT_SIZE |
|
||||||
|
|
||||||
class RankListAdapter( val mList: List<RankByUpdateResp.BookBean>, recyclerView: RecyclerView) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
|
|
||||||
private lateinit var mContext: Context |
|
||||||
var isLoadingMore: Boolean = false |
|
||||||
private var lastVisibleItem: Int = 0 |
|
||||||
private var totalItemCount: Int = 0 |
|
||||||
private val visibleThreshold = 1 |
|
||||||
private var mOnLoadMoreListener: OnLoadMoreListener? = null |
|
||||||
|
|
||||||
init { |
|
||||||
if (recyclerView.layoutManager is LinearLayoutManager) { |
|
||||||
val manager = recyclerView.layoutManager as LinearLayoutManager? |
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { |
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { |
|
||||||
super.onScrolled(recyclerView, dx, dy) |
|
||||||
totalItemCount = manager!!.itemCount |
|
||||||
lastVisibleItem = manager.findLastVisibleItemPosition() |
|
||||||
if (!isLoadingMore && totalItemCount == lastVisibleItem + visibleThreshold && totalItemCount >= COMMENT_SIZE) { |
|
||||||
if (mOnLoadMoreListener != null) { |
|
||||||
mOnLoadMoreListener!!.onLoadMore() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fun setOnLoadMoreListener(listener: OnLoadMoreListener) { |
|
||||||
this.mOnLoadMoreListener = listener |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder { |
|
||||||
mContext = viewGroup.context |
|
||||||
|
|
||||||
val view: View |
|
||||||
when (viewType) { |
|
||||||
VALUE_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.rlv_item_book_list, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
EMPTY_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.rlv_empty_view, viewGroup, false) |
|
||||||
return EmptyHolder(view) |
|
||||||
} |
|
||||||
PROCESS_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext).inflate(R.layout.load_more_layout, viewGroup, false) |
|
||||||
return MoreHolder(view) |
|
||||||
} |
|
||||||
} |
|
||||||
throw IllegalArgumentException() |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
if (viewHolder is ViewHolder) { |
|
||||||
val bookBean = mList[i] |
|
||||||
viewHolder.tvBookName.text = bookBean.title |
|
||||||
viewHolder.tvBookAuthor.text = bookBean.author |
|
||||||
viewHolder.tvBookDescription.text = bookBean.description |
|
||||||
GlideImageLoader.displayCornerImage(mContext, bookBean.cover, viewHolder.ivBook) |
|
||||||
viewHolder.itemView.setOnClickListener { |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, bookBean.id) |
|
||||||
mContext.startActivity(intent) |
|
||||||
} |
|
||||||
}else if (viewHolder is MoreHolder){ |
|
||||||
viewHolder.bindModule(isLoadingMore) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return if (mList.isEmpty()) { |
|
||||||
1 |
|
||||||
} else mList.size + 1 |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int { |
|
||||||
if (mList.isNotEmpty() && position == itemCount - 1) { |
|
||||||
return PROCESS_ITEM |
|
||||||
} |
|
||||||
return when { |
|
||||||
mList.isEmpty() -> EMPTY_ITEM |
|
||||||
else -> VALUE_ITEM |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var ivBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var tvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var tvBookAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
var tvBookDescription: TextView = itemView.findViewById(R.id.tv_book_description) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
|
|
||||||
private const val VALUE_ITEM = 100 //正常item |
|
||||||
|
|
||||||
private const val EMPTY_ITEM = 101 //空白item |
|
||||||
|
|
||||||
private const val PROCESS_ITEM = 102 |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,173 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookDetailActivity |
|
||||||
import com.novel.read.adapter.holder.EmptyHolder |
|
||||||
import com.novel.read.adapter.holder.MoreHolder |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.constants.Constant.COMMENT_SIZE |
|
||||||
import com.novel.read.inter.OnLoadMoreListener |
|
||||||
import com.novel.read.model.protocol.SearchResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
|
|
||||||
class SearchAdapter(private val mList: List<SearchResp.BookBean>, recyclerView: RecyclerView) : |
|
||||||
RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
|
|
||||||
private var mContext: Context? = null |
|
||||||
|
|
||||||
private var book = false |
|
||||||
private var mClickListener: OnItemClickListener? = null |
|
||||||
|
|
||||||
var isLoadingMore: Boolean = false |
|
||||||
private var lastVisibleItem: Int = 0 |
|
||||||
private var totalItemCount: Int = 0 |
|
||||||
private val visibleThreshold = 1 |
|
||||||
private var mOnLoadMoreListener: OnLoadMoreListener? = null |
|
||||||
|
|
||||||
init { |
|
||||||
if (recyclerView.layoutManager is LinearLayoutManager) { |
|
||||||
val manager = recyclerView.layoutManager as LinearLayoutManager? |
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { |
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { |
|
||||||
super.onScrolled(recyclerView, dx, dy) |
|
||||||
totalItemCount = manager!!.itemCount |
|
||||||
lastVisibleItem = manager.findLastVisibleItemPosition() |
|
||||||
if (!isLoadingMore && totalItemCount == lastVisibleItem + visibleThreshold && totalItemCount >= COMMENT_SIZE) { |
|
||||||
if (mOnLoadMoreListener != null) { |
|
||||||
mOnLoadMoreListener!!.onLoadMore() |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fun setOnLoadMoreListener(listener: OnLoadMoreListener) { |
|
||||||
this.mOnLoadMoreListener = listener |
|
||||||
} |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecyclerView.ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view: View |
|
||||||
when (i) { |
|
||||||
VALUE_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext) |
|
||||||
.inflate(R.layout.rlv_item_search, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
BOOK_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext) |
|
||||||
.inflate(R.layout.rlv_item_book_list_search, viewGroup, false) |
|
||||||
return BookHolder(view) |
|
||||||
} |
|
||||||
EMPTY_ITEM -> { |
|
||||||
view = |
|
||||||
LayoutInflater.from(mContext).inflate(R.layout.rlv_empty_view, viewGroup, false) |
|
||||||
return EmptyHolder(view) |
|
||||||
} |
|
||||||
PROCESS_ITEM -> { |
|
||||||
view = LayoutInflater.from(mContext) |
|
||||||
.inflate(R.layout.load_more_layout, viewGroup, false) |
|
||||||
return MoreHolder(view) |
|
||||||
} |
|
||||||
else -> throw IllegalArgumentException() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
when (viewHolder) { |
|
||||||
is ViewHolder -> { |
|
||||||
val bookBean = mList[i] |
|
||||||
viewHolder.mTvBookName.text = bookBean.title |
|
||||||
viewHolder.itemView.setOnClickListener { view -> |
|
||||||
mClickListener!!.onItemClick(view, i) |
|
||||||
} |
|
||||||
} |
|
||||||
is BookHolder -> { |
|
||||||
val bookBean = mList[i] |
|
||||||
viewHolder.tvBookName.text = bookBean.title |
|
||||||
viewHolder.tvBookAuthor.text = bookBean.author |
|
||||||
viewHolder.tvBookDescription.text = bookBean.description |
|
||||||
GlideImageLoader.displayCornerImage(mContext!!, bookBean.cover!!, viewHolder.ivBook) |
|
||||||
viewHolder.itemView.setOnClickListener { view -> |
|
||||||
val intent = Intent(mContext, NovelBookDetailActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.BookId, bookBean.id) |
|
||||||
mContext!!.startActivity(intent) |
|
||||||
} |
|
||||||
} |
|
||||||
is MoreHolder -> viewHolder.bindModule(isLoadingMore) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return if (mList.isEmpty()) { |
|
||||||
1 |
|
||||||
} else mList.size + 1 |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int { |
|
||||||
if (mList.isNotEmpty() && position == itemCount - 1) { |
|
||||||
return PROCESS_ITEM |
|
||||||
} |
|
||||||
|
|
||||||
return if (mList.isEmpty()) { |
|
||||||
EMPTY_ITEM |
|
||||||
} else { |
|
||||||
if (book) { |
|
||||||
BOOK_ITEM |
|
||||||
} else { |
|
||||||
VALUE_ITEM |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
fun setHolderType(book: Boolean) { |
|
||||||
this.book = book |
|
||||||
notifyDataSetChanged() |
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mTvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
internal class BookHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var ivBook: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var tvBookName: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
var tvBookAuthor: TextView = itemView.findViewById(R.id.tv_book_author) |
|
||||||
var tvBookDescription: TextView = itemView.findViewById(R.id.tv_book_description) |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
fun setOnItemClickListener(mListener: OnItemClickListener) { |
|
||||||
this.mClickListener = mListener |
|
||||||
} |
|
||||||
|
|
||||||
interface OnItemClickListener { |
|
||||||
fun onItemClick(view: View, pos: Int) |
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
|
|
||||||
private const val VALUE_ITEM = 100 //正常item |
|
||||||
|
|
||||||
private const val EMPTY_ITEM = 101 //空白item |
|
||||||
|
|
||||||
private const val BOOK_ITEM = 102 //书本item |
|
||||||
|
|
||||||
private const val PROCESS_ITEM = 103 |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,61 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import android.widget.ImageView |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.activity.NovelBookTypeListActivity |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.model.protocol.CategoryTypeResp |
|
||||||
import com.novel.read.utlis.GlideImageLoader |
|
||||||
|
|
||||||
class StackAdapter(private val mList: List<CategoryTypeResp.CategoryBean>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { |
|
||||||
|
|
||||||
private var mContext: Context? = null |
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RecyclerView.ViewHolder { |
|
||||||
if (mContext == null) { |
|
||||||
mContext = viewGroup.context |
|
||||||
} |
|
||||||
val view: View = LayoutInflater.from(mContext).inflate(R.layout.rlv_item_book_type, viewGroup, false) |
|
||||||
return ViewHolder(view) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, i: Int) { |
|
||||||
if (viewHolder is ViewHolder) { |
|
||||||
|
|
||||||
var input = mList[i].title |
|
||||||
val regex = "(.{2})" |
|
||||||
input = input.replace(regex.toRegex(), "$1\n") |
|
||||||
viewHolder.mTvType.text = input |
|
||||||
viewHolder.itemView.setOnClickListener { view -> |
|
||||||
val intent = Intent(mContext, NovelBookTypeListActivity::class.java) |
|
||||||
intent.putExtra(Constant.Bundle.CategoryId, mList[i].id.toString()) |
|
||||||
intent.putExtra(Constant.Bundle.mTitle, mList[i].title) |
|
||||||
mContext!!.startActivity(intent) |
|
||||||
} |
|
||||||
GlideImageLoader.displayCornerImage( |
|
||||||
mContext!!, |
|
||||||
mList[i].cover, |
|
||||||
viewHolder.mIvType, |
|
||||||
R.drawable.ic_type_default |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
override fun getItemCount(): Int { |
|
||||||
return mList.size |
|
||||||
} |
|
||||||
|
|
||||||
internal class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
var mIvType: ImageView = itemView.findViewById(R.id.iv_book) |
|
||||||
var mTvType: TextView = itemView.findViewById(R.id.tv_book_name) |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,40 +0,0 @@ |
|||||||
package com.novel.read.adapter; |
|
||||||
|
|
||||||
import android.content.Context; |
|
||||||
import android.view.LayoutInflater; |
|
||||||
import android.view.View; |
|
||||||
import android.view.ViewGroup; |
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull; |
|
||||||
|
|
||||||
public abstract class ViewHolderImpl<T> implements IViewHolder<T> { |
|
||||||
private View view; |
|
||||||
private Context context; |
|
||||||
|
|
||||||
protected abstract int getItemLayoutId(); |
|
||||||
|
|
||||||
@NotNull |
|
||||||
@Override |
|
||||||
public View createItemView(ViewGroup parent) { |
|
||||||
view = LayoutInflater.from(parent.getContext()) |
|
||||||
.inflate(getItemLayoutId(), parent, false); |
|
||||||
context = parent.getContext(); |
|
||||||
return view; |
|
||||||
} |
|
||||||
|
|
||||||
protected <V extends View> V findById(int id){ |
|
||||||
return (V) view.findViewById(id); |
|
||||||
} |
|
||||||
|
|
||||||
protected Context getContext(){ |
|
||||||
return context; |
|
||||||
} |
|
||||||
|
|
||||||
protected View getItemView(){ |
|
||||||
return view; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onClick() { |
|
||||||
} |
|
||||||
} |
|
@ -1,22 +0,0 @@ |
|||||||
package com.novel.read.adapter |
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment |
|
||||||
import androidx.fragment.app.FragmentManager |
|
||||||
import androidx.fragment.app.FragmentPagerAdapter |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by Administrator on 2017/2/24. |
|
||||||
*/ |
|
||||||
|
|
||||||
class ViewPageAdapter(fm: FragmentManager, private val fragmentList: List<Fragment>) : |
|
||||||
FragmentPagerAdapter(fm) { |
|
||||||
|
|
||||||
override fun getItem(position: Int): Fragment { |
|
||||||
return fragmentList[position] |
|
||||||
} |
|
||||||
|
|
||||||
override fun getCount(): Int { |
|
||||||
return fragmentList.size |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,50 +0,0 @@ |
|||||||
package com.novel.read.adapter.holder; |
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable; |
|
||||||
import android.widget.TextView; |
|
||||||
|
|
||||||
import androidx.core.content.ContextCompat; |
|
||||||
|
|
||||||
import com.novel.read.R; |
|
||||||
import com.novel.read.adapter.ViewHolderImpl; |
|
||||||
import com.novel.read.model.db.dbManage.BookManager; |
|
||||||
import com.novel.read.utlis.StringUtils; |
|
||||||
import com.novel.read.widget.page.TxtChapter; |
|
||||||
|
|
||||||
public class CategoryHolder extends ViewHolderImpl<TxtChapter> { |
|
||||||
|
|
||||||
private TextView mTvChapter; |
|
||||||
|
|
||||||
@Override |
|
||||||
public void initView() { |
|
||||||
mTvChapter = findById(R.id.category_tv_chapter); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onBind(TxtChapter value, int pos){ |
|
||||||
//首先判断是否该章已下载
|
|
||||||
Drawable drawable = null; |
|
||||||
if (value.getBookId() != null && BookManager.isChapterCached(value.getBookId(),value.getTitle())){ |
|
||||||
drawable = ContextCompat.getDrawable(getContext(),R.drawable.selector_category_load); |
|
||||||
} |
|
||||||
else { |
|
||||||
drawable = ContextCompat.getDrawable(getContext(), R.drawable.selector_category_unload); |
|
||||||
} |
|
||||||
|
|
||||||
mTvChapter.setSelected(false); |
|
||||||
mTvChapter.setTextColor(ContextCompat.getColor(getContext(),R.color.colorTitle)); |
|
||||||
mTvChapter.setCompoundDrawablesWithIntrinsicBounds(drawable,null,null,null); |
|
||||||
mTvChapter.setText(StringUtils.INSTANCE.convertCC(value.getTitle())); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected int getItemLayoutId() { |
|
||||||
return R.layout.rlv_item_category; |
|
||||||
} |
|
||||||
|
|
||||||
public void setSelectedChapter(){ |
|
||||||
mTvChapter.setTextColor(ContextCompat.getColor(getContext(),R.color.light_red)); |
|
||||||
mTvChapter.setSelected(true); |
|
||||||
} |
|
||||||
} |
|
@ -1,6 +0,0 @@ |
|||||||
package com.novel.read.adapter.holder |
|
||||||
|
|
||||||
import android.view.View |
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
class EmptyHolder(itemView: View) : RecyclerView.ViewHolder(itemView) |
|
@ -1,34 +0,0 @@ |
|||||||
package com.novel.read.adapter.holder |
|
||||||
|
|
||||||
import android.view.View |
|
||||||
import android.widget.ProgressBar |
|
||||||
import android.widget.TextView |
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView |
|
||||||
|
|
||||||
import com.novel.read.R |
|
||||||
|
|
||||||
/** |
|
||||||
* @author: LiJun 390057892@qq.com |
|
||||||
* @date: 2018/4/4 9:28 |
|
||||||
*/ |
|
||||||
|
|
||||||
class MoreHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
|
||||||
|
|
||||||
private val mProgressBar: ProgressBar = itemView.findViewById(R.id.progressBar) |
|
||||||
private val mTvName: TextView = itemView.findViewById(R.id.tv_name) |
|
||||||
private val mTvEnd: TextView = itemView.findViewById(R.id.tv_end) |
|
||||||
|
|
||||||
fun bindModule(loadMore: Boolean) { |
|
||||||
if (loadMore) { |
|
||||||
mTvName.visibility = View.VISIBLE |
|
||||||
mProgressBar.visibility = View.VISIBLE |
|
||||||
mTvEnd.visibility = View.GONE |
|
||||||
} else { |
|
||||||
mTvName.visibility = View.GONE |
|
||||||
mProgressBar.visibility = View.GONE |
|
||||||
mTvEnd.visibility = View.VISIBLE |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,178 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import android.content.Context |
||||||
|
import android.content.res.Configuration |
||||||
|
import android.os.Bundle |
||||||
|
import android.util.AttributeSet |
||||||
|
import android.view.Menu |
||||||
|
import android.view.MenuItem |
||||||
|
import android.view.View |
||||||
|
import android.view.WindowManager |
||||||
|
import android.widget.FrameLayout |
||||||
|
import androidx.appcompat.app.AppCompatActivity |
||||||
|
import androidx.viewbinding.ViewBinding |
||||||
|
import com.novel.read.R |
||||||
|
import com.novel.read.constant.AppConst |
||||||
|
import com.novel.read.constant.Theme |
||||||
|
import com.novel.read.lib.* |
||||||
|
import com.novel.read.ui.widget.TitleBar |
||||||
|
import com.novel.read.utils.ColorUtils |
||||||
|
import com.novel.read.utils.LanguageUtils |
||||||
|
import com.novel.read.utils.ext.disableAutoFill |
||||||
|
import com.novel.read.utils.ext.* |
||||||
|
import kotlinx.coroutines.CoroutineScope |
||||||
|
import kotlinx.coroutines.MainScope |
||||||
|
import kotlinx.coroutines.cancel |
||||||
|
|
||||||
|
abstract class BaseActivity<VB : ViewBinding>( |
||||||
|
val fullScreen: Boolean = true, |
||||||
|
private val theme: Theme = Theme.Auto, |
||||||
|
private val toolBarTheme: Theme = Theme.Auto, |
||||||
|
private val transparent: Boolean = false |
||||||
|
) : AppCompatActivity(), |
||||||
|
CoroutineScope by MainScope() { |
||||||
|
|
||||||
|
protected val binding: VB by lazy { getViewBinding() } |
||||||
|
|
||||||
|
val isInMultiWindow: Boolean |
||||||
|
get() { |
||||||
|
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { |
||||||
|
isInMultiWindowMode |
||||||
|
} else { |
||||||
|
false |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun attachBaseContext(newBase: Context) { |
||||||
|
super.attachBaseContext(LanguageUtils.setConfiguration(newBase)) |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract fun getViewBinding(): VB |
||||||
|
|
||||||
|
override fun onCreateView( |
||||||
|
parent: View?, |
||||||
|
name: String, |
||||||
|
context: Context, |
||||||
|
attrs: AttributeSet |
||||||
|
): View? { |
||||||
|
if (AppConst.menuViewNames.contains(name) && parent?.parent is FrameLayout) { |
||||||
|
(parent.parent as View).setBackgroundColor(backgroundColor) |
||||||
|
} |
||||||
|
return super.onCreateView(parent, name, context, attrs) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) { |
||||||
|
window.decorView.disableAutoFill() |
||||||
|
initTheme() |
||||||
|
super.onCreate(savedInstanceState) |
||||||
|
setContentView(binding.root) |
||||||
|
setupSystemBar() |
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { |
||||||
|
findViewById<TitleBar>(R.id.title_bar) |
||||||
|
?.onMultiWindowModeChanged(isInMultiWindowMode, fullScreen) |
||||||
|
} |
||||||
|
onActivityCreated(savedInstanceState) |
||||||
|
observeLiveBus() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration?) { |
||||||
|
super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig) |
||||||
|
findViewById<TitleBar>(R.id.title_bar) |
||||||
|
?.onMultiWindowModeChanged(isInMultiWindowMode, fullScreen) |
||||||
|
setupSystemBar() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) { |
||||||
|
super.onConfigurationChanged(newConfig) |
||||||
|
findViewById<TitleBar>(R.id.title_bar) |
||||||
|
?.onMultiWindowModeChanged(isInMultiWindow, fullScreen) |
||||||
|
setupSystemBar() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onDestroy() { |
||||||
|
super.onDestroy() |
||||||
|
cancel() |
||||||
|
} |
||||||
|
|
||||||
|
abstract fun onActivityCreated(savedInstanceState: Bundle?) |
||||||
|
|
||||||
|
final override fun onCreateOptionsMenu(menu: Menu?): Boolean { |
||||||
|
return menu?.let { |
||||||
|
val bool = onCompatCreateOptionsMenu(it) |
||||||
|
it.applyTint(this, toolBarTheme) |
||||||
|
bool |
||||||
|
} ?: super.onCreateOptionsMenu(menu) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onMenuOpened(featureId: Int, menu: Menu): Boolean { |
||||||
|
menu.applyOpenTint(this) |
||||||
|
return super.onMenuOpened(featureId, menu) |
||||||
|
} |
||||||
|
|
||||||
|
open fun onCompatCreateOptionsMenu(menu: Menu) = super.onCreateOptionsMenu(menu) |
||||||
|
|
||||||
|
final override fun onOptionsItemSelected(item: MenuItem): Boolean { |
||||||
|
item.let { |
||||||
|
if (it.itemId == android.R.id.home) { |
||||||
|
supportFinishAfterTransition() |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
||||||
|
return onCompatOptionsItemSelected(item) |
||||||
|
} |
||||||
|
|
||||||
|
open fun onCompatOptionsItemSelected(item: MenuItem) = super.onOptionsItemSelected(item) |
||||||
|
|
||||||
|
private fun initTheme() { |
||||||
|
when (theme) { |
||||||
|
Theme.Transparent -> setTheme(R.style.AppTheme_Transparent) |
||||||
|
Theme.Dark -> { |
||||||
|
setTheme(R.style.AppTheme_Dark) |
||||||
|
ATH.applyBackgroundTint(window.decorView) |
||||||
|
} |
||||||
|
Theme.Light -> { |
||||||
|
setTheme(R.style.AppTheme_Light) |
||||||
|
ATH.applyBackgroundTint(window.decorView) |
||||||
|
} |
||||||
|
else -> { |
||||||
|
if (ColorUtils.isColorLight(primaryColor)) { |
||||||
|
setTheme(R.style.AppTheme_Light) |
||||||
|
} else { |
||||||
|
setTheme(R.style.AppTheme_Dark) |
||||||
|
} |
||||||
|
ATH.applyBackgroundTint(window.decorView) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun setupSystemBar() { |
||||||
|
if (fullScreen && !isInMultiWindow) { |
||||||
|
window.clearFlags( |
||||||
|
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS |
||||||
|
or WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
||||||
|
) |
||||||
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) |
||||||
|
window.decorView.systemUiVisibility = |
||||||
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
||||||
|
} |
||||||
|
ATH.setStatusBarColorAuto(this, fullScreen) |
||||||
|
if (toolBarTheme == Theme.Dark) { |
||||||
|
ATH.setLightStatusBar(window, false) |
||||||
|
} else if (toolBarTheme == Theme.Light) { |
||||||
|
ATH.setLightStatusBar(window, true) |
||||||
|
} |
||||||
|
upNavigationBarColor() |
||||||
|
} |
||||||
|
|
||||||
|
open fun upNavigationBarColor() { |
||||||
|
ATH.setNavigationBarColorAuto(this) |
||||||
|
} |
||||||
|
|
||||||
|
open fun observeLiveBus() { |
||||||
|
} |
||||||
|
|
||||||
|
override fun finish() { |
||||||
|
currentFocus?.hideSoftInput() |
||||||
|
super.finish() |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import android.view.LayoutInflater |
||||||
|
import android.view.View |
||||||
|
import android.view.ViewGroup |
||||||
|
import androidx.viewbinding.ViewBinding |
||||||
|
import com.chad.library.adapter.base.BaseQuickAdapter |
||||||
|
import com.chad.library.adapter.base.BaseSectionQuickAdapter |
||||||
|
import com.chad.library.adapter.base.entity.SectionEntity |
||||||
|
import com.chad.library.adapter.base.viewholder.BaseViewHolder |
||||||
|
|
||||||
|
abstract class BaseBindingAdapter<T, VB : ViewBinding>(data: MutableList<T>? = null) : |
||||||
|
BaseQuickAdapter<T, VBViewHolder<VB>>(0, data) { |
||||||
|
|
||||||
|
abstract fun createViewBinding(inflater: LayoutInflater, parent: ViewGroup): VB |
||||||
|
|
||||||
|
override fun onCreateDefViewHolder(parent: ViewGroup, viewType: Int): VBViewHolder<VB> { |
||||||
|
val viewBinding = createViewBinding(LayoutInflater.from(parent.context), parent) |
||||||
|
return VBViewHolder(viewBinding, viewBinding.root) |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
class VBViewHolder<VB : ViewBinding>(val vb: VB, view: View) : BaseViewHolder(view) |
||||||
|
|
||||||
|
|
||||||
|
@JvmName("bind") |
||||||
|
fun <VB : ViewBinding> BaseViewHolder.withBinding(bind: (View) -> VB): BaseViewHolder = |
||||||
|
BaseViewHolderWithBinding(bind(itemView)) |
||||||
|
|
||||||
|
@JvmName("getBinding") |
||||||
|
@Suppress("UNCHECKED_CAST") |
||||||
|
fun <VB : ViewBinding> BaseViewHolder.getViewBinding(): VB { |
||||||
|
if (this is BaseViewHolderWithBinding<*>) { |
||||||
|
return binding as VB |
||||||
|
} else { |
||||||
|
throw IllegalStateException("The binding could not be found.") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class BaseViewHolderWithBinding<VB : ViewBinding>(val binding: VB) : BaseViewHolder(binding.root) |
@ -0,0 +1,58 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import android.os.Bundle |
||||||
|
import android.view.View |
||||||
|
import androidx.fragment.app.DialogFragment |
||||||
|
import androidx.fragment.app.FragmentManager |
||||||
|
import com.novel.read.lib.ThemeStore |
||||||
|
import com.novel.read.help.coroutine.Coroutine |
||||||
|
import kotlinx.coroutines.CoroutineScope |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.Job |
||||||
|
import kotlin.coroutines.CoroutineContext |
||||||
|
|
||||||
|
|
||||||
|
abstract class BaseDialogFragment : DialogFragment(), CoroutineScope { |
||||||
|
override val coroutineContext: CoroutineContext |
||||||
|
get() = job + Dispatchers.Main |
||||||
|
private lateinit var job: Job |
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) { |
||||||
|
super.onCreate(savedInstanceState) |
||||||
|
job = Job() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||||
|
super.onViewCreated(view, savedInstanceState) |
||||||
|
view.setBackgroundColor(ThemeStore.backgroundColor()) |
||||||
|
onFragmentCreated(view, savedInstanceState) |
||||||
|
observeLiveBus() |
||||||
|
} |
||||||
|
|
||||||
|
abstract fun onFragmentCreated(view: View, savedInstanceState: Bundle?) |
||||||
|
|
||||||
|
override fun show(manager: FragmentManager, tag: String?) { |
||||||
|
try { |
||||||
|
//在每个add事务前增加一个remove事务,防止连续的add |
||||||
|
manager.beginTransaction().remove(this).commit() |
||||||
|
super.show(manager, tag) |
||||||
|
} catch (e: Exception) { |
||||||
|
//同一实例使用不同的tag会异常,这里捕获一下 |
||||||
|
e.printStackTrace() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onDestroy() { |
||||||
|
super.onDestroy() |
||||||
|
job.cancel() |
||||||
|
} |
||||||
|
|
||||||
|
fun <T> execute( |
||||||
|
scope: CoroutineScope = this, |
||||||
|
context: CoroutineContext = Dispatchers.IO, |
||||||
|
block: suspend CoroutineScope.() -> T |
||||||
|
) = Coroutine.async(scope, context) { block() } |
||||||
|
|
||||||
|
open fun observeLiveBus() { |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,96 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import android.content.res.Configuration |
||||||
|
import android.os.Bundle |
||||||
|
import android.view.* |
||||||
|
import androidx.appcompat.view.SupportMenuInflater |
||||||
|
import androidx.appcompat.widget.Toolbar |
||||||
|
import androidx.fragment.app.Fragment |
||||||
|
import com.novel.read.R |
||||||
|
import com.novel.read.ui.widget.TitleBar |
||||||
|
import com.novel.read.utils.ext.* |
||||||
|
import kotlinx.coroutines.CoroutineScope |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.Job |
||||||
|
import kotlin.coroutines.CoroutineContext |
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate") |
||||||
|
abstract class BaseFragment(layoutID: Int) : Fragment(layoutID), |
||||||
|
CoroutineScope { |
||||||
|
lateinit var job: Job |
||||||
|
var supportToolbar: Toolbar? = null |
||||||
|
private set |
||||||
|
|
||||||
|
val menuInflater: MenuInflater |
||||||
|
@SuppressLint("RestrictedApi") |
||||||
|
get() = SupportMenuInflater(requireContext()) |
||||||
|
|
||||||
|
override val coroutineContext: CoroutineContext |
||||||
|
get() = job + Dispatchers.Main |
||||||
|
|
||||||
|
override fun onCreateView( |
||||||
|
inflater: LayoutInflater, |
||||||
|
container: ViewGroup?, |
||||||
|
savedInstanceState: Bundle? |
||||||
|
): View? { |
||||||
|
job = Job() |
||||||
|
return super.onCreateView(inflater, container, savedInstanceState) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
||||||
|
super.onViewCreated(view, savedInstanceState) |
||||||
|
onMultiWindowModeChanged() |
||||||
|
onFragmentCreated(view, savedInstanceState) |
||||||
|
observeLiveBus() |
||||||
|
} |
||||||
|
|
||||||
|
abstract fun onFragmentCreated(view: View, savedInstanceState: Bundle?) |
||||||
|
|
||||||
|
override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean) { |
||||||
|
super.onMultiWindowModeChanged(isInMultiWindowMode) |
||||||
|
onMultiWindowModeChanged() |
||||||
|
} |
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) { |
||||||
|
super.onConfigurationChanged(newConfig) |
||||||
|
onMultiWindowModeChanged() |
||||||
|
} |
||||||
|
|
||||||
|
private fun onMultiWindowModeChanged() { |
||||||
|
(activity as? BaseActivity<*>)?.let { |
||||||
|
view?.findViewById<TitleBar>(R.id.title_bar) |
||||||
|
?.onMultiWindowModeChanged(it.isInMultiWindow, it.fullScreen) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onDestroy() { |
||||||
|
super.onDestroy() |
||||||
|
job.cancel() |
||||||
|
} |
||||||
|
|
||||||
|
fun setSupportToolbar(toolbar: Toolbar) { |
||||||
|
supportToolbar = toolbar |
||||||
|
supportToolbar?.let { |
||||||
|
it.menu.apply { |
||||||
|
onCompatCreateOptionsMenu(this) |
||||||
|
applyTint(requireContext()) |
||||||
|
} |
||||||
|
|
||||||
|
it.setOnMenuItemClickListener { item -> |
||||||
|
onCompatOptionsItemSelected(item) |
||||||
|
true |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
open fun observeLiveBus() { |
||||||
|
} |
||||||
|
|
||||||
|
open fun onCompatCreateOptionsMenu(menu: Menu) { |
||||||
|
} |
||||||
|
|
||||||
|
open fun onCompatOptionsItemSelected(item: MenuItem) { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import androidx.fragment.app.DialogFragment |
||||||
|
import androidx.preference.* |
||||||
|
import com.novel.read.ui.widget.prefs.EditTextPreferenceDialog |
||||||
|
import com.novel.read.ui.widget.prefs.ListPreferenceDialog |
||||||
|
import com.novel.read.ui.widget.prefs.MultiSelectListPreferenceDialog |
||||||
|
|
||||||
|
abstract class BasePreferenceFragment : PreferenceFragmentCompat() { |
||||||
|
|
||||||
|
private val dialogFragmentTag = "androidx.preference.PreferenceFragment.DIALOG" |
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi") |
||||||
|
override fun onDisplayPreferenceDialog(preference: Preference) { |
||||||
|
|
||||||
|
var handled = false |
||||||
|
if (callbackFragment is OnPreferenceDisplayDialogCallback) { |
||||||
|
handled = |
||||||
|
(callbackFragment as OnPreferenceDisplayDialogCallback) |
||||||
|
.onPreferenceDisplayDialog(this, preference) |
||||||
|
} |
||||||
|
if (!handled && activity is OnPreferenceDisplayDialogCallback) { |
||||||
|
handled = (activity as OnPreferenceDisplayDialogCallback) |
||||||
|
.onPreferenceDisplayDialog(this, preference) |
||||||
|
} |
||||||
|
|
||||||
|
if (handled) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
// check if dialog is already showing |
||||||
|
if (parentFragmentManager.findFragmentByTag(dialogFragmentTag) != null) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
val f: DialogFragment = when (preference) { |
||||||
|
is EditTextPreference -> { |
||||||
|
EditTextPreferenceDialog.newInstance(preference.getKey()) |
||||||
|
} |
||||||
|
is ListPreference -> { |
||||||
|
ListPreferenceDialog.newInstance(preference.getKey()) |
||||||
|
} |
||||||
|
is MultiSelectListPreference -> { |
||||||
|
MultiSelectListPreferenceDialog.newInstance(preference.getKey()) |
||||||
|
} |
||||||
|
else -> { |
||||||
|
throw IllegalArgumentException( |
||||||
|
"Cannot display dialog for an unknown Preference type: " |
||||||
|
+ preference.javaClass.simpleName |
||||||
|
+ ". Make sure to implement onPreferenceDisplayDialog() to handle " |
||||||
|
+ "displaying a custom dialog for this Preference." |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
f.setTargetFragment(this, 0) |
||||||
|
f.show(parentFragmentManager, dialogFragmentTag) |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,25 +1,26 @@ |
|||||||
package com.novel.read.base |
package com.novel.read.base |
||||||
|
|
||||||
import android.app.Service |
import android.app.Service |
||||||
|
import android.content.Intent |
||||||
|
import com.novel.read.help.coroutine.Coroutine |
||||||
|
import kotlinx.coroutines.CoroutineScope |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.MainScope |
||||||
|
import kotlinx.coroutines.cancel |
||||||
|
import kotlin.coroutines.CoroutineContext |
||||||
|
|
||||||
import io.reactivex.disposables.CompositeDisposable |
abstract class BaseService : Service(), CoroutineScope by MainScope() { |
||||||
import io.reactivex.disposables.Disposable |
|
||||||
|
|
||||||
abstract class BaseService : Service() { |
fun <T> execute( |
||||||
|
scope: CoroutineScope = this, |
||||||
|
context: CoroutineContext = Dispatchers.IO, |
||||||
|
block: suspend CoroutineScope.() -> T |
||||||
|
) = Coroutine.async(scope, context) { block() } |
||||||
|
|
||||||
private var mDisposable: CompositeDisposable? = null |
override fun onBind(intent: Intent?) = null |
||||||
|
|
||||||
protected fun addDisposable(disposable: Disposable) { |
|
||||||
if (mDisposable == null) { |
|
||||||
mDisposable = CompositeDisposable() |
|
||||||
} |
|
||||||
mDisposable!!.add(disposable) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
override fun onDestroy() { |
||||||
super.onDestroy() |
super.onDestroy() |
||||||
if (mDisposable != null) { |
cancel() |
||||||
mDisposable!!.dispose() |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
@ -0,0 +1,154 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import android.app.Application |
||||||
|
import android.content.Context |
||||||
|
import androidx.annotation.CallSuper |
||||||
|
import androidx.lifecycle.AndroidViewModel |
||||||
|
import androidx.lifecycle.viewModelScope |
||||||
|
import com.novel.read.App |
||||||
|
import com.novel.read.R |
||||||
|
import com.novel.read.network.api.ApiException |
||||||
|
import com.novel.read.help.coroutine.Coroutine |
||||||
|
import kotlinx.coroutines.* |
||||||
|
import org.jetbrains.anko.AnkoLogger |
||||||
|
import org.jetbrains.anko.toast |
||||||
|
import retrofit2.HttpException |
||||||
|
import java.net.ConnectException |
||||||
|
import java.net.SocketTimeoutException |
||||||
|
import java.net.UnknownHostException |
||||||
|
import kotlin.coroutines.CoroutineContext |
||||||
|
|
||||||
|
typealias Block<T> = suspend (CoroutineScope) -> T |
||||||
|
typealias Error = suspend (Exception) -> Unit |
||||||
|
typealias Cancel = suspend (Exception) -> Unit |
||||||
|
|
||||||
|
open class BaseViewModel(application: Application) : AndroidViewModel(application), |
||||||
|
CoroutineScope by MainScope(), |
||||||
|
AnkoLogger { |
||||||
|
|
||||||
|
val context: Context by lazy { this.getApplication<App>() } |
||||||
|
|
||||||
|
fun <T> execute( |
||||||
|
scope: CoroutineScope = this, |
||||||
|
context: CoroutineContext = Dispatchers.IO, |
||||||
|
block: suspend CoroutineScope.() -> T |
||||||
|
): Coroutine<T> { |
||||||
|
return Coroutine.async(scope, context) { block() } |
||||||
|
} |
||||||
|
|
||||||
|
fun <R> submit( |
||||||
|
scope: CoroutineScope = this, |
||||||
|
context: CoroutineContext = Dispatchers.IO, |
||||||
|
block: suspend CoroutineScope.() -> Deferred<R> |
||||||
|
): Coroutine<R> { |
||||||
|
return Coroutine.async(scope, context) { block().await() } |
||||||
|
} |
||||||
|
|
||||||
|
@CallSuper |
||||||
|
override fun onCleared() { |
||||||
|
super.onCleared() |
||||||
|
cancel() |
||||||
|
} |
||||||
|
|
||||||
|
open fun toast(message: Int) { |
||||||
|
launch { |
||||||
|
context.toast(message) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
open fun toast(message: CharSequence?) { |
||||||
|
launch { |
||||||
|
context.toast(message ?: toString()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
open fun longToast(message: Int) { |
||||||
|
launch { |
||||||
|
context.toast(message) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
open fun longToast(message: CharSequence?) { |
||||||
|
launch { |
||||||
|
context.toast(message ?: toString()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建并执行协程 |
||||||
|
* @param block 协程中执行 |
||||||
|
* @param error 错误时执行 |
||||||
|
* @param cancel 取消时只需 |
||||||
|
* @param showErrorToast 是否弹出错误吐司 |
||||||
|
* @return Job |
||||||
|
*/ |
||||||
|
protected fun launch( |
||||||
|
block: Block<Unit>, |
||||||
|
error: Error? = null, |
||||||
|
cancel: Cancel? = null, |
||||||
|
showErrorToast: Boolean = true |
||||||
|
): Job { |
||||||
|
return viewModelScope.launch { |
||||||
|
try { |
||||||
|
block.invoke(this) |
||||||
|
} catch (e: Exception) { |
||||||
|
when (e) { |
||||||
|
is CancellationException -> { |
||||||
|
cancel?.invoke(e) |
||||||
|
} |
||||||
|
else -> { |
||||||
|
onError(e, showErrorToast) |
||||||
|
error?.invoke(e) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建并执行协程 |
||||||
|
* @param block 协程中执行 |
||||||
|
* @return Deferred<T> |
||||||
|
*/ |
||||||
|
protected fun <T> async(block: Block<T>): Deferred<T> { |
||||||
|
return viewModelScope.async { block.invoke(this) } |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 取消协程 |
||||||
|
* @param job 协程job |
||||||
|
*/ |
||||||
|
protected fun cancelJob(job: Job?) { |
||||||
|
if (job != null && job.isActive && !job.isCompleted && !job.isCancelled) { |
||||||
|
job.cancel() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 统一处理错误 |
||||||
|
* @param e 异常 |
||||||
|
* @param showErrorToast 是否显示错误吐司 |
||||||
|
*/ |
||||||
|
private fun onError(e: Exception, showErrorToast: Boolean) { |
||||||
|
when (e) { |
||||||
|
is ApiException -> { |
||||||
|
when (e.code) { |
||||||
|
-1001 -> { |
||||||
|
// 登录失效,清除用户信息、清除cookie/token |
||||||
|
} |
||||||
|
// 其他api错误 |
||||||
|
-1 -> if (showErrorToast) toast(e.message) |
||||||
|
// 其他错误 |
||||||
|
else -> if (showErrorToast) toast(e.message) |
||||||
|
} |
||||||
|
} |
||||||
|
// 网络请求失败 |
||||||
|
is ConnectException, is SocketTimeoutException, is UnknownHostException, is HttpException -> |
||||||
|
if (showErrorToast) toast(R.string.network_request_failed) |
||||||
|
// 其他错误 |
||||||
|
else -> |
||||||
|
if (showErrorToast) toast(e.message ?: return) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,63 +0,0 @@ |
|||||||
package com.novel.read.base |
|
||||||
|
|
||||||
import android.app.Application |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.content.res.Configuration |
|
||||||
import android.util.Log |
|
||||||
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate |
|
||||||
|
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.service.DownloadService |
|
||||||
import com.novel.read.utlis.LocalManageUtil |
|
||||||
import com.novel.read.utlis.SpUtil |
|
||||||
|
|
||||||
|
|
||||||
import org.litepal.LitePal |
|
||||||
import kotlin.properties.Delegates |
|
||||||
|
|
||||||
/** |
|
||||||
* create by zlj on 2019/6/10 |
|
||||||
*/ |
|
||||||
class MyApp : Application() { |
|
||||||
|
|
||||||
override fun onCreate() { |
|
||||||
super.onCreate() |
|
||||||
context = applicationContext |
|
||||||
LitePal.initialize(this) |
|
||||||
setNight() |
|
||||||
LocalManageUtil.setApplicationLanguage(this) |
|
||||||
startService(Intent(context, DownloadService::class.java)) |
|
||||||
} |
|
||||||
|
|
||||||
private fun setNight() { |
|
||||||
if (SpUtil.getBooleanValue(Constant.NIGHT, false)) { |
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) |
|
||||||
} else { |
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) { |
|
||||||
SpUtil.init(base) |
|
||||||
//保存系统选择语言 |
|
||||||
LocalManageUtil.saveSystemCurrentLanguage(base) |
|
||||||
super.attachBaseContext(LocalManageUtil.setLocal(base)) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) { |
|
||||||
super.onConfigurationChanged(newConfig) |
|
||||||
//保存系统选择语言 |
|
||||||
LocalManageUtil.onConfigurationChanged(applicationContext) |
|
||||||
} |
|
||||||
|
|
||||||
companion object { |
|
||||||
var context: Context by Delegates.notNull() |
|
||||||
private set |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -1,78 +0,0 @@ |
|||||||
package com.novel.read.base |
|
||||||
|
|
||||||
import android.content.Context |
|
||||||
import android.content.Intent |
|
||||||
import android.os.Bundle |
|
||||||
import android.view.View |
|
||||||
import androidx.appcompat.app.AppCompatActivity |
|
||||||
import androidx.appcompat.app.AppCompatDelegate |
|
||||||
import com.novel.read.R |
|
||||||
import com.novel.read.constants.Constant |
|
||||||
import com.novel.read.utlis.LocalManageUtil |
|
||||||
import com.novel.read.utlis.SpUtil |
|
||||||
import com.novel.read.utlis.StatusBarUtil |
|
||||||
|
|
||||||
/** |
|
||||||
* create by 赵利君 on 2019/6/10 |
|
||||||
* describe: |
|
||||||
*/ |
|
||||||
abstract class NovelBaseActivity : AppCompatActivity() { |
|
||||||
|
|
||||||
private var mNowMode: Boolean = false |
|
||||||
|
|
||||||
protected abstract val layoutId: Int |
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) { |
|
||||||
super.onCreate(savedInstanceState) |
|
||||||
StatusBarUtil.setBarsStyle(this, R.color.colorPrimary, true) |
|
||||||
mNowMode = SpUtil.getBooleanValue(Constant.NIGHT) |
|
||||||
setContentView(layoutId) |
|
||||||
initView() |
|
||||||
initData() |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
private fun setTheme() { |
|
||||||
if (SpUtil.getBooleanValue(Constant.NIGHT) != mNowMode) { |
|
||||||
if (SpUtil.getBooleanValue(Constant.NIGHT)) { |
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) |
|
||||||
} else { |
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) |
|
||||||
} |
|
||||||
recreate() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected abstract fun initView() |
|
||||||
|
|
||||||
protected abstract fun initData() |
|
||||||
|
|
||||||
override fun onResume() { |
|
||||||
super.onResume() |
|
||||||
setTheme() |
|
||||||
} |
|
||||||
|
|
||||||
protected fun gone(vararg views: View) { |
|
||||||
if (views.isNotEmpty()) { |
|
||||||
for (view in views) { |
|
||||||
view.visibility = View.GONE |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected fun visible(vararg views: View) { |
|
||||||
if (views.isNotEmpty()) { |
|
||||||
for (view in views) { |
|
||||||
view.visibility = View.VISIBLE |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected fun isVisible(view: View): Boolean { |
|
||||||
return view.visibility == View.VISIBLE |
|
||||||
} |
|
||||||
|
|
||||||
override fun attachBaseContext(newBase: Context) { |
|
||||||
super.attachBaseContext(LocalManageUtil.setLocal(newBase)) |
|
||||||
} |
|
||||||
} |
|
@ -1,59 +0,0 @@ |
|||||||
package com.novel.read.base |
|
||||||
|
|
||||||
|
|
||||||
import android.content.Intent |
|
||||||
import android.os.Bundle |
|
||||||
|
|
||||||
import android.view.LayoutInflater |
|
||||||
import android.view.View |
|
||||||
import android.view.ViewGroup |
|
||||||
import androidx.annotation.LayoutRes |
|
||||||
import androidx.fragment.app.Fragment |
|
||||||
|
|
||||||
|
|
||||||
abstract class NovelBaseFragment : Fragment() { |
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { |
|
||||||
return inflater.inflate(getLayoutId(),null) |
|
||||||
} |
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { |
|
||||||
super.onViewCreated(view, savedInstanceState) |
|
||||||
initView() |
|
||||||
initData() |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 加载布局 |
|
||||||
*/ |
|
||||||
@LayoutRes |
|
||||||
abstract fun getLayoutId():Int |
|
||||||
|
|
||||||
abstract fun initView() |
|
||||||
|
|
||||||
abstract fun initData() |
|
||||||
|
|
||||||
fun toActivity(toClsActivity: Class<*>) { |
|
||||||
this.toActivity(toClsActivity, null as Bundle?) |
|
||||||
} |
|
||||||
|
|
||||||
fun toActivity(toClsActivity: Class<*>, bundle: Bundle?) { |
|
||||||
val intent = Intent(this.context, toClsActivity) |
|
||||||
if (bundle != null) { |
|
||||||
intent.putExtras(bundle) |
|
||||||
} |
|
||||||
|
|
||||||
this.startActivity(intent) |
|
||||||
} |
|
||||||
|
|
||||||
fun toActivityForResult(toClsActivity: Class<*>, bundle: Bundle?, requestCode: Int) { |
|
||||||
val intent = Intent(this.context, toClsActivity) |
|
||||||
if (bundle != null) { |
|
||||||
intent.putExtras(bundle) |
|
||||||
} |
|
||||||
|
|
||||||
startActivityForResult(intent, requestCode) |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,15 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel |
||||||
|
import androidx.viewbinding.ViewBinding |
||||||
|
import com.novel.read.constant.Theme |
||||||
|
|
||||||
|
abstract class VMBaseActivity<VB : ViewBinding,VM : ViewModel>( |
||||||
|
fullScreen: Boolean = true, |
||||||
|
theme: Theme = Theme.Auto, |
||||||
|
toolBarTheme: Theme = Theme.Auto |
||||||
|
) : BaseActivity<VB>(fullScreen, theme, toolBarTheme) { |
||||||
|
|
||||||
|
protected abstract val viewModel: VM |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
package com.novel.read.base |
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel |
||||||
|
|
||||||
|
abstract class VMBaseFragment<VM : ViewModel>(layoutID: Int) : BaseFragment(layoutID) { |
||||||
|
|
||||||
|
protected abstract val viewModel: VM |
||||||
|
|
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
import android.annotation.SuppressLint |
||||||
|
import android.graphics.Color |
||||||
|
import java.text.SimpleDateFormat |
||||||
|
|
||||||
|
@SuppressLint("SimpleDateFormat") |
||||||
|
object AppConst { |
||||||
|
|
||||||
|
const val APP_TAG = "TuZi" |
||||||
|
const val AppId = "20210306161" |
||||||
|
const val AppSecret = "c14f6a2b3dcah893a31b9i4f40f5cc08" |
||||||
|
|
||||||
|
const val channelIdDownload = "channel_download" |
||||||
|
const val channelIdReadAloud = "channel_read_aloud" |
||||||
|
|
||||||
|
val timeFormat: SimpleDateFormat by lazy { |
||||||
|
SimpleDateFormat("HH:mm") |
||||||
|
} |
||||||
|
|
||||||
|
val dateFormat: SimpleDateFormat by lazy { |
||||||
|
SimpleDateFormat("yyyy/MM/dd HH:mm") |
||||||
|
} |
||||||
|
|
||||||
|
val fileNameFormat: SimpleDateFormat by lazy { |
||||||
|
SimpleDateFormat("yy-MM-dd-HH-mm-ss") |
||||||
|
} |
||||||
|
|
||||||
|
val keyboardToolChars: List<String> by lazy { |
||||||
|
arrayListOf( |
||||||
|
"※", "@", "&", "|", "%", "/", ":", "[", "]", "{", "}", "<", ">", "\\", |
||||||
|
"$", "#", "!", ".", "href", "src", "textNodes", "xpath", "json", "css", |
||||||
|
"id", "class", "tag" |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
const val notificationIdRead = 1144771 |
||||||
|
const val notificationIdDownload = 1144774 |
||||||
|
|
||||||
|
|
||||||
|
const val refresh = 1 |
||||||
|
const val loading = 2 |
||||||
|
const val complete = 3 |
||||||
|
const val error = 4 |
||||||
|
const val loadMore = 5 |
||||||
|
const val loadComplete = 6 |
||||||
|
const val loadMoreFail = 7 |
||||||
|
const val noMore = 8 |
||||||
|
|
||||||
|
@kotlin.jvm.JvmField |
||||||
|
val tagColors = intArrayOf( |
||||||
|
Color.parseColor("#90C5F0"), |
||||||
|
Color.parseColor("#91CED5"), |
||||||
|
Color.parseColor("#F88F55"), |
||||||
|
Color.parseColor("#C0AFD0"), |
||||||
|
Color.parseColor("#E78F8F"), |
||||||
|
Color.parseColor("#67CCB7"), |
||||||
|
Color.parseColor("#F6BC7E"), |
||||||
|
Color.parseColor("#90C5F0"), |
||||||
|
Color.parseColor("#91CED5") |
||||||
|
) |
||||||
|
|
||||||
|
const val home = 0 |
||||||
|
const val man = 1 |
||||||
|
const val woman = 2 |
||||||
|
|
||||||
|
const val shellName = "001" |
||||||
|
|
||||||
|
val menuViewNames = arrayOf( |
||||||
|
"com.android.internal.view.menu.ListMenuItemView", |
||||||
|
"androidx.appcompat.view.menu.ListMenuItemView" |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
import java.util.regex.Pattern |
||||||
|
|
||||||
|
object AppPattern { |
||||||
|
val JS_PATTERN: Pattern = |
||||||
|
Pattern.compile("(<js>[\\w\\W]*?</js>|@js:[\\w\\W]*$)", Pattern.CASE_INSENSITIVE) |
||||||
|
val EXP_PATTERN: Pattern = Pattern.compile("\\{\\{([\\w\\W]*?)\\}\\}") |
||||||
|
val imgPattern: Pattern = |
||||||
|
Pattern.compile("<img .*?src.*?=.*?\"(.*?(?:,\\{.*\\})?)\".*?>", Pattern.CASE_INSENSITIVE) |
||||||
|
|
||||||
|
val nameRegex = Regex("\\s+作\\s*者.*") |
||||||
|
val authorRegex = Regex(".*?作\\s*?者[::]") |
||||||
|
val fileNameRegex = Regex("[\\\\/:*?\"<>|.]") |
||||||
|
val splitGroupRegex = Regex("[,;,;]") |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
object BookType { |
||||||
|
const val default = 0 // 0 文本 |
||||||
|
const val audio = 1 // 1 音频 |
||||||
|
const val local = "loc_book" |
||||||
|
const val net = "net_book" |
||||||
|
|
||||||
|
|
||||||
|
const val serial="01" |
||||||
|
const val stop="02" |
||||||
|
const val complete="03" |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
object EventBus { |
||||||
|
const val MEDIA_BUTTON = "mediaButton" |
||||||
|
const val RECREATE = "RECREATE" |
||||||
|
const val UP_BOOK = "upBookToc" |
||||||
|
const val UPDATE_BOOK = "UPDATE_BOOK" |
||||||
|
const val ALOUD_STATE = "aloud_state" |
||||||
|
const val TTS_PROGRESS = "ttsStart" |
||||||
|
const val TTS_DS = "ttsDs" |
||||||
|
const val BATTERY_CHANGED = "batteryChanged" |
||||||
|
const val TIME_CHANGED = "timeChanged" |
||||||
|
const val UP_CONFIG = "upConfig" |
||||||
|
const val OPEN_CHAPTER = "openChapter" |
||||||
|
const val AUDIO_SUB_TITLE = "audioSubTitle" |
||||||
|
const val AUDIO_STATE = "audioState" |
||||||
|
const val AUDIO_PROGRESS = "audioProgress" |
||||||
|
const val AUDIO_SIZE = "audioSize" |
||||||
|
const val AUDIO_SPEED = "audioSpeed" |
||||||
|
const val SHOW_RSS = "showRss" |
||||||
|
const val SHOW_AD = "showAd" |
||||||
|
const val WEB_SERVICE = "webService" |
||||||
|
const val UP_DOWNLOAD = "upDownload" |
||||||
|
const val SAVE_CONTENT = "saveContent" |
||||||
|
const val CHECK_SOURCE = "checkSource" |
||||||
|
const val CHECK_SOURCE_DONE = "checkSourceDone" |
||||||
|
const val REPLACE_RULE_SAVE = "replaceRuleSave" |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
object IntentAction { |
||||||
|
const val start = "start" |
||||||
|
const val play = "play" |
||||||
|
const val stop = "stop" |
||||||
|
const val resume = "resume" |
||||||
|
const val pause = "pause" |
||||||
|
const val addTimer = "addTimer" |
||||||
|
const val setTimer = "setTimer" |
||||||
|
const val prevParagraph = "prevParagraph" |
||||||
|
const val nextParagraph = "nextParagraph" |
||||||
|
const val upTtsSpeechRate = "upTtsSpeechRate" |
||||||
|
const val adjustProgress = "adjustProgress" |
||||||
|
const val adjustSpeed = "adjustSpeed" |
||||||
|
const val prev = "prev" |
||||||
|
const val next = "next" |
||||||
|
const val moveTo = "moveTo" |
||||||
|
const val init = "init" |
||||||
|
const val remove = "remove" |
||||||
|
|
||||||
|
|
||||||
|
//page skip use |
||||||
|
const val bookTypeId = "bookTypeId" |
||||||
|
const val channelName = "channelName" |
||||||
|
const val bookId = "bookId" |
||||||
|
const val rankType = "rankType" |
||||||
|
const val homeType = "homeType" |
||||||
|
|
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
object LayoutType { |
||||||
|
const val HOT = 1 |
||||||
|
const val CLICK = 2 |
||||||
|
const val RECOMMEND= 3 |
||||||
|
const val END = 4 |
||||||
|
|
||||||
|
const val BOY_HOT = 6 |
||||||
|
const val BOY_END = 7 |
||||||
|
const val BOY_SEARCH = 8 |
||||||
|
|
||||||
|
const val GIRL_HOT = 9 |
||||||
|
const val GIRL_END = 10 |
||||||
|
const val GIRL_SEARCH = 11 |
||||||
|
|
||||||
|
const val HEAD = 100 |
||||||
|
const val OTHER = 101 |
||||||
|
|
||||||
|
|
||||||
|
const val INIT_BOOK = 102 |
||||||
|
const val SEARCH_BOOK = 103 |
||||||
|
} |
@ -0,0 +1,69 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
object PreferKey { |
||||||
|
const val versionCode = "versionCode" |
||||||
|
const val language = "language" |
||||||
|
const val themeMode = "themeMode" |
||||||
|
const val hideStatusBar = "hideStatusBar" |
||||||
|
const val clickTurnPage = "clickTurnPage" |
||||||
|
const val clickAllNext = "clickAllNext" |
||||||
|
const val hideNavigationBar = "hideNavigationBar" |
||||||
|
const val precisionSearch = "precisionSearch" |
||||||
|
const val speakEngine = "speakEngine" |
||||||
|
const val readAloudByPage = "readAloudByPage" |
||||||
|
const val ttsSpeechRate = "ttsSpeechRate" |
||||||
|
const val prevKeys = "prevKeyCodes" |
||||||
|
const val nextKeys = "nextKeyCodes" |
||||||
|
const val bookshelfLayout = "bookshelfLayout" |
||||||
|
const val bookshelfSort = "bookshelfSort" |
||||||
|
const val recordLog = "recordLog" |
||||||
|
const val processText = "process_text" |
||||||
|
const val cleanCache = "cleanCache" |
||||||
|
const val saveTabPosition = "saveTabPosition" |
||||||
|
const val fontFolder = "fontFolder" |
||||||
|
const val backupPath = "backupUri" |
||||||
|
const val restoreIgnore = "restoreIgnore" |
||||||
|
const val threadCount = "threadCount" |
||||||
|
const val webPort = "webPort" |
||||||
|
const val keepLight = "keep_light" |
||||||
|
const val webService = "webService" |
||||||
|
const val webDavUrl = "web_dav_url" |
||||||
|
const val webDavAccount = "web_dav_account" |
||||||
|
const val webDavPassword = "web_dav_password" |
||||||
|
const val webDavCreateDir = "webDavCreateDir" |
||||||
|
const val webDavCacheBackup = "webDavCacheBackup" |
||||||
|
const val changeSourceLoadToc = "changeSourceLoadToc" |
||||||
|
const val changeSourceLoadInfo = "changeSourceLoadInfo" |
||||||
|
const val chineseConverterType = "chineseConverterType" |
||||||
|
const val launcherIcon = "launcherIcon" |
||||||
|
const val textSelectAble = "selectText" |
||||||
|
const val lastBackup = "lastBackup" |
||||||
|
const val shareLayout = "shareLayout" |
||||||
|
const val readStyleSelect = "readStyleSelect" |
||||||
|
const val systemTypefaces = "system_typefaces" |
||||||
|
const val readBodyToLh = "readBodyToLh" |
||||||
|
const val textFullJustify = "textFullJustify" |
||||||
|
const val textBottomJustify = "textBottomJustify" |
||||||
|
const val autoReadSpeed = "autoReadSpeed" |
||||||
|
const val barElevation = "barElevation" |
||||||
|
const val transparentStatusBar = "transparentStatusBar" |
||||||
|
const val defaultCover = "defaultCover" |
||||||
|
const val replaceEnableDefault = "replaceEnableDefault" |
||||||
|
const val showBrightnessView = "showBrightnessView" |
||||||
|
const val autoClearExpired = "autoClearExpired" |
||||||
|
|
||||||
|
const val cPrimary = "colorPrimary" |
||||||
|
const val cAccent = "colorAccent" |
||||||
|
const val cBackground = "colorBackground" |
||||||
|
const val cBBackground = "colorBottomBackground" |
||||||
|
|
||||||
|
const val cNPrimary = "colorPrimaryNight" |
||||||
|
const val cNAccent = "colorAccentNight" |
||||||
|
const val cNBackground = "colorBackgroundNight" |
||||||
|
const val cNBBackground = "colorBottomBackgroundNight" |
||||||
|
|
||||||
|
const val installCount = "installCount" |
||||||
|
const val installTime = "installTime" |
||||||
|
const val appraiseShow = "appraiseShow" |
||||||
|
|
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
object Status { |
||||||
|
const val STOP = 0 |
||||||
|
const val PLAY = 1 |
||||||
|
const val PAUSE = 3 |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.novel.read.constant |
||||||
|
|
||||||
|
import com.novel.read.help.AppConfig |
||||||
|
import com.novel.read.utils.ColorUtils |
||||||
|
|
||||||
|
|
||||||
|
enum class Theme { |
||||||
|
Dark, Light, Auto, Transparent; |
||||||
|
|
||||||
|
companion object { |
||||||
|
fun getTheme() = |
||||||
|
if (AppConfig.isNightTheme) Dark |
||||||
|
else Light |
||||||
|
|
||||||
|
fun getTheme(backgroundColor: Int) = |
||||||
|
if (ColorUtils.isColorLight(backgroundColor)) Light |
||||||
|
else Dark |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
# 存储数据用 |
||||||
|
* dao 数据操作 |
||||||
|
* entities 数据模型 |
||||||
|
* \Book 书籍信息 |
||||||
|
* \BookChapter 目录信息 |
||||||
|
* \BookGroup 书籍分组 |
||||||
|
* \Bookmark 书签 |
||||||
|
* \BookSource 书源 |
||||||
|
* \Cookie http cookie |
||||||
|
* \ReplaceRule 替换规则 |
||||||
|
* \RssArticle rss条目 |
||||||
|
* \RssReadRecord rss阅读记录 |
||||||
|
* \RssSource rss源 |
||||||
|
* \RssStar rss收藏 |
||||||
|
* \SearchBook 搜索结果 |
||||||
|
* \SearchKeyword 搜索关键字 |
||||||
|
* \TxtTocRule txt文件目录规则 |
@ -0,0 +1,50 @@ |
|||||||
|
package com.novel.read.data.db |
||||||
|
|
||||||
|
import android.content.ContentValues |
||||||
|
import com.novel.read.data.db.entity.Book |
||||||
|
import org.litepal.LitePal |
||||||
|
|
||||||
|
|
||||||
|
class BookDao { |
||||||
|
|
||||||
|
fun getAllBooks(): MutableList<Book> = LitePal.findAll(Book::class.java) |
||||||
|
|
||||||
|
fun lastReadBook(): Book = LitePal.order("durChapterTime desc").findFirst(Book::class.java) |
||||||
|
|
||||||
|
fun update(book: Book) { |
||||||
|
val values = ContentValues() |
||||||
|
values.put("authorPenname", book.authorPenname) |
||||||
|
values.put("bookName", book.bookName) |
||||||
|
values.put("bookStatus", book.bookStatus) |
||||||
|
values.put("categoryName", book.categoryName) |
||||||
|
values.put("channelName", book.channelName) |
||||||
|
values.put("cName", book.cName) |
||||||
|
values.put("coverImageUrl", book.coverImageUrl) |
||||||
|
values.put("introduction", book.introduction) |
||||||
|
values.put("keyWord", book.keyWord) |
||||||
|
values.put("lastUpdateChapterDate", book.lastUpdateChapterDate) |
||||||
|
values.put("status", book.status) |
||||||
|
values.put("wordCount", book.wordCount) |
||||||
|
values.put("durChapterTime", book.durChapterTime) |
||||||
|
values.put("durChapterIndex", book.durChapterIndex) |
||||||
|
values.put("durChapterPos", book.durChapterPos) |
||||||
|
values.put("durChapterTitle", book.durChapterTitle) |
||||||
|
values.put("totalChapterNum", book.totalChapterNum) |
||||||
|
LitePal.updateAll(Book::class.java, values, "bookId=?", book.bookId.toString()) |
||||||
|
} |
||||||
|
|
||||||
|
fun getBook(bookId: String): Book? = |
||||||
|
LitePal.where("bookId=?", bookId).findFirst(Book::class.java) |
||||||
|
|
||||||
|
fun insert(book: Book) = book.saveOrUpdate("bookId=?", book.bookId.toString()) |
||||||
|
|
||||||
|
fun delete(book: Book): Int = |
||||||
|
LitePal.deleteAll(Book::class.java, "bookId=?", book.bookId.toString()) |
||||||
|
|
||||||
|
fun saveBook(book: List<Book>?) { |
||||||
|
if (book != null && book.isNotEmpty()) { |
||||||
|
LitePal.saveAll(book) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package com.novel.read.data.db |
||||||
|
|
||||||
|
class BookDatabase private constructor() { |
||||||
|
|
||||||
|
companion object { |
||||||
|
private var instance: BookDatabase? = null |
||||||
|
get() { |
||||||
|
if (field == null) { |
||||||
|
field = BookDatabase() |
||||||
|
} |
||||||
|
return field |
||||||
|
} |
||||||
|
|
||||||
|
fun get(): BookDatabase { |
||||||
|
return instance!! |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private var chapterDao: ChapterDao? = null |
||||||
|
private var bookDao: BookDao? = null |
||||||
|
private var readRecordDao: ReadRecordDao? = null |
||||||
|
private var bookMarkDao: BookMarkDao? = null |
||||||
|
private var searchHistoryDao: SearchHistoryDao? = null |
||||||
|
|
||||||
|
fun getChapterDao(): ChapterDao { |
||||||
|
if (chapterDao == null) { |
||||||
|
chapterDao = ChapterDao() |
||||||
|
} |
||||||
|
return chapterDao!! |
||||||
|
} |
||||||
|
|
||||||
|
fun getBookDao(): BookDao { |
||||||
|
if (bookDao == null) { |
||||||
|
bookDao = BookDao() |
||||||
|
} |
||||||
|
return bookDao!! |
||||||
|
} |
||||||
|
|
||||||
|
fun getReadRecordDao(): ReadRecordDao { |
||||||
|
if (readRecordDao == null) { |
||||||
|
readRecordDao = ReadRecordDao() |
||||||
|
} |
||||||
|
return readRecordDao!! |
||||||
|
} |
||||||
|
|
||||||
|
fun getBookMarkDao(): BookMarkDao { |
||||||
|
if (bookMarkDao == null) { |
||||||
|
bookMarkDao = BookMarkDao() |
||||||
|
} |
||||||
|
return bookMarkDao!! |
||||||
|
} |
||||||
|
|
||||||
|
fun getSearchDao(): SearchHistoryDao { |
||||||
|
if (searchHistoryDao == null) { |
||||||
|
searchHistoryDao = SearchHistoryDao() |
||||||
|
} |
||||||
|
return searchHistoryDao!! |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
package com.novel.read.data.db |
||||||
|
|
||||||
|
import com.novel.read.data.db.entity.Bookmark |
||||||
|
import org.litepal.LitePal |
||||||
|
|
||||||
|
class BookMarkDao { |
||||||
|
|
||||||
|
fun observeByBook(bookId: Long): List<Bookmark>? = |
||||||
|
LitePal.where("bookId=?", bookId.toString()).find(Bookmark::class.java) |
||||||
|
|
||||||
|
fun liveDataSearch(bookId: String, key: String): List<Bookmark>? = |
||||||
|
LitePal.where( |
||||||
|
"bookId=? and (chapterName like ? or content like ?)", |
||||||
|
bookId.toString(), |
||||||
|
"%${key}%", "%${key}%" |
||||||
|
) |
||||||
|
.find(Bookmark::class.java) |
||||||
|
|
||||||
|
fun insert(bookmark: Bookmark) { |
||||||
|
bookmark.saveOrUpdate( |
||||||
|
"bookId=? and chapterIndex=?", |
||||||
|
bookmark.bookId.toString(), |
||||||
|
bookmark.chapterIndex.toString() |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
fun update(bookmark: Bookmark) { |
||||||
|
bookmark.saveOrUpdate( |
||||||
|
"bookId=? and chapterIndex=?", |
||||||
|
bookmark.bookId.toString(), |
||||||
|
bookmark.chapterIndex.toString() |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
fun delete(bookmark: Bookmark) { |
||||||
|
bookmark.delete() |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
package com.novel.read.data.db |
||||||
|
|
||||||
|
import com.novel.read.data.db.entity.BookChapter |
||||||
|
import org.litepal.LitePal |
||||||
|
|
||||||
|
class ChapterDao { |
||||||
|
|
||||||
|
fun observeByBook(bookId: String): List<BookChapter>? = |
||||||
|
LitePal.where("bookId=?", bookId.toString()).find(BookChapter::class.java) |
||||||
|
|
||||||
|
fun liveDataSearch(bookId: String, key: String): List<BookChapter>? = |
||||||
|
LitePal.where("bookId=? and chapterName like ?", bookId, "%${key}%") |
||||||
|
.find(BookChapter::class.java) |
||||||
|
|
||||||
|
fun getChapter(chapterId: Long): BookChapter? = |
||||||
|
LitePal.where("chapterId =?", chapterId.toString()).findFirst(BookChapter::class.java) |
||||||
|
|
||||||
|
fun getChapter(bookId: Long, chapterIndex: Int): BookChapter? = |
||||||
|
LitePal.where("bookId=? and chapterIndex =?", bookId.toString(), chapterIndex.toString()) |
||||||
|
.findFirst(BookChapter::class.java) |
||||||
|
|
||||||
|
fun getChapterList(bookId: Long): List<BookChapter>? = |
||||||
|
LitePal.where("bookId=?", bookId.toString()).find(BookChapter::class.java) |
||||||
|
|
||||||
|
fun getChapterList(bookId: Long, start: Int, end: Int): List<BookChapter> = |
||||||
|
LitePal.where( |
||||||
|
"bookId=? and chapterIndex >=? and chapterIndex <=?", |
||||||
|
bookId.toString(), |
||||||
|
start.toString(), |
||||||
|
end.toString() |
||||||
|
).order("chapterIndex desc").find(BookChapter::class.java) |
||||||
|
|
||||||
|
fun getChapterCount(bookId: Long): Int { |
||||||
|
return LitePal.where("bookId=?", bookId.toString()).count(BookChapter::class.java) |
||||||
|
} |
||||||
|
|
||||||
|
fun insert(bookChapters: Array<BookChapter>) { |
||||||
|
if (bookChapters.isNotEmpty()) { |
||||||
|
LitePal.deleteAll( |
||||||
|
BookChapter::class.java, |
||||||
|
"bookId=?", |
||||||
|
bookChapters[0].bookId.toString() |
||||||
|
) |
||||||
|
} |
||||||
|
LitePal.saveAll(bookChapters.toList()) |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.novel.read.data.db |
||||||
|
|
||||||
|
import com.novel.read.data.db.entity.ReadRecord |
||||||
|
import org.litepal.LitePal |
||||||
|
|
||||||
|
class ReadRecordDao { |
||||||
|
|
||||||
|
fun getReadTime(bookName: String): Long? = |
||||||
|
LitePal.where("bookName =?", bookName).findFirst(ReadRecord::class.java)?.readTime |
||||||
|
|
||||||
|
fun insert(readRecord: ReadRecord) { |
||||||
|
readRecord.saveOrUpdate("bookId=?", readRecord.bookId.toString()) |
||||||
|
} |
||||||
|
|
||||||
|
fun delete(readRecord: ReadRecord) { |
||||||
|
readRecord.delete() |
||||||
|
} |
||||||
|
|
||||||
|
fun getAll(): List<ReadRecord> { |
||||||
|
return LitePal.findAll(ReadRecord::class.java) |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.novel.read.data.db |
||||||
|
|
||||||
|
import com.novel.read.data.db.entity.SearchHistory |
||||||
|
import org.litepal.LitePal |
||||||
|
|
||||||
|
class SearchHistoryDao { |
||||||
|
|
||||||
|
fun getListByTime(): MutableList<SearchHistory>? = |
||||||
|
LitePal.order("saveTime desc").limit(5).find(SearchHistory::class.java) |
||||||
|
|
||||||
|
fun insert(searchHistory: SearchHistory, key: String) { |
||||||
|
searchHistory.saveOrUpdate("key=?", key) |
||||||
|
} |
||||||
|
|
||||||
|
fun deleteAll() { |
||||||
|
LitePal.deleteAll(SearchHistory::class.java) |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.novel.read.data.db.entity |
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName |
||||||
|
import com.novel.read.constant.AppPattern |
||||||
|
import com.novel.read.constant.BookType |
||||||
|
import com.novel.read.utils.MD5Utils |
||||||
|
import org.litepal.crud.LitePalSupport |
||||||
|
import kotlin.math.max |
||||||
|
|
||||||
|
data class Book( |
||||||
|
val authorPenname: String, |
||||||
|
val bookId: Long, |
||||||
|
val bookName: String, |
||||||
|
val bookStatus: String, |
||||||
|
val categoryName: String?, |
||||||
|
val channelName: String?, |
||||||
|
@SerializedName("className") |
||||||
|
val cName: String?, |
||||||
|
val coverImageUrl: String, |
||||||
|
val introduction: String, |
||||||
|
val keyWord: String, |
||||||
|
var lastUpdateChapterDate: String, |
||||||
|
val status: Int, |
||||||
|
val wordCount: Long, |
||||||
|
var totalChapterNum: Int = 0, // 书籍目录总数 |
||||||
|
var durChapterTitle: String? = null, // 当前章节名称 |
||||||
|
var durChapterIndex: Int = 0, // 当前章节索引 |
||||||
|
var durChapterPos: Int = 0, // 当前阅读的进度(首行字符的索引位置) |
||||||
|
var durChapterTime: Long = System.currentTimeMillis(), // 最近一次阅读书籍的时间(打开正文的时间) |
||||||
|
var origin: String = BookType.net, |
||||||
|
var originName: String = "", |
||||||
|
var bookTypeId: Int = 0 |
||||||
|
) : LitePalSupport() { |
||||||
|
|
||||||
|
fun isLocalBook(): Boolean { |
||||||
|
return origin == BookType.local |
||||||
|
} |
||||||
|
|
||||||
|
fun getFolderName(): String { |
||||||
|
return bookName.replace(AppPattern.fileNameRegex, "") + MD5Utils.md5Encode16(coverImageUrl) |
||||||
|
} |
||||||
|
|
||||||
|
fun isEpub(): Boolean { |
||||||
|
return originName.endsWith(".epub", true) |
||||||
|
} |
||||||
|
|
||||||
|
fun canUpdate(): Boolean { |
||||||
|
return bookStatus == BookType.serial |
||||||
|
} |
||||||
|
|
||||||
|
fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0) |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.novel.read.data.db.entity |
||||||
|
|
||||||
|
import org.litepal.crud.LitePalSupport |
||||||
|
|
||||||
|
data class BookChapter( |
||||||
|
// val bookId: Int, |
||||||
|
// val chapterList: List<Chapter>, |
||||||
|
// val volumeId: Int, |
||||||
|
// val volumeName: String |
||||||
|
|
||||||
|
val chapterId: Long, |
||||||
|
val bookId: Long, |
||||||
|
val chapterIndex: Int, |
||||||
|
var chapterName: String, |
||||||
|
val createTimeValue: Long, |
||||||
|
val updateDate: String, |
||||||
|
val updateTimeValue: Long, |
||||||
|
val chapterUrl: String?, |
||||||
|
) : LitePalSupport() |
@ -0,0 +1,16 @@ |
|||||||
|
package com.novel.read.data.db.entity |
||||||
|
|
||||||
|
import org.litepal.crud.LitePalSupport |
||||||
|
import java.io.Serializable |
||||||
|
|
||||||
|
data class Bookmark( |
||||||
|
var time: Long = System.currentTimeMillis(), |
||||||
|
var bookId: Long = 0, |
||||||
|
var bookName: String = "", |
||||||
|
val bookAuthor: String = "", |
||||||
|
var chapterIndex: Int = 0, |
||||||
|
var pageIndex: Int = 0, |
||||||
|
var chapterName: String = "", |
||||||
|
var content: String = "" |
||||||
|
|
||||||
|
) : LitePalSupport(), Serializable |
@ -0,0 +1,10 @@ |
|||||||
|
package com.novel.read.data.db.entity |
||||||
|
|
||||||
|
data class ChapterDetailEntity( |
||||||
|
val chapterContent: String, |
||||||
|
val chapterIndex: Int, |
||||||
|
val chapterName: String, |
||||||
|
val isRecommend: String, |
||||||
|
val isVIP: String, |
||||||
|
val wordCount: Int |
||||||
|
) |
@ -0,0 +1,9 @@ |
|||||||
|
package com.novel.read.data.db.entity |
||||||
|
|
||||||
|
import org.litepal.crud.LitePalSupport |
||||||
|
|
||||||
|
data class HttpTTS( |
||||||
|
val id: Long = System.currentTimeMillis(), |
||||||
|
var name: String = "", |
||||||
|
var url: String = "" |
||||||
|
) : LitePalSupport() |
@ -0,0 +1,15 @@ |
|||||||
|
package com.novel.read.data.db.entity |
||||||
|
|
||||||
|
import org.litepal.crud.LitePalSupport |
||||||
|
|
||||||
|
import java.io.Serializable |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by zlj |
||||||
|
*/ |
||||||
|
class ReadRecord( |
||||||
|
var androidId: String = "", |
||||||
|
var bookName: String = "", |
||||||
|
var bookId: Long = 0L, |
||||||
|
var readTime: Long = 0L |
||||||
|
) : LitePalSupport(), Serializable |
@ -0,0 +1,20 @@ |
|||||||
|
package com.novel.read.data.model |
||||||
|
|
||||||
|
data class AppUpdateResp( |
||||||
|
val appEdition: AppEdition |
||||||
|
) |
||||||
|
|
||||||
|
data class AppEdition( |
||||||
|
val createTime: String, |
||||||
|
val editionCode: String, |
||||||
|
val editionId: Int, |
||||||
|
val fileUrl: String, |
||||||
|
val forceUpdate: Int, |
||||||
|
val insideEditionCode: Int, |
||||||
|
val isDel: Int, |
||||||
|
val packageSize: String, |
||||||
|
val pushTime: String, |
||||||
|
val shellName: String, |
||||||
|
val status: Int, |
||||||
|
val upgradeContent: String |
||||||
|
) |
@ -0,0 +1,33 @@ |
|||||||
|
package com.novel.read.data.model |
||||||
|
|
||||||
|
data class BookInfoResp( |
||||||
|
val book: BookResp |
||||||
|
) |
||||||
|
|
||||||
|
data class BookResp( |
||||||
|
val authorInformation: Any, |
||||||
|
val authorName: String, |
||||||
|
val authorUserId: Long, |
||||||
|
val bookClass: Any, |
||||||
|
val bookId: Long, |
||||||
|
val bookName: String, |
||||||
|
val bookSId: String, |
||||||
|
val bookStatus: Any, |
||||||
|
val bookTypeId: Int, |
||||||
|
val categoryName: String?, |
||||||
|
val channelName: Any?, |
||||||
|
val coverImageUrl: String, |
||||||
|
val createTime: Long, |
||||||
|
val endStatus: Int, |
||||||
|
val extBookId: Any, |
||||||
|
val hits: Any, |
||||||
|
val hotStatus: Any, |
||||||
|
val introduction: String, |
||||||
|
val keyWord: String, |
||||||
|
val lastUpdateChapterDate: String, |
||||||
|
val rankNumber: Any, |
||||||
|
val rankType: Any, |
||||||
|
val recommendStatus: Any, |
||||||
|
val validFlag: Int, |
||||||
|
val wordCount: Long |
||||||
|
) |
@ -0,0 +1,52 @@ |
|||||||
|
package com.novel.read.data.model |
||||||
|
|
||||||
|
import com.novel.read.utils.StringUtils |
||||||
|
|
||||||
|
data class BookListResp( |
||||||
|
val authorInformation: String, |
||||||
|
var authorName: String?, |
||||||
|
val authorUserId: Long, |
||||||
|
val bookClass: Int, |
||||||
|
val bookId: Long, |
||||||
|
val bookName: String, |
||||||
|
val bookSId: String, |
||||||
|
val bookStatus: Int, |
||||||
|
val bookTypeId: Int, |
||||||
|
val categoryName: String?, |
||||||
|
val channelName: String?, |
||||||
|
val coverImageUrl: String, |
||||||
|
val createTime: Long, |
||||||
|
val endStatus: Int, |
||||||
|
val hotStatus: Int, |
||||||
|
val introduction: String?, |
||||||
|
val keyWord: String, |
||||||
|
val lastUpdateChapterDate: String?, |
||||||
|
val recommendStatus: Int, |
||||||
|
val validFlag: Int, |
||||||
|
val wordCount: Long |
||||||
|
|
||||||
|
) { |
||||||
|
fun getBAuthorName(): String { |
||||||
|
return StringUtils.convertCC(authorName!!) |
||||||
|
} |
||||||
|
|
||||||
|
fun getBBookName(): String { |
||||||
|
return StringUtils.convertCC(bookName) |
||||||
|
} |
||||||
|
|
||||||
|
fun getBCategoryName(): String { |
||||||
|
return StringUtils.convertCC(categoryName ?: "") |
||||||
|
} |
||||||
|
|
||||||
|
fun getBChannel(): String { |
||||||
|
return StringUtils.convertCC(channelName!!) |
||||||
|
} |
||||||
|
|
||||||
|
fun getBIntroduction(): String { |
||||||
|
return StringUtils.convertCC(introduction!!) |
||||||
|
} |
||||||
|
|
||||||
|
fun getBKeyWord(): String { |
||||||
|
return StringUtils.convertCC(keyWord) |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue