diff --git a/app/src/main/java/io/legato/kazusa/ui/about/AboutActivity.kt b/app/src/main/java/io/legato/kazusa/ui/about/AboutActivity.kt index b557582b1..565887c86 100644 --- a/app/src/main/java/io/legato/kazusa/ui/about/AboutActivity.kt +++ b/app/src/main/java/io/legato/kazusa/ui/about/AboutActivity.kt @@ -1,53 +1,97 @@ package io.legato.kazusa.ui.about -import android.os.Bundle -import android.text.Spannable -import android.text.SpannableString -import android.util.TypedValue -import android.view.Menu -import android.view.MenuItem -import io.legato.kazusa.R -import io.legato.kazusa.base.BaseActivity -import io.legato.kazusa.databinding.ActivityAboutBinding //import io.legado.app.lib.theme.accentColor //import io.legado.app.lib.theme.filletBackground +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import androidx.annotation.StringRes +import androidx.core.net.toUri +import androidx.lifecycle.lifecycleScope +import io.legato.kazusa.R +import io.legato.kazusa.base.BaseActivity +import io.legato.kazusa.constant.AppLog +import io.legato.kazusa.databinding.ActivityAboutBinding +import io.legato.kazusa.help.CrashHandler +import io.legato.kazusa.help.config.AppConfig +import io.legato.kazusa.help.coroutine.Coroutine +import io.legato.kazusa.help.update.AppUpdate +import io.legato.kazusa.ui.widget.dialog.TextDialog +import io.legato.kazusa.ui.widget.dialog.WaitDialog +import io.legato.kazusa.utils.FileDoc +import io.legato.kazusa.utils.compress.ZipUtils +import io.legato.kazusa.utils.createFileIfNotExist +import io.legato.kazusa.utils.createFolderIfNotExist +import io.legato.kazusa.utils.delete +import io.legato.kazusa.utils.externalCache +import io.legato.kazusa.utils.find +import io.legato.kazusa.utils.list +import io.legato.kazusa.utils.openInputStream +import io.legato.kazusa.utils.openOutputStream import io.legato.kazusa.utils.openUrl import io.legato.kazusa.utils.share +import io.legato.kazusa.utils.showDialogFragment +import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.viewbindingdelegate.viewBinding +import kotlinx.coroutines.delay +import splitties.init.appCtx +import java.io.File class AboutActivity : BaseActivity() { override val binding by viewBinding(ActivityAboutBinding::inflate) + private val waitDialog by lazy { + WaitDialog(this).setText(R.string.checking_update) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + setSupportActionBar(binding.topBar) - val fTag = "aboutFragment" - var aboutFragment = supportFragmentManager.findFragmentByTag(fTag) - if (aboutFragment == null) aboutFragment = AboutFragment() - supportFragmentManager.beginTransaction() - .replace(R.id.fl_fragment, aboutFragment, fTag) - .commit() - binding.tvAppSummary.post { - kotlin.runCatching { - val typedValue = TypedValue() - val context = binding.root.context - context.theme.resolveAttribute( - androidx.appcompat.R.attr.colorPrimary, - typedValue, - true - ) - val accentColor = typedValue.data - val spannableString = SpannableString(binding.tvAppSummary.text) - val gzh = getString(R.string.legado_gzh) - val start = spannableString.indexOf(gzh) - spannableString.setSpan( - accentColor, start, start + gzh.length, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE - ) - binding.tvAppSummary.text = spannableString - } + binding.btnUpdate.setOnClickListener { + checkUpdate() + } + + binding.btnGithub.setOnClickListener { + openUrl(R.string.github_url) + } + + binding.btnWeb.setOnClickListener { + openUrl(R.string.legado_url) + } + + binding.llContributors.setOnClickListener { + openUrl(R.string.contributors_url) + } + + binding.llUpdateLog.setOnClickListener { + showMdFile(getString(R.string.update_log), "updateLog.md") + } + + binding.llPrivacyPolicy.setOnClickListener { + showMdFile(getString(R.string.privacy_policy), "privacyPolicy.md") + } + + binding.llLicense.setOnClickListener { + showMdFile(getString(R.string.license), "LICENSE.md") + } + + binding.llDisclaimer.setOnClickListener { + showMdFile(getString(R.string.disclaimer), "disclaimer.md") + } + + binding.llCrashLog.setOnClickListener { + showDialogFragment() + } + + binding.llSaveLog.setOnClickListener { + saveLog() + } + + binding.llCreateHeapDump.setOnClickListener { + createHeapDump() } } @@ -58,7 +102,6 @@ class AboutActivity : BaseActivity() { override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.menu_scoring -> openUrl("market://details?id=$packageName") R.id.menu_share_it -> share( getString(R.string.app_share_description), getString(R.string.app_name) @@ -67,4 +110,118 @@ class AboutActivity : BaseActivity() { return super.onCompatOptionsItemSelected(item) } + private fun showMdFile(title: String, fileName: String) { + val mdText = String(this.assets.open(fileName).readBytes()) + showDialogFragment(TextDialog(title, mdText, TextDialog.Mode.MD)) + } + + private fun checkUpdate() { + waitDialog.show() + AppUpdate.gitHubUpdate?.run { + check(lifecycleScope) + .onSuccess { + showDialogFragment(UpdateDialog(it)) + }.onError { + appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}") + }.onFinally { + waitDialog.dismiss() + } + } + } + + @Suppress("SameParameterValue") + private fun openUrl(@StringRes addressID: Int) { + this.openUrl(getString(addressID)) + } + + private fun saveLog() { + Coroutine.async { + val backupPath = AppConfig.backupPath ?: let { + appCtx.toastOnUi("未设置备份目录") + return@async + } + if (!AppConfig.recordLog) { + appCtx.toastOnUi("未开启日志记录,请去其他设置里打开记录日志") + delay(3000) + } + val doc = FileDoc.fromUri(backupPath.toUri(), true) + copyLogs(doc) + copyHeapDump(doc) + appCtx.toastOnUi("已保存至备份目录") + }.onError { + AppLog.put("保存日志出错\n${it.localizedMessage}", it, true) + } + } + + private fun createHeapDump() { + Coroutine.async { + val backupPath = AppConfig.backupPath ?: let { + appCtx.toastOnUi("未设置备份目录") + return@async + } + if (!AppConfig.recordHeapDump) { + appCtx.toastOnUi("未开启堆转储记录,请去其他设置里打开记录堆转储") + delay(3000) + } + appCtx.toastOnUi("开始创建堆转储") + System.gc() + CrashHandler.doHeapDump(true) + val doc = FileDoc.fromUri(backupPath.toUri(), true) + if (!copyHeapDump(doc)) { + appCtx.toastOnUi("未找到堆转储文件") + } else { + appCtx.toastOnUi("已保存至备份目录") + } + }.onError { + AppLog.put("保存堆转储失败\n${it.localizedMessage}", it) + } + } + + private fun copyLogs(doc: FileDoc) { + val cacheDir = appCtx.externalCache + val logFiles = File(cacheDir, "logs") + val crashFiles = File(cacheDir, "crash") + val logcatFile = File(cacheDir, "logcat.txt") + + dumpLogcat(logcatFile) + + val zipFile = File(cacheDir, "logs.zip") + ZipUtils.zipFiles(arrayListOf(logFiles, crashFiles, logcatFile), zipFile) + + doc.find("logs.zip")?.delete() + + zipFile.inputStream().use { input -> + doc.createFileIfNotExist("logs.zip").openOutputStream().getOrNull() + ?.use { + input.copyTo(it) + } + } + zipFile.delete() + } + + private fun copyHeapDump(doc: FileDoc): Boolean { + val heapFile = FileDoc.fromFile(File(appCtx.externalCache, "heapDump")).list() + ?.firstOrNull() ?: return false + doc.find("heapDump")?.delete() + val heapDumpDoc = doc.createFolderIfNotExist("heapDump") + heapFile.openInputStream().getOrNull()?.use { input -> + heapDumpDoc.createFileIfNotExist(heapFile.name).openOutputStream().getOrNull() + ?.use { + input.copyTo(it) + } + } + return true + } + + private fun dumpLogcat(file: File) { + try { + val process = Runtime.getRuntime().exec("logcat -d") + file.outputStream().use { + process.inputStream.copyTo(it) + } + } catch (e: Exception) { + AppLog.put("保存Logcat失败\n$e", e) + } + } + } diff --git a/app/src/main/java/io/legato/kazusa/ui/about/AboutFragment.kt b/app/src/main/java/io/legato/kazusa/ui/about/AboutFragment.kt deleted file mode 100644 index e96624dfd..000000000 --- a/app/src/main/java/io/legato/kazusa/ui/about/AboutFragment.kt +++ /dev/null @@ -1,213 +0,0 @@ -package io.legato.kazusa.ui.about - -import android.os.Bundle -import android.view.View -import androidx.annotation.StringRes -import androidx.lifecycle.lifecycleScope -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat -import io.legato.kazusa.R -import io.legato.kazusa.constant.AppConst.appInfo -import io.legato.kazusa.constant.AppLog -import io.legato.kazusa.help.CrashHandler -import io.legato.kazusa.help.config.AppConfig -import io.legato.kazusa.help.coroutine.Coroutine -import io.legato.kazusa.help.update.AppUpdate -import io.legato.kazusa.ui.widget.dialog.TextDialog -import io.legato.kazusa.ui.widget.dialog.WaitDialog -import io.legato.kazusa.utils.FileDoc -import io.legato.kazusa.utils.compress.ZipUtils -import io.legato.kazusa.utils.createFileIfNotExist -import io.legato.kazusa.utils.createFolderIfNotExist -import io.legato.kazusa.utils.delete -import io.legato.kazusa.utils.externalCache -import io.legato.kazusa.utils.find -import io.legato.kazusa.utils.list -import io.legato.kazusa.utils.openInputStream -import io.legato.kazusa.utils.openOutputStream -import io.legato.kazusa.utils.openUrl -import io.legato.kazusa.utils.sendMail -import io.legato.kazusa.utils.sendToClip -import io.legato.kazusa.utils.showDialogFragment -import io.legato.kazusa.utils.toastOnUi -import kotlinx.coroutines.delay -import splitties.init.appCtx -import java.io.File -import androidx.core.net.toUri - -class AboutFragment : PreferenceFragmentCompat() { - - private val waitDialog by lazy { - WaitDialog(requireContext()) - } - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - addPreferencesFromResource(R.xml.about) - findPreference("update_log")?.summary = - "${getString(R.string.version)} ${appInfo.versionName}" - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - listView.overScrollMode = View.OVER_SCROLL_NEVER - } - - override fun onPreferenceTreeClick(preference: Preference): Boolean { - when (preference.key) { - "contributors" -> openUrl(R.string.contributors_url) - "update_log" -> showMdFile(getString(R.string.update_log), "updateLog.md") - "check_update" -> checkUpdate() - "mail" -> requireContext().sendMail(getString(R.string.email)) - "license" -> showMdFile(getString(R.string.license), "LICENSE.md") - "disclaimer" -> showMdFile(getString(R.string.disclaimer), "disclaimer.md") - "privacyPolicy" -> showMdFile(getString(R.string.privacy_policy), "privacyPolicy.md") - "gzGzh" -> requireContext().sendToClip(getString(R.string.legado_gzh)) - "crashLog" -> showDialogFragment() - "saveLog" -> saveLog() - "createHeapDump" -> createHeapDump() - } - return super.onPreferenceTreeClick(preference) - } - - @Suppress("SameParameterValue") - private fun openUrl(@StringRes addressID: Int) { - requireContext().openUrl(getString(addressID)) - } - - /** - * 显示md文件 - */ - private fun showMdFile(title: String, fileName: String) { - val mdText = String(requireContext().assets.open(fileName).readBytes()) - showDialogFragment(TextDialog(title, mdText, TextDialog.Mode.MD)) - } - - /** - * 检测更新 - */ - private fun checkUpdate() { - waitDialog.show() - AppUpdate.gitHubUpdate?.run { - check(lifecycleScope) - .onSuccess { - showDialogFragment( - UpdateDialog(it) - ) - }.onError { - appCtx.toastOnUi("${getString(R.string.check_update)}\n${it.localizedMessage}") - }.onFinally { - waitDialog.dismiss() - } - } - } - - -// /** -// * 加入qq群 -// */ -// private fun joinQQGroup(key: String): Boolean { -// val intent = Intent() -// intent.data = -// "mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D$key".toUri() -// // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 -// // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) -// kotlin.runCatching { -// startActivity(intent) -// return true -// }.onFailure { -// toastOnUi("添加失败,请手动添加") -// } -// return false -// } - - private fun saveLog() { - Coroutine.async { - val backupPath = AppConfig.backupPath ?: let { - appCtx.toastOnUi("未设置备份目录") - return@async - } - if (!AppConfig.recordLog) { - appCtx.toastOnUi("未开启日志记录,请去其他设置里打开记录日志") - delay(3000) - } - val doc = FileDoc.fromUri(backupPath.toUri(), true) - copyLogs(doc) - copyHeapDump(doc) - appCtx.toastOnUi("已保存至备份目录") - }.onError { - AppLog.put("保存日志出错\n${it.localizedMessage}", it, true) - } - } - - private fun createHeapDump() { - Coroutine.async { - val backupPath = AppConfig.backupPath ?: let { - appCtx.toastOnUi("未设置备份目录") - return@async - } - if (!AppConfig.recordHeapDump) { - appCtx.toastOnUi("未开启堆转储记录,请去其他设置里打开记录堆转储") - delay(3000) - } - appCtx.toastOnUi("开始创建堆转储") - System.gc() - CrashHandler.doHeapDump(true) - val doc = FileDoc.fromUri(backupPath.toUri(), true) - if (!copyHeapDump(doc)) { - appCtx.toastOnUi("未找到堆转储文件") - } else { - appCtx.toastOnUi("已保存至备份目录") - } - }.onError { - AppLog.put("保存堆转储失败\n${it.localizedMessage}", it) - } - } - - private fun copyLogs(doc: FileDoc) { - val cacheDir = appCtx.externalCache - val logFiles = File(cacheDir, "logs") - val crashFiles = File(cacheDir, "crash") - val logcatFile = File(cacheDir, "logcat.txt") - - dumpLogcat(logcatFile) - - val zipFile = File(cacheDir, "logs.zip") - ZipUtils.zipFiles(arrayListOf(logFiles, crashFiles, logcatFile), zipFile) - - doc.find("logs.zip")?.delete() - - zipFile.inputStream().use { input -> - doc.createFileIfNotExist("logs.zip").openOutputStream().getOrNull() - ?.use { - input.copyTo(it) - } - } - zipFile.delete() - } - - private fun copyHeapDump(doc: FileDoc): Boolean { - val heapFile = FileDoc.fromFile(File(appCtx.externalCache, "heapDump")).list() - ?.firstOrNull() ?: return false - doc.find("heapDump")?.delete() - val heapDumpDoc = doc.createFolderIfNotExist("heapDump") - heapFile.openInputStream().getOrNull()?.use { input -> - heapDumpDoc.createFileIfNotExist(heapFile.name).openOutputStream().getOrNull() - ?.use { - input.copyTo(it) - } - } - return true - } - - private fun dumpLogcat(file: File) { - try { - val process = Runtime.getRuntime().exec("logcat -d") - file.outputStream().use { - process.inputStream.copyTo(it) - } - } catch (e: Exception) { - AppLog.put("保存Logcat失败\n$e", e) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/book/search/BookAdapter.kt b/app/src/main/java/io/legato/kazusa/ui/book/search/BookAdapter.kt index d0d99e1cb..e3f2d58f3 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/search/BookAdapter.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/search/BookAdapter.kt @@ -5,8 +5,8 @@ import android.view.ViewGroup import io.legato.kazusa.base.adapter.ItemViewHolder import io.legato.kazusa.base.adapter.RecyclerAdapter import io.legato.kazusa.data.entities.Book -import io.legato.kazusa.databinding.ItemFilletTextBinding import io.legato.kazusa.databinding.ItemSearchHistoryBinding +import io.legato.kazusa.utils.gone class BookAdapter(context: Context, val callBack: CallBack) : @@ -39,6 +39,7 @@ class BookAdapter(context: Context, val callBack: CallBack) : } } } + binding.btnDelete.gone() } interface CallBack { diff --git a/app/src/main/java/io/legato/kazusa/ui/book/search/HistoryKeyAdapter.kt b/app/src/main/java/io/legato/kazusa/ui/book/search/HistoryKeyAdapter.kt index bfcde9630..864cee218 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/search/HistoryKeyAdapter.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/search/HistoryKeyAdapter.kt @@ -4,7 +4,6 @@ import android.view.ViewGroup import io.legato.kazusa.base.adapter.ItemViewHolder import io.legato.kazusa.base.adapter.RecyclerAdapter import io.legato.kazusa.data.entities.SearchKeyword -import io.legato.kazusa.databinding.ItemFilletTextBinding import io.legato.kazusa.databinding.ItemSearchHistoryBinding import io.legato.kazusa.ui.widget.anima.explosion_field.ExplosionField import splitties.views.onLongClick @@ -47,6 +46,11 @@ class HistoryKeyAdapter(activity: SearchActivity, val callBack: CallBack) : } } } + binding.btnDelete.setOnClickListener { + getItemByLayoutPosition(holder.layoutPosition)?.let { + callBack.deleteHistory(it) + } + } } interface CallBack { diff --git a/app/src/main/java/io/legato/kazusa/ui/book/search/SearchActivity.kt b/app/src/main/java/io/legato/kazusa/ui/book/search/SearchActivity.kt index b1d7ebdc5..fa280c0ec 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/search/SearchActivity.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/search/SearchActivity.kt @@ -5,17 +5,18 @@ import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem -import android.view.View.GONE import android.view.View.VISIBLE -import android.widget.TextView +import android.view.inputmethod.EditorInfo import androidx.activity.viewModels -import androidx.appcompat.widget.SearchView import androidx.core.os.bundleOf import androidx.core.view.isVisible +import androidx.core.widget.doAfterTextChanged import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.android.flexbox.FlexboxLayoutManager +import com.google.android.material.search.SearchBar +import com.google.android.material.search.SearchView import io.legato.kazusa.R import io.legato.kazusa.base.VMBaseActivity import io.legato.kazusa.constant.AppLog @@ -25,15 +26,12 @@ import io.legato.kazusa.data.entities.Book import io.legato.kazusa.data.entities.SearchKeyword import io.legato.kazusa.databinding.ActivityBookSearchBinding import io.legato.kazusa.lib.dialogs.alert -//import io.legado.app.lib.theme.accentColor -//import io.legado.app.lib.theme.backgroundColor -//import io.legado.app.lib.theme.primaryColor -//import io.legado.app.lib.theme.primaryTextColor import io.legato.kazusa.ui.about.AppLogDialog import io.legato.kazusa.ui.book.info.BookInfoActivity import io.legato.kazusa.ui.book.source.manage.BookSourceActivity import io.legato.kazusa.utils.applyNavigationBarMargin import io.legato.kazusa.utils.applyNavigationBarPadding +import io.legato.kazusa.utils.applyStatusBarPadding import io.legato.kazusa.utils.getPrefBoolean import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.invisible @@ -73,9 +71,10 @@ class SearchActivity : VMBaseActivity? = null private var historyFlowJob: Job? = null @@ -85,9 +84,9 @@ class SearchActivity : VMBaseActivity - isManualStopSearch = false - viewModel.saveSearchKey(searchKey) - viewModel.searchKey = "" - viewModel.search(searchKey) - } - visibleInputHelp(false) - return true - } + private fun initMaterialSearch() { - override fun onQueryTextChange(newText: String): Boolean { - viewModel.stop() - binding.fbStartStop.invisible() - upHistory(newText.trim()) - return false + binding.appBar.applyStatusBarPadding() + + searchBar.setOnMenuItemClickListener { item -> + onCompatOptionsItemSelected(item) + } + + searchBar.setNavigationOnClickListener { + finish() + } + + searchView.setupWithSearchBar(searchBar) + + binding.searchView.show() + binding.searchView.editText.requestFocus() + + searchView.editText.hint = getString(R.string.search_book_key) + searchView.editText.setOnEditorActionListener { _, actionId, _ -> + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + val key = searchView.text.toString().trim() + if (key.isNotEmpty()) { + isManualStopSearch = false + viewModel.saveSearchKey(key) + viewModel.searchKey = "" + viewModel.search(key) + visibleInputHelp() + searchView.hide() + return@setOnEditorActionListener true + } } - }) -// searchView.setOnQueryTextFocusChangeListener { _, hasFocus -> -// if (binding.refreshProgressBar.isAutoLoading || (!hasFocus && adapter.isNotEmpty() && searchView.query.isNotBlank())) { -// visibleInputHelp(false) -// } else { -// visibleInputHelp(true) -// } -// } - visibleInputHelp(true) + false + } + + searchView.editText.doAfterTextChanged { + viewModel.stop() + binding.fbStartStop.invisible() + upHistory(it?.toString()?.trim().orEmpty()) + } + + searchView.addTransitionListener { _, _, newState -> + if (newState == SearchView.TransitionState.HIDDEN) { + // 当 SearchView 关闭时,将搜索文本设置回 SearchBar + searchBar.setText(searchView.text) + } + } + + searchView.addTransitionListener { _, oldState, newState -> + if (oldState == SearchView.TransitionState.HIDDEN && newState == SearchView.TransitionState.SHOWN) { + searchView.editText.requestFocus() + } + } + + visibleInputHelp() } private fun initRecyclerView() { -// binding.recyclerView.setEdgeEffectColor(primaryColor) -// binding.rvBookshelfSearch.setEdgeEffectColor(primaryColor) -// binding.rvHistoryKey.setEdgeEffectColor(primaryColor) binding.rvBookshelfSearch.layoutManager = FlexboxLayoutManager(this) binding.rvBookshelfSearch.adapter = bookAdapter binding.rvBookshelfSearch.applyNavigationBarMargin() @@ -261,16 +279,10 @@ class SearchActivity : VMBaseActivity(androidx.appcompat.R.id.search_src_text) - .requestFocus() + searchView.editText.requestFocus() } else { - searchView.setQuery(key, true) + searchView.setText(key) } } @@ -338,13 +354,9 @@ class SearchActivity : VMBaseActivity { - searchView.setQuery(key, true) + searchView.text.toString() == key -> { + searchView.setText(key) } withContext(IO) { appDb.bookDao.findByName(key).isEmpty() } -> { - searchView.setQuery(key, true) + searchView.setText(key) } else -> { - searchView.setQuery(key, false) + searchView.setText(key) } } } diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/dialog/WaitDialog.kt b/app/src/main/java/io/legato/kazusa/ui/widget/dialog/WaitDialog.kt index 84d633c11..4fc095a1d 100644 --- a/app/src/main/java/io/legato/kazusa/ui/widget/dialog/WaitDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/widget/dialog/WaitDialog.kt @@ -2,17 +2,23 @@ package io.legato.kazusa.ui.widget.dialog import android.app.Dialog import android.content.Context +import android.view.LayoutInflater +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import io.legato.kazusa.R import io.legato.kazusa.databinding.DialogWaitBinding +class WaitDialog(context: Context) { -@Suppress("unused") -class WaitDialog(context: Context) : Dialog(context) { + private val binding: DialogWaitBinding = + DialogWaitBinding.inflate(LayoutInflater.from(context)) - val binding = DialogWaitBinding.inflate(layoutInflater) + private val dialog: Dialog = MaterialAlertDialogBuilder(context) + .setView(binding.root) + .setCancelable(false) + .create() init { - setCanceledOnTouchOutside(false) - setContentView(binding.root) + binding.tvMsg.setText(R.string.loading) } fun setText(text: String): WaitDialog { @@ -20,9 +26,31 @@ class WaitDialog(context: Context) : Dialog(context) { return this } - fun setText(res: Int): WaitDialog { - binding.tvMsg.setText(res) + fun setText(resId: Int): WaitDialog { + binding.tvMsg.setText(resId) return this } -} \ No newline at end of file + fun show(): WaitDialog { + dialog.show() + return this + } + + fun dismiss() { + dialog.dismiss() + } + + fun isShowing(): Boolean { + return dialog.isShowing + } + + fun setOnCancelListener(listener: () -> Unit): WaitDialog { + dialog.setOnCancelListener { listener() } + return this + } + + fun setCancelable(cancelable: Boolean): WaitDialog { + dialog.setCancelable(cancelable) + return this + } +} diff --git a/app/src/main/res/drawable/ic_cfg_web.xml b/app/src/main/res/drawable/ic_cfg_web.xml index 4297eaf19..2d6afd37a 100644 --- a/app/src/main/res/drawable/ic_cfg_web.xml +++ b/app/src/main/res/drawable/ic_cfg_web.xml @@ -1,3 +1,10 @@ - - + + diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml new file mode 100644 index 000000000..4c621150a --- /dev/null +++ b/app/src/main/res/drawable/ic_github.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 5b408d035..711410be4 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -1,5 +1,5 @@ - - + android:fitsSystemWindows="true"> - + + + + + + + + + + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - + android:layout_marginStart="16dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:strokeWidth="0dp"> + + + + + + + - + android:layout_marginHorizontal="16dp" + android:layout_marginVertical="8dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/cd_about"> - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_book_search.xml b/app/src/main/res/layout/activity_book_search.xml index ac451e945..033f5b4ca 100644 --- a/app/src/main/res/layout/activity_book_search.xml +++ b/app/src/main/res/layout/activity_book_search.xml @@ -1,34 +1,66 @@ - - + android:backgroundTint="?attr/colorSurface" + app:layout_constraintTop_toTopOf="parent"> - + + + + + + + + + + + + + + + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - - - + android:layout_height="match_parent"> - - - - - - - - - - + android:clickable="true" + android:focusable="true" + android:orientation="vertical" + android:visibility="visible"> - + + + + + + + + + + + + + + + + + + + android:layout_gravity="bottom|end" /> - + diff --git a/app/src/main/res/layout/item_search.xml b/app/src/main/res/layout/item_search.xml index 402317f8b..41f5c8c89 100644 --- a/app/src/main/res/layout/item_search.xml +++ b/app/src/main/res/layout/item_search.xml @@ -4,7 +4,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:app="http://schemas.android.com/apk/res-auto" - android:padding="16dp" + android:paddingHorizontal="16dp" + android:paddingVertical="8dp" android:background="?attr/selectableItemBackground" android:orientation="horizontal" android:scrollbars="none"> diff --git a/app/src/main/res/layout/item_search_history.xml b/app/src/main/res/layout/item_search_history.xml index 21f09bd23..b869e71cf 100644 --- a/app/src/main/res/layout/item_search_history.xml +++ b/app/src/main/res/layout/item_search_history.xml @@ -1,30 +1,35 @@ + android:gravity="center_vertical"> + android:text="@string/text" + android:textSize="16sp" /> + + diff --git a/app/src/main/res/layout/view_search.xml b/app/src/main/res/layout/view_search.xml index 06dae2cf8..ce50bf8f0 100644 --- a/app/src/main/res/layout/view_search.xml +++ b/app/src/main/res/layout/view_search.xml @@ -3,7 +3,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/search_view" - android:theme="?attr/actionBarStyle" android:background="@drawable/bg_searchview" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/app/src/main/res/menu/about.xml b/app/src/main/res/menu/about.xml index f13fe31ae..133940e61 100644 --- a/app/src/main/res/menu/about.xml +++ b/app/src/main/res/menu/about.xml @@ -10,9 +10,4 @@ app:showAsAction="always" tools:ignore="AlwaysShowAction" /> - \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index ade154441..5dd187c0c 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1234,5 +1234,7 @@ 列表 网格 降序 + 检查更新中... + 没有内容哦 diff --git a/app/src/main/res/values/non_translat.xml b/app/src/main/res/values/non_translat.xml index b5b2145a5..e59c45215 100644 --- a/app/src/main/res/values/non_translat.xml +++ b/app/src/main/res/values/non_translat.xml @@ -5,7 +5,8 @@ gekunfei@live.com https://github.com/gedoor/legado/graphs/contributors - + https://github.com/HapeLee/legado + https://gedoor.github.io/ http://%1$s:%2$d GitHub 【%s】 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aac668bf1..6533ae1b3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1237,5 +1237,7 @@ 每行列数 升序 降序 + 检查更新中... + 没有内容哦 diff --git a/app/src/main/res/xml/about.xml b/app/src/main/res/xml/about.xml index 472c6798e..56c63c5fa 100644 --- a/app/src/main/res/xml/about.xml +++ b/app/src/main/res/xml/about.xml @@ -22,43 +22,34 @@ app:allowDividerBelow="false" app:iconSpaceReserved="false" /> - + - + - + - + - + - - - - - + \ No newline at end of file