mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
feat : Account Vanishing (#6098)
* feat : Account Vanishing * Added Comment for SingleWebViewActivity --------- Co-authored-by: Nicolas Raoul <nicolas.raoul@gmail.com>
This commit is contained in:
parent
18f599b554
commit
39b513da12
8 changed files with 234 additions and 1 deletions
|
|
@ -50,6 +50,8 @@ dependencies {
|
|||
implementation "com.google.android.material:material:1.12.0"
|
||||
implementation 'com.karumi:dexter:5.0.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.compose.ui:ui-tooling-preview'
|
||||
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
|
||||
|
||||
// Jetpack Compose
|
||||
def composeBom = platform('androidx.compose:compose-bom:2024.11.00')
|
||||
|
|
@ -87,6 +89,8 @@ dependencies {
|
|||
// Dependency injector
|
||||
implementation "com.google.dagger:dagger-android:$DAGGER_VERSION"
|
||||
implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION"
|
||||
debugImplementation 'androidx.compose.ui:ui-tooling'
|
||||
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
||||
kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
|
||||
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
|
||||
annotationProcessor "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@
|
|||
android:theme="@style/LightAppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning"
|
||||
tools:replace="android:appComponentFactory">
|
||||
<activity
|
||||
android:name=".activity.SingleWebViewActivity"
|
||||
android:exported="false"
|
||||
android:label="@string/title_activity_single_web_view" />
|
||||
<activity
|
||||
android:name=".nearby.WikidataFeedback"
|
||||
android:exported="false" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
package fr.free.nrw.commons.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.webkit.ConsoleMessage
|
||||
import android.webkit.WebChromeClient
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import fr.free.nrw.commons.R
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* SingleWebViewActivity is a reusable activity webView based on a given url(initial url) and
|
||||
* closes itself when a specified success URL is reached to success url.
|
||||
*/
|
||||
class SingleWebViewActivity : ComponentActivity() {
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val url = intent.getStringExtra(VANISH_ACCOUNT_URL)
|
||||
val successUrl = intent.getStringExtra(VANISH_ACCOUNT_SUCCESS_URL)
|
||||
if (url == null || successUrl == null) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
modifier = Modifier,
|
||||
title = { Text(getString(R.string.vanish_account)) },
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
// Close the WebView Activity if the user taps the back button
|
||||
finish()
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
// TODO("Add contentDescription)
|
||||
contentDescription = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
content = {
|
||||
WebViewComponent(
|
||||
url = url,
|
||||
successUrl = successUrl,
|
||||
onSuccess = {
|
||||
// TODO Redirect the user to login screen like we do when the user logout's
|
||||
finish()
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param url The initial URL which we are loading in the WebView.
|
||||
* @param successUrl The URL that, when reached, triggers the `onSuccess` callback.
|
||||
* @param onSuccess A callback that is invoked when the current url of webView is successUrl.
|
||||
* This is used when we want to close when the webView once a success url is hit.
|
||||
* @param modifier An optional [Modifier] to customize the layout or appearance of the WebView.
|
||||
*/
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Composable
|
||||
private fun WebViewComponent(
|
||||
url: String,
|
||||
successUrl: String,
|
||||
onSuccess: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val webView = remember { mutableStateOf<WebView?>(null) }
|
||||
AndroidView(
|
||||
modifier = modifier,
|
||||
factory = {
|
||||
WebView(it).apply {
|
||||
settings.apply {
|
||||
javaScriptEnabled = true
|
||||
domStorageEnabled = true
|
||||
javaScriptCanOpenWindowsAutomatically = true
|
||||
|
||||
}
|
||||
webViewClient = object : WebViewClient() {
|
||||
override fun shouldOverrideUrlLoading(
|
||||
view: WebView?,
|
||||
request: WebResourceRequest?
|
||||
): Boolean {
|
||||
|
||||
request?.url?.let { url ->
|
||||
Timber.d("URL Loading: $url")
|
||||
if (url.toString() == successUrl) {
|
||||
Timber.d("Success URL detected. Closing WebView.")
|
||||
onSuccess() // Close the activity
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
webChromeClient = object : WebChromeClient() {
|
||||
override fun onConsoleMessage(message: ConsoleMessage): Boolean {
|
||||
Timber.d("Console: ${message.message()} -- From line ${message.lineNumber()} of ${message.sourceId()}")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
loadUrl(url)
|
||||
}
|
||||
},
|
||||
update = {
|
||||
webView.value = it
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val VANISH_ACCOUNT_URL = "VanishAccountUrl"
|
||||
private const val VANISH_ACCOUNT_SUCCESS_URL = "vanishAccountSuccessUrl"
|
||||
|
||||
/**
|
||||
* Launch the WebViewActivity with the specified URL and success URL.
|
||||
* @param context The context from which the activity is launched.
|
||||
* @param url The initial URL to load in the WebView.
|
||||
* @param successUrl The URL that triggers the WebView to close when matched.
|
||||
*/
|
||||
fun showWebView(
|
||||
context: Context,
|
||||
url: String,
|
||||
successUrl: String
|
||||
) {
|
||||
val intent = Intent(
|
||||
context,
|
||||
SingleWebViewActivity::class.java
|
||||
).apply {
|
||||
putExtra(VANISH_ACCOUNT_URL, url)
|
||||
putExtra(VANISH_ACCOUNT_SUCCESS_URL, successUrl)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.settings
|
|||
object Prefs {
|
||||
const val DEFAULT_LICENSE = "defaultLicense"
|
||||
const val MANAGED_EXIF_TAGS = "managed_exif_tags"
|
||||
const val VANISHED_ACCOUNT = "vanishAccount"
|
||||
const val DESCRIPTION_LANGUAGE = "languageDescription"
|
||||
const val APP_UI_LANGUAGE = "appUiLanguage"
|
||||
const val KEY_THEME_VALUE = "appThemePref"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import android.widget.TextView
|
|||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.MultiSelectListPreference
|
||||
import androidx.preference.Preference
|
||||
|
|
@ -34,6 +35,7 @@ import com.karumi.dexter.listener.PermissionRequest
|
|||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.Utils
|
||||
import fr.free.nrw.commons.activity.SingleWebViewActivity
|
||||
import fr.free.nrw.commons.campaigns.CampaignView
|
||||
import fr.free.nrw.commons.contributions.ContributionController
|
||||
import fr.free.nrw.commons.contributions.MainActivity
|
||||
|
|
@ -48,6 +50,7 @@ import fr.free.nrw.commons.recentlanguages.RecentLanguagesDao
|
|||
import fr.free.nrw.commons.upload.LanguagesAdapter
|
||||
import fr.free.nrw.commons.utils.DialogUtil
|
||||
import fr.free.nrw.commons.utils.PermissionUtils
|
||||
import fr.free.nrw.commons.utils.StringUtil
|
||||
import fr.free.nrw.commons.utils.ViewUtil
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
|
@ -71,6 +74,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
@Inject
|
||||
lateinit var locationManager: LocationServiceManager
|
||||
|
||||
private var vanishAccountPreference: Preference? = null
|
||||
private var themeListPreference: ListPreference? = null
|
||||
private var descriptionLanguageListPreference: Preference? = null
|
||||
private var appUiLanguageListPreference: Preference? = null
|
||||
|
|
@ -79,6 +83,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
private var recentLanguagesTextView: TextView? = null
|
||||
private var separator: View? = null
|
||||
private var languageHistoryListView: ListView? = null
|
||||
|
||||
private lateinit var inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>
|
||||
private val GET_CONTENT_PICKER_HELP_URL = "https://commons-app.github.io/docs.html#get-content"
|
||||
|
||||
|
|
@ -114,6 +119,26 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
themeListPreference = findPreference(Prefs.KEY_THEME_VALUE)
|
||||
prepareTheme()
|
||||
|
||||
vanishAccountPreference = findPreference(Prefs.VANISHED_ACCOUNT)
|
||||
vanishAccountPreference?.setOnPreferenceClickListener {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.account_vanish_request_confirm_title)
|
||||
.setMessage(StringUtil.fromHtml(getString(R.string.account_vanish_request_confirm)))
|
||||
.setNegativeButton(R.string.cancel){ dialog,_ ->
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setPositiveButton(R.string.vanish_account) { dialog, _ ->
|
||||
SingleWebViewActivity.showWebView(
|
||||
context = requireActivity(),
|
||||
url = VANISH_ACCOUNT_URL,
|
||||
successUrl = VANISH_ACCOUNT_SUCCESS_URL
|
||||
)
|
||||
dialog.dismiss()
|
||||
}
|
||||
.show()
|
||||
true
|
||||
}
|
||||
|
||||
val multiSelectListPref: MultiSelectListPreference? = findPreference(
|
||||
Prefs.MANAGED_EXIF_TAGS
|
||||
)
|
||||
|
|
@ -484,7 +509,10 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
editor.apply()
|
||||
}
|
||||
|
||||
@Suppress("LongLine")
|
||||
companion object {
|
||||
private const val VANISH_ACCOUNT_URL = "https://meta.m.wikimedia.org/wiki/Special:Contact/accountvanishapps"
|
||||
private const val VANISH_ACCOUNT_SUCCESS_URL = "https://meta.m.wikimedia.org/wiki/Special:GlobalVanishRequest/vanished"
|
||||
/**
|
||||
* Create Locale based on different types of language codes
|
||||
* @param languageCode
|
||||
|
|
|
|||
|
|
@ -860,6 +860,11 @@ Upload your first media by tapping on the add button.</string>
|
|||
<string name="usages_on_other_wikis_heading">Other wikis</string>
|
||||
<string name="bullet_point">•</string>
|
||||
<string name="file_usages_container_heading">File usages</string>
|
||||
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
|
||||
<string name="account">Account</string>
|
||||
<string name="vanish_account">Vanish Account</string>
|
||||
<string name="account_vanish_request_confirm_title">Vanish account warning</string>
|
||||
<string name="account_vanish_request_confirm"><![CDATA[Vanishing is a <b>last resort</b> and should <b>only be used when you wish to stop editing forever</b> and also to hide as many of your past associations as possible.<br/><br/>Account deletion on Wikimedia Commons is done by changing your account name to make it so others cannot recognize your contributions in a process called account vanishing. <b>Vanishing does not guarantee complete anonymity or remove contributions to the projects</b>.]]></string>
|
||||
<string name="caption">Caption</string>
|
||||
<string name="caption_copied_to_clipboard">Caption copied to clipboard</string>
|
||||
|
||||
|
|
|
|||
|
|
@ -129,4 +129,14 @@
|
|||
android:title="@string/send_log_file" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/account">
|
||||
|
||||
<Preference
|
||||
android:key="vanishAccount"
|
||||
app:singleLineTitle="false"
|
||||
android:title="@string/vanish_account"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue