diff --git a/app/build.gradle b/app/build.gradle index e4d1cd81c..058b0e089 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,8 +42,8 @@ android { minSdkVersion 16 targetSdkVersion 25 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - versionCode 5003 - versionName "v5.0.3-EH" + versionCode 6101 + versionName "v6.1.1-EH" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" @@ -214,7 +214,7 @@ dependencies { releaseCompile "com.google.firebase:firebase-crash:$firebase_version" //SnappyDB (EH) - compile 'io.paperdb:paperdb:2.0' + compile 'io.paperdb:paperdb:2.1' //JVE (Regex) (EH) compile 'ru.lanwen.verbalregex:java-verbal-expressions:1.4' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0a886481f..5762deea3 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ @@ -106,8 +107,8 @@ + android:label="@string/label_login"> + - - - - - - - - diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt index 35cbb90e3..4ea2402d7 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt @@ -67,7 +67,7 @@ class NHentai(context: Context) : HttpSource() { = parseResultPage(response) override fun mangaDetailsParse(response: Response) - = parseGallery(jsonParser.parse(response.body().string()).asJsonObject) + = parseGallery(jsonParser.parse(response.body()!!.string()).asJsonObject) //Used so we can use a different URL for fetching manga details and opening the details in the browser override fun fetchMangaDetails(manga: SManga): Observable { @@ -85,7 +85,7 @@ class NHentai(context: Context) : HttpSource() { = nhGet(baseUrl + "/api/gallery/" + url.split("/").last()) fun parseResultPage(response: Response): MangasPage { - val res = jsonParser.parse(response.body().string()).asJsonObject + val res = jsonParser.parse(response.body()!!.string()).asJsonObject val error = res.get("error") if(error == null) { @@ -154,7 +154,7 @@ class NHentai(context: Context) : HttpSource() { ?: client.newCall(urlToDetailsRequest(url)) .asObservableSuccess() .map { - rawParseGallery(jsonParser.parse(it.body().string()).asJsonObject) + rawParseGallery(jsonParser.parse(it.body()!!.string()).asJsonObject) }.toBlocking().first() }!! diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt index 163d45345..171cc94cb 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt @@ -4,54 +4,8 @@ import android.support.v7.app.AppCompatActivity import eu.kanade.tachiyomi.util.LocaleHelper abstract class BaseActivity : AppCompatActivity() { - init { @Suppress("LeakingThis") LocaleHelper.updateConfiguration(this) } - - var willLock = false - var disableLock = false - override fun onRestart() { - super.onRestart() - if(willLock && lockEnabled() && !disableLock) { - showLockActivity(this) - } - - willLock = false - } - - override fun onStop() { - super.onStop() - tryLock() - } - - fun tryLock() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - val mUsageStatsManager = getSystemService("usagestats") as UsageStatsManager - val time = System.currentTimeMillis() - // We get usage stats for the last 20 seconds - val stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 20, time) - // Sort the stats by the last time used - if (stats != null) { - val mySortedMap = TreeMap() - for (usageStats in stats) { - mySortedMap.put(usageStats.lastTimeUsed, usageStats) - } - if (!mySortedMap.isEmpty()) { - if(mySortedMap[mySortedMap.lastKey()]?.packageName != packageName) { - willLock = true - } - } - } - } else { - val am = getSystemService(Service.ACTIVITY_SERVICE) as ActivityManager - val tasks: List - tasks = am.getRunningTasks(1) - val running = tasks[0] - if (running.topActivity.packageName != packageName) { - willLock = true - } - } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index aa5d57961..9dd87e1af 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -16,12 +16,6 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) : */ private var mangas: List = emptyList() - //EH - private val sourceManager: SourceManager by injectLazy() - - private val searchEngine = SearchEngine() - private val metadataHelper = MetadataHelper() - var asyncSearchText: String? = null /** @@ -36,49 +30,6 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) : performFilter() } - // --> EH - /** - * Filters the list of manga applying [filterObject] for each element. - * - * @param param the filter. Not used. - */ - override fun updateDataSet(param: String?) { - //Async search filter (EH) - val filtered = asyncSearchText?.let { search -> - mangas.filter { - filterObject(it, search) - } - } ?: mangas - //The rest of the filters run on the main loop - Handler(Looper.getMainLooper()).post { - filterItems(filtered) - notifyDataSetChanged() - } - } - - /** - * Filters a manga depending on a query. - * - * @param manga the manga to filter. - * @param query the query to apply. - * @return true if the manga should be included, false otherwise. - */ - override fun filterObject(manga: Manga, query: String): Boolean = with(manga) { - if(!isLewdSource(manga.source)) { - //Regular searching for normal manga - title.toLowerCase().contains(query) || - author != null && author!!.toLowerCase().contains(query) - } else { - //Use gallery search engine for EH manga - val metadata = metadataHelper.fetchMetadata(manga.url, manga.source) - metadata?.let { - searchEngine.matches(it, searchEngine.parseQuery(query)) - } ?: title.contains(query, ignoreCase = true) //Use regular searching when the metadata is not set up for this gallery - } - } - - // <-- EH - /** * Returns the position in the adapter for the given manga. * @@ -89,7 +40,9 @@ class LibraryCategoryAdapter(view: LibraryCategoryView) : } fun performFilter() { - updateDataSet(mangas.filter { it.filter(searchText) }) + updateDataSet(mangas.filter { + it.filter(searchText) + }) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt index ef3f3f247..109ce113d 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt @@ -102,19 +102,6 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att fun onBind(category: Category) { this.category = category - //TODO Fix - // --> EH - val presenter = fragment.presenter - - searchSubscription = presenter - .searchSubject - .debounce(10L, TimeUnit.MILLISECONDS) - .subscribe { text -> //Debounce search (EH) - adapter.asyncSearchText = text?.trim()?.toLowerCase() - adapter.updateDataSet() - } - // <-- EH - adapter.mode = if (controller.selectedMangas.isNotEmpty()) { FlexibleAdapter.MODE_MULTI } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index 2e78c001d..d73478491 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -12,10 +12,18 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.util.inflate import eu.kanade.tachiyomi.widget.AutofitRecyclerView +import exh.isLewdSource +import exh.metadata.MetadataHelper +import exh.search.SearchEngine import kotlinx.android.synthetic.main.catalogue_grid_item.view.* class LibraryItem(val manga: Manga) : AbstractFlexibleItem(), IFilterable { + // --> EH + private val searchEngine = SearchEngine() + private val metadataHelper = MetadataHelper() + // <-- EH + override fun getLayoutRes(): Int { return R.layout.catalogue_grid_item } @@ -53,6 +61,15 @@ class LibraryItem(val manga: Manga) : AbstractFlexibleItem(), IFi * @return true if the manga should be included, false otherwise. */ override fun filter(constraint: String): Boolean { + // --> EH + if(!isLewdSource(manga.source)) { + //Use gallery search engine for EH manga + metadataHelper.fetchMetadata(manga.url, manga.source)?.let { + return searchEngine.matches(it, searchEngine.parseQuery(constraint)) + } + } + // <-- EH + return manga.title.contains(constraint, true) || (manga.author?.contains(constraint, true) ?: false) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 50e7b5542..2adeadc5f 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -1,8 +1,13 @@ package eu.kanade.tachiyomi.ui.main import android.animation.ObjectAnimator +import android.app.ActivityManager +import android.app.Service +import android.app.usage.UsageStats +import android.app.usage.UsageStatsManager import android.content.Intent import android.graphics.Color +import android.os.Build import android.os.Bundle import android.support.v4.view.GravityCompat import android.support.v4.widget.DrawerLayout @@ -10,6 +15,8 @@ import android.support.v7.graphics.drawable.DrawerArrowDrawable import android.view.ViewGroup import com.bluelinelabs.conductor.* import com.bluelinelabs.conductor.changehandler.FadeChangeHandler +import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler +import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler import eu.kanade.tachiyomi.Migrations import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper @@ -26,8 +33,14 @@ import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersController import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController import eu.kanade.tachiyomi.ui.setting.SettingsMainController +import exh.ui.batchadd.BatchAddController +import exh.ui.lock.LockChangeHandler +import exh.ui.lock.LockController +import exh.ui.lock.lockEnabled +import exh.ui.lock.notifyLockSecurity import kotlinx.android.synthetic.main.main_activity.* import uy.kohesive.injekt.injectLazy +import java.util.* class MainActivity : BaseActivity() { @@ -86,9 +99,8 @@ class MainActivity : BaseActivity() { R.id.nav_drawer_recently_read -> setRoot(RecentlyReadController(), id) R.id.nav_drawer_catalogues -> setRoot(CatalogueController(), id) R.id.nav_drawer_latest_updates -> setRoot(LatestUpdatesController(), id) - //TODO // --> EH - R.id.nav_drawer_batch_add -> setFragment(BatchAddFragment.newInstance(), id) + R.id.nav_drawer_batch_add -> setRoot(BatchAddController(), id) // <-- EH R.id.nav_drawer_downloads -> { router.pushController(RouterTransaction.with(DownloadController()) @@ -137,6 +149,17 @@ class MainActivity : BaseActivity() { }) + //Show lock + if (savedInstanceState == null) { + val lockEnabled = lockEnabled(preferences) + if (lockEnabled) { + doLock() + + //Check lock security + notifyLockSecurity(this) + } + } + syncActivityViewWithController(router.backstack.lastOrNull()?.controller()) if (savedInstanceState == null) { @@ -144,15 +167,6 @@ class MainActivity : BaseActivity() { if (Migrations.upgrade(preferences)) { ChangelogDialogController().showDialog(router) } - - //Show lock - val lockEnabled = lockEnabled(preferences) - if(lockEnabled) { - showLockActivity(this) - - //Check lock security - notifyLockSecurity(this) - } } } @@ -253,6 +267,54 @@ class MainActivity : BaseActivity() { } } + // --> EH + //Lock code + var willLock = false + var disableLock = false + override fun onRestart() { + super.onRestart() + if(willLock && lockEnabled() && !disableLock) { + doLock() + } + + willLock = false + } + + override fun onStop() { + super.onStop() + tryLock() + } + + fun tryLock() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + val mUsageStatsManager = getSystemService("usagestats") as UsageStatsManager + val time = System.currentTimeMillis() + // We get usage stats for the last 20 seconds + val sortedStats = + mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, + time - 1000 * 20, + time) + ?.associateBy { + it.lastTimeUsed + }?.toSortedMap() + if(sortedStats != null && sortedStats.isNotEmpty()) + if(sortedStats[sortedStats.lastKey()]?.packageName != packageName) + willLock = true + } else { + val am = getSystemService(Service.ACTIVITY_SERVICE) as ActivityManager + val running = am.getRunningTasks(1)[0] + if (running.topActivity.packageName != packageName) { + willLock = true + } + } + } + + fun doLock() { + router.pushController(RouterTransaction.with(LockController()) + .popChangeHandler(LockChangeHandler())) + } + // <-- EH + companion object { // Shortcut actions const val SHORTCUT_LIBRARY = "eu.kanade.tachiyomi.SHOW_LIBRARY" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt index 63f1bbb24..650138ce5 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt @@ -1,19 +1,15 @@ package eu.kanade.tachiyomi.ui.setting import android.content.Intent -import android.os.Bundle import android.support.v7.preference.PreferenceScreen -import android.view.View -import eu.kanade.tachiyomi.data.preference.PreferencesHelper import exh.ui.migration.MetadataFetchDialog import exh.ui.login.LoginActivity -import uy.kohesive.injekt.injectLazy /** * EH Settings fragment */ -class SettingsEhFragment : SettingsController() { +class SettingsEhController : SettingsController() { override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) { title = "E-Hentai" @@ -27,13 +23,24 @@ class SettingsEhFragment : SettingsController() { .asObservable().subscribeUntilDestroy { isChecked = it } + + onChange { newVal -> + newVal as Boolean + if(!newVal) { + preferences.enableExhentai().set(false) + true + } else { + startActivity(Intent(context, LoginActivity::class.java)) + false + } + } } switchPreference { title = "Use Hentai@Home Network" summary = "Do you wish to load images through the Hentai@Home Network? Disabling this option will reduce the amount of pages you are able to view" key = "enable_hah" - defaultValue = "true" + defaultValue = true } switchPreference { @@ -41,11 +48,11 @@ class SettingsEhFragment : SettingsController() { summaryOn = "Currently showing Japanese titles in search results. Clear the chapter cache after changing this (in the Advanced section)" summaryOff = "Currently showing English/Romanized titles in search results. Clear the chapter cache after changing this (in the Advanced section)" key = "use_jp_title" - defaultValue = "false" + defaultValue = false } switchPreference { - defaultValue = "true" + defaultValue = true key = "secure_exh" title = "Secure ExHentai/E-Hentai" summary = "Use the HTTPS version of ExHentai/E-Hentai." @@ -91,15 +98,13 @@ class SettingsEhFragment : SettingsController() { "rc_2", "rc_3" ) - dependency = "enable_exhentai" - } + }.dependency = "enable_exhentai" listPreference { defaultValue = "tr_2" title = "Thumbnail rows" summary = "Affects loading speeds. It is recommended to set this to the maximum size your hath perks allow" key = "ex_thumb_rows" - dependency = "enable_exhentai" entries = arrayOf( "4", "10 (requires 'More Thumbs' hath perk)", @@ -112,7 +117,7 @@ class SettingsEhFragment : SettingsController() { "tr_10", "tr_20" ) - } + }.dependency = "enable_exhentai" preferenceCategory { title = "Advanced" @@ -122,48 +127,14 @@ class SettingsEhFragment : SettingsController() { title = "Migrate library metadata" isPersistent = false key = "ex_migrate_library" - summary = "Fetch the library metadata to enable tag searching in the library. This button will be visible even if you have already fetched the metadata" /> + summary = "Fetch the library metadata to enable tag searching in the library. This button will be visible even if you have already fetched the metadata" + + onClick { + activity?.let { + MetadataFetchDialog().askMigration(it) + } + } } } } - - private val preferences: PreferencesHelper by injectLazy() - - val enableExhentaiPref by lazy { - findPreference("enable_exhentai") as SwitchPreference - } - - val migrateLibraryPref by lazy { - findPreference("ex_migrate_library") as Preference - } - - val useJpTitlePref by lazy { - findPreference("use_jp_title") as SwitchPreference - } - - override fun onViewCreated(view: View, savedState: Bundle?) { - super.onViewCreated(view, savedState) - - enableExhentaiPref.setOnPreferenceChangeListener { preference, newVal -> - newVal as Boolean - (activity as SettingsActivity).parentFlags = SettingsActivity.FLAG_EH_RECREATE - if(!newVal) { - preferences.enableExhentai().set(false) - true - } else { - startActivity(Intent(context, LoginActivity::class.java)) - false - } - } - - migrateLibraryPref.setOnPreferenceClickListener { - MetadataFetchDialog().askMigration(activity) - true - } - - useJpTitlePref.setOnPreferenceChangeListener { preference, any -> - (activity as SettingsActivity).parentFlags = SettingsActivity.FLAG_EH_RECREATE - true - } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index 5a755b4a6..ee2a241f9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -13,6 +13,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.util.LocaleHelper +import exh.ui.lock.LockPreference import kotlinx.android.synthetic.main.pref_library_columns.view.* import rx.Observable import uy.kohesive.injekt.Injekt @@ -175,6 +176,13 @@ class SettingsGeneralController : SettingsController() { true } } + LockPreference(context).apply { + key = "pref_app_lock" + title = "Application lock" + isPersistent = false + + addPreference(this) + } } class LibraryColumnsDialog : DialogController() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 4953429fb..171d62629 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -48,6 +48,12 @@ class SettingsMainController : SettingsController() { titleRes = R.string.backup onClick { navigateTo(SettingsBackupController()) } } + preference { + iconRes = R.drawable.eh_ic_ehlogo_red_24dp + iconTint = tintColor + titleRes = R.string.pref_category_eh + onClick { navigateTo(SettingsEhController()) } + } preference { iconRes = R.drawable.ic_code_black_24dp iconTint = tintColor diff --git a/app/src/main/java/exh/GalleryAdder.kt b/app/src/main/java/exh/GalleryAdder.kt index d34556b78..4ed75f612 100755 --- a/app/src/main/java/exh/GalleryAdder.kt +++ b/app/src/main/java/exh/GalleryAdder.kt @@ -56,68 +56,75 @@ class GalleryAdder { val outJson = JsonParser().parse(networkHelper.client.newCall(Request.Builder() .url(API_BASE) .post(RequestBody.create(JSON, json.toString())) - .build()).execute().body().string()).obj + .build()).execute().body()!!.string()).obj val obj = outJson["tokenlist"].array.first() return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/" } - fun addGallery(url: String, fav: Boolean = false): Manga { - val urlObj = Uri.parse(url) - val source = when(urlObj.host) { - "g.e-hentai.org", "e-hentai.org" -> EH_SOURCE_ID - "exhentai.org" -> EXH_SOURCE_ID - else -> throw MalformedURLException("Not a valid gallery URL!") - } - - val realUrl = when (urlObj.pathSegments.first().toLowerCase()) { - "g" -> { - //Is already gallery page, do nothing - url - } - "s" -> { - //Is page, fetch gallery token and use that - getGalleryUrlFromPage(url) - } - else -> { - throw MalformedURLException("Not a valid gallery URL!") - } - } - - val sourceObj = sourceManager.get(source) - ?: throw IllegalStateException("Could not find EH source!") - - val pathOnlyUrl = getUrlWithoutDomain(realUrl) - - //Use manga in DB if possible, otherwise, make a new manga - val manga = db.getManga(pathOnlyUrl, source).executeAsBlocking() - ?: Manga.create(source).apply { - this.url = pathOnlyUrl - title = realUrl - } - - //Copy basics - manga.copyFrom(sourceObj.fetchMangaDetails(manga).toBlocking().first()) - - //Apply metadata - metadataHelper.fetchEhMetadata(realUrl, isExSource(source))?.copyTo(manga) - - if(fav) manga.favorite = true - - db.insertManga(manga).executeAsBlocking().insertedId()?.let { - manga.id = it - } - - //Fetch and copy chapters + fun addGallery(url: String, fav: Boolean = false): GalleryAddEvent { try { - sourceObj.fetchChapterList(manga).map { - syncChaptersWithSource(db, it, manga, sourceObj) - }.toBlocking().first() - } catch (e: Exception) { - Timber.w(e, "Failed to update chapters for gallery: ${manga.title}!") - } + val urlObj = Uri.parse(url) + val source = when (urlObj.host) { + "g.e-hentai.org", "e-hentai.org" -> EH_SOURCE_ID + "exhentai.org" -> EXH_SOURCE_ID + else -> return GalleryAddEvent.Fail.UnknownType(url) + } - return manga + val realUrl = when (urlObj.pathSegments.first().toLowerCase()) { + "g" -> { + //Is already gallery page, do nothing + url + } + "s" -> { + //Is page, fetch gallery token and use that + getGalleryUrlFromPage(url) + } + else -> { + return GalleryAddEvent.Fail.UnknownType(url) + } + } + + val sourceObj = sourceManager.get(source) + ?: return GalleryAddEvent.Fail.Error(url, "Could not find EH source!") + + val pathOnlyUrl = getUrlWithoutDomain(realUrl) + + //Use manga in DB if possible, otherwise, make a new manga + val manga = db.getManga(pathOnlyUrl, source).executeAsBlocking() + ?: Manga.create(source).apply { + this.url = pathOnlyUrl + title = realUrl + } + + //Copy basics + manga.copyFrom(sourceObj.fetchMangaDetails(manga).toBlocking().first()) + + //Apply metadata + metadataHelper.fetchEhMetadata(realUrl, isExSource(source))?.copyTo(manga) + + if (fav) manga.favorite = true + + db.insertManga(manga).executeAsBlocking().insertedId()?.let { + manga.id = it + } + + //Fetch and copy chapters + try { + sourceObj.fetchChapterList(manga).map { + syncChaptersWithSource(db, it, manga, sourceObj) + }.toBlocking().first() + } catch (e: Exception) { + Timber.e(e, "Failed to update chapters for gallery: ${manga.title}!") + return GalleryAddEvent.Fail.Error(url, "Failed to update chapters for gallery: $url") + } + + return GalleryAddEvent.Success(url, manga) + } catch(e: Exception) { + Timber.e(e, "Could not add gallery!") + return GalleryAddEvent.Fail.Error(url, + ((e.message ?: "Unknown error!") + " (Gallery: $url)").trim()) + } } private fun getUrlWithoutDomain(orig: String): String { @@ -133,4 +140,28 @@ class GalleryAdder { return orig } } +} + +sealed class GalleryAddEvent { + abstract val logMessage: String + abstract val galleryUrl: String + open val galleryTitle: String? = null + + class Success(override val galleryUrl: String, + val manga: Manga): GalleryAddEvent() { + override val logMessage = "[OK] Added gallery: $galleryTitle" + override val galleryTitle: String + get() = manga.title + } + + sealed class Fail: GalleryAddEvent() { + class UnknownType(override val galleryUrl: String): Fail() { + override val logMessage = "[ERROR] Unknown gallery type for gallery: $galleryUrl" + } + + class Error(override val galleryUrl: String, + val message: String): Fail() { + override val logMessage = "[ERROR] $message" + } + } } \ No newline at end of file diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddController.kt b/app/src/main/java/exh/ui/batchadd/BatchAddController.kt index a4d994d0b..401cd9120 100755 --- a/app/src/main/java/exh/ui/batchadd/BatchAddController.kt +++ b/app/src/main/java/exh/ui/batchadd/BatchAddController.kt @@ -1,131 +1,145 @@ package exh.ui.batchadd -import android.content.pm.ActivityInfo import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.TextView import com.afollestad.materialdialogs.MaterialDialog +import com.jakewharton.rxbinding.view.clicks import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment -import exh.GalleryAdder -import exh.metadata.nullIfBlank -import kotlinx.android.synthetic.main.eh_fragment_batch_add.* -import timber.log.Timber -import kotlin.concurrent.thread +import eu.kanade.tachiyomi.ui.base.controller.NucleusController +import eu.kanade.tachiyomi.util.combineLatest +import eu.kanade.tachiyomi.util.plusAssign +import kotlinx.android.synthetic.main.eh_fragment_batch_add.view.* +import rx.android.schedulers.AndroidSchedulers +import rx.subscriptions.CompositeSubscription /** - * LoginActivity + * Batch add screen */ +class BatchAddController : NucleusController() { + override fun inflateView(inflater: LayoutInflater, container: ViewGroup) = + inflater.inflate(R.layout.eh_fragment_batch_add, container, false)!! -class BatchAddFragment : BaseFragment() { + override fun getTitle() = "Batch add" - private val galleryAdder by lazy { GalleryAdder() } + override fun createPresenter() = BatchAddPresenter() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?) - = inflater.inflate(R.layout.eh_fragment_batch_add, container, false)!! + override fun onViewCreated(view: View, savedViewState: Bundle?) { + super.onViewCreated(view, savedViewState) - override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { - setToolbarTitle("Batch add") - - setup() - } - - fun setup() { - btn_add_galleries.setOnClickListener { - val galleries = galleries_box.text.toString() - //Check text box has content - if(galleries.isNullOrBlank()) { - noGalleriesSpecified() - return@setOnClickListener + with(view) { + btn_add_galleries.clicks().subscribeUntilDestroy { + addGalleries(galleries_box.text.toString()) } - //Too lazy to actually deal with orientation changes - activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR + progress_dismiss_btn.clicks().subscribeUntilDestroy { + presenter.currentlyAddingRelay.call(false) + } - val splitGalleries = galleries.split("\n").map { - it.trim().nullIfBlank() - }.filterNotNull() + val progressSubscriptions = CompositeSubscription() - val dialog = MaterialDialog.Builder(context) - .title("Adding galleries...") - .progress(false, splitGalleries.size, true) - .cancelable(false) - .canceledOnTouchOutside(false) + presenter.currentlyAddingRelay + .observeOn(AndroidSchedulers.mainThread()) + .subscribeUntilDestroy { + progressSubscriptions.clear() + if(it) { + showProgress(this) + progressSubscriptions += presenter.progressRelay + .observeOn(AndroidSchedulers.mainThread()) + .combineLatest(presenter.progressTotalRelay, { progress, total -> + //Show hide dismiss button + progress_dismiss_btn.visibility = + if(progress == total) + View.VISIBLE + else View.GONE + + formatProgress(progress, total) + }).subscribeUntilDestroy { + progress_text.text = it + } + + progressSubscriptions += presenter.progressTotalRelay + .observeOn(AndroidSchedulers.mainThread()) + .subscribeUntilDestroy { + progress_bar.max = it + } + + progressSubscriptions += presenter.progressRelay + .observeOn(AndroidSchedulers.mainThread()) + .subscribeUntilDestroy { + progress_bar.progress = it + } + + presenter.eventRelay + ?.observeOn(AndroidSchedulers.mainThread()) + ?.subscribeUntilDestroy { + progress_log.append("$it\n") + }?.let { + progressSubscriptions += it + } + } else hideProgress(this) + } + } + } + + private val View.progressViews + get() = listOf( + progress_title_view, + progress_log_wrapper, + progress_bar, + progress_text, + progress_dismiss_btn + ) + + private val View.inputViews + get() = listOf( + input_title_view, + galleries_box, + btn_add_galleries + ) + + private var List.visibility: Int + get() = throw UnsupportedOperationException() + set(v) { forEach { it.visibility = v } } + + private fun showProgress(target: View? = view) { + target?.apply { + progressViews.visibility = View.VISIBLE + inputViews.visibility = View.GONE + }?.progress_log?.text = "" + } + + private fun hideProgress(target: View? = view) { + target?.apply { + progressViews.visibility = View.GONE + inputViews.visibility = View.VISIBLE + }?.galleries_box?.setText("", TextView.BufferType.EDITABLE) + } + + private fun formatProgress(progress: Int, total: Int) = "$progress/$total" + + private fun addGalleries(galleries: String) { + //Check text box has content + if(galleries.isBlank()) { + noGalleriesSpecified() + return + } + + presenter.addGalleries(galleries) + } + + private fun noGalleriesSpecified() { + activity?.let { + MaterialDialog.Builder(it) + .title("No galleries to add!") + .content("You must specify at least one gallery to add!") + .positiveText("Ok") + .onPositive { materialDialog, _ -> materialDialog.dismiss() } + .cancelable(true) + .canceledOnTouchOutside(true) .show() - - val succeeded = mutableListOf() - val failed = mutableListOf() - - thread { - splitGalleries.forEachIndexed { i, s -> - activity.runOnUiThread { - dialog.setContent("Processing: $s") - } - if(addGallery(s)) { - succeeded.add(s) - } else { - failed.add(s) - } - activity.runOnUiThread { - dialog.setProgress(i + 1) - } - } - - //Show report - val succeededCount = succeeded.size - val failedCount = failed.size - - if(succeeded.isEmpty()) succeeded += "None" - if(failed.isEmpty()) failed += "None" - val succeededReport = succeeded.joinToString(separator = "\n", prefix = "Added:\n") - val failedReport = failed.joinToString(separator = "\n", prefix = "Failed:\n") - - val summary = "Summary:\nAdded: $succeededCount gallerie(s)\nFailed: $failedCount gallerie(s)" - - val report = listOf(succeededReport, failedReport, summary).joinToString(separator = "\n\n") - - activity.runOnUiThread { - //Enable orientation changes again - activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR - - dialog.dismiss() - - MaterialDialog.Builder(context) - .title("Batch add report") - .content(report) - .positiveText("Ok") - .cancelable(true) - .canceledOnTouchOutside(true) - .show() - } - } - } } - - fun addGallery(url: String): Boolean { - try { - galleryAdder.addGallery(url, true) - } catch(t: Throwable) { - Timber.e(t, "Could not add gallery!") - return false - } - return true - } - - fun noGalleriesSpecified() { - MaterialDialog.Builder(context) - .title("No galleries to add!") - .content("You must specify at least one gallery to add!") - .positiveText("Ok") - .onPositive { materialDialog, _ -> materialDialog.dismiss() } - .cancelable(true) - .canceledOnTouchOutside(true) - .show() - } - - companion object { - fun newInstance() = BatchAddFragment() - } } diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt index 439487748..40dffcb15 100644 --- a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt +++ b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt @@ -1,5 +1,51 @@ package exh.ui.batchadd -/** - * Created by nulldev on 8/23/17. - */ +import com.jakewharton.rxrelay.BehaviorRelay +import com.jakewharton.rxrelay.ReplayRelay +import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter +import exh.GalleryAddEvent +import exh.GalleryAdder +import exh.metadata.nullIfBlank +import kotlin.concurrent.thread + +class BatchAddPresenter: BasePresenter() { + + private val galleryAdder by lazy { GalleryAdder() } + + val progressTotalRelay = BehaviorRelay.create(0)!! + val progressRelay = BehaviorRelay.create(0)!! + var eventRelay: ReplayRelay? = null + val currentlyAddingRelay = BehaviorRelay.create(false)!! + + fun addGalleries(galleries: String) { + eventRelay = ReplayRelay.create() + val splitGalleries = galleries.split("\n").map { + it.trim().nullIfBlank() + }.filterNotNull() + + progressRelay.call(0) + progressTotalRelay.call(splitGalleries.size) + + currentlyAddingRelay.call(true) + + thread { + val succeeded = mutableListOf() + val failed = mutableListOf() + + splitGalleries.forEachIndexed { i, s -> + val result = galleryAdder.addGallery(s, true) + if(result is GalleryAddEvent.Success) { + succeeded.add(s) + } else { + failed.add(s) + } + progressRelay.call(i + 1) + eventRelay?.call(result.logMessage) + } + + //Show report + val summary = "\nSummary:\nAdded: ${succeeded.size} gallerie(s)\nFailed: ${failed.size} gallerie(s)" + eventRelay?.call(summary) + } + } +} diff --git a/app/src/main/java/exh/ui/intercept/InterceptActivity.kt b/app/src/main/java/exh/ui/intercept/InterceptActivity.kt index d46811b7d..f3adbb2b2 100755 --- a/app/src/main/java/exh/ui/intercept/InterceptActivity.kt +++ b/app/src/main/java/exh/ui/intercept/InterceptActivity.kt @@ -6,12 +6,11 @@ import android.view.MenuItem import com.afollestad.materialdialogs.MaterialDialog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.base.activity.BaseActivity -import eu.kanade.tachiyomi.ui.manga.MangaActivity import exh.GalleryAdder -import kotlinx.android.synthetic.main.toolbar.* import timber.log.Timber import kotlin.concurrent.thread +//TODO :( class InterceptActivity : BaseActivity() { private val galleryAdder = GalleryAdder() @@ -19,12 +18,9 @@ class InterceptActivity : BaseActivity() { var finished = false override fun onCreate(savedInstanceState: Bundle?) { - setAppTheme() super.onCreate(savedInstanceState) setContentView(R.layout.eh_activity_intercept) - setupToolbar(toolbar, backNavigation = false) - if(savedInstanceState == null) thread { setup() } } @@ -54,8 +50,9 @@ class InterceptActivity : BaseActivity() { if(Intent.ACTION_VIEW == intent.action) { val manga = galleryAdder.addGallery(intent.dataString) - if(!finished) - startActivity(MangaActivity.newIntent(this, manga, true)) + //TODO +// if(!finished) +// startActivity(MangaActivity.newIntent(this, manga, true)) onBackPressed() } } diff --git a/app/src/main/java/exh/ui/lock/LockActivity.kt b/app/src/main/java/exh/ui/lock/LockActivity.kt deleted file mode 100755 index a8e428541..000000000 --- a/app/src/main/java/exh/ui/lock/LockActivity.kt +++ /dev/null @@ -1,60 +0,0 @@ -package exh.ui.lock - -import android.os.Bundle -import com.afollestad.materialdialogs.MaterialDialog -import com.andrognito.pinlockview.PinLockListener -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.ui.base.activity.BaseActivity -import kotlinx.android.synthetic.main.activity_lock.* -import uy.kohesive.injekt.injectLazy - -class LockActivity : BaseActivity() { - - val prefs: PreferencesHelper by injectLazy() - - override fun onCreate(savedInstanceState: Bundle?) { - disableLock = true - - setTheme(R.style.Theme_Tachiyomi_Dark) - super.onCreate(savedInstanceState) - - if(!lockEnabled(prefs)) { - finish() - return - } - - setContentView(R.layout.activity_lock) - - pin_lock_view.attachIndicatorDots(indicator_dots) - - pin_lock_view.pinLength = prefs.lockLength().getOrDefault() - pin_lock_view.setPinLockListener(object : PinLockListener { - override fun onEmpty() {} - - override fun onComplete(pin: String) { - if(sha512(pin, prefs.lockSalt().get()!!) == prefs.lockHash().get()) { - //Yay! - finish() - } else { - MaterialDialog.Builder(this@LockActivity) - .title("PIN code incorrect") - .content("The PIN code you entered is incorrect. Please try again.") - .cancelable(true) - .canceledOnTouchOutside(true) - .positiveText("Ok") - .autoDismiss(true) - .show() - pin_lock_view.resetPinLockView() - } - } - - override fun onPinChange(pinLength: Int, intermediatePin: String?) {} - }) - } - - override fun onBackPressed() { - moveTaskToBack(true) - } -} diff --git a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt new file mode 100644 index 000000000..e70227396 --- /dev/null +++ b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt @@ -0,0 +1,41 @@ +package exh.ui.lock + +import android.animation.Animator +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.view.View +import android.view.ViewGroup +import com.bluelinelabs.conductor.ControllerChangeHandler +import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler +import java.util.ArrayList + +class LockChangeHandler : AnimatorChangeHandler { + constructor(): super() + + constructor(removesFromViewOnPush: Boolean) : super(removesFromViewOnPush) + + constructor(duration: Long) : super(duration) + + constructor(duration: Long, removesFromViewOnPush: Boolean) : super(duration, removesFromViewOnPush) + + override fun getAnimator(container: ViewGroup, from: View?, to: View?, isPush: Boolean, toAddedToContainer: Boolean): Animator { + val animator = AnimatorSet() + val viewAnimators = ArrayList() + + if (!isPush && from != null) { + viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_X, 5f)) + viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_Y, 5f)) + viewAnimators.add(ObjectAnimator.ofFloat(from, View.ALPHA, 0f)) + } + + animator.playTogether(viewAnimators) + return animator + } + + override fun resetFromView(from: View) {} + + override fun copy(): ControllerChangeHandler = + LockChangeHandler(animationDuration, removesFromViewOnPush()) + +} + diff --git a/app/src/main/java/exh/ui/lock/LockController.kt b/app/src/main/java/exh/ui/lock/LockController.kt new file mode 100755 index 000000000..59e5ff6b3 --- /dev/null +++ b/app/src/main/java/exh/ui/lock/LockController.kt @@ -0,0 +1,68 @@ +package exh.ui.lock + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.afollestad.materialdialogs.MaterialDialog +import com.andrognito.pinlockview.PinLockListener +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.ui.base.controller.NucleusController +import kotlinx.android.synthetic.main.activity_lock.view.* +import uy.kohesive.injekt.injectLazy + +class LockController : NucleusController() { + override fun inflateView(inflater: LayoutInflater, container: ViewGroup) + = inflater.inflate(R.layout.activity_lock, container, false)!! + + override fun createPresenter() = LockPresenter() + + override fun getTitle() = "Application locked" + + val prefs: PreferencesHelper by injectLazy() + + override fun onViewCreated(view: View, savedViewState: Bundle?) { + super.onViewCreated(view, savedViewState) + + if(!lockEnabled(prefs)) { + closeLock() + return + } + + with(view) { + pin_lock_view.attachIndicatorDots(indicator_dots) + + pin_lock_view.pinLength = prefs.lockLength().getOrDefault() + pin_lock_view.setPinLockListener(object : PinLockListener { + override fun onEmpty() {} + + override fun onComplete(pin: String) { + if (sha512(pin, prefs.lockSalt().get()!!) == prefs.lockHash().get()) { + //Yay! + closeLock() + } else { + MaterialDialog.Builder(context) + .title("PIN code incorrect") + .content("The PIN code you entered is incorrect. Please try again.") + .cancelable(true) + .canceledOnTouchOutside(true) + .positiveText("Ok") + .autoDismiss(true) + .show() + pin_lock_view.resetPinLockView() + } + } + + override fun onPinChange(pinLength: Int, intermediatePin: String?) {} + }) + } + } + + fun closeLock() { + router.popCurrentController() + } + + override fun handleBack() = true +} diff --git a/app/src/main/java/exh/ui/lock/LockPreference.kt b/app/src/main/java/exh/ui/lock/LockPreference.kt index cc7da2646..8985d3e21 100755 --- a/app/src/main/java/exh/ui/lock/LockPreference.kt +++ b/app/src/main/java/exh/ui/lock/LockPreference.kt @@ -17,7 +17,7 @@ import java.security.SecureRandom class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : Preference(context, attrs) { - val secureRandom by lazy { SecureRandom() } + private val secureRandom by lazy { SecureRandom() } val prefs: PreferencesHelper by injectLazy() @@ -26,12 +26,11 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut updateSummary() } - fun updateSummary() { - if(lockEnabled(prefs)) { - summary = "Application is locked" - } else { - summary = "Application is not locked, tap to lock" - } + private fun updateSummary() { + summary = if(lockEnabled(prefs)) + "Application is locked" + else + "Application is not locked, tap to lock" } override fun onClick() { @@ -65,7 +64,7 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut } } - fun savePassword(password: String) { + private fun savePassword(password: String) { val salt: String? val hash: String? val length: Int diff --git a/app/src/main/java/exh/ui/lock/LockPresenter.kt b/app/src/main/java/exh/ui/lock/LockPresenter.kt new file mode 100644 index 000000000..22c02d31c --- /dev/null +++ b/app/src/main/java/exh/ui/lock/LockPresenter.kt @@ -0,0 +1,6 @@ +package exh.ui.lock + +import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter + +class LockPresenter: BasePresenter() + diff --git a/app/src/main/java/exh/ui/lock/LockUtils.kt b/app/src/main/java/exh/ui/lock/LockUtils.kt index e2e88897b..3ecc4aec0 100755 --- a/app/src/main/java/exh/ui/lock/LockUtils.kt +++ b/app/src/main/java/exh/ui/lock/LockUtils.kt @@ -44,13 +44,6 @@ fun lockEnabled(prefs: PreferencesHelper = Injekt.get()) && prefs.lockSalt().get() != null && prefs.lockLength().getOrDefault() != -1 -/** - * Lock the screen - */ -fun showLockActivity(activity: Activity) { - activity.startActivity(Intent(activity, LockActivity::class.java)) -} - /** * Check if the lock will function properly * diff --git a/app/src/main/java/exh/ui/login/LoginActivity.kt b/app/src/main/java/exh/ui/login/LoginActivity.kt index a205b50ec..a997969fb 100755 --- a/app/src/main/java/exh/ui/login/LoginActivity.kt +++ b/app/src/main/java/exh/ui/login/LoginActivity.kt @@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.source.online.all.EHentai import eu.kanade.tachiyomi.ui.base.activity.BaseActivity import exh.EXH_SOURCE_ID import kotlinx.android.synthetic.main.eh_activity_login.* -import kotlinx.android.synthetic.main.toolbar.* import rx.Observable import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers @@ -34,13 +33,10 @@ class LoginActivity : BaseActivity() { val sourceManager: SourceManager by injectLazy() override fun onCreate(savedInstanceState: Bundle?) { - setAppTheme() super.onCreate(savedInstanceState) setContentView(R.layout.eh_activity_login) setup() - - setupToolbar(toolbar, backNavigation = false) } fun setup() { @@ -187,7 +183,7 @@ class LoginActivity : BaseActivity() { document.getElementsByName('submit')[0].style.visibility = 'visible'; document.querySelector('td[width="60%"][valign="top"]').style.visibility = 'visible'; - function hide(e) {if(e !== null && e !== undefined) e.style.display = 'none';} + function hide(e) {if(e != null) e.style.display = 'none';} hide(document.querySelector(".errorwrap")); hide(document.querySelector('td[width="40%"][valign="top"]')); @@ -202,7 +198,7 @@ class LoginActivity : BaseActivity() { hide(fd[2]); hide(child.querySelector('br')); var error = document.querySelector(".page > div > .borderwrap"); - if(error !== null) error.style.visibility = 'visible'; + if(error != null) error.style.visibility = 'visible'; hide(fh[0]); hide(fh[1]); hide(document.querySelector("#gfooter")); @@ -211,7 +207,7 @@ class LoginActivity : BaseActivity() { e.style.color = "white"; }); var pc = document.querySelector(".postcolor"); - if(pc !== null) pc.style.color = "#26353F"; + if(pc != null) pc.style.color = "#26353F"; })() """ } diff --git a/app/src/main/res/layout/activity_lock.xml b/app/src/main/res/layout/activity_lock.xml index e6898f560..7005ce1ba 100755 --- a/app/src/main/res/layout/activity_lock.xml +++ b/app/src/main/res/layout/activity_lock.xml @@ -1,29 +1,29 @@ - + android:layout_height="match_parent" + android:background="@color/backgroundDark"> + app:layout_constraintTop_toBottomOf="@+id/indicator_dots" /> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_chainStyle="packed" /> \ No newline at end of file diff --git a/app/src/main/res/layout/eh_activity_intercept.xml b/app/src/main/res/layout/eh_activity_intercept.xml index 518bb973e..3c5209a39 100755 --- a/app/src/main/res/layout/eh_activity_intercept.xml +++ b/app/src/main/res/layout/eh_activity_intercept.xml @@ -17,8 +17,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - - + android:layout_height="match_parent" + android:animateLayoutChanges="true" + android:padding="16dp "> + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintLeft_toLeftOf="@+id/input_title_view" + app:layout_constraintRight_toRightOf="@+id/input_title_view" + app:layout_constraintTop_toBottomOf="@+id/input_title_view" />