From 76670f8bf8cfe86afdbc1b5215dbc11330bde7cb Mon Sep 17 00:00:00 2001 From: Paul Hawke Date: Fri, 20 Dec 2024 16:53:46 -0600 Subject: [PATCH] Convert MediaLicenseFragment to kotlin --- .../commons/repository/UploadRepository.kt | 2 +- .../upload/license/MediaLicenseContract.kt | 4 +- .../upload/license/MediaLicenseFragment.java | 205 ------------------ .../upload/license/MediaLicenseFragment.kt | 201 +++++++++++++++++ .../upload/license/MediaLicensePresenter.kt | 2 +- 5 files changed, 205 insertions(+), 209 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java create mode 100644 app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt index 377953254..f679960b9 100644 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt +++ b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt @@ -243,7 +243,7 @@ class UploadRepository @Inject constructor( * * @param licenseName */ - fun setSelectedLicense(licenseName: String) { + fun setSelectedLicense(licenseName: String?) { uploadModel.selectedLicense = licenseName } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseContract.kt b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseContract.kt index 27ec1521e..b0ca4ebf2 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseContract.kt @@ -11,13 +11,13 @@ interface MediaLicenseContract { fun setSelectedLicense(license: String?) - fun updateLicenseSummary(selectedLicense: String?, numberOfItems: Int?) + fun updateLicenseSummary(selectedLicense: String?, numberOfItems: Int) } interface UserActionListener : BasePresenter { fun getLicenses() - fun selectLicense(licenseName: String) + fun selectLicense(licenseName: String?) fun isWLMSupportedForThisPlace(): Boolean } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java deleted file mode 100644 index 5fb82f2f6..000000000 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.java +++ /dev/null @@ -1,205 +0,0 @@ -package fr.free.nrw.commons.upload.license; - -import android.app.Activity; -import android.net.Uri; -import android.os.Bundle; -import android.text.Html; -import android.text.SpannableStringBuilder; -import android.text.method.LinkMovementMethod; -import android.text.style.ClickableSpan; -import android.text.style.URLSpan; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.ArrayAdapter; -import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding; -import fr.free.nrw.commons.upload.UploadActivity; -import fr.free.nrw.commons.utils.DialogUtil; -import java.util.List; - -import javax.inject.Inject; -import fr.free.nrw.commons.R; -import fr.free.nrw.commons.Utils; -import fr.free.nrw.commons.upload.UploadBaseFragment; -import timber.log.Timber; - -public class MediaLicenseFragment extends UploadBaseFragment implements MediaLicenseContract.View { - - @Inject - MediaLicenseContract.UserActionListener presenter; - - private FragmentMediaLicenseBinding binding; - private ArrayAdapter adapter; - private List licenses; - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - binding = FragmentMediaLicenseBinding.inflate(inflater, container, false); - return binding.getRoot(); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - binding.tvTitle.setText(getString(R.string.step_count, - callback.getIndexInViewFlipper(this) + 1, - callback.getTotalNumberOfSteps(), - getString(R.string.license_step_title)) - ); - setTvSubTitle(); - binding.btnPrevious.setOnClickListener(v -> - callback.onPreviousButtonClicked(callback.getIndexInViewFlipper(this)) - ); - - binding.btnSubmit.setOnClickListener(v -> - callback.onNextButtonClicked(callback.getIndexInViewFlipper(this)) - ); - - binding.tooltip.setOnClickListener(v -> - DialogUtil.showAlertDialog(requireActivity(), - getString(R.string.license_step_title), - getString(R.string.license_tooltip), - getString(android.R.string.ok), - null) - ); - - initPresenter(); - initLicenseSpinner(); - presenter.getLicenses(); - } - - /** - * Removes the tv Subtitle If the activity is the instance of [UploadActivity] and - * if multiple files aren't selected. - */ - private void setTvSubTitle() { - final Activity activity = getActivity(); - if (activity instanceof UploadActivity) { - final boolean isMultipleFileSelected = ((UploadActivity) activity).getIsMultipleFilesSelected(); - if (!isMultipleFileSelected) { - binding.tvSubtitle.setVisibility(View.GONE); - } - } - } - - private void initPresenter() { - presenter.onAttachView(this); - } - - /** - * Initialise the license spinner - */ - private void initLicenseSpinner() { - if (getActivity() == null) { - return; - } - adapter = new ArrayAdapter<>(getActivity().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item); - binding.spinnerLicenseList.setAdapter(adapter); - binding.spinnerLicenseList.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView adapterView, View view, int position, - long l) { - String licenseName = adapterView.getItemAtPosition(position).toString(); - presenter.selectLicense(licenseName); - } - - @Override - public void onNothingSelected(AdapterView adapterView) { - presenter.selectLicense(null); - } - }); - } - - @Override - public void setLicenses(List licenses) { - adapter.clear(); - this.licenses = licenses; - adapter.addAll(this.licenses); - adapter.notifyDataSetChanged(); - } - - @Override - public void setSelectedLicense(String license) { - int position = licenses.indexOf(getString(Utils.licenseNameFor(license))); - // Check if position is valid - if (position < 0) { - Timber.d("Invalid position: %d. Using default licenses", position); - position = licenses.size() - 1; - } else { - Timber.d("Position: %d %s", position, getString(Utils.licenseNameFor(license))); - } - binding.spinnerLicenseList.setSelection(position); - } - - @Override - public void updateLicenseSummary(String licenseSummary, Integer numberOfItems) { - String licenseHyperLink = "" + - getString(Utils.licenseNameFor(licenseSummary)) + "
"; - - setTextViewHTML(binding.tvShareLicenseSummary, getResources() - .getQuantityString(R.plurals.share_license_summary, numberOfItems, - licenseHyperLink)); - } - - private void setTextViewHTML(TextView textView, String text) { - CharSequence sequence = Html.fromHtml(text); - SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence); - URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class); - for (URLSpan span : urls) { - makeLinkClickable(strBuilder, span); - } - textView.setText(strBuilder); - textView.setMovementMethod(LinkMovementMethod.getInstance()); - } - - private void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span) { - int start = strBuilder.getSpanStart(span); - int end = strBuilder.getSpanEnd(span); - int flags = strBuilder.getSpanFlags(span); - ClickableSpan clickable = new ClickableSpan() { - @Override - public void onClick(View view) { - // Handle hyperlink click - String hyperLink = span.getURL(); - launchBrowser(hyperLink); - } - }; - strBuilder.setSpan(clickable, start, end, flags); - strBuilder.removeSpan(span); - } - - private void launchBrowser(String hyperLink) { - Utils.handleWebUrl(getContext(), Uri.parse(hyperLink)); - } - - @Override - public void onDestroyView() { - presenter.onDetachView(); - //Free the adapter to avoid memory leaks - adapter = null; - binding = null; - super.onDestroyView(); - } - - @Override - protected void onBecameVisible() { - super.onBecameVisible(); - /** - * Show the wlm info message if the upload is a WLM upload - */ - if(callback.isWLMUpload() && presenter.isWLMSupportedForThisPlace()){ - binding.llInfoMonumentUpload.setVisibility(View.VISIBLE); - }else{ - binding.llInfoMonumentUpload.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt new file mode 100644 index 000000000..656aee5de --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt @@ -0,0 +1,201 @@ +package fr.free.nrw.commons.upload.license + +import android.app.Activity +import android.net.Uri +import android.os.Bundle +import android.text.Html +import android.text.SpannableStringBuilder +import android.text.method.LinkMovementMethod +import android.text.style.ClickableSpan +import android.text.style.URLSpan +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.TextView +import fr.free.nrw.commons.R +import fr.free.nrw.commons.Utils +import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding +import fr.free.nrw.commons.upload.UploadActivity +import fr.free.nrw.commons.upload.UploadBaseFragment +import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog +import timber.log.Timber +import javax.inject.Inject + +class MediaLicenseFragment : UploadBaseFragment(), MediaLicenseContract.View { + @Inject + lateinit var presenter: MediaLicenseContract.UserActionListener + + private var _binding: FragmentMediaLicenseBinding? = null + private val binding: FragmentMediaLicenseBinding get() = _binding!! + + private var adapter: ArrayAdapter? = null + private var licenses: List? = null + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentMediaLicenseBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.tvTitle.text = getString( + R.string.step_count, + callback.getIndexInViewFlipper(this) + 1, + callback.totalNumberOfSteps, + getString(R.string.license_step_title) + ) + setTvSubTitle() + binding.btnPrevious.setOnClickListener { + callback.onPreviousButtonClicked( + callback.getIndexInViewFlipper(this) + ) + } + + binding.btnSubmit.setOnClickListener { + callback.onNextButtonClicked( + callback.getIndexInViewFlipper(this) + ) + } + + binding.tooltip.setOnClickListener { + showAlertDialog( + requireActivity(), + getString(R.string.license_step_title), + getString(R.string.license_tooltip), + getString(android.R.string.ok), + null + ) + } + + initPresenter() + initLicenseSpinner() + presenter.getLicenses() + } + + /** + * Removes the tv Subtitle If the activity is the instance of [UploadActivity] and + * if multiple files aren't selected. + */ + private fun setTvSubTitle() { + val activity: Activity? = activity + if (activity is UploadActivity) { + if (!activity.isMultipleFilesSelected) { + binding.tvSubtitle.visibility = View.GONE + } + } + } + + private fun initPresenter() = presenter.onAttachView(this) + + /** + * Initialise the license spinner + */ + private fun initLicenseSpinner() { + if (activity == null) { + return + } + adapter = ArrayAdapter( + requireActivity().applicationContext, + android.R.layout.simple_spinner_dropdown_item + ) + binding.spinnerLicenseList.adapter = adapter + binding.spinnerLicenseList.onItemSelectedListener = + object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(adapterView: AdapterView<*>, view: View, position: Int, l: Long) { + val licenseName = adapterView.getItemAtPosition(position).toString() + presenter.selectLicense(licenseName) + } + + override fun onNothingSelected(adapterView: AdapterView<*>?) { + presenter.selectLicense(null) + } + } + } + + override fun setLicenses(licenses: List?) { + adapter!!.clear() + this.licenses = licenses + adapter!!.addAll(this.licenses!!) + adapter!!.notifyDataSetChanged() + } + + override fun setSelectedLicense(license: String?) { + var position = licenses!!.indexOf(getString(Utils.licenseNameFor(license))) + // Check if position is valid + if (position < 0) { + Timber.d("Invalid position: %d. Using default licenses", position) + position = licenses!!.size - 1 + } else { + Timber.d("Position: %d %s", position, getString(Utils.licenseNameFor(license))) + } + binding.spinnerLicenseList.setSelection(position) + } + + override fun updateLicenseSummary(selectedLicense: String?, numberOfItems: Int) { + val licenseHyperLink = "" + + getString(Utils.licenseNameFor(selectedLicense)) + "
" + + setTextViewHTML( + binding.tvShareLicenseSummary, resources + .getQuantityString( + R.plurals.share_license_summary, numberOfItems, + licenseHyperLink + ) + ) + } + + private fun setTextViewHTML(textView: TextView, text: String) { + val sequence: CharSequence = Html.fromHtml(text) + val strBuilder = SpannableStringBuilder(sequence) + val urls = strBuilder.getSpans( + 0, sequence.length, + URLSpan::class.java + ) + for (span in urls) { + makeLinkClickable(strBuilder, span) + } + textView.text = strBuilder + textView.movementMethod = LinkMovementMethod.getInstance() + } + + private fun makeLinkClickable(strBuilder: SpannableStringBuilder, span: URLSpan) { + val start = strBuilder.getSpanStart(span) + val end = strBuilder.getSpanEnd(span) + val flags = strBuilder.getSpanFlags(span) + val clickable: ClickableSpan = object : ClickableSpan() { + override fun onClick(view: View) { + // Handle hyperlink click + val hyperLink = span.url + launchBrowser(hyperLink) + } + } + strBuilder.setSpan(clickable, start, end, flags) + strBuilder.removeSpan(span) + } + + private fun launchBrowser(hyperLink: String) = + Utils.handleWebUrl(context, Uri.parse(hyperLink)) + + override fun onDestroyView() { + presenter.onDetachView() + //Free the adapter to avoid memory leaks + adapter = null + _binding = null + super.onDestroyView() + } + + override fun onBecameVisible() { + super.onBecameVisible() + /** + * Show the wlm info message if the upload is a WLM upload + */ + binding.llInfoMonumentUpload.visibility = + if (callback.isWLMUpload && presenter.isWLMSupportedForThisPlace()) View.VISIBLE else View.GONE + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt index 816b8caae..25d1a2324 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt @@ -51,7 +51,7 @@ class MediaLicensePresenter @Inject constructor( /** * ask the repository to select a license for the current upload */ - override fun selectLicense(licenseName: String) { + override fun selectLicense(licenseName: String?) { repository.setSelectedLicense(licenseName) view.updateLicenseSummary(repository.getSelectedLicense(), repository.getCount()) }