1 package host.exp.exponent.experience 2 3 import android.app.Activity 4 import android.os.Bundle 5 import android.text.method.LinkMovementMethod 6 import android.view.LayoutInflater 7 import android.view.View 8 import android.view.ViewGroup 9 import androidx.core.text.HtmlCompat 10 import androidx.fragment.app.Fragment 11 import host.exp.exponent.Constants 12 import host.exp.exponent.analytics.EXL 13 import host.exp.expoview.R 14 import host.exp.expoview.databinding.ErrorFragmentBinding 15 import java.util.regex.Pattern 16 17 class ErrorFragment : Fragment() { 18 private var _binding: ErrorFragmentBinding? = null 19 private val binding get() = _binding!! 20 onClickHomenull21 private fun onClickHome() { 22 val activity: Activity? = activity 23 if (activity is ErrorActivity) { 24 activity.onClickHome() 25 } 26 } 27 onClickReloadnull28 private fun onClickReload() { 29 val activity: Activity? = activity 30 if (activity is ErrorActivity) { 31 activity.onClickReload() 32 } 33 } 34 onClickViewErrorLognull35 private fun onClickViewErrorLog() { 36 val activity: Activity? = activity 37 if (activity is ErrorActivity) { 38 activity.onClickViewErrorLog() 39 } 40 } 41 onCreateViewnull42 override fun onCreateView( 43 inflater: LayoutInflater, 44 container: ViewGroup?, 45 savedInstanceState: Bundle? 46 ): View { 47 _binding = ErrorFragmentBinding.inflate(inflater, container, false) 48 49 binding.homeButton.setOnClickListener { onClickHome() } 50 binding.reloadButton.setOnClickListener { onClickReload() } 51 binding.viewErrorLog.setOnClickListener { onClickViewErrorLog() } 52 53 val bundle = arguments 54 val isDebugModeEnabled = bundle!!.getBoolean(ErrorActivity.DEBUG_MODE_KEY) 55 val userErrorMessage = bundle.getString(ErrorActivity.USER_ERROR_MESSAGE_KEY) 56 val developerErrorMessage = bundle.getString(ErrorActivity.DEVELOPER_ERROR_MESSAGE_KEY) 57 val errorHeader = bundle.getString(ErrorActivity.ERROR_HEADER_KEY) 58 59 var defaultErrorMessage = userErrorMessage 60 61 val manifestUrl = bundle.getString(ErrorActivity.MANIFEST_URL_KEY) 62 val isHomeError = bundle.getBoolean(ErrorActivity.IS_HOME_KEY, false) 63 val isShellApp = manifestUrl != null && manifestUrl == Constants.INITIAL_URL 64 65 val userFacingErrorMessage = if (isShellApp) { 66 getString(R.string.error_default_shell) 67 } else { 68 getString(R.string.error_default_client) 69 } 70 if (defaultErrorMessage.isNullOrEmpty()) { 71 defaultErrorMessage = if (isDebugModeEnabled) { 72 developerErrorMessage 73 } else { 74 userFacingErrorMessage 75 } 76 } 77 78 if (isHomeError || manifestUrl == null || manifestUrl == Constants.INITIAL_URL) { 79 // Cannot go home in any of these cases 80 binding.homeButton.visibility = View.GONE 81 } 82 83 // Some errors are in HTML format and contain hyperlinks with instructions / more information ( 84 // eq. EXPERIENCE_SDK_VERSION_OUTDATED). We detect HTML tags and render that text as HTML. 85 val htmlPattern = Pattern.compile("<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>(.*?)</\\1>") 86 87 if (htmlPattern.matcher(defaultErrorMessage).find()) { 88 binding.errorMessage.text = HtmlCompat.fromHtml(defaultErrorMessage!!, HtmlCompat.FROM_HTML_MODE_COMPACT) 89 } else { 90 binding.errorMessage.text = defaultErrorMessage 91 } 92 93 binding.errorMessage.movementMethod = LinkMovementMethod.getInstance() 94 95 if (errorHeader != null) { 96 binding.errorHeader.text = errorHeader 97 } 98 99 EXL.e(TAG, "ErrorActivity message: $defaultErrorMessage") 100 101 return binding.root 102 } 103 104 companion object { 105 private val TAG = ErrorFragment::class.java.simpleName 106 } 107 } 108