diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bc1e14c52..72faea00a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -105,6 +105,34 @@ android:parentActivityName=".ui.setting.SettingsActivity" > + + + + + + + + + + + + + + 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 bd2371111..e372b4fed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.ui.library.LibraryFragment import eu.kanade.tachiyomi.ui.recent_updates.RecentChaptersFragment import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadFragment import eu.kanade.tachiyomi.ui.setting.SettingsActivity +import exh.ui.batchadd.BatchAddFragment import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.toolbar.* import uy.kohesive.injekt.injectLazy @@ -63,6 +64,7 @@ class MainActivity : BaseActivity() { R.id.nav_drawer_recently_read -> setFragment(RecentlyReadFragment.newInstance(), id) R.id.nav_drawer_catalogues -> setFragment(CatalogueFragment.newInstance(), id) R.id.nav_drawer_latest_updates -> setFragment(LatestUpdatesFragment.newInstance(), id) + R.id.nav_drawer_batch_add -> setFragment(BatchAddFragment.newInstance(), id) R.id.nav_drawer_downloads -> setFragment(DownloadFragment.newInstance(), id) R.id.nav_drawer_settings -> { val intent = Intent(this, SettingsActivity::class.java) diff --git a/app/src/main/java/exh/GalleryAdder.kt b/app/src/main/java/exh/GalleryAdder.kt new file mode 100644 index 000000000..acb2557ab --- /dev/null +++ b/app/src/main/java/exh/GalleryAdder.kt @@ -0,0 +1,54 @@ +package exh + +import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.source.SourceManager +import eu.kanade.tachiyomi.util.UrlUtil +import exh.metadata.MetadataHelper +import exh.metadata.copyTo +import uy.kohesive.injekt.injectLazy +import java.net.MalformedURLException +import java.net.URL + +class GalleryAdder { + + private val db: DatabaseHelper by injectLazy() + + private val sourceManager: SourceManager by injectLazy() + + private val metadataHelper = MetadataHelper() + + fun addGallery(url: String, fav: Boolean = false): Manga { + val source = when(URL(url).host) { + "g.e-hentai.org" -> 1 + "exhentai.org" -> 2 + else -> throw MalformedURLException("Not a valid gallery URL!") + } + + val sourceObj = sourceManager.get(source) + + val pathOnlyUrl = UrlUtil.getPath(url) + + //Use manga in DB if possible, otherwise, make a new manga + val manga = db.getManga(pathOnlyUrl, source).executeAsBlocking() + ?: Manga.create(pathOnlyUrl, source).apply { + title = url + } + + sourceObj?.let { + //Copy basics + manga.copyFrom(sourceObj.fetchMangaDetails(manga).toBlocking().first()) + + //Apply metadata + metadataHelper.fetchMetadata(url, source == 2)?.copyTo(manga) + } + + if(fav) manga.favorite = true + + db.insertManga(manga).executeAsBlocking().insertedId()?.let { + manga.id = it + } + + return manga + } +} \ No newline at end of file diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddFragment.kt b/app/src/main/java/exh/ui/batchadd/BatchAddFragment.kt new file mode 100644 index 000000000..5e9cecdb9 --- /dev/null +++ b/app/src/main/java/exh/ui/batchadd/BatchAddFragment.kt @@ -0,0 +1,126 @@ +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 com.afollestad.materialdialogs.MaterialDialog +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 + +/** + * LoginActivity + */ + +class BatchAddFragment : BaseFragment() { + + private val galleryAdder by lazy { GalleryAdder() } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?) + = inflater.inflate(R.layout.eh_fragment_batch_add, container, false)!! + + 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() + + //Too lazy to actually deal with orientation changes + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR + + val splitGalleries = galleries.split("\n").map { + it.trim().nullIfBlank() + }.filterNotNull() + + val dialog = MaterialDialog.Builder(context) + .title("Adding galleries...") + .progress(false, splitGalleries.size, true) + .cancelable(false) + .canceledOnTouchOutside(false) + .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 + 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: ${succeeded.size} gallerie(s)\nFailed: ${failed.size} 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, dialogAction -> materialDialog.dismiss() } + .cancelable(true) + .canceledOnTouchOutside(true) + .show() + } + + companion object { + fun newInstance() = BatchAddFragment() + } +} diff --git a/app/src/main/java/exh/ui/intercept/InterceptActivity.kt b/app/src/main/java/exh/ui/intercept/InterceptActivity.kt new file mode 100644 index 000000000..fa1a7e605 --- /dev/null +++ b/app/src/main/java/exh/ui/intercept/InterceptActivity.kt @@ -0,0 +1,82 @@ +package exh.ui.intercept + +import android.content.Intent +import android.os.Bundle +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 + +class InterceptActivity : BaseActivity() { + + private val galleryAdder = GalleryAdder() + + 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() } + } + + fun setup() { + try { + processLink() + } catch(t: Throwable) { + Timber.e(t, "Could not intercept link!") + if(!finished) + runOnUiThread { + MaterialDialog.Builder(this) + .title("Error") + .content("Could not load this gallery!") + .cancelable(true) + .canceledOnTouchOutside(true) + .cancelListener { onBackPressed() } + .positiveText("Ok") + .onPositive { materialDialog, dialogAction -> onBackPressed() } + .dismissListener { onBackPressed() } + .show() + } + } + } + + fun processLink() { + if(Intent.ACTION_VIEW == intent.action) { + val manga = galleryAdder.addGallery(intent.dataString) + + if(!finished) + startActivity(MangaActivity.newIntent(this, manga, true)) + onBackPressed() + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + android.R.id.home -> onBackPressed() + else -> return super.onOptionsItemSelected(item) + } + return true + } + + override fun onBackPressed() { + if(!finished) + runOnUiThread { + super.onBackPressed() + } + } + + override fun onStop() { + super.onStop() + finished = true + } +} diff --git a/app/src/main/res/drawable/ic_playlist_add_black_24dp.xml b/app/src/main/res/drawable/ic_playlist_add_black_24dp.xml new file mode 100644 index 000000000..0460472b9 --- /dev/null +++ b/app/src/main/res/drawable/ic_playlist_add_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/eh_activity_intercept.xml b/app/src/main/res/layout/eh_activity_intercept.xml new file mode 100644 index 000000000..518bb973e --- /dev/null +++ b/app/src/main/res/layout/eh_activity_intercept.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/eh_fragment_batch_add.xml b/app/src/main/res/layout/eh_fragment_batch_add.xml new file mode 100644 index 000000000..c92600374 --- /dev/null +++ b/app/src/main/res/layout/eh_fragment_batch_add.xml @@ -0,0 +1,54 @@ + + + + + + + + + +