Initial migrate to androidx navigation (#647)

* Neutralize scene firstly

* Remove StageLayout

* Add nav graph

* Rename .java to .kt

* Convert BaseScene to kotlin

* Add GalleryDetailScene to navgraph

No need to check topfragment is callback target fragment, since these callback must be cancelled in fragment's lifecycle when DestroyView

* Restore funcs

* Restore preview

* Revert "Convert BaseScene to kotlin"

Should not do it here
This reverts commit 5d2e3af6ad85fef7604d8df19ee58a957390cdb5.

* Revert "Rename .java to .kt"

This reverts commit 128c655bc98fc54528d58534651d61ff47b2284d.

* Restore drawer

* Remove all getScene usage

* Remove all getStageActivity usage

* Remove all getStageActivity usage

* setupWithNavController

* Refactor MainActivity with viewBinding

* Add navdrawer corresponding navdestination

* Migrate All normal fragment

* Add anims

* Fix statusbar flicker

* Remove SceneApplication

* Remove SceneFragment

* Remove StageActivity

* Drop scene totally

* Dynamically set navgraph

* Restore signin

* Restore login via cookies

* Restore login via webview

* Add some TODOs

* Fixup

* Restore onProvideAssistContent

* Restore checkClipboard

* Restore intent handle

* Fix handle intent

* Remove unused EhUrlOpener

* Let system handle that intent

* Restore handle download intent

* Restore AboveSnackerLayout

* Fix the last navigation
This commit is contained in:
tarsin authored and GitHub committed 2023-01-08 20:37:11 +08:00
1 parent 8f8932f617
commit 8bb5f1e955
30 files changed
+516 -2083

No files matched your search

@@ -16,7 +16,6 @@
package com.hippo.ehviewer;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -25,7 +24,6 @@ import android.os.Debug;
import androidx.annotation.NonNull;
import com.hippo.scene.StageActivity;
import com.hippo.util.PackageUtils;
import com.hippo.util.ReadableTime;
import com.hippo.yorozuya.FileUtils;
@@ -78,27 +76,10 @@ public final class Crash {
// Runtime
String topActivityClazzName = "null";
String topSceneClazzName = "null";
try {
Activity topActivity = ((EhApplication) context.getApplicationContext()).getTopActivity();
if (null != topActivity) {
topActivityClazzName = topActivity.getClass().getName();
if (topActivity instanceof StageActivity) {
Class<?> clazz = ((StageActivity) topActivity).getTopSceneClass();
if (clazz != null) {
topSceneClazzName = clazz.getName();
}
}
}
} catch (Throwable e) {
// Ignore
}
fw.write("======== Runtime ========\r\n");
fw.write("TopActivity=");
fw.write(avoidNull(topActivityClazzName));
fw.write("\r\n");
fw.write("TopScene=");
fw.write(avoidNull(topSceneClazzName));
fw.write("\r\n");
fw.write("\r\n");
@@ -19,6 +19,7 @@ package com.hippo.ehviewer
import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityManager
import android.app.Application
import android.content.ComponentCallbacks2
import android.text.Html
import android.text.method.LinkMovementMethod
@@ -49,7 +50,6 @@ import com.hippo.ehviewer.download.DownloadManager
import com.hippo.ehviewer.spider.SpiderDen
import com.hippo.ehviewer.ui.CommonOperations
import com.hippo.ehviewer.ui.EhActivity
import com.hippo.scene.SceneApplication
import com.hippo.util.BitmapUtils
import com.hippo.util.ExceptionUtils
import com.hippo.util.ReadableTime
@@ -71,7 +71,7 @@ import java.util.Arrays
import javax.net.ssl.TrustManagerFactory
import javax.net.ssl.X509TrustManager
class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderFactory {
class EhApplication : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
private val mIdGenerator = IntIdGenerator()
private val mGlobalStuffMap = HashMap<Int, Any>()
private val mActivityList = ArrayList<Activity>()
@@ -101,7 +101,7 @@ class EhApplication : SceneApplication(), DefaultLifecycleObserver, ImageLoaderF
}
handler?.uncaughtException(t, e)
}
super<SceneApplication>.onCreate()
super<Application>.onCreate()
Native.initialize()
GetText.initialize(this)
Settings.initialize()
@@ -26,12 +26,8 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.browser.customtabs.CustomTabsIntent;
import com.hippo.ehviewer.client.EhUrlOpener;
import com.hippo.ehviewer.client.data.GalleryDetail;
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.Announcer;
import com.hippo.scene.StageActivity;
import eu.kanade.tachiyomi.ui.reader.ReaderActivity;
@@ -77,16 +73,6 @@ public final class UrlOpener {
}
}
}
Announcer announcer = EhUrlOpener.parseUrl(url);
if (null != announcer) {
intent = new Intent(context, MainActivity.class);
intent.setAction(StageActivity.ACTION_START_SCENE);
intent.putExtra(StageActivity.KEY_SCENE_NAME, announcer.getClazz().getName());
intent.putExtra(StageActivity.KEY_SCENE_ARGS, announcer.getArgs());
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return;
}
}
CustomTabsIntent.Builder customTabsIntent = new CustomTabsIntent.Builder();
@@ -1,75 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.client;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import com.hippo.ehviewer.client.data.ListUrlBuilder;
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser;
import com.hippo.ehviewer.client.parser.GalleryListUrlParser;
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser;
import com.hippo.ehviewer.ui.scene.GalleryDetailScene;
import com.hippo.ehviewer.ui.scene.GalleryListScene;
import com.hippo.ehviewer.ui.scene.ProgressScene;
import com.hippo.scene.Announcer;
public class EhUrlOpener {
private static final String TAG = EhUrlOpener.class.getSimpleName();
@Nullable
public static Announcer parseUrl(String url) {
if (TextUtils.isEmpty(url)) {
return null;
}
ListUrlBuilder listUrlBuilder = GalleryListUrlParser.parse(url);
if (listUrlBuilder != null) {
Bundle args = new Bundle();
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_LIST_URL_BUILDER);
args.putParcelable(GalleryListScene.KEY_LIST_URL_BUILDER, listUrlBuilder);
return new Announcer(GalleryListScene.class).setArgs(args);
}
GalleryDetailUrlParser.Result result1 = GalleryDetailUrlParser.parse(url);
if (result1 != null) {
Bundle args = new Bundle();
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN);
args.putLong(GalleryDetailScene.KEY_GID, result1.gid);
args.putString(GalleryDetailScene.KEY_TOKEN, result1.token);
return new Announcer(GalleryDetailScene.class).setArgs(args);
}
GalleryPageUrlParser.Result result2 = GalleryPageUrlParser.parse(url);
if (result2 != null) {
Bundle args = new Bundle();
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN);
args.putLong(ProgressScene.KEY_GID, result2.gid);
args.putString(ProgressScene.KEY_PTOKEN, result2.pToken);
args.putInt(ProgressScene.KEY_PAGE, result2.page);
return new Announcer(ProgressScene.class).setArgs(args);
}
Log.i(TAG, "Can't parse url: " + url);
return null;
}
}
@@ -36,7 +36,6 @@ import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.dao.DownloadInfo
import com.hippo.ehviewer.ui.MainActivity
import com.hippo.ehviewer.ui.scene.DownloadsScene
import com.hippo.scene.StageActivity
import com.hippo.util.ReadableTime
import com.hippo.yorozuya.FileUtils
import com.hippo.yorozuya.SimpleHandler
@@ -186,9 +185,8 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
val bundle = Bundle()
bundle.putString(DownloadsScene.KEY_ACTION, DownloadsScene.ACTION_CLEAR_DOWNLOAD_SERVICE)
val activityIntent = Intent(this, MainActivity::class.java)
activityIntent.action = StageActivity.ACTION_START_SCENE
activityIntent.putExtra(StageActivity.KEY_SCENE_NAME, DownloadsScene::class.java.name)
activityIntent.putExtra(StageActivity.KEY_SCENE_ARGS, bundle)
activityIntent.action = ACTION_START_DOWNLOADSCENE
activityIntent.putExtra(ACTION_START_DOWNLOADSCENE_ARGS, bundle)
val piActivity = PendingIntent.getActivity(
this@DownloadService, 0,
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
@@ -241,9 +239,8 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
val bundle = Bundle()
bundle.putLong(DownloadsScene.KEY_GID, info.gid)
val activityIntent = Intent(this, MainActivity::class.java)
activityIntent.action = StageActivity.ACTION_START_SCENE
activityIntent.putExtra(StageActivity.KEY_SCENE_NAME, DownloadsScene::class.java.name)
activityIntent.putExtra(StageActivity.KEY_SCENE_ARGS, bundle)
activityIntent.action = ACTION_START_DOWNLOADSCENE
activityIntent.putExtra(ACTION_START_DOWNLOADSCENE_ARGS, bundle)
val piActivity = PendingIntent.getActivity(
this@DownloadService, 0,
activityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
@@ -516,6 +513,9 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
}
companion object {
const val ACTION_START_DOWNLOADSCENE = "start_download_scene"
const val ACTION_START_DOWNLOADSCENE_ARGS = "start_download_scene_args"
const val ACTION_START = "start"
const val ACTION_START_RANGE = "start_range"
const val ACTION_START_ALL = "start_all"
@@ -16,6 +16,7 @@
package com.hippo.ehviewer.ui
import android.annotation.SuppressLint
import android.app.assist.AssistContent
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
@@ -26,113 +27,55 @@ import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.PersistableBundle
import android.view.MenuItem
import android.text.TextUtils
import android.view.View
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.IdRes
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.drawerlayout.widget.DrawerLayout.DrawerListener
import com.google.android.material.navigation.NavigationView
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.snackbar.Snackbar
import com.hippo.app.BaseDialogBuilder
import com.hippo.app.EditTextDialogBuilder
import com.hippo.ehviewer.AppConfig
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
import com.hippo.ehviewer.client.EhUrlOpener
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.client.data.ListUrlBuilder
import com.hippo.ehviewer.client.parser.GalleryDetailUrlParser
import com.hippo.ehviewer.client.parser.GalleryListUrlParser
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser
import com.hippo.ehviewer.databinding.ActivityMainBinding
import com.hippo.ehviewer.download.DownloadService
import com.hippo.ehviewer.ui.scene.BaseScene
import com.hippo.ehviewer.ui.scene.CookieSignInScene
import com.hippo.ehviewer.ui.scene.DownloadsScene
import com.hippo.ehviewer.ui.scene.FavoritesScene
import com.hippo.ehviewer.ui.scene.GalleryCommentsScene
import com.hippo.ehviewer.ui.scene.GalleryDetailScene
import com.hippo.ehviewer.ui.scene.GalleryListScene
import com.hippo.ehviewer.ui.scene.GalleryPreviewsScene
import com.hippo.ehviewer.ui.scene.HistoryScene
import com.hippo.ehviewer.ui.scene.ProgressScene
import com.hippo.ehviewer.ui.scene.SelectSiteScene
import com.hippo.ehviewer.ui.scene.SignInScene
import com.hippo.ehviewer.ui.scene.SolidScene
import com.hippo.ehviewer.ui.scene.WebViewSignInScene
import com.hippo.ehviewer.widget.EhStageLayout
import com.hippo.io.UniFileInputStreamPipe
import com.hippo.scene.Announcer
import com.hippo.scene.SceneFragment
import com.hippo.scene.StageActivity
import com.hippo.unifile.UniFile
import com.hippo.util.BitmapUtils
import com.hippo.util.addTextToClipboard
import com.hippo.util.getClipboardManager
import com.hippo.util.getUrlFromClipboard
import com.hippo.widget.DrawerView
import com.hippo.yorozuya.IOUtils
import com.hippo.yorozuya.SimpleHandler
import com.hippo.yorozuya.ViewUtils
import eu.kanade.tachiyomi.util.lang.launchUI
import kotlinx.coroutines.delay
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedListener {
private var settingsLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) refreshTopScene()
}
/*---------------
Whole life cycle
---------------*/
private var mDrawerLayout: DrawerLayout? = null
private var mStageLayout: EhStageLayout? = null
private var mNavView: NavigationView? = null
private var mRightDrawer: DrawerView? = null
private var mNavCheckedItem = 0
override fun getContainerViewId(): Int {
return R.id.fragment_container
}
override fun getLaunchAnnouncer(): Announcer {
return if (EhUtils.needSignedIn()) {
Announcer(SignInScene::class.java)
} else if (Settings.getSelectSite()) {
Announcer(SelectSiteScene::class.java)
} else {
val args = Bundle()
args.putString(
GalleryListScene.KEY_ACTION,
Settings.getLaunchPageGalleryListSceneAction()
)
Announcer(GalleryListScene::class.java).setArgs(args)
}
}
// Sometimes scene can't show directly
private fun processAnnouncer(announcer: Announcer): Announcer {
if (0 == sceneCount) {
if (EhUtils.needSignedIn()) {
val newArgs = Bundle()
newArgs.putString(SignInScene.KEY_TARGET_SCENE, announcer.clazz.name)
newArgs.putBundle(SignInScene.KEY_TARGET_ARGS, announcer.args)
return Announcer(SignInScene::class.java).setArgs(newArgs)
} else if (Settings.getSelectSite()) {
val newArgs = Bundle()
newArgs.putString(SelectSiteScene.KEY_TARGET_SCENE, announcer.clazz.name)
newArgs.putBundle(SelectSiteScene.KEY_TARGET_ARGS, announcer.args)
return Announcer(SelectSiteScene::class.java).setArgs(newArgs)
}
}
return announcer
}
class MainActivity : EhActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
private fun saveImageToTempFile(file: UniFile?): File? {
file ?: return null
@@ -166,16 +109,68 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
}
}
private fun handleIntent(intent: Intent?): Boolean {
if (intent == null) {
return false
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
lifecycleScope.launchUI {
if (!handleIntent(intent)) {
if (intent != null && Intent.ACTION_VIEW == intent.action) {
if (intent.data != null) {
val url = intent.data.toString()
EditTextDialogBuilder(this@MainActivity, url, "")
.setTitle(R.string.error_cannot_parse_the_url)
.setPositiveButton(android.R.string.copy) { _: DialogInterface?, _: Int ->
this@MainActivity.addTextToClipboard(
url,
false
)
}
.show()
}
}
}
}
}
private fun handleIntent(intent: Intent?): Boolean {
intent ?: return false
val action = intent.action
if (Intent.ACTION_VIEW == action) {
val uri = intent.data ?: return false
val announcer = EhUrlOpener.parseUrl(uri.toString())
if (announcer != null) {
startScene(processAnnouncer(announcer))
val url = uri.toString()
if (TextUtils.isEmpty(url)) {
return false
}
val listUrlBuilder = GalleryListUrlParser.parse(url)
if (listUrlBuilder != null) {
val args = Bundle()
args.putString(
GalleryListScene.KEY_ACTION,
GalleryListScene.ACTION_LIST_URL_BUILDER
)
args.putParcelable(GalleryListScene.KEY_LIST_URL_BUILDER, listUrlBuilder)
navController.navigate(R.id.galleryListScene, args)
return true
}
val result1 = GalleryDetailUrlParser.parse(url)
if (result1 != null) {
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN)
args.putLong(GalleryDetailScene.KEY_GID, result1.gid)
args.putString(GalleryDetailScene.KEY_TOKEN, result1.token)
navController.navigate(R.id.galleryDetailScene, args)
return true
}
val result2 = GalleryPageUrlParser.parse(url)
if (result2 != null) {
val args = Bundle()
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN)
args.putLong(ProgressScene.KEY_GID, result2.gid)
args.putString(ProgressScene.KEY_PTOKEN, result2.pToken)
args.putInt(ProgressScene.KEY_PAGE, result2.page)
navController.navigate(R.id.progressScene, args)
return true
}
} else if (Intent.ACTION_SEND == action) {
@@ -183,7 +178,10 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
if ("text/plain" == type) {
val builder = ListUrlBuilder()
builder.keyword = intent.getStringExtra(Intent.EXTRA_TEXT)
startScene(processAnnouncer(GalleryListScene.getStartAnnouncer(builder)))
navController.navigate(
R.id.galleryListScene,
GalleryListScene.getStartArgs(builder)
)
return true
} else if (type != null && type.startsWith("image/")) {
val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
@@ -195,69 +193,50 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
builder.mode = ListUrlBuilder.MODE_IMAGE_SEARCH
builder.imagePath = temp.path
builder.isUseSimilarityScan = true
startScene(processAnnouncer(GalleryListScene.getStartAnnouncer(builder)))
navController.navigate(
R.id.galleryListScene,
GalleryListScene.getStartArgs(builder)
)
return true
}
}
}
} else if (action == DownloadService.ACTION_START_DOWNLOADSCENE) {
val args = intent.getBundleExtra(DownloadService.ACTION_START_DOWNLOADSCENE_ARGS)
navController.navigate(R.id.nav_downloads, args)
}
return false
}
override fun onUnrecognizedIntent(intent: Intent?) {
val clazz = topSceneClass
if (clazz != null && SolidScene::class.java.isAssignableFrom(clazz)) {
// TODO the intent lost
return
}
if (!handleIntent(intent)) {
var handleUrl = false
if (intent != null && Intent.ACTION_VIEW == intent.action) {
handleUrl = true
if (intent.data != null) {
val url = intent.data.toString()
EditTextDialogBuilder(this, url, "")
.setTitle(R.string.error_cannot_parse_the_url)
.setPositiveButton(android.R.string.copy) { _: DialogInterface?, _: Int ->
this.addTextToClipboard(
url,
false
)
}
.show()
}
}
if (0 == sceneCount) {
if (handleUrl) {
finish()
} else {
val args = Bundle()
args.putString(
GalleryListScene.KEY_ACTION,
Settings.getLaunchPageGalleryListSceneAction()
)
startScene(processAnnouncer(Announcer(GalleryListScene::class.java).setArgs(args)))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment
navController = navHostFragment.navController
navController.apply {
graph = navInflater.inflate(R.navigation.nav_graph).apply {
when (Settings.getLaunchPageGalleryListSceneAction()) {
GalleryListScene.ACTION_HOMEPAGE -> setStartDestination(R.id.nav_homepage)
GalleryListScene.ACTION_SUBSCRIPTION -> setStartDestination(R.id.nav_subscription)
GalleryListScene.ACTION_WHATS_HOT -> setStartDestination(R.id.nav_whats_hot)
GalleryListScene.ACTION_TOP_LIST -> setStartDestination(R.id.nav_toplist)
}
}
}
}
if (EhUtils.needSignedIn()) {
navController.navigate(R.id.signInScene)
}
override fun onStartSceneFromIntent(clazz: Class<*>, args: Bundle?): Announcer {
return processAnnouncer(Announcer(clazz).setArgs(args))
}
override fun onCreate2(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)
mStageLayout = ViewUtils.`$$`(this, R.id.fragment_container) as EhStageLayout
mDrawerLayout = ViewUtils.`$$`(this, R.id.draw_view) as DrawerLayout
mNavView = ViewUtils.`$$`(this, R.id.nav_view) as NavigationView
mRightDrawer = ViewUtils.`$$`(this, R.id.right_drawer) as DrawerView
mDrawerLayout?.addDrawerListener(mDrawerOnBackPressedCallback)
binding.navView.setupWithNavController(navController)
binding.drawView.addDrawerListener(mDrawerOnBackPressedCallback)
onBackPressedDispatcher.addCallback(mDrawerOnBackPressedCallback)
if (mNavView != null) {
mNavView!!.setNavigationItemSelectedListener(this)
}
if (savedInstanceState == null) {
if (intent.action != Intent.ACTION_MAIN) {
onNewIntent(intent)
}
checkDownloadLocation()
if (Settings.getMeteredNetworkWarning()) {
checkMeteredNetwork()
@@ -270,8 +249,6 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
}
}
}
} else {
onRestore(savedInstanceState)
}
}
@@ -335,9 +312,9 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
private fun checkMeteredNetwork() {
val cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
if (cm.isActiveNetworkMetered) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && mDrawerLayout != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Snackbar.make(
mDrawerLayout!!,
binding.drawView,
R.string.metered_network_warning,
Snackbar.LENGTH_LONG
)
@@ -353,83 +330,44 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
}
}
private fun onRestore(savedInstanceState: Bundle) {
mNavCheckedItem = savedInstanceState.getInt(KEY_NAV_CHECKED_ITEM)
}
override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
super.onSaveInstanceState(outState, outPersistentState)
outState.putInt(KEY_NAV_CHECKED_ITEM, mNavCheckedItem)
}
override fun onDestroy() {
super.onDestroy()
mDrawerLayout = null
mNavView = null
mRightDrawer = null
}
override fun onResume() {
super.onResume()
setNavCheckedItem(mNavCheckedItem)
checkClipboardUrl()
}
override fun onTransactScene() {
super.onTransactScene()
checkClipboardUrl()
lifecycleScope.launchUI {
delay(300)
checkClipboardUrl()
}
}
private fun checkClipboardUrl() {
SimpleHandler.getInstance().postDelayed({
if (!isSolid) {
checkClipboardUrlInternal()
}
}, 300)
}
private val isSolid: Boolean
get() {
val topClass = topSceneClass
return topClass == null || SolidScene::class.java.isAssignableFrom(topClass)
}
private fun createAnnouncerFromClipboardUrl(url: String): Announcer? {
val result1 = GalleryDetailUrlParser.parse(url, false)
if (result1 != null) {
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN)
args.putLong(GalleryDetailScene.KEY_GID, result1.gid)
args.putString(GalleryDetailScene.KEY_TOKEN, result1.token)
return Announcer(GalleryDetailScene::class.java).setArgs(args)
}
val result2 = GalleryPageUrlParser.parse(url, false)
if (result2 != null) {
val args = Bundle()
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN)
args.putLong(ProgressScene.KEY_GID, result2.gid)
args.putString(ProgressScene.KEY_PTOKEN, result2.pToken)
args.putInt(ProgressScene.KEY_PAGE, result2.page)
return Announcer(ProgressScene::class.java).setArgs(args)
}
return null
}
private fun checkClipboardUrlInternal() {
val text = this.getClipboardManager().getUrlFromClipboard(this)
val hashCode = text?.hashCode() ?: 0
if (text != null && hashCode != 0 && Settings.getClipboardTextHashCode() != hashCode) {
val announcer = createAnnouncerFromClipboardUrl(text)
if (announcer != null && mDrawerLayout != null) {
val result1 = GalleryDetailUrlParser.parse(text, false)
var launch: (() -> Unit)? = null
if (result1 != null) {
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN)
args.putLong(GalleryDetailScene.KEY_GID, result1.gid)
args.putString(GalleryDetailScene.KEY_TOKEN, result1.token)
launch = { navController.navigate(R.id.galleryDetailScene, args) }
}
val result2 = GalleryPageUrlParser.parse(text, false)
if (result2 != null) {
val args = Bundle()
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN)
args.putLong(ProgressScene.KEY_GID, result2.gid)
args.putString(ProgressScene.KEY_PTOKEN, result2.pToken)
args.putInt(ProgressScene.KEY_PAGE, result2.page)
launch = { navController.navigate(R.id.progressScene, args) }
}
launch?.let {
val snackbar = Snackbar.make(
mDrawerLayout!!,
binding.drawView,
R.string.clipboard_gallery_url_snack_message,
Snackbar.LENGTH_SHORT
)
snackbar.setAction(R.string.clipboard_gallery_url_snack_action) {
startScene(
announcer
)
it()
}
snackbar.show()
}
@@ -437,26 +375,21 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
Settings.putClipboardTextHashCode(hashCode)
}
override fun onSceneViewCreated(scene: SceneFragment, savedInstanceState: Bundle?) {
super.onSceneViewCreated(scene, savedInstanceState)
createDrawerView(scene)
}
@SuppressLint("RtlHardcoded")
fun createDrawerView(scene: SceneFragment?) {
if (scene is BaseScene && mRightDrawer != null && mDrawerLayout != null) {
mRightDrawer!!.removeAllViews()
fun createDrawerView(scene: Fragment?) {
if (scene is BaseScene) {
binding.rightDrawer.removeAllViews()
val drawerView = scene.createDrawerView(
scene.layoutInflater, mRightDrawer, null
scene.layoutInflater, binding.rightDrawer, null
)
if (drawerView != null) {
mRightDrawer!!.addView(drawerView)
mDrawerLayout!!.setDrawerLockMode(
binding.rightDrawer.addView(drawerView)
binding.drawView.setDrawerLockMode(
DrawerLayout.LOCK_MODE_UNLOCKED,
GravityCompat.END
)
} else {
mDrawerLayout!!.setDrawerLockMode(
binding.drawView.setDrawerLockMode(
DrawerLayout.LOCK_MODE_LOCKED_CLOSED,
GravityCompat.END
)
@@ -464,39 +397,32 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
}
}
override fun onSceneViewDestroyed(scene: SceneFragment) {
super.onSceneViewDestroyed(scene)
if (scene is BaseScene) {
scene.destroyDrawerView()
}
}
fun addAboveSnackView(view: View?) {
mStageLayout?.addAboveSnackView(view)
binding.absnacker.addAboveSnackView(view)
}
fun removeAboveSnackView(view: View?) {
mStageLayout?.removeAboveSnackView(view)
binding.absnacker.removeAboveSnackView(view)
}
fun setDrawerLockMode(lockMode: Int, edgeGravity: Int) {
mDrawerLayout?.setDrawerLockMode(lockMode, edgeGravity)
binding.drawView.setDrawerLockMode(lockMode, edgeGravity)
}
fun getDrawerLockMode(edgeGravity: Int): Int? {
return mDrawerLayout?.getDrawerLockMode(edgeGravity)
fun getDrawerLockMode(edgeGravity: Int): Int {
return binding.drawView.getDrawerLockMode(edgeGravity)
}
fun openDrawer(drawerGravity: Int) {
mDrawerLayout?.openDrawer(drawerGravity)
binding.drawView.openDrawer(drawerGravity)
}
fun closeDrawer(drawerGravity: Int) {
mDrawerLayout?.closeDrawer(drawerGravity)
binding.drawView.closeDrawer(drawerGravity)
}
fun toggleDrawer(drawerGravity: Int) {
mDrawerLayout?.run {
binding.drawView.run {
if (isDrawerOpen(drawerGravity)) {
closeDrawer(drawerGravity)
} else {
@@ -506,14 +432,6 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
}
fun setNavCheckedItem(@IdRes resId: Int) {
mNavCheckedItem = resId
mNavView?.run {
if (resId == 0) {
setCheckedItem(R.id.nav_stub)
} else {
setCheckedItem(resId)
}
}
}
@JvmOverloads
@@ -537,77 +455,17 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
).show()
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Don't select twice
if (item.isChecked) {
return false
}
val id = item.itemId
when (id) {
R.id.nav_homepage -> {
val args = Bundle()
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_HOMEPAGE)
startSceneFirstly(
Announcer(GalleryListScene::class.java)
.setArgs(args)
)
}
R.id.nav_subscription -> {
val args = Bundle()
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_SUBSCRIPTION)
startSceneFirstly(
Announcer(GalleryListScene::class.java)
.setArgs(args)
)
}
R.id.nav_whats_hot -> {
val args = Bundle()
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_WHATS_HOT)
startSceneFirstly(
Announcer(GalleryListScene::class.java)
.setArgs(args)
)
}
R.id.nav_toplist -> {
val args = Bundle()
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_TOP_LIST)
startSceneFirstly(
Announcer(GalleryListScene::class.java)
.setArgs(args)
)
}
R.id.nav_favourite -> {
startScene(Announcer(FavoritesScene::class.java))
}
R.id.nav_history -> {
startScene(Announcer(HistoryScene::class.java))
}
R.id.nav_downloads -> {
startScene(Announcer(DownloadsScene::class.java))
}
R.id.nav_settings -> {
val intent = Intent(this, SettingsActivity::class.java)
settingsLauncher.launch(intent)
}
}
if (id != R.id.nav_stub) {
mDrawerLayout?.closeDrawers()
}
return true
var mShareUrl: String? = null
override fun onProvideAssistContent(outContent: AssistContent?) {
super.onProvideAssistContent(outContent)
mShareUrl?.let { outContent?.webUri = Uri.parse(mShareUrl) }
}
private val mDrawerOnBackPressedCallback =
object : OnBackPressedCallback(false), DrawerListener {
val slideThreshold = 0.05
override fun handleOnBackPressed() {
mDrawerLayout?.closeDrawers()
binding.drawView.closeDrawers()
}
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
@@ -618,26 +476,4 @@ class MainActivity : StageActivity(), NavigationView.OnNavigationItemSelectedLis
override fun onDrawerClosed(drawerView: View) {}
override fun onDrawerStateChanged(newState: Int) {}
}
companion object {
private const val KEY_NAV_CHECKED_ITEM = "nav_checked_item"
init {
registerLaunchMode(SignInScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
registerLaunchMode(
WebViewSignInScene::class.java,
SceneFragment.LAUNCH_MODE_SINGLE_TASK
)
registerLaunchMode(CookieSignInScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
registerLaunchMode(SelectSiteScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
registerLaunchMode(GalleryListScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TOP)
registerLaunchMode(GalleryDetailScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
registerLaunchMode(GalleryCommentsScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
registerLaunchMode(GalleryPreviewsScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
registerLaunchMode(DownloadsScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
registerLaunchMode(FavoritesScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TASK)
registerLaunchMode(HistoryScene::class.java, SceneFragment.LAUNCH_MODE_SINGLE_TOP)
registerLaunchMode(ProgressScene::class.java, SceneFragment.LAUNCH_MODE_STANDARD)
}
}
}
@@ -20,6 +20,7 @@ import android.view.MenuItem
import android.widget.TextView
import androidx.annotation.StringRes
import androidx.fragment.app.FragmentTransaction
import androidx.navigation.ActivityNavigator
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
@@ -78,4 +79,9 @@ class SettingsActivity : EhActivity() {
fun resetAppbarLiftStatus() {
mAppbarLayout?.setExpanded(true)
}
override fun finish() {
super.finish()
ActivityNavigator.applyPopAnimationsToPendingTransition(this)
}
}
@@ -25,7 +25,6 @@ import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
@@ -36,12 +35,17 @@ import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.navigation.NavOptions;
import androidx.navigation.fragment.NavHostFragment;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.SceneFragment;
public abstract class BaseScene extends SceneFragment {
import rikka.core.res.ResourcesKt;
public abstract class BaseScene extends Fragment {
public static final int LENGTH_SHORT = 0;
public static final int LENGTH_LONG = 1;
@@ -185,15 +189,7 @@ public abstract class BaseScene extends SceneFragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
view.getViewTreeObserver().removeOnPreDrawListener(this);
startPostponedEnterTransition();
return true;
}
});
view.setBackground(ResourcesKt.resolveDrawable(requireActivity().getTheme(), android.R.attr.windowBackground));
// Update left drawer locked state
if (needShowLeftDrawer()) {
@@ -207,6 +203,14 @@ public abstract class BaseScene extends SceneFragment {
// Hide soft ime
hideSoftInput();
getMainActivity().createDrawerView(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
destroyDrawerView();
}
@Nullable
@@ -278,4 +282,27 @@ public abstract class BaseScene extends SceneFragment {
public Resources.Theme getTheme() {
return requireActivity().getTheme();
}
public void navigate(int id, Bundle args) {
navigate(id, args, false);
}
public void navigate(int id, Bundle args, boolean singleTop) {
var options = new NavOptions.Builder().setLaunchSingleTop(singleTop)
.setEnterAnim(R.anim.scene_open_enter).setExitAnim(R.anim.scene_open_exit)
.setPopEnterAnim(R.anim.scene_close_enter).setPopExitAnim(R.anim.scene_close_exit)
.build();
NavHostFragment.findNavController(this).navigate(id, args, options);
}
public void navigateToTop() {
var navController = NavHostFragment.findNavController(this);
var id = navController.getGraph().getStartDestinationId();
var options = new NavOptions.Builder()
.setEnterAnim(R.anim.scene_open_enter).setExitAnim(R.anim.scene_open_exit)
.setPopEnterAnim(R.anim.scene_close_enter).setPopExitAnim(R.anim.scene_close_exit)
.setPopUpTo(id, true)
.build();
navController.navigate(id, null, options);
}
}
@@ -47,7 +47,7 @@ import com.hippo.yorozuya.ViewUtils;
import okhttp3.Cookie;
public class CookieSignInScene extends SolidScene implements EditText.OnEditorActionListener,
public class CookieSignInScene extends BaseScene implements EditText.OnEditorActionListener,
View.OnClickListener {
/*---------------
@@ -285,8 +285,8 @@ public class CookieSignInScene extends SolidScene implements EditText.OnEditorAc
private class CookieSignInListener implements EhClient.Callback<Object> {
@Override
public void onSuccess(Object result) {
setResult(RESULT_OK, null);
finish();
// TODO: getProfile
navigateToTop();
}
@Override
@@ -65,7 +65,6 @@ import com.hippo.ehviewer.download.DownloadService
import com.hippo.ehviewer.download.DownloadService.Companion.clear
import com.hippo.ehviewer.spider.SpiderDen
import com.hippo.ehviewer.widget.SimpleRatingView
import com.hippo.scene.Announcer
import com.hippo.unifile.UniFile
import com.hippo.view.ViewTransition
import com.hippo.widget.FabLayout
@@ -154,10 +153,6 @@ class DownloadsScene : BaseToolbarScene(), DownloadInfoListener, OnClickFabListe
return false
}
override fun onNewArguments(args: Bundle) {
handleArguments(args)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val context = context
@@ -969,8 +964,7 @@ class DownloadsScene : BaseToolbarScene(), DownloadInfoListener, OnClickFabListe
GalleryDetailScene.ACTION_GALLERY_INFO
)
args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, list[index])
val announcer = Announcer(GalleryDetailScene::class.java).setArgs(args)
startScene(announcer)
navigate(R.id.galleryDetailScene, args)
} else if (start === v) {
val intent = Intent(activity, DownloadService::class.java)
intent.action = DownloadService.ACTION_START
@@ -20,29 +20,23 @@ import android.content.Context;
import android.widget.Toast;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import com.hippo.ehviewer.EhApplication;
import com.hippo.ehviewer.client.EhClient;
import com.hippo.ehviewer.ui.EhActivity;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.SceneFragment;
import com.hippo.scene.StageActivity;
public abstract class EhCallback<E extends SceneFragment, T> implements EhClient.Callback<T> {
public abstract class EhCallback<E extends Fragment, T> implements EhClient.Callback<T> {
private final EhApplication mApplication;
private final int mStageId;
private final String mSceneTag;
public EhCallback(Context context, int stageId, String sceneTag) {
public EhCallback(Context context) {
mApplication = (EhApplication) context.getApplicationContext();
mStageId = stageId;
mSceneTag = sceneTag;
}
public abstract boolean isInstance(SceneFragment scene);
public Context getContent() {
Context context = getStageActivity();
Context context = mApplication.getTopActivity();
if (context == null) {
context = getApplication();
}
@@ -53,26 +47,8 @@ public abstract class EhCallback<E extends SceneFragment, T> implements EhClient
return mApplication;
}
public StageActivity getStageActivity() {
return mApplication.findStageActivityById(mStageId);
}
@SuppressWarnings("unchecked")
public E getScene() {
StageActivity stage = mApplication.findStageActivityById(mStageId);
if (stage == null) {
return null;
}
SceneFragment scene = stage.findSceneByTag(mSceneTag);
if (isInstance(scene)) {
return (E) scene;
} else {
return null;
}
}
public void showTip(@StringRes int id, int length) {
StageActivity activity = getStageActivity();
EhActivity activity = mApplication.getTopActivity();
if (activity instanceof MainActivity) {
((MainActivity) activity).showTip(id, length);
} else {
@@ -82,7 +58,7 @@ public abstract class EhCallback<E extends SceneFragment, T> implements EhClient
}
public void showTip(String tip, int length) {
StageActivity activity = getStageActivity();
EhActivity activity = mApplication.getTopActivity();
if (activity instanceof MainActivity) {
((MainActivity) activity).showTip(tip, length);
} else {
@@ -65,8 +65,6 @@ import com.hippo.ehviewer.ui.annotation.DrawerLifeCircle;
import com.hippo.ehviewer.ui.annotation.ViewLifeCircle;
import com.hippo.ehviewer.ui.annotation.WholeLifeCircle;
import com.hippo.ehviewer.widget.GalleryInfoContentHelper;
import com.hippo.scene.Announcer;
import com.hippo.scene.SceneFragment;
import com.hippo.widget.ContentLayout;
import com.hippo.widget.FabLayout;
import com.hippo.yorozuya.AssertUtils;
@@ -460,8 +458,7 @@ public class FavoritesScene extends SearchBarScene implements
Bundle args = new Bundle();
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO);
args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, gi);
Announcer announcer = new Announcer(GalleryDetailScene.class).setArgs(args);
startScene(announcer);
navigate(R.id.galleryDetailScene, args);
}
}
return true;
@@ -727,15 +724,14 @@ public class FavoritesScene extends SearchBarScene implements
}
}
private static class AddFavoritesListener extends EhCallback<FavoritesScene, Void> {
private class AddFavoritesListener extends EhCallback<FavoritesScene, Void> {
private final int mTaskId;
private final String mKeyword;
private final List<GalleryInfo> mBackup;
private AddFavoritesListener(Context context, int stageId,
String sceneTag, int taskId, String keyword, List<GalleryInfo> backup) {
super(context, stageId, sceneTag);
private AddFavoritesListener(Context context, int taskId, String keyword, List<GalleryInfo> backup) {
super(context);
mTaskId = taskId;
mKeyword = keyword;
mBackup = backup;
@@ -743,10 +739,8 @@ public class FavoritesScene extends SearchBarScene implements
@Override
public void onSuccess(Void result) {
FavoritesScene scene = getScene();
if (scene != null) {
scene.onGetFavoritesLocal(mKeyword, mTaskId);
}
FavoritesScene scene = FavoritesScene.this;
scene.onGetFavoritesLocal(mKeyword, mTaskId);
}
@Override
@@ -755,32 +749,24 @@ public class FavoritesScene extends SearchBarScene implements
// But how to known which one is failed?
EhDB.putLocalFavorites(mBackup);
FavoritesScene scene = getScene();
if (scene != null) {
scene.onGetFavoritesLocal(mKeyword, mTaskId);
}
FavoritesScene scene = FavoritesScene.this;
scene.onGetFavoritesLocal(mKeyword, mTaskId);
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof FavoritesScene;
}
}
private static class GetFavoritesListener extends EhCallback<FavoritesScene, FavoritesParser.Result> {
private class GetFavoritesListener extends EhCallback<FavoritesScene, FavoritesParser.Result> {
private final int mTaskId;
// Local fav is shown now, but operation need be done for cloud fav
private final boolean mLocal;
private final String mKeyword;
private GetFavoritesListener(Context context, int stageId,
String sceneTag, int taskId, boolean local, String keyword) {
super(context, stageId, sceneTag);
private GetFavoritesListener(Context context, int taskId, boolean local, String keyword) {
super(context);
mTaskId = taskId;
mLocal = local;
mKeyword = keyword;
@@ -791,37 +777,28 @@ public class FavoritesScene extends SearchBarScene implements
// Put fav cat
Settings.putFavCat(result.catArray);
Settings.putFavCount(result.countArray);
FavoritesScene scene = getScene();
if (scene != null) {
if (mLocal) {
scene.onGetFavoritesLocal(mKeyword, mTaskId);
} else {
scene.onGetFavoritesSuccess(result, mTaskId);
}
FavoritesScene scene = FavoritesScene.this;
if (mLocal) {
scene.onGetFavoritesLocal(mKeyword, mTaskId);
} else {
scene.onGetFavoritesSuccess(result, mTaskId);
}
}
@Override
public void onFailure(Exception e) {
FavoritesScene scene = getScene();
if (scene != null) {
if (mLocal) {
e.printStackTrace();
scene.onGetFavoritesLocal(mKeyword, mTaskId);
} else {
scene.onGetFavoritesFailure(e, mTaskId);
}
FavoritesScene scene = FavoritesScene.this;
if (mLocal) {
e.printStackTrace();
scene.onGetFavoritesLocal(mKeyword, mTaskId);
} else {
scene.onGetFavoritesFailure(e, mTaskId);
}
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof FavoritesScene;
}
}
private static class FavDrawerHolder extends RecyclerView.ViewHolder {
@@ -1039,9 +1016,7 @@ public class FavoritesScene extends SearchBarScene implements
EhRequest request = new EhRequest();
request.setMethod(EhClient.METHOD_ADD_FAVORITES_RANGE);
request.setCallback(new AddFavoritesListener(getContext(),
activity.getStageId(), getTag(),
taskId, mUrlBuilder.getKeyword(), modifyGiListBackup));
request.setCallback(new AddFavoritesListener(getContext(), taskId, mUrlBuilder.getKeyword(), modifyGiListBackup));
request.setArgs(gidArray, tokenArray, mModifyFavCat);
request.enqueue(FavoritesScene.this);
} else {
@@ -1062,7 +1037,6 @@ public class FavoritesScene extends SearchBarScene implements
EhRequest request = new EhRequest();
request.setMethod(EhClient.METHOD_MODIFY_FAVORITES);
request.setCallback(new GetFavoritesListener(getContext(),
activity.getStageId(), getTag(),
taskId, local, mUrlBuilder.getKeyword()));
request.setArgs(url, gidArray, mModifyFavCat);
request.enqueue(FavoritesScene.this);
@@ -1077,7 +1051,6 @@ public class FavoritesScene extends SearchBarScene implements
EhRequest request = new EhRequest();
request.setMethod(EhClient.METHOD_GET_FAVORITES);
request.setCallback(new GetFavoritesListener(getContext(),
activity.getStageId(), getTag(),
taskId, false, mUrlBuilder.getKeyword()));
request.setArgs(url);
request.enqueue(FavoritesScene.this);
@@ -72,7 +72,6 @@ import com.hippo.ehviewer.client.data.ListUrlBuilder;
import com.hippo.ehviewer.client.parser.VoteCommentParser;
import com.hippo.ehviewer.dao.Filter;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.SceneFragment;
import com.hippo.text.URLImageGetter;
import com.hippo.util.ClipboardUtilKt;
import com.hippo.util.ExceptionUtils;
@@ -313,8 +312,7 @@ public final class GalleryCommentsScene extends BaseToolbarScene
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_VOTE_COMMENT)
.setArgs(mGalleryDetail.apiUid, mGalleryDetail.apiKey, mGalleryDetail.getGid(), mGalleryDetail.getToken(), id, vote)
.setCallback(new VoteCommentListener(context,
activity.getStageId(), getTag()));
.setCallback(new VoteCommentListener(context));
request.enqueue(this);
}
@@ -450,7 +448,7 @@ public final class GalleryCommentsScene extends BaseToolbarScene
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_GET_GALLERY_DETAIL)
.setArgs(url)
.setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
.setCallback(new RefreshCommentListener(activity));
request.enqueue(this);
}
}
@@ -634,8 +632,7 @@ public final class GalleryCommentsScene extends BaseToolbarScene
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_GET_COMMENT_GALLERY)
.setArgs(url, comment, mCommentId != 0 ? Long.toString(mCommentId) : null)
.setCallback(new CommentGalleryListener(context,
activity.getStageId(), getTag(), mCommentId));
.setCallback(new CommentGalleryListener(context, mCommentId));
request.enqueue(this);
hideSoftInput();
hideEditPanel(true);
@@ -654,10 +651,6 @@ public final class GalleryCommentsScene extends BaseToolbarScene
mAdapter.notifyDataSetChanged();
updateView(true);
Bundle re = new Bundle();
re.putParcelable(KEY_COMMENT_LIST, result);
setResult(SceneFragment.RESULT_OK, re);
}
private void onRefreshGalleryFailure() {
@@ -680,9 +673,6 @@ public final class GalleryCommentsScene extends BaseToolbarScene
mGalleryDetail.comments = result;
mAdapter.notifyDataSetChanged();
Bundle re = new Bundle();
re.putParcelable(KEY_COMMENT_LIST, result);
setResult(SceneFragment.RESULT_OK, re);
// Remove text
if (mEditText != null) {
@@ -723,10 +713,6 @@ public final class GalleryCommentsScene extends BaseToolbarScene
}
mAdapter.notifyItemChanged(position);
Bundle re = new Bundle();
re.putParcelable(KEY_COMMENT_LIST, mGalleryDetail.comments);
setResult(SceneFragment.RESULT_OK, re);
}
@Override
@@ -741,50 +727,41 @@ public final class GalleryCommentsScene extends BaseToolbarScene
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_GET_GALLERY_DETAIL)
.setArgs(url)
.setCallback(new RefreshCommentListener(activity, activity.getStageId(), getTag()));
.setCallback(new RefreshCommentListener(activity));
request.enqueue(this);
}
}
}
private static class RefreshCommentListener extends EhCallback<GalleryCommentsScene, GalleryDetail> {
private class RefreshCommentListener extends EhCallback<GalleryCommentsScene, GalleryDetail> {
public RefreshCommentListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
public RefreshCommentListener(Context context) {
super(context);
}
@Override
public void onSuccess(GalleryDetail result) {
GalleryCommentsScene scene = getScene();
if (scene != null) {
scene.onRefreshGallerySuccess(result.comments);
}
GalleryCommentsScene scene = GalleryCommentsScene.this;
scene.onRefreshGallerySuccess(result.comments);
}
@Override
public void onFailure(Exception e) {
GalleryCommentsScene scene = getScene();
if (scene != null) {
scene.onRefreshGalleryFailure();
}
GalleryCommentsScene scene = GalleryCommentsScene.this;
scene.onRefreshGalleryFailure();
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryCommentsScene;
}
}
private static class CommentGalleryListener extends EhCallback<GalleryCommentsScene, GalleryCommentList> {
private class CommentGalleryListener extends EhCallback<GalleryCommentsScene, GalleryCommentList> {
private final long mCommentId;
public CommentGalleryListener(Context context, int stageId, String sceneTag, long commentId) {
super(context, stageId, sceneTag);
public CommentGalleryListener(Context context, long commentId) {
super(context);
mCommentId = commentId;
}
@@ -792,10 +769,8 @@ public final class GalleryCommentsScene extends BaseToolbarScene
public void onSuccess(GalleryCommentList result) {
showTip(mCommentId != 0 ? R.string.edit_comment_successfully : R.string.comment_successfully, LENGTH_SHORT);
GalleryCommentsScene scene = getScene();
if (scene != null) {
scene.onCommentGallerySuccess(result);
}
GalleryCommentsScene scene = GalleryCommentsScene.this;
scene.onCommentGallerySuccess(result);
}
@Override
@@ -806,17 +781,12 @@ public final class GalleryCommentsScene extends BaseToolbarScene
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryCommentsScene;
}
}
private static class VoteCommentListener extends EhCallback<GalleryCommentsScene, VoteCommentParser.Result> {
private class VoteCommentListener extends EhCallback<GalleryCommentsScene, VoteCommentParser.Result> {
public VoteCommentListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
public VoteCommentListener(Context context) {
super(context);
}
@Override
@@ -826,10 +796,8 @@ public final class GalleryCommentsScene extends BaseToolbarScene
(0 != result.vote ? R.string.vote_down_successfully : R.string.cancel_vote_down_successfully),
LENGTH_SHORT);
GalleryCommentsScene scene = getScene();
if (scene != null) {
scene.onVoteCommentSuccess(result);
}
GalleryCommentsScene scene = GalleryCommentsScene.this;
scene.onVoteCommentSuccess(result);
}
@Override
@@ -840,11 +808,6 @@ public final class GalleryCommentsScene extends BaseToolbarScene
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryCommentsScene;
}
}
private static class InfoHolder extends RecyclerView.ViewHolder {
@@ -925,7 +888,7 @@ public final class GalleryCommentsScene extends BaseToolbarScene
ListUrlBuilder lub = new ListUrlBuilder();
lub.setMode(ListUrlBuilder.MODE_UPLOADER);
lub.setKeyword(value.user);
GalleryListScene.startScene(GalleryCommentsScene.this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
});
time.setText(ReadableTime.getTimeAgo(value.time));
comment.setText(generateComment(comment.getContext(), comment, value));
@@ -97,8 +97,6 @@ import com.hippo.ehviewer.ui.GalleryInfoBottomSheet;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.ehviewer.ui.annotation.WholeLifeCircle;
import com.hippo.ehviewer.widget.GalleryRatingBar;
import com.hippo.scene.Announcer;
import com.hippo.scene.SceneFragment;
import com.hippo.text.URLImageGetter;
import com.hippo.unifile.UniFile;
import com.hippo.util.AppHelper;
@@ -624,6 +622,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
}
EhApplication.getDownloadManager().addDownloadInfoListener(this);
((MainActivity)requireActivity()).setMShareUrl(getGalleryDetailUrl());
return view;
}
@@ -635,6 +634,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
Context context = getContext();
AssertUtils.assertNotNull(context);
EhApplication.getDownloadManager().removeDownloadInfoListener(this);
((MainActivity)requireActivity()).setMShareUrl(null);
mTip = null;
mViewTransition = null;
@@ -720,8 +720,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
return false;
}
EhClient.Callback<?> callback = new GetGalleryDetailListener(context,
activity.getStageId(), getTag());
EhClient.Callback<?> callback = new GetGalleryDetailListener(context);
mRequestId = ((EhApplication) context.getApplicationContext()).putGlobalStuff(callback);
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_GET_GALLERY_DETAIL)
@@ -1007,7 +1006,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
ListUrlBuilder lub = new ListUrlBuilder();
lub.setMode(ListUrlBuilder.MODE_NORMAL);
lub.setKeyword("\"" + keyword + "\"");
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
return;
}
String artist = getArtist(gd.tags);
@@ -1015,14 +1014,14 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
ListUrlBuilder lub = new ListUrlBuilder();
lub.setMode(ListUrlBuilder.MODE_TAG);
lub.setKeyword("artist:" + artist);
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
return;
}
if (null != gd.getUploader()) {
ListUrlBuilder lub = new ListUrlBuilder();
lub.setMode(ListUrlBuilder.MODE_UPLOADER);
lub.setKeyword(gd.getUploader());
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
}
}
@@ -1042,7 +1041,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
lub.setMode(ListUrlBuilder.MODE_IMAGE_SEARCH);
lub.setImagePath(path.toString());
lub.setUseSimilarityScan(true);
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
} catch (Throwable e) {
e.printStackTrace();
}
@@ -1068,7 +1067,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
ListUrlBuilder lub = new ListUrlBuilder();
lub.setMode(ListUrlBuilder.MODE_UPLOADER);
lub.setKeyword(uploader);
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
} else if (mCategory == v) {
int category = getCategory();
if (category == EhUtils.NONE || category == EhUtils.PRIVATE || category == EhUtils.UNKNOWN) {
@@ -1076,7 +1075,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
}
ListUrlBuilder lub = new ListUrlBuilder();
lub.setCategory(category);
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
} else if (mDownload == v) {
GalleryInfo galleryInfo = getGalleryInfo();
if (galleryInfo != null) {
@@ -1120,7 +1119,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN);
args.putLong(GalleryDetailScene.KEY_GID, newerVersion.getGid());
args.putString(GalleryDetailScene.KEY_TOKEN, newerVersion.getToken());
startScene(new Announcer(GalleryDetailScene.class).setArgs(args));
navigate(R.id.galleryDetailScene, args);
})
.show();
}
@@ -1134,15 +1133,13 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
if (EhDB.containLocalFavorites(mGalleryDetail.getGid()) || mGalleryDetail.isFavorited) {
mModifyingFavorites = true;
CommonOperations.removeFromFavorites(activity, mGalleryDetail,
new ModifyFavoritesListener(context,
activity.getStageId(), getTag(), true));
new ModifyFavoritesListener(context, true));
remove = true;
}
if (!remove) {
mModifyingFavorites = true;
CommonOperations.addToFavorites(activity, mGalleryDetail,
new ModifyFavoritesListener(context,
activity.getStageId(), getTag(), false));
new ModifyFavoritesListener(context, false));
}
// Update UI
updateFavoriteDrawable();
@@ -1213,14 +1210,12 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
args.putString(GalleryCommentsScene.KEY_TOKEN, mGalleryDetail.getToken());
args.putParcelable(GalleryCommentsScene.KEY_COMMENT_LIST, mGalleryDetail.comments);
args.putParcelable(GalleryCommentsScene.KEY_GALLERY_DETAIL, mGalleryDetail);
startScene(new Announcer(GalleryCommentsScene.class)
.setArgs(args)
.setRequestCode(this, REQUEST_CODE_COMMENT_GALLERY));
navigate(R.id.galleryCommentsScene, args);
} else if (mPreviews == v) {
if (null != mGalleryDetail) {
Bundle args = new Bundle();
args.putParcelable(GalleryPreviewsScene.KEY_GALLERY_INFO, mGalleryDetail);
startScene(new Announcer(GalleryPreviewsScene.class).setArgs(args));
navigate(R.id.galleryPreviewsScene, args);
}
} else {
Object o = v.getTag(R.id.tag);
@@ -1228,7 +1223,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
ListUrlBuilder lub = new ListUrlBuilder();
lub.setMode(ListUrlBuilder.MODE_TAG);
lub.setKeyword(tag);
GalleryListScene.startScene(this, lub);
navigate(R.id.galleryListScene, GalleryListScene.getStartArgs(lub), true);
return;
}
@@ -1354,8 +1349,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_VOTE_TAG)
.setArgs(mGalleryDetail.apiUid, mGalleryDetail.apiKey, mGalleryDetail.getGid(), mGalleryDetail.getToken(), tag, vote)
.setCallback(new VoteTagListener(context,
activity.getStageId(), getTag()));
.setCallback(new VoteTagListener(context));
request.enqueue(this);
}
@@ -1383,15 +1377,13 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
if (EhDB.containLocalFavorites(mGalleryDetail.getGid()) || mGalleryDetail.isFavorited) {
mModifyingFavorites = true;
CommonOperations.removeFromFavorites(activity, mGalleryDetail,
new ModifyFavoritesListener(activity,
activity.getStageId(), getTag(), true));
new ModifyFavoritesListener(activity, true));
remove = true;
}
if (!remove) {
mModifyingFavorites = true;
CommonOperations.addToFavorites(activity, mGalleryDetail,
new ModifyFavoritesListener(activity,
activity.getStageId(), getTag(), false), true);
new ModifyFavoritesListener(activity, false), true);
}
// Update UI
updateFavoriteDrawable();
@@ -1406,23 +1398,6 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
return false;
}
@Override
protected void onSceneResult(int requestCode, int resultCode, Bundle data) {
if (requestCode == REQUEST_CODE_COMMENT_GALLERY) {
if (resultCode != RESULT_OK || data == null) {
return;
}
GalleryCommentList comments = data.getParcelable(GalleryCommentsScene.KEY_COMMENT_LIST);
if (mGalleryDetail == null && comments == null) {
return;
}
mGalleryDetail.comments = comments;
bindComments(comments.comments);
} else {
super.onSceneResult(requestCode, resultCode, data);
}
}
private void updateDownloadText() {
if (null == mDownload) {
return;
@@ -1537,25 +1512,15 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
mModifyingFavorites = false;
}
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
String url = getGalleryDetailUrl();
if (url != null) {
outContent.setWebUri(Uri.parse(url));
}
}
@IntDef({STATE_INIT, STATE_NORMAL, STATE_REFRESH, STATE_REFRESH_HEADER, STATE_FAILED})
@Retention(RetentionPolicy.SOURCE)
private @interface State {
}
private static class GetGalleryDetailListener extends EhCallback<GalleryDetailScene, GalleryDetail> {
private class GetGalleryDetailListener extends EhCallback<GalleryDetailScene, GalleryDetail> {
public GetGalleryDetailListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
public GetGalleryDetailListener(Context context) {
super(context);
}
@Override
@@ -1569,36 +1534,27 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
EhDB.putHistoryInfo(result);
// Notify success
GalleryDetailScene scene = getScene();
if (scene != null) {
scene.onGetGalleryDetailSuccess(result);
}
GalleryDetailScene scene = GalleryDetailScene.this;
scene.onGetGalleryDetailSuccess(result);
}
@Override
public void onFailure(Exception e) {
getApplication().removeGlobalStuff(this);
GalleryDetailScene scene = getScene();
if (scene != null) {
scene.onGetGalleryDetailFailure(e);
}
GalleryDetailScene scene = GalleryDetailScene.this;
scene.onGetGalleryDetailFailure(e);
}
@Override
public void onCancel() {
getApplication().removeGlobalStuff(this);
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryDetailScene;
}
}
private static class VoteTagListener extends EhCallback<GalleryDetailScene, VoteTagParser.Result> {
public VoteTagListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
public VoteTagListener(Context context) {
super(context);
}
@Override
@@ -1618,19 +1574,14 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryDetailScene;
}
}
private static class RateGalleryListener extends EhCallback<GalleryDetailScene, RateGalleryParser.Result> {
private class RateGalleryListener extends EhCallback<GalleryDetailScene, RateGalleryParser.Result> {
private final long mGid;
public RateGalleryListener(Context context, int stageId, String sceneTag, long gid) {
super(context, stageId, sceneTag);
super(context);
mGid = gid;
}
@@ -1638,17 +1589,8 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
public void onSuccess(RateGalleryParser.Result result) {
showTip(R.string.rate_successfully, LENGTH_SHORT);
GalleryDetailScene scene = getScene();
if (scene != null) {
scene.onRateGallerySuccess(result);
} else {
// Update rating in cache
GalleryDetail gd = EhApplication.getGalleryDetailCache().get(mGid);
if (gd != null) {
gd.setRating(result.rating);
gd.ratingCount = result.ratingCount;
}
}
GalleryDetailScene scene = GalleryDetailScene.this;
scene.onRateGallerySuccess(result);
}
@Override
@@ -1660,22 +1602,17 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryDetailScene;
}
}
private static class ModifyFavoritesListener extends EhCallback<GalleryDetailScene, Void> {
private class ModifyFavoritesListener extends EhCallback<GalleryDetailScene, Void> {
private final boolean mAddOrRemove;
/**
* @param addOrRemove false for add, true for remove
*/
public ModifyFavoritesListener(Context context, int stageId, String sceneTag, boolean addOrRemove) {
super(context, stageId, sceneTag);
public ModifyFavoritesListener(Context context, boolean addOrRemove) {
super(context);
mAddOrRemove = addOrRemove;
}
@@ -1683,33 +1620,22 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
public void onSuccess(Void result) {
showTip(mAddOrRemove ? R.string.remove_from_favorite_success :
R.string.add_to_favorite_success, LENGTH_SHORT);
GalleryDetailScene scene = getScene();
if (scene != null) {
scene.onModifyFavoritesSuccess(mAddOrRemove);
}
GalleryDetailScene scene = GalleryDetailScene.this;
scene.onModifyFavoritesSuccess(mAddOrRemove);
}
@Override
public void onFailure(Exception e) {
showTip(mAddOrRemove ? R.string.remove_from_favorite_failure :
R.string.add_to_favorite_failure, LENGTH_LONG);
GalleryDetailScene scene = getScene();
if (scene != null) {
scene.onModifyFavoritesFailure();
}
GalleryDetailScene scene = GalleryDetailScene.this;
scene.onModifyFavoritesFailure();
}
@Override
public void onCancel() {
GalleryDetailScene scene = getScene();
if (scene != null) {
scene.onModifyFavoritesCancel();
}
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryDetailScene;
GalleryDetailScene scene = GalleryDetailScene.this;
scene.onModifyFavoritesCancel();
}
}
@@ -1718,7 +1644,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
private final GalleryInfo mGalleryInfo;
public DownloadArchiveListener(Context context, int stageId, String sceneTag, GalleryInfo galleryInfo) {
super(context, stageId, sceneTag);
super(context);
mGalleryInfo = galleryInfo;
}
@@ -1756,11 +1682,6 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryDetailScene;
}
}
private static class DeleteDialogHelper implements DialogInterface.OnClickListener {
@@ -1862,7 +1783,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
EhRequest request = new EhRequest();
request.setMethod(EhClient.METHOD_DOWNLOAD_ARCHIVE);
request.setArgs(mGalleryDetail.getGid(), mGalleryDetail.getToken(), mArchiveFormParamOr, res, isHAtH);
request.setCallback(new DownloadArchiveListener(context, activity.getStageId(), getTag(), mGalleryDetail));
request.setCallback(new DownloadArchiveListener(context, 1, getTag(), mGalleryDetail));
request.enqueue(GalleryDetailScene.this);
}
@@ -2073,7 +1994,7 @@ public class GalleryDetailScene extends CollapsingToolbarScene implements View.O
.setArgs(mGalleryDetail.apiUid, mGalleryDetail.apiKey,
mGalleryDetail.getGid(), mGalleryDetail.getToken(), mRatingBar.getRating())
.setCallback(new RateGalleryListener(context,
activity.getStageId(), getTag(), mGalleryDetail.getGid()));
1, getTag(), mGalleryDetail.getGid()));
request.enqueue(GalleryDetailScene.this);
}
}
@@ -92,8 +92,6 @@ import com.hippo.ehviewer.ui.CommonOperations
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter
import com.hippo.ehviewer.widget.GalleryInfoContentHelper
import com.hippo.ehviewer.widget.SearchLayout
import com.hippo.scene.Announcer
import com.hippo.scene.SceneFragment
import com.hippo.view.BringOutTransition
import com.hippo.view.ViewTransition
import com.hippo.widget.FabLayout
@@ -211,27 +209,19 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
}
private fun handleArgs(args: Bundle?) {
args ?: return
mUrlBuilder = when (args.getString(KEY_ACTION)) {
val action = args?.getString(KEY_ACTION) ?: ACTION_HOMEPAGE
mUrlBuilder = when (action) {
ACTION_HOMEPAGE -> ListUrlBuilder()
ACTION_SUBSCRIPTION -> ListUrlBuilder(MODE_SUBSCRIPTION)
ACTION_WHATS_HOT -> ListUrlBuilder(MODE_WHATS_HOT)
ACTION_TOP_LIST -> ListUrlBuilder(MODE_TOPLIST, mKeyword = "11")
ACTION_LIST_URL_BUILDER -> args.getParcelable<ListUrlBuilder>(KEY_LIST_URL_BUILDER)
ACTION_LIST_URL_BUILDER -> args?.getParcelable<ListUrlBuilder>(KEY_LIST_URL_BUILDER)
?.copy() ?: ListUrlBuilder()
else -> throw IllegalStateException("Wrong KEY_ACTION:${args.getString(KEY_ACTION)} when handle args!")
else -> throw IllegalStateException("Wrong KEY_ACTION:${args?.getString(KEY_ACTION)} when handle args!")
}
}
override fun onNewArguments(args: Bundle) {
handleArgs(args)
onUpdateUrlBuilder()
mHelper?.refresh()
setState(STATE_NORMAL)
showSearchBar()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mDownloadManager.addDownloadInfoListener(mDownloadInfoListener)
@@ -619,8 +609,7 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO)
args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, gi)
val announcer = Announcer(GalleryDetailScene::class.java).setArgs(args)
startScene(announcer)
navigate(R.id.galleryDetailScene, args)
}
override fun onClickPrimaryFab(view: FabLayout, fab: FloatingActionButton) {
@@ -805,13 +794,13 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
CommonOperations.removeFromFavorites(
activity,
gi,
RemoveFromFavoriteListener(context, activity.stageId, tag)
RemoveFromFavoriteListener(context)
)
} else {
CommonOperations.addToFavorites(
activity,
gi,
AddToFavoriteListener(context, activity.stageId, tag)
AddToFavoriteListener(context)
)
}
@@ -1102,30 +1091,25 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
@IntDef(STATE_NORMAL, STATE_SIMPLE_SEARCH, STATE_SEARCH, STATE_SEARCH_SHOW_LIST)
@Retention(AnnotationRetention.SOURCE)
private annotation class State
private class GetGalleryListListener(
private inner class GetGalleryListListener(
context: Context,
stageId: Int,
sceneTag: String?,
private val mTaskId: Int
) : EhCallback<GalleryListScene, GalleryListParser.Result>(context, stageId, sceneTag) {
) : EhCallback<GalleryListScene, GalleryListParser.Result>(context) {
override fun onSuccess(result: GalleryListParser.Result) {
val scene = scene
scene?.onGetGalleryListSuccess(result, mTaskId)
val scene = this@GalleryListScene
scene.onGetGalleryListSuccess(result, mTaskId)
}
override fun onFailure(e: Exception) {
val scene = scene
scene?.onGetGalleryListFailure(e, mTaskId)
val scene = this@GalleryListScene
scene.onGetGalleryListFailure(e, mTaskId)
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class AddToFavoriteListener(context: Context, stageId: Int, sceneTag: String?) :
EhCallback<GalleryListScene, Void>(context, stageId, sceneTag) {
private class AddToFavoriteListener(context: Context) :
EhCallback<GalleryListScene, Void>(context) {
override fun onSuccess(result: Void) {
showTip(R.string.add_to_favorite_success, LENGTH_SHORT)
}
@@ -1135,13 +1119,10 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class RemoveFromFavoriteListener(context: Context, stageId: Int, sceneTag: String?) :
EhCallback<GalleryListScene, Void>(context, stageId, sceneTag) {
private class RemoveFromFavoriteListener(context: Context) :
EhCallback<GalleryListScene, Void>(context) {
override fun onSuccess(result: Void) {
showTip(R.string.remove_from_favorite_success, LENGTH_SHORT)
}
@@ -1151,9 +1132,6 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class QsDrawerHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
@@ -1256,27 +1234,32 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
}
override fun onClick() {
startScene(createAnnouncer())
navigate(getDestination(), getArgs())
if (mState == STATE_SIMPLE_SEARCH) {
setState(STATE_NORMAL)
} else if (mState == STATE_SEARCH_SHOW_LIST) {
setState(STATE_SEARCH)
}
}
abstract fun getDestination(): Int
abstract fun createAnnouncer(): Announcer?
abstract fun getArgs(): Bundle
}
private inner class GalleryDetailUrlSuggestion(
private val mGid: Long,
private val mToken: String
) : UrlSuggestion() {
override fun createAnnouncer(): Announcer? {
override fun getDestination(): Int {
return R.id.galleryDetailScene
}
override fun getArgs(): Bundle {
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GID_TOKEN)
args.putLong(GalleryDetailScene.KEY_GID, mGid)
args.putString(GalleryDetailScene.KEY_TOKEN, mToken)
return Announcer(GalleryDetailScene::class.java).setArgs(args)
return args
}
}
@@ -1285,13 +1268,17 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
private val mPToken: String,
private val mPage: Int
) : UrlSuggestion() {
override fun createAnnouncer(): Announcer? {
override fun getDestination(): Int {
return R.id.progressScene
}
override fun getArgs(): Bundle {
val args = Bundle()
args.putString(ProgressScene.KEY_ACTION, ProgressScene.ACTION_GALLERY_TOKEN)
args.putLong(ProgressScene.KEY_GID, mGid)
args.putString(ProgressScene.KEY_PTOKEN, mPToken)
args.putInt(ProgressScene.KEY_PAGE, mPage)
return Announcer(ProgressScene::class.java).setArgs(args)
return args
}
}
@@ -1340,7 +1327,7 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
request.setCallback(
GetGalleryListListener(
context,
activity.stageId, tag, taskId
taskId
)
)
request.setArgs(
@@ -1356,7 +1343,7 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
request.setCallback(
GetGalleryListListener(
context,
activity.stageId, tag, taskId
taskId
)
)
request.setArgs(url)
@@ -1492,15 +1479,11 @@ class GalleryListScene : SearchBarScene(), OnDragHandlerListener, SearchLayout.H
}
@JvmStatic
fun startScene(scene: SceneFragment, lub: ListUrlBuilder?) {
scene.startScene(getStartAnnouncer(lub))
}
fun getStartAnnouncer(lub: ListUrlBuilder?): Announcer {
fun getStartArgs(lub: ListUrlBuilder): Bundle {
val args = Bundle()
args.putString(KEY_ACTION, ACTION_LIST_URL_BUILDER)
args.putParcelable(KEY_LIST_URL_BUILDER, lub)
return Announcer(GalleryListScene::class.java).setArgs(args)
return args
}
}
}
@@ -49,7 +49,6 @@ import com.hippo.ehviewer.client.data.GalleryPreview;
import com.hippo.ehviewer.client.data.PreviewSet;
import com.hippo.ehviewer.client.exception.EhException;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.SceneFragment;
import com.hippo.widget.ContentLayout;
import com.hippo.widget.LoadImageView;
import com.hippo.widget.recyclerview.AutoGridLayoutManager;
@@ -251,40 +250,31 @@ public class GalleryPreviewsScene extends BaseToolbarScene {
}
}
private static class GetPreviewSetListener extends EhCallback<GalleryPreviewsScene, Pair<PreviewSet, Integer>> {
private class GetPreviewSetListener extends EhCallback<GalleryPreviewsScene, Pair<PreviewSet, Integer>> {
private final int mTaskId;
public GetPreviewSetListener(Context context, int stageId, String sceneTag, int taskId) {
super(context, stageId, sceneTag);
super(context);
mTaskId = taskId;
}
@Override
public void onSuccess(Pair<PreviewSet, Integer> result) {
GalleryPreviewsScene scene = getScene();
if (scene != null) {
scene.onGetPreviewSetSuccess(result, mTaskId);
}
GalleryPreviewsScene scene = GalleryPreviewsScene.this;
scene.onGetPreviewSetSuccess(result, mTaskId);
}
@Override
public void onFailure(Exception e) {
GalleryPreviewsScene scene = getScene();
if (scene != null) {
scene.onGetPreviewSetFailure(e, mTaskId);
}
GalleryPreviewsScene scene = GalleryPreviewsScene.this;
scene.onGetPreviewSetFailure(e, mTaskId);
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof GalleryPreviewsScene;
}
}
private static class GalleryPreviewHolder extends RecyclerView.ViewHolder {
@@ -348,7 +338,7 @@ public class GalleryPreviewsScene extends BaseToolbarScene {
EhRequest request = new EhRequest();
request.setMethod(EhClient.METHOD_GET_PREVIEW_SET);
request.setCallback(new GetPreviewSetListener(getContext(),
activity.getStageId(), getTag(), taskId));
1, getTag(), taskId));
request.setArgs(url);
request.enqueue(GalleryPreviewsScene.this);
}
@@ -48,8 +48,6 @@ import com.hippo.ehviewer.download.DownloadManager.DownloadInfoListener
import com.hippo.ehviewer.ui.CommonOperations
import com.hippo.ehviewer.ui.dialog.SelectItemWithIconAdapter
import com.hippo.ehviewer.widget.SimpleRatingView
import com.hippo.scene.Announcer
import com.hippo.scene.SceneFragment
import com.hippo.view.ViewTransition
import com.hippo.widget.LoadImageView
import com.hippo.widget.recyclerview.AutoStaggeredGridLayoutManager
@@ -223,8 +221,7 @@ class HistoryScene : BaseToolbarScene() {
val args = Bundle()
args.putString(GalleryDetailScene.KEY_ACTION, GalleryDetailScene.ACTION_GALLERY_INFO)
args.putParcelable(GalleryDetailScene.KEY_GALLERY_INFO, gi)
val announcer = Announcer(GalleryDetailScene::class.java).setArgs(args)
startScene(announcer)
navigate(R.id.galleryDetailScene, args)
return true
}
@@ -293,13 +290,13 @@ class HistoryScene : BaseToolbarScene() {
CommonOperations.removeFromFavorites(
activity,
gi,
RemoveFromFavoriteListener(context, activity.stageId, tag)
RemoveFromFavoriteListener(context)
)
} else {
CommonOperations.addToFavorites(
activity,
gi,
AddToFavoriteListener(context, activity.stageId, tag)
AddToFavoriteListener(context)
)
}
@@ -325,8 +322,8 @@ class HistoryScene : BaseToolbarScene() {
return true
}
private class AddToFavoriteListener(context: Context?, stageId: Int, sceneTag: String?) :
EhCallback<GalleryListScene?, Void?>(context, stageId, sceneTag) {
private class AddToFavoriteListener(context: Context?) :
EhCallback<GalleryListScene?, Void?>(context) {
override fun onSuccess(result: Void?) {
showTip(R.string.add_to_favorite_success, LENGTH_SHORT)
}
@@ -336,13 +333,10 @@ class HistoryScene : BaseToolbarScene() {
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class RemoveFromFavoriteListener(context: Context?, stageId: Int, sceneTag: String?) :
EhCallback<GalleryListScene?, Void?>(context, stageId, sceneTag) {
private class RemoveFromFavoriteListener(context: Context?) :
EhCallback<GalleryListScene?, Void?>(context) {
override fun onSuccess(result: Void?) {
showTip(R.string.remove_from_favorite_success, LENGTH_SHORT)
}
@@ -352,9 +346,6 @@ class HistoryScene : BaseToolbarScene() {
}
override fun onCancel() {}
override fun isInstance(scene: SceneFragment): Boolean {
return scene is GalleryListScene
}
}
private class HistoryHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
@@ -32,8 +32,6 @@ import com.hippo.ehviewer.R;
import com.hippo.ehviewer.client.EhClient;
import com.hippo.ehviewer.client.EhRequest;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.Announcer;
import com.hippo.scene.SceneFragment;
import com.hippo.util.ExceptionUtils;
import com.hippo.view.ViewTransition;
import com.hippo.yorozuya.AssertUtils;
@@ -97,7 +95,7 @@ public final class ProgressScene extends BaseScene implements View.OnClickListen
.setMethod(EhClient.METHOD_GET_GALLERY_TOKEN)
.setArgs(mGid, mPToken, mPage)
.setCallback(new GetGalleryTokenListener(context,
activity.getStageId(), getTag()));
1, getTag()));
request.enqueue(this);
return true;
}
@@ -209,8 +207,7 @@ public final class ProgressScene extends BaseScene implements View.OnClickListen
arg.putLong(GalleryDetailScene.KEY_GID, mGid);
arg.putString(GalleryDetailScene.KEY_TOKEN, result);
arg.putInt(GalleryDetailScene.KEY_PAGE, mPage);
startScene(new Announcer(GalleryDetailScene.class).setArgs(arg));
finish();
navigate(R.id.galleryDetailScene, arg);
}
private void onGetGalleryTokenFailure(Exception e) {
@@ -226,35 +223,26 @@ public final class ProgressScene extends BaseScene implements View.OnClickListen
}
}
private static class GetGalleryTokenListener extends EhCallback<ProgressScene, String> {
private class GetGalleryTokenListener extends EhCallback<ProgressScene, String> {
public GetGalleryTokenListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
super(context);
}
@Override
public void onSuccess(String result) {
ProgressScene scene = getScene();
if (scene != null) {
scene.onGetGalleryTokenSuccess(result);
}
ProgressScene scene = ProgressScene.this;
scene.onGetGalleryTokenSuccess(result);
}
@Override
public void onFailure(Exception e) {
ProgressScene scene = getScene();
if (scene != null) {
scene.onGetGalleryTokenFailure(e);
}
ProgressScene scene = ProgressScene.this;
scene.onGetGalleryTokenFailure(e);
}
@Override
public void onCancel() {
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof ProgressScene;
}
}
}
@@ -33,7 +33,7 @@ import com.hippo.ehviewer.client.EhUrl;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.yorozuya.ViewUtils;
public class SelectSiteScene extends SolidScene implements View.OnClickListener {
public class SelectSiteScene extends BaseScene implements View.OnClickListener {
private MaterialButtonToggleGroup mButtonGroup;
private View mOk;
@@ -82,13 +82,11 @@ public class SelectSiteScene extends SolidScene implements View.OnClickListener
if (id == R.id.site_e) {
Settings.putSelectSite(false);
Settings.putGallerySite(EhUrl.SITE_E);
startSceneForCheckStep(CHECK_STEP_SELECT_SITE, getArguments());
finish();
navigateToTop();
} else if (id == R.id.site_ex) {
Settings.putSelectSite(false);
Settings.putGallerySite(EhUrl.SITE_EX);
startSceneForCheckStep(CHECK_STEP_SELECT_SITE, getArguments());
finish();
navigateToTop();
} else {
showTip(R.string.no_select, LENGTH_SHORT);
}
@@ -42,21 +42,16 @@ import com.hippo.ehviewer.client.EhUrl;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.ehviewer.client.parser.ProfileParser;
import com.hippo.ehviewer.ui.MainActivity;
import com.hippo.scene.Announcer;
import com.hippo.scene.SceneFragment;
import com.hippo.util.ExceptionUtils;
import com.hippo.yorozuya.AssertUtils;
import com.hippo.yorozuya.IntIdGenerator;
import com.hippo.yorozuya.ViewUtils;
public final class SignInScene extends SolidScene implements EditText.OnEditorActionListener,
public final class SignInScene extends BaseScene implements EditText.OnEditorActionListener,
View.OnClickListener {
private static final String KEY_REQUEST_ID = "request_id";
private static final int REQUEST_CODE_WEBVIEW = 0;
private static final int REQUEST_CODE_COOKIE = 0;
/*---------------
View life cycle
---------------*/
@@ -202,17 +197,6 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
}
}
@Override
protected void onSceneResult(int requestCode, int resultCode, Bundle data) {
if (REQUEST_CODE_WEBVIEW == requestCode) {
if (RESULT_OK == resultCode) {
getProfile();
}
} else {
super.onSceneResult(requestCode, resultCode, data);
}
}
@Override
public void onClick(View v) {
MainActivity activity = getMainActivity();
@@ -225,9 +209,9 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
} else if (mSignIn == v) {
signIn();
} else if (mSignInViaWebView == v) {
startScene(new Announcer(WebViewSignInScene.class).setRequestCode(this, REQUEST_CODE_WEBVIEW));
navigate(R.id.webViewSignInScene, null);
} else if (mSignInViaCookies == v) {
startScene(new Announcer(CookieSignInScene.class).setRequestCode(this, REQUEST_CODE_COOKIE));
navigate(R.id.cookieSignInScene, null);
} else if (mSkipSigningIn == v) {
// Set gallery size SITE_E if skip sign in
Settings.putGallerySite(EhUrl.SITE_E);
@@ -282,8 +266,7 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
// Clean up for sign in
EhUtils.signOut();
EhCallback<?, ?> callback = new SignInListener(context,
activity.getStageId(), getTag());
EhCallback<?, ?> callback = new SignInListener(context);
mRequestId = ((EhApplication) context.getApplicationContext()).putGlobalStuff(callback);
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_SIGN_IN)
@@ -304,8 +287,7 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
hideSoftInput();
showProgress(true);
EhCallback<?, ?> callback = new GetProfileListener(context,
activity.getStageId(), getTag());
EhCallback<?, ?> callback = new GetProfileListener(context);
mRequestId = ((EhApplication) context.getApplicationContext()).putGlobalStuff(callback);
EhRequest request = new EhRequest()
.setMethod(EhClient.METHOD_GET_PROFILE)
@@ -317,11 +299,11 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
private void redirectTo() {
Settings.putNeedSignIn(false);
MainActivity activity = getMainActivity();
if (null != activity) {
startSceneForCheckStep(CHECK_STEP_SIGN_IN, getArguments());
if (Settings.getSelectSite()) {
navigate(R.id.selectSiteScene, null);
} else {
navigateToTop();
}
finish();
}
private void whetherToSkip(Exception e) {
@@ -357,10 +339,10 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
redirectTo();
}
private static class SignInListener extends EhCallback<SignInScene, String> {
private class SignInListener extends EhCallback<SignInScene, String> {
public SignInListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
public SignInListener(Context context) {
super(context);
}
@Override
@@ -368,10 +350,8 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
getApplication().removeGlobalStuff(this);
Settings.putDisplayName(result);
SignInScene scene = getScene();
if (scene != null) {
scene.onSignInEnd(null);
}
SignInScene scene = SignInScene.this;
scene.onSignInEnd(null);
}
@Override
@@ -379,27 +359,20 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
getApplication().removeGlobalStuff(this);
e.printStackTrace();
SignInScene scene = getScene();
if (scene != null) {
scene.onSignInEnd(e);
}
SignInScene scene = SignInScene.this;
scene.onSignInEnd(e);
}
@Override
public void onCancel() {
getApplication().removeGlobalStuff(this);
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof SignInScene;
}
}
private static class GetProfileListener extends EhCallback<SignInScene, ProfileParser.Result> {
private class GetProfileListener extends EhCallback<SignInScene, ProfileParser.Result> {
public GetProfileListener(Context context, int stageId, String sceneTag) {
super(context, stageId, sceneTag);
public GetProfileListener(Context context) {
super(context);
}
@Override
@@ -408,10 +381,8 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
Settings.putDisplayName(result.displayName);
Settings.putAvatar(result.avatar);
SignInScene scene = getScene();
if (scene != null) {
scene.onGetProfileEnd();
}
SignInScene scene = SignInScene.this;
scene.onGetProfileEnd();
}
@Override
@@ -419,20 +390,13 @@ public final class SignInScene extends SolidScene implements EditText.OnEditorAc
getApplication().removeGlobalStuff(this);
e.printStackTrace();
SignInScene scene = getScene();
if (scene != null) {
scene.onGetProfileEnd();
}
SignInScene scene = SignInScene.this;
scene.onGetProfileEnd();
}
@Override
public void onCancel() {
getApplication().removeGlobalStuff(this);
}
@Override
public boolean isInstance(SceneFragment scene) {
return scene instanceof SignInScene;
}
}
}
@@ -1,70 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.ui.scene;
import android.os.Bundle;
import android.util.Log;
import com.hippo.ehviewer.Settings;
import com.hippo.scene.Announcer;
/**
* Scene for safety, can't be covered
*/
public class SolidScene extends BaseScene {
public static final int CHECK_STEP_SIGN_IN = 1;
public static final int CHECK_STEP_SELECT_SITE = 2;
public static final String KEY_TARGET_SCENE = "target_scene";
public static final String KEY_TARGET_ARGS = "target_args";
private static final String TAG = SolidScene.class.getSimpleName();
public void startSceneForCheckStep(int checkStep, Bundle args) {
switch (checkStep) {
case CHECK_STEP_SIGN_IN:
if (Settings.getSelectSite()) {
startScene(new Announcer(SelectSiteScene.class).setArgs(args), true);
break;
}
case CHECK_STEP_SELECT_SITE:
String targetScene = null;
Bundle targetArgs = null;
if (null != args) {
targetScene = args.getString(KEY_TARGET_SCENE);
targetArgs = args.getBundle(KEY_TARGET_ARGS);
}
Class<?> clazz = null;
if (targetScene != null) {
try {
clazz = Class.forName(targetScene);
} catch (ClassNotFoundException e) {
Log.e(TAG, "Can't find class with name: " + targetScene);
}
}
if (clazz != null) {
startScene(new Announcer(clazz).setArgs(targetArgs));
} else {
Bundle newArgs = new Bundle();
newArgs.putString(GalleryListScene.KEY_ACTION, Settings.getLaunchPageGalleryListSceneAction());
startScene(new Announcer(GalleryListScene.class).setArgs(newArgs));
}
break;
}
}
}
@@ -44,7 +44,7 @@ import okhttp3.Cookie;
import okhttp3.HttpUrl;
import rikka.core.res.ResourcesKt;
public class WebViewSignInScene extends SolidScene {
public class WebViewSignInScene extends BaseScene {
/*---------------
View life cycle
@@ -147,8 +147,8 @@ public class WebViewSignInScene extends SolidScene {
}
if (getId && getHash) {
setResult(RESULT_OK, null);
finish();
navigateToTop();
// TODO: getProfile
}
}
}
@@ -1,26 +1,9 @@
/*
* Copyright 2022 Tarsin Norbin
*
* This file is part of EhViewer
*
* EhViewer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* EhViewer is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with EhViewer.
* If not, see <https://www.gnu.org/licenses/>.
*/
package com.hippo.ehviewer.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -29,21 +12,20 @@ import androidx.core.view.ViewCompat;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import com.google.android.material.snackbar.Snackbar;
import com.hippo.scene.StageLayout;
import com.hippo.yorozuya.LayoutUtils;
import java.util.ArrayList;
import java.util.List;
public class EhStageLayout extends StageLayout implements CoordinatorLayout.AttachedBehavior {
public class AboveSnackerLayout extends FrameLayout implements CoordinatorLayout.AttachedBehavior {
private List<View> mAboveSnackViewList;
public EhStageLayout(Context context, AttributeSet attrs) {
public AboveSnackerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EhStageLayout(Context context, AttributeSet attrs, int defStyle) {
public AboveSnackerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@@ -76,19 +58,19 @@ public class EhStageLayout extends StageLayout implements CoordinatorLayout.Atta
@NonNull
@Override
public EhStageLayout.Behavior getBehavior() {
return new EhStageLayout.Behavior();
public AboveSnackerLayout.Behavior getBehavior() {
return new AboveSnackerLayout.Behavior();
}
public static class Behavior extends CoordinatorLayout.Behavior<EhStageLayout> {
public static class Behavior extends CoordinatorLayout.Behavior<AboveSnackerLayout> {
@Override
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull EhStageLayout child, @NonNull View dependency) {
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull AboveSnackerLayout child, @NonNull View dependency) {
return dependency instanceof Snackbar.SnackbarLayout;
}
@Override
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, EhStageLayout child, @NonNull View dependency) {
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, AboveSnackerLayout child, @NonNull View dependency) {
for (int i = 0, n = child.getAboveSnackViewCount(); i < n; i++) {
View view = child.getAboveSnackViewAt(i);
if (view != null) {
@@ -100,7 +82,7 @@ public class EhStageLayout extends StageLayout implements CoordinatorLayout.Atta
}
@Override
public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull EhStageLayout child, @NonNull View dependency) {
public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull AboveSnackerLayout child, @NonNull View dependency) {
for (int i = 0, n = child.getAboveSnackViewCount(); i < n; i++) {
View view = child.getAboveSnackViewAt(i);
if (view != null) {
@@ -1,50 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.scene;
import android.os.Bundle;
public final class Announcer {
Class<?> clazz;
Bundle args;
SceneFragment requestFrom;
int requestCode;
public Announcer(Class<?> clazz) {
this.clazz = clazz;
}
public Class<?> getClazz() {
return clazz;
}
public Bundle getArgs() {
return args;
}
public Announcer setArgs(Bundle args) {
this.args = args;
return this;
}
public Announcer setRequestCode(SceneFragment requestFrom, int requestCode) {
this.requestFrom = requestFrom;
this.requestCode = requestCode;
return this;
}
}
@@ -1,56 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.scene;
import android.app.Application;
import android.util.SparseArray;
import com.hippo.yorozuya.IntIdGenerator;
public abstract class SceneApplication extends Application {
private final IntIdGenerator mIdGenerator = new IntIdGenerator();
private final SparseArray<StageActivity> mStageMap = new SparseArray<>();
void registerStageActivity(StageActivity stage) {
int id = mIdGenerator.nextId();
mStageMap.put(id, stage);
stage.onRegister(id);
}
void registerStageActivity(StageActivity stage, int id) {
if (mStageMap.indexOfKey(id) >= 0) {
throw new IllegalStateException("The id exists: " + id);
}
mStageMap.put(id, stage);
stage.onRegister(id);
}
void unregisterStageActivity(int id) {
int index = mStageMap.indexOfKey(id);
if (index >= 0) {
StageActivity stage = mStageMap.valueAt(index);
mStageMap.remove(id);
stage.onUnregister();
}
}
public StageActivity findStageActivityById(int id) {
return mStageMap.get(id);
}
}
@@ -1,169 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.scene;
import android.app.assist.AssistContent;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.hippo.ehviewer.R;
import com.hippo.yorozuya.collect.IntList;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import rikka.core.res.ResourcesKt;
public class SceneFragment extends Fragment {
public static final int LAUNCH_MODE_STANDARD = 0;
public static final int LAUNCH_MODE_SINGLE_TOP = 1;
public static final int LAUNCH_MODE_SINGLE_TASK = 2;
/**
* Standard scene result: operation canceled.
*/
public static final int RESULT_CANCELED = 0;
/**
* Standard scene result: operation succeeded.
*/
public static final int RESULT_OK = -1;
int resultCode = RESULT_CANCELED;
Bundle result = null;
List<String> mRequestSceneTagList = new ArrayList<>(0);
IntList mRequestCodeList = new IntList(0);
public void onNewArguments(@NonNull Bundle args) {
}
public void startScene(Announcer announcer, boolean horizontal) {
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
((StageActivity) activity).startScene(announcer, horizontal);
}
}
public void startScene(Announcer announcer) {
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
((StageActivity) activity).startScene(announcer);
}
}
public void finish() {
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
((StageActivity) activity).finishScene(this);
}
}
public void finishStage() {
FragmentActivity activity = getActivity();
if (activity != null) {
activity.finish();
}
}
/**
* @return negative for error
*/
public int getStackIndex() {
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
return ((StageActivity) activity).getSceneIndex(this);
} else {
return -1;
}
}
public void onProvideAssistContent(AssistContent outContent) {
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.setTag(R.id.fragment_tag, getTag());
view.setBackground(ResourcesKt.resolveDrawable(requireActivity().getTheme(), android.R.attr.windowBackground));
// Notify
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
((StageActivity) activity).onSceneViewCreated(this, savedInstanceState);
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
// Notify
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
((StageActivity) activity).onSceneViewDestroyed(this);
}
}
@Override
public void onDestroy() {
super.onDestroy();
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
((StageActivity) activity).onSceneDestroyed(this);
}
}
void addRequest(String requestSceneTag, int requestCode) {
mRequestSceneTagList.add(requestSceneTag);
mRequestCodeList.add(requestCode);
}
void returnResult(StageActivity stage) {
for (int i = 0, size = Math.min(mRequestSceneTagList.size(), mRequestCodeList.size()); i < size; i++) {
String tag = mRequestSceneTagList.get(i);
int code = mRequestCodeList.get(i);
SceneFragment scene = stage.findSceneByTag(tag);
if (scene != null) {
scene.onSceneResult(code, resultCode, result);
}
}
mRequestSceneTagList.clear();
mRequestCodeList.clear();
}
protected void onSceneResult(int requestCode, int resultCode, Bundle data) {
}
public void setResult(int resultCode, Bundle result) {
this.resultCode = resultCode;
this.result = result;
}
@IntDef({LAUNCH_MODE_STANDARD, LAUNCH_MODE_SINGLE_TOP, LAUNCH_MODE_SINGLE_TASK})
@Retention(RetentionPolicy.SOURCE)
public @interface LaunchMode {
}
}
@@ -1,655 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.scene;
import android.app.assist.AssistContent;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ui.EhActivity;
import com.hippo.yorozuya.AssertUtils;
import com.hippo.yorozuya.IntIdGenerator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class StageActivity extends EhActivity {
public static final String ACTION_START_SCENE = "start_scene";
public static final String KEY_SCENE_NAME = "stage_activity_scene_name";
public static final String KEY_SCENE_ARGS = "stage_activity_scene_args";
private static final String TAG = StageActivity.class.getSimpleName();
private static final String KEY_STAGE_ID = "stage_activity_stage_id";
private static final String KEY_SCENE_TAG_LIST = "stage_activity_scene_tag_list";
private static final String KEY_NEXT_ID = "stage_activity_next_id";
private static final Map<Class<?>, Integer> sLaunchModeMap = new HashMap<>();
private final ArrayList<String> mSceneTagList = new ArrayList<>();
private final ArrayList<String> mDelaySceneTagList = new ArrayList<>();
private final AtomicInteger mIdGenerator = new AtomicInteger();
private final SceneViewComparator mSceneViewComparator = new SceneViewComparator();
private final OnBackPressedCallback callback = new BackPressCallBack();
private int mStageId = IntIdGenerator.INVALID_ID;
public static void registerLaunchMode(Class<?> clazz, @SceneFragment.LaunchMode int launchMode) {
if (launchMode != SceneFragment.LAUNCH_MODE_STANDARD &&
launchMode != SceneFragment.LAUNCH_MODE_SINGLE_TOP &&
launchMode != SceneFragment.LAUNCH_MODE_SINGLE_TASK) {
throw new IllegalStateException("Invalid launch mode: " + launchMode);
}
sLaunchModeMap.put(clazz, launchMode);
}
public abstract int getContainerViewId();
/**
* @return {@code true} for start scene
*/
private boolean startSceneFromIntent(Intent intent) {
String clazzStr = intent.getStringExtra(KEY_SCENE_NAME);
if (null == clazzStr) {
return false;
}
Class<?> clazz;
try {
clazz = Class.forName(clazzStr);
} catch (ClassNotFoundException e) {
Log.e(TAG, "Can't find class " + clazzStr, e);
return false;
}
Bundle args = intent.getBundleExtra(KEY_SCENE_ARGS);
Announcer announcer = onStartSceneFromIntent(clazz, args);
if (announcer == null) {
return false;
}
startScene(announcer);
return true;
}
/**
* Start scene from {@code Intent}, it might be not safe,
* Correct it here.
*
* @return {@code null} for do not start scene
*/
@Nullable
protected Announcer onStartSceneFromIntent(@NonNull Class<?> clazz, @Nullable Bundle args) {
return new Announcer(clazz).setArgs(args);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent == null || !ACTION_START_SCENE.equals(intent.getAction()) ||
!startSceneFromIntent(intent)) {
onUnrecognizedIntent(intent);
}
}
/**
* Called when launch with action {@code android.intent.action.MAIN}
*/
@Nullable
protected abstract Announcer getLaunchAnnouncer();
/**
* Can't recognize intent in first time {@code onCreate} and {@code onNewIntent},
* null included.
*/
protected void onUnrecognizedIntent(@Nullable Intent intent) {
}
/**
* Call {@code setContentView} here. Do <b>NOT</b> call {@code startScene} here
*/
protected abstract void onCreate2(@Nullable Bundle savedInstanceState);
@Override
protected final void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getOnBackPressedDispatcher().addCallback(callback);
if (savedInstanceState != null) {
mStageId = savedInstanceState.getInt(KEY_STAGE_ID, IntIdGenerator.INVALID_ID);
ArrayList<String> list = savedInstanceState.getStringArrayList(KEY_SCENE_TAG_LIST);
if (list != null) {
mSceneTagList.addAll(list);
mDelaySceneTagList.addAll(list);
}
mIdGenerator.lazySet(savedInstanceState.getInt(KEY_NEXT_ID));
updateBackPressCallBackStatus();
}
if (mStageId == IntIdGenerator.INVALID_ID) {
((SceneApplication) getApplicationContext()).registerStageActivity(this);
} else {
((SceneApplication) getApplicationContext()).registerStageActivity(this, mStageId);
}
// Create layout
onCreate2(savedInstanceState);
Intent intent = getIntent();
if (savedInstanceState == null) {
if (intent != null) {
String action = intent.getAction();
if (Intent.ACTION_MAIN.equals(action)) {
Announcer announcer = getLaunchAnnouncer();
if (announcer != null) {
startScene(announcer);
return;
}
} else if (ACTION_START_SCENE.equals(action)) {
if (startSceneFromIntent(intent)) {
return;
}
}
}
// Can't recognize intent
onUnrecognizedIntent(intent);
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_STAGE_ID, mStageId);
outState.putStringArrayList(KEY_SCENE_TAG_LIST, mSceneTagList);
outState.putInt(KEY_NEXT_ID, mIdGenerator.getAndIncrement());
}
@Override
protected void onDestroy() {
super.onDestroy();
((SceneApplication) getApplicationContext()).unregisterStageActivity(mStageId);
}
public void onSceneViewCreated(SceneFragment scene, Bundle savedInstanceState) {
}
public void onSceneViewDestroyed(SceneFragment scene) {
}
void onSceneDestroyed(SceneFragment scene) {
mDelaySceneTagList.remove(scene.getTag());
}
protected void onRegister(int id) {
mStageId = id;
}
protected void onUnregister() {
}
protected void onTransactScene() {
}
public int getStageId() {
return mStageId;
}
public int getSceneCount() {
return mSceneTagList.size();
}
public int getSceneLaunchMode(Class<?> clazz) {
Integer integer = sLaunchModeMap.get(clazz);
if (integer == null) {
throw new RuntimeException("Not register " + clazz.getName());
} else {
return integer;
}
}
private SceneFragment newSceneInstance(Class<?> clazz) {
try {
return (SceneFragment) clazz.newInstance();
} catch (InstantiationException e) {
throw new IllegalStateException("Can't instance " + clazz.getName(), e);
} catch (IllegalAccessException e) {
throw new IllegalStateException("The constructor of " +
clazz.getName() + " is not visible", e);
} catch (ClassCastException e) {
throw new IllegalStateException(clazz.getName() + " can not cast to scene", e);
}
}
public void startScene(Announcer announcer) {
startScene(announcer, false);
}
public void startScene(Announcer announcer, boolean horizontal) {
startSceneInternal(announcer, horizontal);
updateBackPressCallBackStatus();
}
public void startSceneInternal(Announcer announcer, boolean horizontal) {
Class<?> clazz = announcer.clazz;
Bundle args = announcer.args;
FragmentManager fragmentManager = getSupportFragmentManager();
int launchMode = getSceneLaunchMode(clazz);
// Check LAUNCH_MODE_SINGLE_TASK
if (launchMode == SceneFragment.LAUNCH_MODE_SINGLE_TASK) {
for (int i = 0, n = mSceneTagList.size(); i < n; i++) {
String tag = mSceneTagList.get(i);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
Log.e(TAG, "Can't find fragment with tag: " + tag);
continue;
}
if (clazz.isInstance(fragment)) { // Get it
FragmentTransaction transaction = fragmentManager.beginTransaction();
// Use default animation
if (horizontal) {
transaction.setCustomAnimations(R.anim.scene_open_enter_horizontal, R.anim.scene_open_exit);
} else {
transaction.setCustomAnimations(R.anim.scene_open_enter, R.anim.scene_open_exit);
}
// Remove top fragments
for (int j = i + 1; j < n; j++) {
String topTag = mSceneTagList.get(j);
Fragment topFragment = fragmentManager.findFragmentByTag(topTag);
if (null == topFragment) {
Log.e(TAG, "Can't find fragment with tag: " + topTag);
continue;
}
// Clear shared element
topFragment.setSharedElementEnterTransition(null);
topFragment.setSharedElementReturnTransition(null);
topFragment.setEnterTransition(null);
topFragment.setExitTransition(null);
// Remove it
transaction.remove(topFragment);
}
// Remove tag from index i+1
mSceneTagList.subList(i + 1, mSceneTagList.size()).clear();
mDelaySceneTagList.subList(i + 1, mDelaySceneTagList.size()).clear();
// Attach fragment
if (fragment.isDetached()) {
transaction.attach(fragment);
}
// Commit
transaction.commitAllowingStateLoss();
onTransactScene();
// New arguments
if (args != null && fragment instanceof SceneFragment) {
// TODO Call onNewArguments when view created ?
((SceneFragment) fragment).onNewArguments(args);
}
return;
}
}
}
// Get current fragment
SceneFragment currentScene = null;
if (mSceneTagList.size() > 0) {
// Get last tag
String tag = mSceneTagList.get(mSceneTagList.size() - 1);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment != null) {
AssertUtils.assertTrue(fragment instanceof SceneFragment);
currentScene = (SceneFragment) fragment;
}
}
// Check LAUNCH_MODE_SINGLE_TASK
if (clazz.isInstance(currentScene) && launchMode == SceneFragment.LAUNCH_MODE_SINGLE_TOP) {
if (args != null) {
currentScene.onNewArguments(args);
}
return;
}
// Create new scene
SceneFragment newScene = newSceneInstance(clazz);
newScene.setArguments(args);
// Create new scene tag
String newTag = Integer.toString(mIdGenerator.getAndIncrement());
// Add new tag to list
mSceneTagList.add(newTag);
mDelaySceneTagList.add(newTag);
FragmentTransaction transaction = fragmentManager.beginTransaction();
// Animation
if (currentScene != null) {
// Clear shared item
currentScene.setSharedElementEnterTransition(null);
currentScene.setSharedElementReturnTransition(null);
currentScene.setEnterTransition(null);
currentScene.setExitTransition(null);
newScene.setSharedElementEnterTransition(null);
newScene.setSharedElementReturnTransition(null);
newScene.setEnterTransition(null);
newScene.setExitTransition(null);
// Set default animation
if (horizontal) {
transaction.setCustomAnimations(R.anim.scene_open_enter_horizontal, R.anim.scene_open_exit);
} else {
transaction.setCustomAnimations(R.anim.scene_open_enter, R.anim.scene_open_exit);
}
// Detach current scene
if (!currentScene.isDetached()) {
transaction.detach(currentScene);
} else {
Log.e(TAG, "Current scene is detached");
}
}
// Add new scene
transaction.add(getContainerViewId(), newScene, newTag);
// Commit
transaction.commitAllowingStateLoss();
onTransactScene();
// Check request
if (announcer.requestFrom != null) {
newScene.addRequest(announcer.requestFrom.getTag(), announcer.requestCode);
}
}
public void startSceneFirstly(Announcer announcer) {
Class<?> clazz = announcer.clazz;
Bundle args = announcer.args;
FragmentManager fragmentManager = getSupportFragmentManager();
int launchMode = getSceneLaunchMode(clazz);
boolean forceNewScene = launchMode == SceneFragment.LAUNCH_MODE_STANDARD;
boolean createNewScene = true;
boolean findScene = false;
SceneFragment scene = null;
FragmentTransaction transaction = fragmentManager.beginTransaction();
// Set default animation
transaction.setCustomAnimations(R.anim.scene_open_enter, R.anim.scene_open_exit);
String findSceneTag = null;
for (int i = 0, n = mSceneTagList.size(); i < n; i++) {
String tag = mSceneTagList.get(i);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
Log.e(TAG, "Can't find fragment with tag: " + tag);
continue;
}
// Clear shared element
fragment.setSharedElementEnterTransition(null);
fragment.setSharedElementReturnTransition(null);
fragment.setEnterTransition(null);
fragment.setExitTransition(null);
// Check is target scene
if (!forceNewScene && !findScene && clazz.isInstance(fragment) &&
(launchMode == SceneFragment.LAUNCH_MODE_SINGLE_TASK || !fragment.isDetached())) {
scene = (SceneFragment) fragment;
findScene = true;
createNewScene = false;
findSceneTag = tag;
if (fragment.isDetached()) {
transaction.attach(fragment);
}
} else {
// Remove it
transaction.remove(fragment);
}
}
// Handle tag list
mSceneTagList.clear();
if (null != findSceneTag) {
mSceneTagList.add(findSceneTag);
}
if (createNewScene) {
scene = newSceneInstance(clazz);
scene.setArguments(args);
// Create scene tag
String tag = Integer.toString(mIdGenerator.getAndIncrement());
// Add tag to list
mSceneTagList.add(tag);
mDelaySceneTagList.add(tag);
// Add scene
transaction.add(getContainerViewId(), scene, tag);
}
// Commit
transaction.commitAllowingStateLoss();
onTransactScene();
if (!createNewScene && args != null) {
// TODO Call onNewArguments when view created ?
scene.onNewArguments(args);
}
updateBackPressCallBackStatus();
}
int getSceneIndex(SceneFragment scene) {
return getTagIndex(scene.getTag());
}
int getTagIndex(String tag) {
return mSceneTagList.indexOf(tag);
}
void sortSceneViews(List<View> views) {
views.sort(mSceneViewComparator);
}
public void finishScene(SceneFragment scene) {
finishScene(scene.getTag());
updateBackPressCallBackStatus();
}
private void finishScene(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
// Get scene
Fragment scene = fragmentManager.findFragmentByTag(tag);
if (scene == null) {
Log.e(TAG, "finishScene: Can't find scene by tag: " + tag);
return;
}
// Get scene index
int index = mSceneTagList.indexOf(tag);
if (index < 0) {
Log.e(TAG, "finishScene: Can't find the tag in tag list: " + tag);
return;
}
if (mSceneTagList.size() == 1) {
// It is the last fragment, finish Activity now
Log.i(TAG, "finishScene: It is the last scene, finish activity now");
finish();
return;
}
Fragment next = null;
if (index == mSceneTagList.size() - 1) {
// It is first fragment, show the next one
next = fragmentManager.findFragmentByTag(mSceneTagList.get(index - 1));
}
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (next != null) {
// Clear shared item
scene.setSharedElementEnterTransition(null);
scene.setSharedElementReturnTransition(null);
scene.setEnterTransition(null);
scene.setExitTransition(null);
next.setSharedElementEnterTransition(null);
next.setSharedElementReturnTransition(null);
next.setEnterTransition(null);
next.setExitTransition(null);
// Do not show animate if it is not the first fragment
transaction.setCustomAnimations(R.anim.scene_close_enter, R.anim.scene_close_exit);
// Attach fragment
transaction.attach(next);
}
transaction.remove(scene);
transaction.commitAllowingStateLoss();
onTransactScene();
// Remove tag
mSceneTagList.remove(index);
// Return result
if (scene instanceof SceneFragment) {
((SceneFragment) scene).returnResult(this);
}
}
public void refreshTopScene() {
int index = mSceneTagList.size() - 1;
if (index < 0) {
return;
}
String tag = mSceneTagList.get(index);
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
return;
}
fragmentManager.beginTransaction().detach(fragment).commitAllowingStateLoss();
fragmentManager.beginTransaction().attach(fragment).commitAllowingStateLoss();
updateBackPressCallBackStatus();
}
public void updateBackPressCallBackStatus() {
callback.setEnabled(mSceneTagList.size() > 1);
}
@Override
public void onProvideAssistContent(AssistContent outContent) {
super.onProvideAssistContent(outContent);
int size = mSceneTagList.size();
String tag = mSceneTagList.get(size - 1);
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
Log.e(TAG, "onProvideAssistContent: Can't find scene by tag: " + tag);
return;
}
if (fragment instanceof SceneFragment scene) {
scene.onProvideAssistContent(outContent);
} else {
Log.e(TAG, "onProvideAssistContent: The fragment is not SceneFragment");
}
}
public SceneFragment findSceneByTag(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment != null) {
return (SceneFragment) fragment;
} else {
return null;
}
}
@Nullable
public Class<?> getTopSceneClass() {
int index = mSceneTagList.size() - 1;
if (index < 0) {
return null;
}
String tag = mSceneTagList.get(index);
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
if (null == fragment) {
return null;
}
return fragment.getClass();
}
class BackPressCallBack extends OnBackPressedCallback {
public BackPressCallBack() {
super(false);
}
@Override
public void handleOnBackPressed() {
int size = mSceneTagList.size();
String tag = mSceneTagList.get(size - 1);
SceneFragment scene;
Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
Log.e(TAG, "onBackPressed: Can't find scene by tag: " + tag);
return;
}
if (!(fragment instanceof SceneFragment)) {
Log.e(TAG, "onBackPressed: The fragment is not SceneFragment");
return;
}
scene = (SceneFragment) fragment;
finishScene(scene);
}
}
private final class SceneViewComparator implements Comparator<View> {
private int getIndex(View view) {
Object o = view.getTag(R.id.fragment_tag);
if (o instanceof String) {
return mDelaySceneTagList.indexOf(o);
} else {
return -1;
}
}
@Override
public int compare(View lhs, View rhs) {
return getIndex(lhs) - getIndex(rhs);
}
}
}
@@ -1,156 +0,0 @@
/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.scene;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.hippo.ehviewer.R;
import java.lang.reflect.Field;
import java.util.ArrayList;
public class StageLayout extends FrameLayout {
private Field mDisappearingChildrenField;
private ArrayList<View> mSuperDisappearingChildren;
private ArrayList<View> mSortedScenes;
private View mDumpView;
private boolean mDoTrick;
public StageLayout(Context context) {
super(context);
init(context);
}
public StageLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public StageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
try {
mDisappearingChildrenField = ViewGroup.class.getDeclaredField("mDisappearingChildren");
mDisappearingChildrenField.setAccessible(true);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
if (mDisappearingChildrenField != null) {
mDumpView = new View(context);
addView(mDumpView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
}
@SuppressWarnings("unchecked")
private void getSuperDisappearingChildren() {
if (mDisappearingChildrenField == null || mSuperDisappearingChildren != null) {
return;
}
try {
mSuperDisappearingChildren = (ArrayList<View>) mDisappearingChildrenField.get(this);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private boolean beforeDispatchDraw() {
getSuperDisappearingChildren();
if (mSuperDisappearingChildren == null ||
mSuperDisappearingChildren.size() <= 0 || getChildCount() <= 1) { // only dump view
return false;
}
// Get stage
StageActivity stage = null;
Context context = getContext();
if (context instanceof StageActivity) {
stage = (StageActivity) context;
}
if (stage == null) {
return false;
}
if (null == mSortedScenes) {
mSortedScenes = new ArrayList<>();
}
// Add all scene view to mSortedScenes
ArrayList<View> disappearingChildren = mSuperDisappearingChildren;
ArrayList<View> sortedScenes = mSortedScenes;
for (int i = 1, n = getChildCount(); i < n; i++) { // Skip dump view
View view = getChildAt(i);
if (null != view.getTag(R.id.fragment_tag)) {
sortedScenes.add(view);
}
}
for (int i = 0, n = disappearingChildren.size(); i < n; i++) {
View view = disappearingChildren.get(i);
if (null != view.getTag(R.id.fragment_tag)) {
sortedScenes.add(view);
}
}
stage.sortSceneViews(sortedScenes);
return true;
}
private void afterDispatchDraw() {
if (null != mSortedScenes) {
mSortedScenes.clear();
}
}
@Override
protected void dispatchDraw(Canvas canvas) {
mDoTrick = beforeDispatchDraw();
super.dispatchDraw(canvas);
afterDispatchDraw();
mDoTrick = false;
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (mDoTrick) {
ArrayList<View> sortedScenes = mSortedScenes;
if (child == mDumpView) {
boolean more = false;
for (int i = 0, n = sortedScenes.size(); i < n; i++) {
more |= super.drawChild(canvas, sortedScenes.get(i), drawingTime);
}
return more;
} else if (sortedScenes.contains(child)) {
// Skip
return false;
}
}
return super.drawChild(canvas, child, drawingTime);
}
}