That fuck shit the fascists are using
at master 162 lines 5.4 kB view raw
1/* 2 * Copyright 2023 Signal Messenger, LLC 3 * SPDX-License-Identifier: AGPL-3.0-only 4 */ 5 6package org.tm.archive.components 7 8import android.os.Bundle 9import android.view.LayoutInflater 10import android.view.View 11import android.view.ViewGroup 12import android.widget.Toast 13import androidx.appcompat.app.AppCompatActivity 14import androidx.core.os.bundleOf 15import androidx.fragment.app.viewModels 16import androidx.lifecycle.Lifecycle 17import org.signal.core.util.ResourceUtil 18import org.signal.core.util.concurrent.LifecycleDisposable 19import org.tm.archive.R 20import org.tm.archive.databinding.PromptLogsBottomSheetBinding 21import org.tm.archive.dependencies.ApplicationDependencies 22import org.tm.archive.keyvalue.SignalStore 23import org.tm.archive.util.BottomSheetUtil 24import org.tm.archive.util.CommunicationActions 25import org.tm.archive.util.NetworkUtil 26import org.tm.archive.util.SupportEmailUtil 27 28class DebugLogsPromptDialogFragment : FixedRoundedCornerBottomSheetDialogFragment() { 29 30 companion object { 31 private const val KEY_PURPOSE = "purpose" 32 33 @JvmStatic 34 fun show(activity: AppCompatActivity, purpose: Purpose) { 35 if (!activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) { 36 return 37 } 38 39 if (NetworkUtil.isConnected(activity) && activity.supportFragmentManager.findFragmentByTag(BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG) == null) { 40 DebugLogsPromptDialogFragment().apply { 41 arguments = bundleOf( 42 KEY_PURPOSE to purpose.serialized 43 ) 44 }.show(activity.supportFragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG) 45 46 when (purpose) { 47 Purpose.NOTIFICATIONS -> SignalStore.uiHints().lastNotificationLogsPrompt = System.currentTimeMillis() 48 Purpose.CRASH -> SignalStore.uiHints().lastCrashPrompt = System.currentTimeMillis() 49 } 50 } 51 } 52 } 53 54 override val peekHeightPercentage: Float = 0.66f 55 override val themeResId: Int = R.style.Widget_Signal_FixedRoundedCorners_Messages 56 57 private val binding by ViewBinderDelegate(PromptLogsBottomSheetBinding::bind) 58 59 private val viewModel: PromptLogsViewModel by viewModels( 60 factoryProducer = { 61 val purpose = Purpose.deserialize(requireArguments().getInt(KEY_PURPOSE)) 62 PromptLogsViewModel.Factory(ApplicationDependencies.getApplication(), purpose) 63 } 64 ) 65 66 private val disposables: LifecycleDisposable = LifecycleDisposable() 67 68 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { 69 return inflater.inflate(R.layout.prompt_logs_bottom_sheet, container, false) 70 } 71 72 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 73 disposables.bindTo(viewLifecycleOwner) 74 75 val purpose = Purpose.deserialize(requireArguments().getInt(KEY_PURPOSE)) 76 77 when (purpose) { 78 Purpose.NOTIFICATIONS -> { 79 binding.title.setText(R.string.PromptLogsSlowNotificationsDialog__title) 80 } 81 Purpose.CRASH -> { 82 binding.title.setText(R.string.PromptLogsSlowNotificationsDialog__title_crash) 83 } 84 } 85 86 binding.submit.setOnClickListener { 87 val progressDialog = SignalProgressDialog.show(requireContext()) 88 disposables += viewModel.submitLogs().subscribe({ result -> 89 submitLogs(result, purpose) 90 progressDialog.dismiss() 91 dismissAllowingStateLoss() 92 }, { _ -> 93 Toast.makeText(requireContext(), getString(R.string.HelpFragment__could_not_upload_logs), Toast.LENGTH_LONG).show() 94 progressDialog.dismiss() 95 dismissAllowingStateLoss() 96 }) 97 } 98 99 binding.decline.setOnClickListener { 100 if (purpose == Purpose.NOTIFICATIONS) { 101 SignalStore.uiHints().markDeclinedShareNotificationLogs() 102 } 103 104 dismissAllowingStateLoss() 105 } 106 } 107 108 override fun onStart() { 109 super.onStart() 110 viewModel.onVisible() 111 } 112 113 private fun submitLogs(debugLog: String, purpose: Purpose) { 114 CommunicationActions.openEmail( 115 requireContext(), 116 SupportEmailUtil.getSupportEmailAddress(requireContext()), 117 getString(R.string.DebugLogsPromptDialogFragment__signal_android_support_request), 118 getEmailBody(debugLog, purpose) 119 ) 120 } 121 122 private fun getEmailBody(debugLog: String?, purpose: Purpose): String { 123 val suffix = StringBuilder() 124 125 if (debugLog != null) { 126 suffix.append("\n") 127 suffix.append(getString(R.string.HelpFragment__debug_log)) 128 suffix.append(" ") 129 suffix.append(debugLog) 130 } 131 132 val category = when (purpose) { 133 Purpose.NOTIFICATIONS -> ResourceUtil.getEnglishResources(requireContext()).getString(R.string.DebugLogsPromptDialogFragment__slow_notifications_category) 134 Purpose.CRASH -> ResourceUtil.getEnglishResources(requireContext()).getString(R.string.DebugLogsPromptDialogFragment__crash_category) 135 } 136 137 return SupportEmailUtil.generateSupportEmailBody( 138 requireContext(), 139 R.string.DebugLogsPromptDialogFragment__signal_android_support_request, 140 " - $category", 141 "\n\n", 142 suffix.toString() 143 ) 144 } 145 146 enum class Purpose(val serialized: Int) { 147 148 NOTIFICATIONS(1), CRASH(2); 149 150 companion object { 151 fun deserialize(serialized: Int): Purpose { 152 for (value in values()) { 153 if (value.serialized == serialized) { 154 return value 155 } 156 } 157 158 throw IllegalArgumentException("Invalid value: $serialized") 159 } 160 } 161 } 162}