From 4887dc1e612f6587955e268f1cff9468db8c71c4 Mon Sep 17 00:00:00 2001 From: machiav3lli Date: Fri, 28 Jan 2022 01:15:10 +0100 Subject: [PATCH] Remove: Old Repository classes and layouts --- .../droidify/screen/EditRepositoryFragment.kt | 487 ------------------ .../droidify/screen/RepositoriesAdapter.kt | 91 ---- .../droidify/screen/RepositoriesFragment.kt | 82 --- .../droidify/screen/RepositoryFragment.kt | 176 ------- .../looker/droidify/screen/ScreenActivity.kt | 7 - .../looker/droidify/screen/TabsFragment.kt | 6 - src/main/res/layout/edit_repository.xml | 134 ----- src/main/res/layout/repository_item.xml | 43 -- 8 files changed, 1026 deletions(-) delete mode 100644 src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt delete mode 100644 src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt delete mode 100644 src/main/kotlin/com/looker/droidify/screen/RepositoriesFragment.kt delete mode 100644 src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt delete mode 100644 src/main/res/layout/edit_repository.xml delete mode 100644 src/main/res/layout/repository_item.xml diff --git a/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt b/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt deleted file mode 100644 index 86a5423a..00000000 --- a/src/main/kotlin/com/looker/droidify/screen/EditRepositoryFragment.kt +++ /dev/null @@ -1,487 +0,0 @@ -package com.looker.droidify.screen - -import android.content.ClipboardManager -import android.content.Context -import android.graphics.PorterDuff -import android.graphics.PorterDuffColorFilter -import android.net.Uri -import android.os.Bundle -import android.text.Selection -import android.util.Base64 -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog -import androidx.core.widget.doAfterTextChanged -import androidx.fragment.app.DialogFragment -import androidx.lifecycle.lifecycleScope -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.looker.droidify.R -import com.looker.droidify.database.entity.Repository -import com.looker.droidify.databinding.EditRepositoryBinding -import com.looker.droidify.network.Downloader -import com.looker.droidify.service.Connection -import com.looker.droidify.service.SyncService -import com.looker.droidify.utility.RxUtils -import com.looker.droidify.utility.Utils -import com.looker.droidify.utility.extension.resources.getColorFromAttr -import com.looker.droidify.utility.extension.text.nullIfEmpty -import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers -import io.reactivex.rxjava3.core.Single -import io.reactivex.rxjava3.disposables.Disposable -import io.reactivex.rxjava3.schedulers.Schedulers -import kotlinx.coroutines.launch -import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.Request -import java.net.URI -import java.net.URL -import java.nio.charset.Charset -import java.util.* -import kotlin.math.min - -class EditRepositoryFragment() : ScreenFragment() { - - private var _editRepositoryBinding: EditRepositoryBinding? = null - private val editRepositoryBinding get() = _editRepositoryBinding!! - - companion object { - private const val EXTRA_REPOSITORY_ID = "repositoryId" - - private val checkPaths = listOf("", "fdroid/repo", "repo") - } - - constructor(repositoryId: Long?) : this() { - arguments = Bundle().apply { - repositoryId?.let { putLong(EXTRA_REPOSITORY_ID, it) } - } - } - - private class Layout(view: EditRepositoryBinding) { - val address = view.address - val addressMirror = view.addressMirror - val fingerprint = view.fingerprint - val username = view.username - val password = view.password - val overlay = view.overlay - val skip = view.skip - } - - private val repositoryId: Long? - get() = requireArguments().let { - if (it.containsKey(EXTRA_REPOSITORY_ID)) - it.getLong(EXTRA_REPOSITORY_ID) else null - } - - private lateinit var errorColorFilter: PorterDuffColorFilter - - private var saveMenuItem: MenuItem? = null - private var layout: Layout? = null - - private val syncConnection = Connection(SyncService::class.java) - private var checkDisposable: Disposable? = null - - private var takenAddresses = emptySet() - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - _editRepositoryBinding = EditRepositoryBinding.inflate(layoutInflater) - - syncConnection.bind(requireContext()) - - screenActivity.onToolbarCreated(toolbar) - collapsingToolbar.title = - getString(if (repositoryId != null) R.string.edit_repository else R.string.add_repository) - - saveMenuItem = toolbar.menu.add(R.string.save) - .setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_save)) - .setEnabled(false) - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) - .setOnMenuItemClickListener { - onSaveRepositoryClick(true) - true - } - - val content = fragmentBinding.fragmentContent - errorColorFilter = PorterDuffColorFilter( - content.context - .getColorFromAttr(R.attr.colorError).defaultColor, PorterDuff.Mode.SRC_IN - ) - - content.addView(editRepositoryBinding.root) - val layout = Layout(editRepositoryBinding) - this.layout = layout - - val validChar: (Char) -> Boolean = - { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' } - - layout.fingerprint.doAfterTextChanged { text -> - fun logicalPosition(text: String, position: Int): Int { - return if (position > 0) text.asSequence().take(position) - .count(validChar) else position - } - - fun realPosition(text: String, position: Int): Int { - return if (position > 0) { - var left = position - val index = text.indexOfFirst { - validChar(it) && run { - left -= 1 - left <= 0 - } - } - if (index >= 0) min(index + 1, text.length) else text.length - } else { - position - } - } - - val inputString = text.toString() - val outputString = inputString.uppercase(Locale.US) - .filter(validChar).windowed(2, 2, true).take(32).joinToString(separator = " ") - if (inputString != outputString) { - val inputStart = logicalPosition(inputString, Selection.getSelectionStart(text)) - val inputEnd = logicalPosition(inputString, Selection.getSelectionEnd(text)) - text?.replace(0, text.length, outputString) - Selection.setSelection( - text, - realPosition(outputString, inputStart), - realPosition(outputString, inputEnd) - ) - } - } - - if (savedInstanceState == null) { - val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it) } - if (repository == null) { - val clipboardManager = - requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val text = clipboardManager.primaryClip - ?.let { if (it.itemCount > 0) it else null } - ?.getItemAt(0)?.text?.toString().orEmpty() - val (addressText, fingerprintText) = try { - val uri = Uri.parse(URL(text).toString()) - val fingerprintText = uri.getQueryParameter("fingerprint")?.nullIfEmpty() - ?: uri.getQueryParameter("FINGERPRINT")?.nullIfEmpty() - Pair( - uri.buildUpon().path(uri.path?.pathCropped) - .query(null).fragment(null).build().toString(), fingerprintText - ) - } catch (e: Exception) { - Pair(null, null) - } - layout.address.setText(addressText) - layout.fingerprint.setText(fingerprintText) - } else { - layout.address.setText(repository.address) - val mirrors = repository.mirrors.map { it.withoutKnownPath } - if (mirrors.isNotEmpty()) { - layout.addressMirror.visibility = View.VISIBLE - layout.address.apply { - setPaddingRelative( - paddingStart, paddingTop, - paddingEnd + layout.addressMirror.layoutParams.width, paddingBottom - ) - } - layout.addressMirror.setOnClickListener { - SelectMirrorDialog(mirrors) - .show(childFragmentManager, SelectMirrorDialog::class.java.name) - } - } - layout.fingerprint.setText(repository.fingerprint) - val (usernameText, passwordText) = repository.authentication.nullIfEmpty() - ?.let { if (it.startsWith("Basic ")) it.substring(6) else null } - ?.let { - try { - Base64.decode(it, Base64.NO_WRAP).toString(Charset.defaultCharset()) - } catch (e: Exception) { - e.printStackTrace() - null - } - } - ?.let { - val index = it.indexOf(':') - if (index >= 0) Pair( - it.substring(0, index), - it.substring(index + 1) - ) else null - } - ?: Pair(null, null) - layout.username.setText(usernameText) - layout.password.setText(passwordText) - } - } - - layout.address.doAfterTextChanged { invalidateAddress() } - layout.fingerprint.doAfterTextChanged { invalidateFingerprint() } - layout.username.doAfterTextChanged { invalidateUsernamePassword() } - layout.password.doAfterTextChanged { invalidateUsernamePassword() } - - (layout.overlay.parent as ViewGroup).layoutTransition?.setDuration(200L) - layout.overlay.background!!.apply { - mutate() - alpha = 0xcc - } - layout.skip.setOnClickListener { - if (checkDisposable != null) { - checkDisposable?.dispose() - checkDisposable = null - onSaveRepositoryClick(false) - } - } - - lifecycleScope.launch { - val list = screenActivity.db.repositoryDao.all - takenAddresses = list.asSequence().filter { it.id != repositoryId } - .flatMap { (it.mirrors + it.address).asSequence() } - .map { it.withoutKnownPath }.toSet() - invalidateAddress() - } - invalidateAddress() - invalidateFingerprint() - invalidateUsernamePassword() - } - - override fun onDestroyView() { - super.onDestroyView() - - saveMenuItem = null - layout = null - - syncConnection.unbind(requireContext()) - checkDisposable?.dispose() - checkDisposable = null - _editRepositoryBinding = null - } - - private var addressError = false - private var fingerprintError = false - private var usernamePasswordError = false - - private fun invalidateAddress() { - invalidateAddress(layout!!.address.text.toString()) - } - - private fun invalidateAddress(addressText: String) { - val layout = layout!! - val normalizedAddress = normalizeAddress(addressText) - val addressErrorResId = if (normalizedAddress != null) { - if (normalizedAddress.withoutKnownPath in takenAddresses) { - R.string.already_exists - } else { - null - } - } else { - R.string.invalid_address - } - addressError = addressErrorResId != null - addressErrorResId?.let { layout.address.error = getString(it) } - invalidateState() - } - - private fun invalidateFingerprint() { - val layout = layout!! - val fingerprint = layout.fingerprint.text.toString().replace(" ", "") - val fingerprintInvalid = fingerprint.isNotEmpty() && fingerprint.length != 64 - fingerprintError = fingerprintInvalid - invalidateState() - } - - private fun invalidateUsernamePassword() { - val layout = layout!! - val username = layout.username.text.toString() - val password = layout.password.text.toString() - val usernameInvalid = username.contains(':') - val usernameEmpty = username.isEmpty() && password.isNotEmpty() - val passwordEmpty = username.isNotEmpty() && password.isEmpty() - usernamePasswordError = usernameInvalid || usernameEmpty || passwordEmpty - invalidateState() - } - - private fun invalidateState() { - val layout = layout!! - saveMenuItem!!.isEnabled = !addressError && !fingerprintError && - !usernamePasswordError && checkDisposable == null - layout.apply { - sequenceOf(address, addressMirror, fingerprint, username, password) - .forEach { it.isEnabled = checkDisposable == null } - } - layout.overlay.visibility = if (checkDisposable != null) View.VISIBLE else View.GONE - } - - private val String.pathCropped: String - get() { - val index = indexOfLast { it != '/' } - return if (index >= 0 && index < length - 1) substring(0, index + 1) else this - } - - private val String.withoutKnownPath: String - get() { - val cropped = pathCropped - val endsWith = checkPaths.asSequence().filter { it.isNotEmpty() } - .sortedByDescending { it.length }.find { cropped.endsWith("/$it") } - return if (endsWith != null) cropped.substring( - 0, - cropped.length - endsWith.length - 1 - ) else cropped - } - - private fun normalizeAddress(address: String): String? { - val uri = try { - val uri = URI(address) - if (uri.isAbsolute) uri.normalize() else null - } catch (e: Exception) { - null - } - val path = uri?.path?.pathCropped - return if (uri != null && path != null) { - try { - URI( - uri.scheme, - uri.userInfo, - uri.host, - uri.port, - path, - uri.query, - uri.fragment - ).toString() - } catch (e: Exception) { - null - } - } else { - null - } - } - - private fun setMirror(address: String) { - layout?.address?.setText(address) - } - - private fun onSaveRepositoryClick(check: Boolean) { - if (checkDisposable == null) { - val layout = layout!! - val address = normalizeAddress(layout.address.text.toString())!! - val fingerprint = layout.fingerprint.text.toString().replace(" ", "") - val username = layout.username.text.toString().nullIfEmpty() - val password = layout.password.text.toString().nullIfEmpty() - val paths = sequenceOf("", "fdroid/repo", "repo") - val authentication = username?.let { u -> - password - ?.let { p -> - Base64.encodeToString( - "$u:$p".toByteArray(Charset.defaultCharset()), - Base64.NO_WRAP - ) - } - } - ?.let { "Basic $it" }.orEmpty() - - if (check) { - checkDisposable = paths - .fold(Single.just("")) { oldAddressSingle, checkPath -> - oldAddressSingle - .flatMap { oldAddress -> - if (oldAddress.isEmpty()) { - val builder = Uri.parse(address).buildUpon() - .let { - if (checkPath.isEmpty()) it else it.appendEncodedPath( - checkPath - ) - } - val newAddress = builder.build() - val indexAddress = builder.appendPath("index.jar").build() - RxUtils - .callSingle { - Downloader - .createCall( - Request.Builder().method("HEAD", null) - .url(indexAddress.toString().toHttpUrl()), - authentication, - null - ) - } - .subscribeOn(Schedulers.io()) - .map { if (it.code == 200) newAddress.toString() else "" } - } else { - Single.just(oldAddress) - } - } - } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { result, throwable -> - checkDisposable = null - throwable?.printStackTrace() - val resultAddress = - result?.let { if (it.isEmpty()) null else it } ?: address - val allow = resultAddress == address || run { - layout.address.setText(resultAddress) - invalidateAddress(resultAddress) - !addressError - } - if (allow) { - onSaveRepositoryProceedInvalidate( - resultAddress, - fingerprint, - authentication - ) - } else { - invalidateState() - } - } - invalidateState() - } else { - onSaveRepositoryProceedInvalidate(address, fingerprint, authentication) - } - } - } - - private fun onSaveRepositoryProceedInvalidate( - address: String, - fingerprint: String, - authentication: String, - ) { - val binder = syncConnection.binder - if (binder != null) { - val repositoryId = repositoryId - if (repositoryId != null && binder.isCurrentlySyncing(repositoryId)) { - MessageDialog(MessageDialog.Message.CantEditSyncing).show(childFragmentManager) - invalidateState() - } else { - val repository = repositoryId?.let { screenActivity.db.repositoryDao.get(it) } - ?.edit(address, fingerprint, authentication) - ?: Repository.newRepository(address, fingerprint, authentication) - val changedRepository = screenActivity.db.repositoryDao.put(repository) - if (repositoryId == null && changedRepository.enabled) { - binder.sync(changedRepository) - } - requireActivity().onBackPressed() - } - } else { - invalidateState() - } - } - - class SelectMirrorDialog() : DialogFragment() { - companion object { - private const val EXTRA_MIRRORS = "mirrors" - } - - constructor(mirrors: List) : this() { - arguments = Bundle().apply { - putStringArrayList(EXTRA_MIRRORS, ArrayList(mirrors)) - } - } - - override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog { - val mirrors = requireArguments().getStringArrayList(EXTRA_MIRRORS)!! - return MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.select_mirror) - .setItems(mirrors.toTypedArray()) { _, position -> - (parentFragment as EditRepositoryFragment) - .setMirror(mirrors[position]) - } - .setNegativeButton(R.string.cancel, null) - .create() - } - } -} diff --git a/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt b/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt deleted file mode 100644 index de0f7283..00000000 --- a/src/main/kotlin/com/looker/droidify/screen/RepositoriesAdapter.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.looker.droidify.screen - -import android.content.res.ColorStateList -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import coil.load -import com.google.android.material.card.MaterialCardView -import com.google.android.material.imageview.ShapeableImageView -import com.google.android.material.textview.MaterialTextView -import com.looker.droidify.R -import com.looker.droidify.database.entity.Repository -import com.looker.droidify.utility.extension.resources.clear -import com.looker.droidify.utility.extension.resources.getColorFromAttr -import com.looker.droidify.utility.extension.resources.inflate -import com.looker.droidify.utility.getRepository -import com.looker.droidify.widget.CursorRecyclerAdapter - -class RepositoriesAdapter( - private val onClick: (Repository) -> Unit, - private val onSwitch: (repository: Repository, isEnabled: Boolean) -> Boolean, -) : - CursorRecyclerAdapter() { - enum class ViewType { REPOSITORY } - - private class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val item = itemView.findViewById(R.id.repository_item)!! - val checkMark = itemView.findViewById(R.id.repository_state)!! - val repoName = itemView.findViewById(R.id.repository_name)!! - val repoDesc = itemView.findViewById(R.id.repository_description)!! - - var isEnabled = true - - val textColor: ColorStateList - get() = if (isEnabled) itemView.context.getColorFromAttr(R.attr.colorOnPrimaryContainer) - else itemView.context.getColorFromAttr(R.attr.colorOnBackground) - - } - - override val viewTypeClass: Class - get() = ViewType::class.java - - override fun getItemEnumViewType(position: Int): ViewType { - return ViewType.REPOSITORY - } - - private fun getRepository(position: Int): Repository { - return moveTo(position).getRepository() - } - - override fun onCreateViewHolder( - parent: ViewGroup, - viewType: ViewType, - ): RecyclerView.ViewHolder { - return ViewHolder(parent.inflate(R.layout.repository_item)).apply { - itemView.setOnLongClickListener { - onClick(getRepository(adapterPosition)) - true - } - itemView.setOnClickListener { - isEnabled = !isEnabled - onSwitch(getRepository(adapterPosition), isEnabled) - } - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - holder as ViewHolder - val repository = getRepository(position) - - holder.isEnabled = repository.enabled - holder.repoName.text = repository.name - holder.repoDesc.text = repository.description.trim() - - holder.item.setCardBackgroundColor( - if (repository.enabled) holder.item.context.getColorFromAttr(R.attr.colorPrimaryContainer) - else holder.item.context.getColorFromAttr(android.R.attr.colorBackground) - ) - - holder.checkMark.apply { - if (repository.enabled) load(R.drawable.ic_check) - else clear() - } - - holder.textColor.let { - holder.repoName.setTextColor(it) - holder.repoDesc.setTextColor(it) - holder.checkMark.imageTintList = it - } - } -} diff --git a/src/main/kotlin/com/looker/droidify/screen/RepositoriesFragment.kt b/src/main/kotlin/com/looker/droidify/screen/RepositoriesFragment.kt deleted file mode 100644 index b6d59e9d..00000000 --- a/src/main/kotlin/com/looker/droidify/screen/RepositoriesFragment.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.looker.droidify.screen - -import android.database.Cursor -import android.os.Bundle -import android.view.LayoutInflater -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.looker.droidify.R -import com.looker.droidify.database.CursorOwner -import com.looker.droidify.service.Connection -import com.looker.droidify.service.SyncService -import com.looker.droidify.utility.Utils -import com.looker.droidify.utility.extension.resources.getDrawableCompat -import me.zhanghai.android.fastscroll.FastScrollerBuilder - -class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback { - private var recyclerView: RecyclerView? = null - - private val syncConnection = Connection(SyncService::class.java) - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - val view = fragmentBinding.root.apply { - val content = fragmentBinding.fragmentContent - content.addView(RecyclerView(content.context).apply { - id = android.R.id.list - layoutManager = LinearLayoutManager(context) - isMotionEventSplittingEnabled = false - setHasFixedSize(true) - adapter = RepositoriesAdapter({ screenActivity.navigateRepository(it.id) }, - { repository, isEnabled -> - repository.enabled != isEnabled && - syncConnection.binder?.setEnabled(repository, isEnabled) == true - }) - recyclerView = this - FastScrollerBuilder(this) - .useMd2Style() - .setThumbDrawable(this.context.getDrawableCompat(R.drawable.scrollbar_thumb)) - .build() - }) - } - this.toolbar = fragmentBinding.toolbar - this.collapsingToolbar = fragmentBinding.collapsingToolbar - return view - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - syncConnection.bind(requireContext()) - screenActivity.cursorOwner.attach(this, CursorOwner.Request.Repositories) - - screenActivity.onToolbarCreated(toolbar) - toolbar.menu.add(R.string.add_repository) - .setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_add)) - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) - .setOnMenuItemClickListener { - view.post { screenActivity.navigateAddRepository() } - true - } - collapsingToolbar.title = getString(R.string.repositories) - } - - override fun onDestroyView() { - super.onDestroyView() - - recyclerView = null - - syncConnection.unbind(requireContext()) - screenActivity.cursorOwner.detach(this) - } - - override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) { - (recyclerView?.adapter as? RepositoriesAdapter)?.cursor = cursor - } -} diff --git a/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt b/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt deleted file mode 100644 index 097fae82..00000000 --- a/src/main/kotlin/com/looker/droidify/screen/RepositoryFragment.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.looker.droidify.screen - -import android.os.Bundle -import android.text.SpannableStringBuilder -import android.text.format.DateUtils -import android.text.style.ForegroundColorSpan -import android.text.style.TypefaceSpan -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.widget.LinearLayoutCompat -import androidx.core.widget.NestedScrollView -import androidx.lifecycle.lifecycleScope -import com.looker.droidify.R -import com.looker.droidify.databinding.TitleTextItemBinding -import com.looker.droidify.service.Connection -import com.looker.droidify.service.SyncService -import com.looker.droidify.utility.Utils -import com.looker.droidify.utility.extension.resources.getColorFromAttr -import com.looker.droidify.utility.extension.resources.sizeScaled -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import java.util.* - -class RepositoryFragment() : ScreenFragment() { - - private var titleBinding: TitleTextItemBinding? = null - - companion object { - private const val EXTRA_REPOSITORY_ID = "repositoryId" - } - - constructor(repositoryId: Long) : this() { - arguments = Bundle().apply { - putLong(EXTRA_REPOSITORY_ID, repositoryId) - } - } - - private val repositoryId: Long - get() = requireArguments().getLong(EXTRA_REPOSITORY_ID) - - private var layout: LinearLayoutCompat? = null - - private val syncConnection = Connection(SyncService::class.java) - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - titleBinding = TitleTextItemBinding.inflate(layoutInflater) - syncConnection.bind(requireContext()) - - lifecycleScope.launch(Dispatchers.Main) { updateRepositoryView() } - - screenActivity.onToolbarCreated(toolbar) - collapsingToolbar.title = getString(R.string.repository) - - toolbar.menu.apply { - add(R.string.edit_repository) - .setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_edit)) - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) - .setOnMenuItemClickListener { - view.post { screenActivity.navigateEditRepository(repositoryId) } - true - } - - add(R.string.delete) - .setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_delete)) - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) - .setOnMenuItemClickListener { - MessageDialog(MessageDialog.Message.DeleteRepositoryConfirm).show( - childFragmentManager - ) - true - } - } - - val content = fragmentBinding.fragmentContent - val scroll = NestedScrollView(content.context) - scroll.id = android.R.id.list - scroll.isFillViewport = true - content.addView(scroll) - val layout = LinearLayoutCompat(scroll.context) - layout.orientation = LinearLayoutCompat.VERTICAL - resources.sizeScaled(8).let { layout.setPadding(0, it, 0, it) } - this.layout = layout - scroll.addView( - layout, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - } - - override fun onDestroyView() { - super.onDestroyView() - - layout = null - titleBinding = null - syncConnection.unbind(requireContext()) - } - - private fun updateRepositoryView() { - val repository = screenActivity.db.repositoryDao.get(repositoryId) - val layout = layout!! - layout.removeAllViews() - if (repository == null) { - layout.addTitleText(R.string.address, getString(R.string.unknown)) - } else { - layout.addTitleText(R.string.address, repository.address) - if (repository.updated > 0L) { - collapsingToolbar.title = repository.name - layout.addTitleText(R.string.name, repository.name) - layout.addTitleText(R.string.description, repository.description.replace('\n', ' ')) - layout.addTitleText(R.string.recently_updated, run { - val lastUpdated = repository.updated - if (lastUpdated > 0L) { - val date = Date(repository.updated) - val format = - if (DateUtils.isToday(date.time)) DateUtils.FORMAT_SHOW_TIME else - DateUtils.FORMAT_SHOW_TIME or DateUtils.FORMAT_SHOW_DATE - DateUtils.formatDateTime(layout.context, date.time, format) - } else { - getString(R.string.unknown) - } - }) - if (repository.enabled && (repository.lastModified.isNotEmpty() || repository.entityTag.isNotEmpty())) { - layout.addTitleText( - R.string.number_of_applications, - screenActivity.db.productDao.countForRepository(repository.id).toString() - ) - } - } else { - layout.addTitleText( - R.string.description, - getString(R.string.repository_not_used_DESC) - ) - } - if (repository.fingerprint.isEmpty()) { - if (repository.updated > 0L) { - val builder = - SpannableStringBuilder(getString(R.string.repository_unsigned_DESC)) - builder.setSpan( - ForegroundColorSpan(layout.context.getColorFromAttr(R.attr.colorError).defaultColor), - 0, builder.length, SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE - ) - layout.addTitleText(R.string.fingerprint, builder) - } - } else { - val fingerprint = - SpannableStringBuilder(repository.fingerprint.windowed(2, 2, false) - .take(32).joinToString(separator = " ") { it.uppercase(Locale.US) }) - fingerprint.setSpan( - TypefaceSpan("monospace"), 0, fingerprint.length, - SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE - ) - layout.addTitleText(R.string.fingerprint, fingerprint) - } - } - } - - private fun LinearLayoutCompat.addTitleText(titleResId: Int, text: CharSequence) { - if (text.isNotEmpty()) { - val binding = TitleTextItemBinding.inflate(layoutInflater) - val layout = binding.root - val titleView = binding.title - val textView = binding.text - titleView.setText(titleResId) - textView.text = text - addView(layout) - } - } - - internal fun onDeleteConfirm() { - if (syncConnection.binder?.deleteRepository(repositoryId) == true) { - requireActivity().onBackPressed() - } - } -} diff --git a/src/main/kotlin/com/looker/droidify/screen/ScreenActivity.kt b/src/main/kotlin/com/looker/droidify/screen/ScreenActivity.kt index 2b87f94d..c9dc2e66 100644 --- a/src/main/kotlin/com/looker/droidify/screen/ScreenActivity.kt +++ b/src/main/kotlin/com/looker/droidify/screen/ScreenActivity.kt @@ -260,12 +260,5 @@ abstract class ScreenActivity : AppCompatActivity() { } internal fun navigateProduct(packageName: String) = pushFragment(AppDetailFragment(packageName)) - internal fun navigateRepositories() = pushFragment(RepositoriesFragment()) internal fun navigatePreferences() = pushFragment(SettingsFragment()) - internal fun navigateAddRepository() = pushFragment(EditRepositoryFragment(null)) - internal fun navigateRepository(repositoryId: Long) = - pushFragment(RepositoryFragment(repositoryId)) - - internal fun navigateEditRepository(repositoryId: Long) = - pushFragment(EditRepositoryFragment(repositoryId)) } diff --git a/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt b/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt index 7071cac5..5490ce4e 100644 --- a/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt +++ b/src/main/kotlin/com/looker/droidify/screen/TabsFragment.kt @@ -177,12 +177,6 @@ class TabsFragment : ScreenFragment() { true } - add(1, 0, 0, R.string.repositories) - .setOnMenuItemClickListener { - view.post { screenActivity.navigateRepositories() } - true - } - add(1, 0, 0, R.string.settings) .setOnMenuItemClickListener { view.post { screenActivity.navigatePreferences() } diff --git a/src/main/res/layout/edit_repository.xml b/src/main/res/layout/edit_repository.xml deleted file mode 100644 index ad4cf03b..00000000 --- a/src/main/res/layout/edit_repository.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/res/layout/repository_item.xml b/src/main/res/layout/repository_item.xml deleted file mode 100644 index d5662e1a..00000000 --- a/src/main/res/layout/repository_item.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file