mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-27 19:47:51 +02:00
Rewrite link intercept activity
Fix compatibility issues between lewd sources and manga info screen
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
### 6.8.0
|
||||||
|
- Various performance improvements
|
||||||
|
- Fix library search query being lost
|
||||||
|
- Upstream merge
|
||||||
|
- Fix Tsumino and HentaiCafe links not triggering a link import
|
||||||
|
- Fix many bugs in link interceptor
|
||||||
|
|
||||||
### 6.6.0
|
### 6.6.0
|
||||||
- Many performance improvements
|
- Many performance improvements
|
||||||
- Stability improvements and bug fixes
|
- Stability improvements and bug fixes
|
||||||
|
@ -105,7 +105,8 @@
|
|||||||
<!-- EH -->
|
<!-- EH -->
|
||||||
<activity
|
<activity
|
||||||
android:name="exh.ui.intercept.InterceptActivity"
|
android:name="exh.ui.intercept.InterceptActivity"
|
||||||
android:label="TachiyomiEH">
|
android:excludeFromRecents="true"
|
||||||
|
android:label="Tachiyomi">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
|
||||||
@ -146,21 +147,35 @@
|
|||||||
android:scheme="https"/>
|
android:scheme="https"/>
|
||||||
<data
|
<data
|
||||||
android:host="www.perveden.com"
|
android:host="www.perveden.com"
|
||||||
|
android:pathPattern="/.*/.*-manga/.*"
|
||||||
android:scheme="http"/>
|
android:scheme="http"/>
|
||||||
<data
|
<data
|
||||||
android:host="www.perveden.com"
|
android:host="www.perveden.com"
|
||||||
|
android:pathPattern="/.*/.*-manga/.*"
|
||||||
android:scheme="https"/>
|
android:scheme="https"/>
|
||||||
<data
|
<data
|
||||||
android:host="hentai.cafe"
|
android:host="hentai.cafe"
|
||||||
|
android:pathPattern="/.*/.*"
|
||||||
android:scheme="http"/>
|
android:scheme="http"/>
|
||||||
<data
|
<data
|
||||||
android:host="hentai.cafe"
|
android:host="hentai.cafe"
|
||||||
|
android:pathPattern="/.*/.*"
|
||||||
android:scheme="https"/>
|
android:scheme="https"/>
|
||||||
<data
|
<data
|
||||||
android:host="www.tsumino.com"
|
android:host="www.tsumino.com"
|
||||||
|
android:pathPrefix="/Book/Info/"
|
||||||
android:scheme="http"/>
|
android:scheme="http"/>
|
||||||
<data
|
<data
|
||||||
android:host="www.tsumino.com"
|
android:host="www.tsumino.com"
|
||||||
|
android:pathPrefix="/Book/Info/"
|
||||||
|
android:scheme="https"/>
|
||||||
|
<data
|
||||||
|
android:host="www.tsumino.com"
|
||||||
|
android:pathPrefix="/Read/View/"
|
||||||
|
android:scheme="http"/>
|
||||||
|
<data
|
||||||
|
android:host="www.tsumino.com"
|
||||||
|
android:pathPrefix="/Read/View/"
|
||||||
android:scheme="https"/>
|
android:scheme="https"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
@ -7,7 +7,11 @@ import eu.kanade.tachiyomi.source.online.LewdSource
|
|||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.util.ChapterRecognition
|
import eu.kanade.tachiyomi.util.ChapterRecognition
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import exh.metadata.models.*
|
import exh.metadata.EMULATED_TAG_NAMESPACE
|
||||||
|
import exh.metadata.models.PervEdenGalleryMetadata
|
||||||
|
import exh.metadata.models.PervEdenLang
|
||||||
|
import exh.metadata.models.PervEdenTitle
|
||||||
|
import exh.metadata.models.Tag
|
||||||
import exh.util.UriFilter
|
import exh.util.UriFilter
|
||||||
import exh.util.UriGroup
|
import exh.util.UriGroup
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
@ -139,7 +143,7 @@ class PervEden(override val id: Long, val pvLang: PervEdenLang) : ParsedHttpSour
|
|||||||
}
|
}
|
||||||
"Genres" -> {
|
"Genres" -> {
|
||||||
if(it is Element && it.tagName() == "a")
|
if(it is Element && it.tagName() == "a")
|
||||||
tags.add(Tag("genre", it.text().toLowerCase(), false))
|
tags.add(Tag(EMULATED_TAG_NAMESPACE, it.text().toLowerCase(), false))
|
||||||
}
|
}
|
||||||
"Type" -> {
|
"Type" -> {
|
||||||
if(it is TextNode) {
|
if(it is TextNode) {
|
||||||
|
@ -8,6 +8,7 @@ import eu.kanade.tachiyomi.source.online.LewdSource
|
|||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import exh.HENTAI_CAFE_SOURCE_ID
|
import exh.HENTAI_CAFE_SOURCE_ID
|
||||||
|
import exh.metadata.EMULATED_TAG_NAMESPACE
|
||||||
import exh.metadata.models.HentaiCafeMetadata
|
import exh.metadata.models.HentaiCafeMetadata
|
||||||
import exh.metadata.models.HentaiCafeMetadata.Companion.BASE_URL
|
import exh.metadata.models.HentaiCafeMetadata.Companion.BASE_URL
|
||||||
import exh.metadata.models.Tag
|
import exh.metadata.models.Tag
|
||||||
@ -128,7 +129,7 @@ class HentaiCafe : ParsedHttpSource(), LewdSource<HentaiCafeMetadata, Document>
|
|||||||
val firstPath = parsed.pathSegments.first()
|
val firstPath = parsed.pathSegments.first()
|
||||||
|
|
||||||
when(firstPath) {
|
when(firstPath) {
|
||||||
"tag" -> tags.add(Tag("tag", it.text(), false))
|
"tag" -> tags.add(Tag(EMULATED_TAG_NAMESPACE, it.text(), false))
|
||||||
"artist" -> {
|
"artist" -> {
|
||||||
artist = it.text()
|
artist = it.text()
|
||||||
tags.add(Tag("artist", it.text(), false))
|
tags.add(Tag("artist", it.text(), false))
|
||||||
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.source.online.LewdSource
|
|||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import exh.TSUMINO_SOURCE_ID
|
import exh.TSUMINO_SOURCE_ID
|
||||||
|
import exh.metadata.EMULATED_TAG_NAMESPACE
|
||||||
import exh.metadata.models.Tag
|
import exh.metadata.models.Tag
|
||||||
import exh.metadata.models.TsuminoMetadata
|
import exh.metadata.models.TsuminoMetadata
|
||||||
import exh.metadata.models.TsuminoMetadata.Companion.BASE_URL
|
import exh.metadata.models.TsuminoMetadata.Companion.BASE_URL
|
||||||
@ -96,7 +97,7 @@ class Tsumino: ParsedHttpSource(), LewdSource<TsuminoMetadata, Document> {
|
|||||||
|
|
||||||
it.getElementById("Tag")?.children()?.let {
|
it.getElementById("Tag")?.children()?.let {
|
||||||
tags.addAll(it.map {
|
tags.addAll(it.map {
|
||||||
Tag("tag", it.text().trim(), false)
|
Tag(EMULATED_TAG_NAMESPACE, it.text().trim(), false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,11 @@ import eu.kanade.tachiyomi.ui.migration.MigrationController
|
|||||||
import eu.kanade.tachiyomi.util.inflate
|
import eu.kanade.tachiyomi.util.inflate
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
import eu.kanade.tachiyomi.widget.DrawerSwipeCloseListener
|
import eu.kanade.tachiyomi.widget.DrawerSwipeCloseListener
|
||||||
|
import exh.FavoritesSyncHelper
|
||||||
import exh.metadata.loadAllMetadata
|
import exh.metadata.loadAllMetadata
|
||||||
import exh.metadata.models.SearchableGalleryMetadata
|
import exh.metadata.models.SearchableGalleryMetadata
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import kotlinx.android.synthetic.main.main_activity.*
|
|
||||||
import kotlinx.android.synthetic.main.library_controller.*
|
import kotlinx.android.synthetic.main.library_controller.*
|
||||||
import kotlinx.android.synthetic.main.main_activity.*
|
import kotlinx.android.synthetic.main.main_activity.*
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
@ -133,6 +133,8 @@ class LibraryController(
|
|||||||
var realm: Realm? = null
|
var realm: Realm? = null
|
||||||
//Cached metadata
|
//Cached metadata
|
||||||
var meta: Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>>? = null
|
var meta: Map<KClass<out SearchableGalleryMetadata>, RealmResults<out SearchableGalleryMetadata>>? = null
|
||||||
|
//Favorites
|
||||||
|
val favorites by lazy { FavoritesSyncHelper(activity!!) }
|
||||||
// <-- EH
|
// <-- EH
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -403,6 +405,9 @@ class LibraryController(
|
|||||||
R.id.action_source_migration -> {
|
R.id.action_source_migration -> {
|
||||||
router.pushController(MigrationController().withFadeTransaction())
|
router.pushController(MigrationController().withFadeTransaction())
|
||||||
}
|
}
|
||||||
|
R.id.action_download_favorites -> {
|
||||||
|
favorites.guiSyncFavorites { }
|
||||||
|
}
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import eu.kanade.tachiyomi.data.glide.GlideApp
|
|||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
@ -45,6 +46,8 @@ import eu.kanade.tachiyomi.util.getResourceColor
|
|||||||
import eu.kanade.tachiyomi.util.snack
|
import eu.kanade.tachiyomi.util.snack
|
||||||
import eu.kanade.tachiyomi.util.toast
|
import eu.kanade.tachiyomi.util.toast
|
||||||
import eu.kanade.tachiyomi.util.truncateCenter
|
import eu.kanade.tachiyomi.util.truncateCenter
|
||||||
|
import exh.EH_SOURCE_ID
|
||||||
|
import exh.EXH_SOURCE_ID
|
||||||
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
import jp.wasabeef.glide.transformations.CropSquareTransformation
|
||||||
import jp.wasabeef.glide.transformations.MaskTransformation
|
import jp.wasabeef.glide.transformations.MaskTransformation
|
||||||
import kotlinx.android.synthetic.main.manga_info_controller.*
|
import kotlinx.android.synthetic.main.manga_info_controller.*
|
||||||
@ -66,6 +69,8 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
*/
|
*/
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
private val sourceManager: SourceManager by injectLazy()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
setOptionsMenuHidden(true)
|
setOptionsMenuHidden(true)
|
||||||
@ -103,22 +108,38 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
manga_artist.clicks().subscribeUntilDestroy {
|
manga_artist.clicks().subscribeUntilDestroy {
|
||||||
performGlobalSearch(manga_artist.text.toString())
|
//EXH Special case E-Hentai/ExHentai to use tag based search
|
||||||
|
var text = manga_artist.text.toString()
|
||||||
|
if(isEHentaiBasedSource())
|
||||||
|
text = wrapTag("artist", text)
|
||||||
|
performGlobalSearch(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
manga_author.longClicks().subscribeUntilDestroy {
|
manga_author.longClicks().subscribeUntilDestroy {
|
||||||
copyToClipboard(manga_author.text.toString(), manga_author.text.toString())
|
//EXH Special case E-Hentai/ExHentai to ignore author field (unused)
|
||||||
|
if(!isEHentaiBasedSource())
|
||||||
|
copyToClipboard(manga_author.text.toString(), manga_author.text.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
manga_author.clicks().subscribeUntilDestroy {
|
manga_author.clicks().subscribeUntilDestroy {
|
||||||
performGlobalSearch(manga_author.text.toString())
|
//EXH Special case E-Hentai/ExHentai to ignore author field (unused)
|
||||||
|
if(!isEHentaiBasedSource())
|
||||||
|
performGlobalSearch(manga_author.text.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
manga_summary.longClicks().subscribeUntilDestroy {
|
manga_summary.longClicks().subscribeUntilDestroy {
|
||||||
copyToClipboard(view.context.getString(R.string.description), manga_summary.text.toString())
|
copyToClipboard(view.context.getString(R.string.description), manga_summary.text.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
manga_genres_tags.setOnTagClickListener { tag -> performGlobalSearch(tag) }
|
manga_genres_tags.setOnTagClickListener { tag ->
|
||||||
|
//EXH Special case E-Hentai/ExHentai to use tag based search
|
||||||
|
var text = tag
|
||||||
|
if(isEHentaiBasedSource()) {
|
||||||
|
val parsed = parseTag(text)
|
||||||
|
text = wrapTag(parsed.first, parsed.second)
|
||||||
|
}
|
||||||
|
performGlobalSearch(text)
|
||||||
|
}
|
||||||
|
|
||||||
manga_cover.longClicks().subscribeUntilDestroy {
|
manga_cover.longClicks().subscribeUntilDestroy {
|
||||||
copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
|
copyToClipboard(view.context.getString(R.string.title), presenter.manga.title)
|
||||||
@ -491,6 +512,32 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
router.pushController(CatalogueSearchController(query).withFadeTransaction())
|
router.pushController(CatalogueSearchController(query).withFadeTransaction())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --> EH
|
||||||
|
private fun wrapTag(namespace: String, tag: String)
|
||||||
|
= if(tag.contains(' '))
|
||||||
|
"$namespace:\"$tag$\""
|
||||||
|
else
|
||||||
|
"$namespace:$tag$"
|
||||||
|
|
||||||
|
private fun parseTag(tag: String) = tag.substringBefore(':').trim() to tag.substringAfter(':').trim()
|
||||||
|
|
||||||
|
private fun isEHentaiBasedSource(): Boolean {
|
||||||
|
val mangaSourceText = manga_source.text
|
||||||
|
|
||||||
|
sourceManager.get(EH_SOURCE_ID)?.let {
|
||||||
|
if(mangaSourceText.startsWith(it.name))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceManager.get(EXH_SOURCE_ID)?.let {
|
||||||
|
if(mangaSourceText.startsWith(it.name))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// <-- EH
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create shortcut using ShortcutManager.
|
* Create shortcut using ShortcutManager.
|
||||||
*
|
*
|
||||||
|
@ -5,6 +5,7 @@ import com.bluelinelabs.conductor.RouterTransaction
|
|||||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
|
||||||
import exh.ui.login.LoginController
|
import exh.ui.login.LoginController
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
|
import rx.schedulers.Schedulers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EH Settings fragment
|
* EH Settings fragment
|
||||||
@ -22,6 +23,7 @@ class SettingsEhController : SettingsController() {
|
|||||||
defaultValue = false
|
defaultValue = false
|
||||||
preferences.enableExhentai()
|
preferences.enableExhentai()
|
||||||
.asObservable()
|
.asObservable()
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribeUntilDestroy {
|
.subscribeUntilDestroy {
|
||||||
isChecked = it
|
isChecked = it
|
||||||
|
@ -74,8 +74,10 @@ class FavoritesSyncHelper(val activity: Activity) {
|
|||||||
|
|
||||||
(exSource ?: ehSource)?.let { source ->
|
(exSource ?: ehSource)?.let { source ->
|
||||||
val favResponse = source.fetchFavorites()
|
val favResponse = source.fetchFavorites()
|
||||||
val ourCategories = ArrayList<Category>(db.getCategories().executeAsBlocking())
|
val ourCategories = db.getCategories().executeAsBlocking().toMutableList()
|
||||||
val ourMangas = ArrayList<Manga>(db.getMangas().executeAsBlocking())
|
val ourMangas = db.getMangas().executeAsBlocking().filter {
|
||||||
|
it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID
|
||||||
|
}.toMutableList()
|
||||||
//Add required categories (categories do not sync upwards)
|
//Add required categories (categories do not sync upwards)
|
||||||
favResponse.second.filter { theirCategory ->
|
favResponse.second.filter { theirCategory ->
|
||||||
ourCategories.find {
|
ourCategories.find {
|
||||||
@ -93,7 +95,7 @@ class FavoritesSyncHelper(val activity: Activity) {
|
|||||||
val categoryMap = (it + ourCategories).associateBy { it.name }
|
val categoryMap = (it + ourCategories).associateBy { it.name }
|
||||||
|
|
||||||
//Insert new mangas
|
//Insert new mangas
|
||||||
val mangaToInsert = java.util.ArrayList<Manga>()
|
val mangaToInsert = mutableListOf<Manga>()
|
||||||
favResponse.first.map {
|
favResponse.first.map {
|
||||||
val category = categoryMap[it.fav]!!
|
val category = categoryMap[it.fav]!!
|
||||||
var manga = it.manga
|
var manga = it.manga
|
||||||
|
@ -83,3 +83,11 @@ fun buildTagsDescription(metadata: SearchableGalleryMetadata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun joinTagsToGenreString(metadata: SearchableGalleryMetadata)
|
||||||
|
= metadata.tags.joinToString { "${it.namespace}: ${it.name}" }
|
||||||
|
|
||||||
|
fun joinEmulatedTagsToGenreString(metadata: SearchableGalleryMetadata)
|
||||||
|
= metadata.tags.filter { it.namespace == EMULATED_TAG_NAMESPACE }.joinToString { it.name.toString() }
|
||||||
|
|
||||||
|
val EMULATED_TAG_NAMESPACE = "tag"
|
@ -4,10 +4,7 @@ import android.net.Uri
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.EX_DATE_FORMAT
|
import exh.metadata.*
|
||||||
import exh.metadata.ONGOING_SUFFIX
|
|
||||||
import exh.metadata.buildTagsDescription
|
|
||||||
import exh.metadata.humanReadableByteCount
|
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
@ -110,12 +107,9 @@ open class ExGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
tags.filter { it.namespace == EH_ARTIST_NAMESPACE }.let {
|
tags.filter { it.namespace == EH_ARTIST_NAMESPACE }.let {
|
||||||
if(it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name!! })
|
if(it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name!! })
|
||||||
}
|
}
|
||||||
//Set author (if we can find one)
|
|
||||||
tags.filter { it.namespace == EH_AUTHOR_NAMESPACE }.let {
|
//Copy tags -> genres
|
||||||
if(it.isNotEmpty()) manga.author = it.joinToString(transform = { it.name!! })
|
manga.genre = joinTagsToGenreString(this)
|
||||||
}
|
|
||||||
//Set genre
|
|
||||||
genre?.let { manga.genre = it }
|
|
||||||
|
|
||||||
//Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
//Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
||||||
//We default to completed
|
//We default to completed
|
||||||
@ -134,6 +128,7 @@ open class ExGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
altTitle?.let { titleDesc += "Alternate Title: $it\n" }
|
altTitle?.let { titleDesc += "Alternate Title: $it\n" }
|
||||||
|
|
||||||
val detailsDesc = StringBuilder()
|
val detailsDesc = StringBuilder()
|
||||||
|
genre?.let { detailsDesc += "Genre: $it\n" }
|
||||||
uploader?.let { detailsDesc += "Uploader: $it\n" }
|
uploader?.let { detailsDesc += "Uploader: $it\n" }
|
||||||
datePosted?.let { detailsDesc += "Posted: ${EX_DATE_FORMAT.format(Date(it))}\n" }
|
datePosted?.let { detailsDesc += "Posted: ${EX_DATE_FORMAT.format(Date(it))}\n" }
|
||||||
visible?.let { detailsDesc += "Visible: $it\n" }
|
visible?.let { detailsDesc += "Visible: $it\n" }
|
||||||
@ -176,7 +171,6 @@ open class ExGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private const val EH_ARTIST_NAMESPACE = "artist"
|
private const val EH_ARTIST_NAMESPACE = "artist"
|
||||||
private const val EH_AUTHOR_NAMESPACE = "author"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,10 +3,7 @@ package exh.metadata.models
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.EX_DATE_FORMAT
|
import exh.metadata.*
|
||||||
import exh.metadata.ONGOING_SUFFIX
|
|
||||||
import exh.metadata.buildTagsDescription
|
|
||||||
import exh.metadata.nullIfBlank
|
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
@ -106,10 +103,14 @@ open class NHentaiMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
if(it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name!! })
|
if(it.isNotEmpty()) manga.artist = it.joinToString(transform = { it.name!! })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var category: String? = null
|
||||||
tags.filter { it.namespace == NHENTAI_CATEGORIES_NAMESPACE }.let {
|
tags.filter { it.namespace == NHENTAI_CATEGORIES_NAMESPACE }.let {
|
||||||
if(it.isNotEmpty()) manga.genre = it.joinToString(transform = { it.name!! })
|
if(it.isNotEmpty()) category = it.joinToString(transform = { it.name!! })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Copy tags -> genres
|
||||||
|
manga.genre = joinEmulatedTagsToGenreString(this)
|
||||||
|
|
||||||
//Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
//Try to automatically identify if it is ongoing, we try not to be too lenient here to avoid making mistakes
|
||||||
//We default to completed
|
//We default to completed
|
||||||
manga.status = SManga.COMPLETED
|
manga.status = SManga.COMPLETED
|
||||||
@ -127,6 +128,7 @@ open class NHentaiMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
shortTitle?.let { titleDesc += "Short Title: $it\n" }
|
shortTitle?.let { titleDesc += "Short Title: $it\n" }
|
||||||
|
|
||||||
val detailsDesc = StringBuilder()
|
val detailsDesc = StringBuilder()
|
||||||
|
category?.let { detailsDesc += "Category: $it\n" }
|
||||||
uploadDate?.let { detailsDesc += "Upload Date: ${EX_DATE_FORMAT.format(Date(it * 1000))}\n" }
|
uploadDate?.let { detailsDesc += "Upload Date: ${EX_DATE_FORMAT.format(Date(it * 1000))}\n" }
|
||||||
pageImageTypes.size.let { detailsDesc += "Length: $it pages\n" }
|
pageImageTypes.size.let { detailsDesc += "Length: $it pages\n" }
|
||||||
favoritesCount?.let { detailsDesc += "Favorited: $it times\n" }
|
favoritesCount?.let { detailsDesc += "Favorited: $it times\n" }
|
||||||
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||||||
import exh.PERV_EDEN_EN_SOURCE_ID
|
import exh.PERV_EDEN_EN_SOURCE_ID
|
||||||
import exh.PERV_EDEN_IT_SOURCE_ID
|
import exh.PERV_EDEN_IT_SOURCE_ID
|
||||||
import exh.metadata.buildTagsDescription
|
import exh.metadata.buildTagsDescription
|
||||||
|
import exh.metadata.joinEmulatedTagsToGenreString
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
@ -77,7 +78,6 @@ open class PervEdenGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type?.let {
|
type?.let {
|
||||||
manga.genre = it
|
|
||||||
detailsDesc += "Type: $it\n"
|
detailsDesc += "Type: $it\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +94,9 @@ open class PervEdenGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
detailsDesc += "Rating: %.2\n".format(it)
|
detailsDesc += "Rating: %.2\n".format(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Copy tags -> genres
|
||||||
|
manga.genre = joinEmulatedTagsToGenreString(this)
|
||||||
|
|
||||||
val tagsDesc = buildTagsDescription(this)
|
val tagsDesc = buildTagsDescription(this)
|
||||||
|
|
||||||
manga.description = listOf(titleDesc.toString(), detailsDesc.toString(), tagsDesc.toString())
|
manga.description = listOf(titleDesc.toString(), detailsDesc.toString(), tagsDesc.toString())
|
||||||
@ -164,6 +167,7 @@ open class PervEdenTitle(var metadata: PervEdenGalleryMetadata? = null,
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class PervEdenLang(val id: Long) {
|
enum class PervEdenLang(val id: Long) {
|
||||||
|
//DO NOT RENAME THESE TO CAPITAL LETTERS! The enum names are used to build URLs
|
||||||
en(PERV_EDEN_EN_SOURCE_ID),
|
en(PERV_EDEN_EN_SOURCE_ID),
|
||||||
it(PERV_EDEN_IT_SOURCE_ID);
|
it(PERV_EDEN_IT_SOURCE_ID);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import android.net.Uri
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.EX_DATE_FORMAT
|
import exh.metadata.EX_DATE_FORMAT
|
||||||
import exh.metadata.buildTagsDescription
|
import exh.metadata.buildTagsDescription
|
||||||
|
import exh.metadata.joinEmulatedTagsToGenreString
|
||||||
import exh.plusAssign
|
import exh.plusAssign
|
||||||
import io.realm.RealmList
|
import io.realm.RealmList
|
||||||
import io.realm.RealmObject
|
import io.realm.RealmObject
|
||||||
@ -96,7 +97,6 @@ open class TsuminoMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
length?.let { detailsDesc += "Length: $it pages\n" }
|
length?.let { detailsDesc += "Length: $it pages\n" }
|
||||||
ratingString?.let { detailsDesc += "Rating: $it\n" }
|
ratingString?.let { detailsDesc += "Rating: $it\n" }
|
||||||
category?.let {
|
category?.let {
|
||||||
manga.genre = it
|
|
||||||
detailsDesc += "Category: $it\n"
|
detailsDesc += "Category: $it\n"
|
||||||
}
|
}
|
||||||
collection?.let { detailsDesc += "Collection: $it\n" }
|
collection?.let { detailsDesc += "Collection: $it\n" }
|
||||||
@ -110,6 +110,9 @@ open class TsuminoMetadata : RealmObject(), SearchableGalleryMetadata {
|
|||||||
detailsDesc += "Character: $charactersString\n"
|
detailsDesc += "Character: $charactersString\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Copy tags -> genres
|
||||||
|
manga.genre = joinEmulatedTagsToGenreString(this)
|
||||||
|
|
||||||
val tagsDesc = buildTagsDescription(this)
|
val tagsDesc = buildTagsDescription(this)
|
||||||
|
|
||||||
manga.description = listOf(titleDesc, detailsDesc.toString(), tagsDesc.toString())
|
manga.description = listOf(titleDesc, detailsDesc.toString(), tagsDesc.toString())
|
||||||
|
@ -5,32 +5,19 @@ import android.os.Bundle
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import exh.GalleryAddEvent
|
|
||||||
import exh.GalleryAdder
|
|
||||||
import kotlinx.android.synthetic.main.eh_activity_intercept.*
|
import kotlinx.android.synthetic.main.eh_activity_intercept.*
|
||||||
import uy.kohesive.injekt.injectLazy
|
import nucleus.factory.RequiresPresenter
|
||||||
import kotlin.concurrent.thread
|
import rx.Subscription
|
||||||
|
import rx.android.schedulers.AndroidSchedulers
|
||||||
|
|
||||||
class InterceptActivity : BaseActivity() {
|
@RequiresPresenter(InterceptActivityPresenter::class)
|
||||||
|
class InterceptActivity : BaseRxActivity<InterceptActivityPresenter>() {
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private var statusSubscription: Subscription? = null
|
||||||
|
|
||||||
private val galleryAdder = GalleryAdder()
|
|
||||||
|
|
||||||
var finished = false
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
//Set theme
|
|
||||||
setTheme(when (preferences.theme()) {
|
|
||||||
2 -> R.style.Theme_Tachiyomi_Dark
|
|
||||||
3 -> R.style.Theme_Tachiyomi_Amoled
|
|
||||||
else -> R.style.Theme_Tachiyomi
|
|
||||||
})
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.eh_activity_intercept)
|
setContentView(R.layout.eh_activity_intercept)
|
||||||
|
|
||||||
@ -38,37 +25,12 @@ class InterceptActivity : BaseActivity() {
|
|||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
if(savedInstanceState == null)
|
processLink()
|
||||||
thread { processLink() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processLink() {
|
private fun processLink() {
|
||||||
if(Intent.ACTION_VIEW == intent.action) {
|
if(Intent.ACTION_VIEW == intent.action)
|
||||||
val result = galleryAdder.addGallery(intent.dataString)
|
presenter.loadGallery(intent.dataString)
|
||||||
|
|
||||||
when(result) {
|
|
||||||
is GalleryAddEvent.Success ->
|
|
||||||
if(!finished)
|
|
||||||
startActivity(Intent(this, MainActivity::class.java)
|
|
||||||
.setAction(MainActivity.SHORTCUT_MANGA)
|
|
||||||
.putExtra(MangaController.MANGA_EXTRA, result.manga.id))
|
|
||||||
is GalleryAddEvent.Fail ->
|
|
||||||
if(!finished)
|
|
||||||
runOnUiThread {
|
|
||||||
MaterialDialog.Builder(this)
|
|
||||||
.title("Error")
|
|
||||||
.content("Could not open this gallery:\n\n${result.logMessage}")
|
|
||||||
.cancelable(true)
|
|
||||||
.canceledOnTouchOutside(true)
|
|
||||||
.cancelListener { onBackPressed() }
|
|
||||||
.positiveText("Ok")
|
|
||||||
.onPositive { _, _ -> onBackPressed() }
|
|
||||||
.dismissListener { onBackPressed() }
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
@ -79,15 +41,36 @@ class InterceptActivity : BaseActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onStart() {
|
||||||
if(!finished)
|
super.onStart()
|
||||||
runOnUiThread {
|
statusSubscription?.unsubscribe()
|
||||||
super.onBackPressed()
|
statusSubscription = presenter.status
|
||||||
}
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe {
|
||||||
|
when(it) {
|
||||||
|
is InterceptResult.Success -> {
|
||||||
|
startActivity(Intent(this, MainActivity::class.java)
|
||||||
|
.setAction(MainActivity.SHORTCUT_MANGA)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
.putExtra(MangaController.MANGA_EXTRA, it.mangaId))
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
is InterceptResult.Failure ->
|
||||||
|
MaterialDialog.Builder(this)
|
||||||
|
.title("Error")
|
||||||
|
.content("Could not open this gallery:\n\n${it.reason}")
|
||||||
|
.cancelable(true)
|
||||||
|
.canceledOnTouchOutside(true)
|
||||||
|
.positiveText("Ok")
|
||||||
|
.cancelListener { onBackPressed() }
|
||||||
|
.dismissListener { onBackPressed() }
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
super.onStop()
|
super.onStop()
|
||||||
finished = true
|
statusSubscription?.unsubscribe()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package exh.ui.intercept
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
import exh.GalleryAddEvent
|
||||||
|
import exh.GalleryAdder
|
||||||
|
import rx.subjects.BehaviorSubject
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
class InterceptActivityPresenter : BasePresenter<InterceptActivity>() {
|
||||||
|
private val galleryAdder = GalleryAdder()
|
||||||
|
|
||||||
|
val status = BehaviorSubject.create<InterceptResult>(InterceptResult.Idle())
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun loadGallery(gallery: String) {
|
||||||
|
//Do not load gallery if already loading
|
||||||
|
if(status.value is InterceptResult.Idle) {
|
||||||
|
status.onNext(InterceptResult.Loading())
|
||||||
|
|
||||||
|
//Load gallery async
|
||||||
|
thread {
|
||||||
|
val result = galleryAdder.addGallery(gallery)
|
||||||
|
|
||||||
|
status.onNext(when (result) {
|
||||||
|
is GalleryAddEvent.Success -> result.manga.id?.let {
|
||||||
|
InterceptResult.Success(it)
|
||||||
|
} ?: InterceptResult.Failure("Manga ID is null!")
|
||||||
|
is GalleryAddEvent.Fail -> InterceptResult.Failure(result.logMessage)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class InterceptResult {
|
||||||
|
class Idle : InterceptResult()
|
||||||
|
class Loading : InterceptResult()
|
||||||
|
data class Success(val mangaId: Long): InterceptResult()
|
||||||
|
data class Failure(val reason: String): InterceptResult()
|
||||||
|
}
|
@ -15,7 +15,8 @@
|
|||||||
<android.support.design.widget.AppBarLayout
|
<android.support.design.widget.AppBarLayout
|
||||||
android:id="@+id/appbar"
|
android:id="@+id/appbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
app:elevation="0dp">
|
||||||
|
|
||||||
<android.support.v7.widget.Toolbar
|
<android.support.v7.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
@ -27,28 +28,29 @@
|
|||||||
|
|
||||||
</android.support.design.widget.AppBarLayout>
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
<LinearLayout
|
android:layout_gravity="center"
|
||||||
android:layout_height="wrap_content"
|
android:background="?attr/colorPrimary"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:orientation="vertical"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center">
|
android:layout_marginBottom="8dp"
|
||||||
|
android:text="Loading gallery..."
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.Title"
|
||||||
|
android:textColor="@color/white" />
|
||||||
|
|
||||||
<TextView
|
<ProgressBar
|
||||||
android:text="Loading gallery..."
|
style="?android:attr/progressBarStyleLarge"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="@style/TextAppearance.Medium.Title" />
|
android:layout_gravity="center"
|
||||||
|
android:indeterminateTint="@color/white" />
|
||||||
<ProgressBar
|
</LinearLayout>
|
||||||
style="?android:attr/progressBarStyleLarge"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center" />
|
|
||||||
</LinearLayout>
|
|
||||||
</FrameLayout>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
@ -240,7 +240,7 @@
|
|||||||
<android.support.v4.widget.NestedScrollView
|
<android.support.v4.widget.NestedScrollView
|
||||||
android:id="@+id/description_scrollview"
|
android:id="@+id/description_scrollview"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
@ -249,7 +249,8 @@
|
|||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/guideline">
|
app:layout_constraintTop_toBottomOf="@+id/guideline"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -273,33 +274,20 @@
|
|||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:longClickable="true"/>
|
android:longClickable="true"/>
|
||||||
|
|
||||||
|
<me.gujun.android.taggroup.TagGroup
|
||||||
|
android:id="@+id/manga_genres_tags"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/TagGroup"
|
||||||
|
app:atg_borderStrokeWidth="1dp"
|
||||||
|
app:atg_backgroundColor="@android:color/transparent"
|
||||||
|
app:atg_borderColor="@color/md_blue_A400"
|
||||||
|
app:atg_textColor="@color/md_blue_A400" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v4.widget.NestedScrollView>
|
</android.support.v4.widget.NestedScrollView>
|
||||||
|
|
||||||
<me.gujun.android.taggroup.TagGroup
|
|
||||||
android:id="@+id/manga_genres_tags"
|
|
||||||
style="@style/TagGroup"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/description_scrollview"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:atg_borderStrokeWidth="1dp"
|
|
||||||
app:atg_backgroundColor="@android:color/transparent"
|
|
||||||
app:atg_borderColor="@color/md_blue_A400"
|
|
||||||
app:atg_textColor="@color/md_blue_A400"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_sync"
|
android:id="@+id/action_download_favorites"
|
||||||
android:icon="@drawable/ic_cloud_download_white_24dp"
|
android:icon="@drawable/ic_cloud_download_white_24dp"
|
||||||
android:title="Download favorites"
|
android:title="Download favorites"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
Reference in New Issue
Block a user