mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-11-03 00:03:53 +01:00
Compare commits
26 commits
27c3f72112
...
a9f23df9e3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9f23df9e3 | ||
|
|
78d29bcf20 | ||
|
|
1a13cb3383 | ||
|
|
9289dcc42c | ||
|
|
efdc9c5548 | ||
|
|
69b3544107 | ||
|
|
5b5aeead88 | ||
|
|
4bacac1f8b | ||
|
|
6aeb3c07cc | ||
|
|
2c41176a6e | ||
|
|
e3dd00bcfa | ||
|
|
262efe4d8c | ||
|
|
2eed441462 | ||
|
|
56fa8ceb5a | ||
|
|
7bf9276d1a | ||
|
|
51da9e4dd6 | ||
|
|
731ff62faf | ||
|
|
fdfd7781e9 | ||
|
|
6e090c8d7a | ||
|
|
44966645ca | ||
|
|
669f3043ae | ||
|
|
5a5e660a43 | ||
|
|
2e05a58e8b | ||
|
|
f1f4e8baff | ||
|
|
828f69fc46 | ||
|
|
b2fe96d680 |
47 changed files with 690 additions and 234 deletions
41
CHANGELOG.md
41
CHANGELOG.md
|
|
@ -1,5 +1,46 @@
|
|||
# Wikimedia Commons for Android
|
||||
|
||||
## v5.3.0
|
||||
|
||||
### What's changed
|
||||
* Enable EmailAuth support
|
||||
* Explore map images no longer show "Unknown"
|
||||
* Fix crash when removing last two images of multiupload
|
||||
* Mark ❌ for closed locations (P3999) in Nearby
|
||||
* Fix two pin labels staying visible at the same time in Explore map
|
||||
* Refactoring and minor UI improvements
|
||||
|
||||
## v5.2.0
|
||||
|
||||
v5.2.0 boasts several new functionalities like:
|
||||
|
||||
* A new refresh button lets you quickly reload the Nearby map
|
||||
* Bookmarks now support categories
|
||||
* Improved feedback and consistency in the user interface
|
||||
* Bug fixes and performance improvements
|
||||
|
||||
### What's changed
|
||||
* Implement "Refresh" button to clear the cache and reload the Nearby map.
|
||||
* `CommonsApplication` migrate to kotlin & some lint fixes.
|
||||
* Revert back to MainScope for database and UI updates and make database operations thread safe.
|
||||
* Hide edit options for logged-out users in Explore screen.
|
||||
* Introduced a button to delete the current folder in custom selector.
|
||||
* Improve Unique File Name Search.
|
||||
* Migration of several modules from Java to Kotlin.
|
||||
* Fix modification on bottom sheet's data when coming from Nearby Banner and clicked on other pins.
|
||||
* Bug fixes and enhancement of Achievements screen.
|
||||
* Show where file is being used on Commons and other wikis.
|
||||
* Migrate android.media.ExifInterface to androidx.exifinterface.media.ExifInterface as android.media.ExifInterface had security flaws on older devices.
|
||||
* Make dialogs modal and always show the upload icon.
|
||||
* Fix unintentional deletion of subfolders and non-images by custom selector.
|
||||
* Bookmark categories.
|
||||
* Add pull down to refresh in the Contributions screen.
|
||||
* Fix race condition and lag when loading pin details, faster overlay management.
|
||||
* Show cached pins in Nearby even when internet is unavailable
|
||||
|
||||
Full changelog with the list of contributors: [`v5.1.2...v5.2.0`](https://github.com/commons-app/apps-android-commons/compare/v5.1.2...v5.2.0).
|
||||
|
||||
|
||||
## v5.1.2
|
||||
|
||||
### What's changed
|
||||
|
|
|
|||
|
|
@ -212,8 +212,8 @@ android {
|
|||
defaultConfig {
|
||||
//applicationId 'fr.free.nrw.commons'
|
||||
|
||||
versionCode 1048
|
||||
versionName '5.2.0'
|
||||
versionCode 1050
|
||||
versionName '5.3.0'
|
||||
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
|
||||
|
||||
minSdkVersion 21
|
||||
|
|
@ -318,7 +318,7 @@ android {
|
|||
buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\""
|
||||
buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Main_Page&welcome=yes\""
|
||||
buildConfigField "String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.org/wiki/Special:PasswordReset\""
|
||||
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://github.com/commons-app/commons-app-documentation/blob/master/android/Privacy-policy.md\""
|
||||
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://commons-app.github.io/privacy-policy\""
|
||||
buildConfigField "String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\""
|
||||
buildConfigField "String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons\""
|
||||
buildConfigField "String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.contributions.contentprovider\""
|
||||
|
|
@ -355,7 +355,7 @@ android {
|
|||
buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\""
|
||||
buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Main_Page&welcome=yes\""
|
||||
buildConfigField "String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/Special:PasswordReset\""
|
||||
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://github.com/commons-app/commons-app-documentation/blob/master/android/Privacy-policy.md\""
|
||||
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://commons-app.github.io/privacy-policy\""
|
||||
buildConfigField "String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\""
|
||||
buildConfigField "String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons.beta\""
|
||||
buildConfigField "String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.beta.contributions.contentprovider\""
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ class LoginActivity : AccountAuthenticatorActivity() {
|
|||
private val delegate: AppCompatDelegate by lazy {
|
||||
AppCompatDelegate.create(this, null)
|
||||
}
|
||||
private var lastLoginResult: LoginResult? = null
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -271,6 +272,7 @@ class LoginActivity : AccountAuthenticatorActivity() {
|
|||
showLoggingProgressBar()
|
||||
loginClient.doLogin(username,
|
||||
password,
|
||||
lastLoginResult,
|
||||
twoFactorCode,
|
||||
Locale.getDefault().language,
|
||||
object : LoginCallback {
|
||||
|
|
@ -280,9 +282,17 @@ class LoginActivity : AccountAuthenticatorActivity() {
|
|||
onLoginSuccess(loginResult)
|
||||
}
|
||||
|
||||
override fun twoFactorPrompt(caught: Throwable, token: String?) = runOnUiThread {
|
||||
override fun twoFactorPrompt(loginResult: LoginResult, caught: Throwable, token: String?) = runOnUiThread {
|
||||
Timber.d("Requesting 2FA prompt")
|
||||
progressDialog!!.dismiss()
|
||||
lastLoginResult = loginResult
|
||||
askUserForTwoFactorAuth()
|
||||
}
|
||||
|
||||
override fun emailAuthPrompt(loginResult: LoginResult, caught: Throwable, token: String?) {
|
||||
Timber.d("Requesting email auth prompt")
|
||||
progressDialog!!.dismiss()
|
||||
lastLoginResult = loginResult
|
||||
askUserForTwoFactorAuth()
|
||||
}
|
||||
|
||||
|
|
@ -341,12 +351,13 @@ class LoginActivity : AccountAuthenticatorActivity() {
|
|||
progressDialog!!.dismiss()
|
||||
with(binding!!) {
|
||||
twoFactorContainer.visibility = View.VISIBLE
|
||||
twoFactorContainer.hint = getString(if (lastLoginResult is LoginResult.EmailAuthResult) R.string.email_auth_code else R.string._2fa_code)
|
||||
loginTwoFactor.visibility = View.VISIBLE
|
||||
loginTwoFactor.requestFocus()
|
||||
}
|
||||
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY)
|
||||
showMessageAndCancelDialog(R.string.login_failed_2fa_needed)
|
||||
showMessageAndCancelDialog(getString(if (lastLoginResult is LoginResult.EmailAuthResult) R.string.login_failed_email_auth_needed else R.string.login_failed_2fa_needed))
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class CsrfTokenClient(
|
|||
try {
|
||||
if (retry > 0) {
|
||||
// Log in explicitly
|
||||
loginClient.loginBlocking(userName, password, "")
|
||||
loginClient.loginBlocking(userName, password)
|
||||
}
|
||||
|
||||
// Get CSRFToken response off the main thread.
|
||||
|
|
@ -92,6 +92,8 @@ class CsrfTokenClient(
|
|||
override fun failure(caught: Throwable?) = retryWithLogin(cb) { caught }
|
||||
|
||||
override fun twoFactorPrompt() = cb.twoFactorPrompt()
|
||||
|
||||
override fun emailAuthPrompt() = cb.emailAuthPrompt()
|
||||
},
|
||||
)
|
||||
|
||||
|
|
@ -165,10 +167,17 @@ class CsrfTokenClient(
|
|||
}
|
||||
|
||||
override fun twoFactorPrompt(
|
||||
loginResult: LoginResult,
|
||||
caught: Throwable,
|
||||
token: String?,
|
||||
) = callback.twoFactorPrompt()
|
||||
|
||||
override fun emailAuthPrompt(
|
||||
loginResult: LoginResult,
|
||||
caught: Throwable,
|
||||
token: String?,
|
||||
) = callback.emailAuthPrompt()
|
||||
|
||||
// Should not happen here, but call the callback just in case.
|
||||
override fun passwordResetPrompt(token: String?) = callback.failure(LoginFailedException("Logged in with temporary password."))
|
||||
|
||||
|
|
@ -190,6 +199,8 @@ class CsrfTokenClient(
|
|||
fun failure(caught: Throwable?)
|
||||
|
||||
fun twoFactorPrompt()
|
||||
|
||||
fun emailAuthPrompt()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@ interface LoginCallback {
|
|||
fun success(loginResult: LoginResult)
|
||||
|
||||
fun twoFactorPrompt(
|
||||
loginResult: LoginResult,
|
||||
caught: Throwable,
|
||||
token: String?,
|
||||
)
|
||||
|
||||
fun emailAuthPrompt(
|
||||
loginResult: LoginResult,
|
||||
caught: Throwable,
|
||||
token: String?,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.free.nrw.commons.auth.login
|
||||
|
||||
import android.text.TextUtils
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.EmailAuthResult
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.OAuthResult
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.ResetPasswordResult
|
||||
import fr.free.nrw.commons.wikidata.WikidataConstants.WIKIPEDIA_URL
|
||||
|
|
@ -51,6 +52,7 @@ class LoginClient(
|
|||
password,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
response.body()!!.query()!!.loginToken(),
|
||||
userLanguage,
|
||||
cb,
|
||||
|
|
@ -75,6 +77,7 @@ class LoginClient(
|
|||
password: String,
|
||||
retypedPassword: String?,
|
||||
twoFactorCode: String?,
|
||||
emailAuthCode: String?,
|
||||
loginToken: String?,
|
||||
userLanguage: String,
|
||||
cb: LoginCallback,
|
||||
|
|
@ -82,7 +85,7 @@ class LoginClient(
|
|||
this.userLanguage = userLanguage
|
||||
|
||||
loginCall =
|
||||
if (twoFactorCode.isNullOrEmpty() && retypedPassword.isNullOrEmpty()) {
|
||||
if (twoFactorCode.isNullOrEmpty() && emailAuthCode.isNullOrEmpty() && retypedPassword.isNullOrEmpty()) {
|
||||
loginInterface.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
|
||||
} else {
|
||||
loginInterface.postLogIn(
|
||||
|
|
@ -90,6 +93,7 @@ class LoginClient(
|
|||
password,
|
||||
retypedPassword,
|
||||
twoFactorCode,
|
||||
emailAuthCode,
|
||||
loginToken,
|
||||
userLanguage,
|
||||
true,
|
||||
|
|
@ -112,10 +116,18 @@ class LoginClient(
|
|||
when (loginResult) {
|
||||
is OAuthResult ->
|
||||
cb.twoFactorPrompt(
|
||||
loginResult,
|
||||
LoginFailedException(loginResult.message),
|
||||
loginToken,
|
||||
)
|
||||
|
||||
is EmailAuthResult ->
|
||||
cb.emailAuthPrompt(
|
||||
loginResult,
|
||||
LoginFailedException(loginResult.message),
|
||||
loginToken
|
||||
)
|
||||
|
||||
is ResetPasswordResult -> cb.passwordResetPrompt(loginToken)
|
||||
|
||||
is LoginResult.Result ->
|
||||
|
|
@ -147,6 +159,7 @@ class LoginClient(
|
|||
fun doLogin(
|
||||
username: String,
|
||||
password: String,
|
||||
lastLoginResult: LoginResult?,
|
||||
twoFactorCode: String,
|
||||
userLanguage: String,
|
||||
loginCallback: LoginCallback,
|
||||
|
|
@ -159,7 +172,10 @@ class LoginClient(
|
|||
) = if (response.isSuccessful) {
|
||||
val loginToken = response.body()?.query()?.loginToken()
|
||||
loginToken?.let {
|
||||
login(username, password, null, twoFactorCode, it, userLanguage, loginCallback)
|
||||
login(username, password, null,
|
||||
if (lastLoginResult is OAuthResult) twoFactorCode else null,
|
||||
if (lastLoginResult is EmailAuthResult) twoFactorCode else null,
|
||||
it, userLanguage, loginCallback)
|
||||
} ?: run {
|
||||
loginCallback.error(IOException("Failed to retrieve login token"))
|
||||
}
|
||||
|
|
@ -181,7 +197,8 @@ class LoginClient(
|
|||
fun loginBlocking(
|
||||
userName: String,
|
||||
password: String,
|
||||
twoFactorCode: String?,
|
||||
twoFactorCode: String? = null,
|
||||
emailAuthCode: String? = null
|
||||
) {
|
||||
val tokenResponse = getLoginToken().execute()
|
||||
if (tokenResponse
|
||||
|
|
@ -195,7 +212,7 @@ class LoginClient(
|
|||
|
||||
val loginToken = tokenResponse.body()?.query()?.loginToken()
|
||||
val tempLoginCall =
|
||||
if (twoFactorCode.isNullOrEmpty()) {
|
||||
if (twoFactorCode.isNullOrEmpty() && emailAuthCode.isNullOrEmpty()) {
|
||||
loginInterface.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
|
||||
} else {
|
||||
loginInterface.postLogIn(
|
||||
|
|
@ -203,6 +220,7 @@ class LoginClient(
|
|||
password,
|
||||
null,
|
||||
twoFactorCode,
|
||||
emailAuthCode,
|
||||
loginToken,
|
||||
userLanguage,
|
||||
true,
|
||||
|
|
@ -214,7 +232,7 @@ class LoginClient(
|
|||
val loginResult = loginResponse.toLoginResult(password) ?: throw IOException("Unexpected response when logging in.")
|
||||
|
||||
if ("UI" == loginResult.status) {
|
||||
if (loginResult is OAuthResult) {
|
||||
if (loginResult is OAuthResult || loginResult is EmailAuthResult) {
|
||||
// TODO: Find a better way to boil up the warning about 2FA
|
||||
throw LoginFailedException(loginResult.message)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ interface LoginInterface {
|
|||
@Field("password") pass: String?,
|
||||
@Field("retype") retypedPass: String?,
|
||||
@Field("OATHToken") twoFactorCode: String?,
|
||||
@Field("logintoken") token: String?,
|
||||
@Field("token") emailAuthToken: String?,
|
||||
@Field("logintoken") loginToken: String?,
|
||||
@Field("uselang") userLanguage: String?,
|
||||
@Field("logincontinue") loginContinue: Boolean,
|
||||
): Call<LoginResponse?>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package fr.free.nrw.commons.auth.login
|
|||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.OAuthResult
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.EmailAuthResult
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.ResetPasswordResult
|
||||
import fr.free.nrw.commons.auth.login.LoginResult.Result
|
||||
import fr.free.nrw.commons.wikidata.mwapi.MwServiceError
|
||||
|
|
@ -27,11 +28,13 @@ internal class ClientLogin {
|
|||
fun toLoginResult(password: String): LoginResult {
|
||||
var userMessage = message
|
||||
if ("UI" == status) {
|
||||
if (requests != null) {
|
||||
for (req in requests) {
|
||||
if ("MediaWiki\\Extension\\OATHAuth\\Auth\\TOTPAuthenticationRequest" == req.id()) {
|
||||
requests?.forEach { request ->
|
||||
request.id()?.let {
|
||||
if (it.endsWith("TOTPAuthenticationRequest")) {
|
||||
return OAuthResult(status, userName, password, message)
|
||||
} else if ("MediaWiki\\Auth\\PasswordAuthenticationRequest" == req.id()) {
|
||||
} else if (it.endsWith("EmailAuthAuthenticationRequest")) {
|
||||
return EmailAuthResult(status, userName, password, message)
|
||||
} else if (it.endsWith("PasswordAuthenticationRequest")) {
|
||||
return ResetPasswordResult(status, userName, password, message)
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +52,7 @@ internal class Request {
|
|||
private val required: String? = null
|
||||
private val provider: String? = null
|
||||
private val account: String? = null
|
||||
private val fields: Map<String, RequestField>? = null
|
||||
internal val fields: Map<String, RequestField>? = null
|
||||
|
||||
fun id(): String? = id
|
||||
}
|
||||
|
|
@ -57,5 +60,5 @@ internal class Request {
|
|||
internal class RequestField {
|
||||
private val type: String? = null
|
||||
private val label: String? = null
|
||||
private val help: String? = null
|
||||
internal val help: String? = null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ sealed class LoginResult(
|
|||
message: String?,
|
||||
) : LoginResult(status, userName, password, message)
|
||||
|
||||
class EmailAuthResult(
|
||||
status: String,
|
||||
userName: String?,
|
||||
password: String?,
|
||||
message: String?,
|
||||
) : LoginResult(status, userName, password, message)
|
||||
|
||||
class ResetPasswordResult(
|
||||
status: String,
|
||||
userName: String?,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package fr.free.nrw.commons.bookmarks.locations
|
||||
|
||||
import android.Manifest.permission
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
|
@ -9,15 +8,12 @@ import android.view.ViewGroup
|
|||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dagger.android.support.DaggerFragment
|
||||
import fr.free.nrw.commons.R
|
||||
import fr.free.nrw.commons.contributions.ContributionController
|
||||
import fr.free.nrw.commons.databinding.FragmentBookmarksLocationsBinding
|
||||
import fr.free.nrw.commons.filepicker.FilePicker
|
||||
import fr.free.nrw.commons.nearby.Place
|
||||
import fr.free.nrw.commons.nearby.fragments.CommonPlaceClickActions
|
||||
import fr.free.nrw.commons.nearby.fragments.PlaceAdapter
|
||||
|
|
@ -41,33 +37,27 @@ class BookmarkLocationsFragment : DaggerFragment() {
|
|||
private val cameraPickLauncherForResult =
|
||||
registerForActivityResult(StartActivityForResult()) { result ->
|
||||
contributionController.handleActivityResultWithCallback(
|
||||
requireActivity(),
|
||||
object: FilePicker.HandleActivityResult {
|
||||
override fun onHandleActivityResult(callbacks: FilePicker.Callbacks) {
|
||||
contributionController.onPictureReturnedFromCamera(
|
||||
result,
|
||||
requireActivity(),
|
||||
callbacks
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
requireActivity()
|
||||
) { callbacks ->
|
||||
contributionController.onPictureReturnedFromCamera(
|
||||
result,
|
||||
requireActivity(),
|
||||
callbacks
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val galleryPickLauncherForResult =
|
||||
registerForActivityResult(StartActivityForResult()) { result ->
|
||||
contributionController.handleActivityResultWithCallback(
|
||||
requireActivity(),
|
||||
object: FilePicker.HandleActivityResult {
|
||||
override fun onHandleActivityResult(callbacks: FilePicker.Callbacks) {
|
||||
contributionController.onPictureReturnedFromGallery(
|
||||
result,
|
||||
requireActivity(),
|
||||
callbacks
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
requireActivity()
|
||||
) { callbacks ->
|
||||
contributionController.onPictureReturnedFromGallery(
|
||||
result,
|
||||
requireActivity(),
|
||||
callbacks
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import kotlinx.coroutines.MainScope
|
|||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.TreeMap
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
|
@ -342,45 +343,36 @@ class ImageAdapter(
|
|||
numberOfSelectedImagesMarkedAsNotForUpload--
|
||||
}
|
||||
notifyItemChanged(position, ImageUnselected())
|
||||
|
||||
// Getting index from all images index when switch is on
|
||||
val indexes =
|
||||
if (showAlreadyActionedImages) {
|
||||
ImageHelper.getIndexList(selectedImages, images)
|
||||
|
||||
// Getting index from actionable images when switch is off
|
||||
} else {
|
||||
ImageHelper.getIndexList(selectedImages, ArrayList(actionableImagesMap.values))
|
||||
}
|
||||
for (index in indexes) {
|
||||
notifyItemChanged(index, ImageSelectedOrUpdated())
|
||||
}
|
||||
} else {
|
||||
val image = images[position]
|
||||
scope.launch(ioDispatcher) {
|
||||
val imageSHA1 = imageLoader.getSHA1(image, defaultDispatcher)
|
||||
withContext(Dispatchers.Main) {
|
||||
if (holder.isItemUploaded()) {
|
||||
Toast.makeText(context, R.string.custom_selector_already_uploaded_image_text, Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
if (holder.isItemNotForUpload()) {
|
||||
numberOfSelectedImagesMarkedAsNotForUpload++
|
||||
}
|
||||
|
||||
// Getting index from all images index when switch is on
|
||||
val indexes: ArrayList<Int> =
|
||||
if (showAlreadyActionedImages) {
|
||||
selectedImages.add(images[position])
|
||||
ImageHelper.getIndexList(selectedImages, images)
|
||||
|
||||
// Getting index from actionable images when switch is off
|
||||
} else {
|
||||
selectedImages.add(ArrayList(actionableImagesMap.values)[position])
|
||||
ImageHelper.getIndexList(selectedImages, ArrayList(actionableImagesMap.values))
|
||||
return@withContext
|
||||
}
|
||||
|
||||
for (index in indexes) {
|
||||
notifyItemChanged(index, ImageSelectedOrUpdated())
|
||||
if (imageSHA1.isNotEmpty() && imageLoader.getFromUploaded(imageSHA1) != null) {
|
||||
holder.itemUploaded()
|
||||
Toast.makeText(context, R.string.custom_selector_already_uploaded_image_text, Toast.LENGTH_SHORT).show()
|
||||
return@withContext
|
||||
}
|
||||
|
||||
if (!holder.isItemUploaded() && imageSHA1.isNotEmpty() && imageLoader.getFromUploaded(imageSHA1) != null) {
|
||||
Toast.makeText(context, R.string.custom_selector_already_uploaded_image_text, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
if (holder.isItemNotForUpload()) {
|
||||
numberOfSelectedImagesMarkedAsNotForUpload++
|
||||
}
|
||||
selectedImages.add(image)
|
||||
notifyItemChanged(position, ImageSelectedOrUpdated())
|
||||
|
||||
imageSelectListener.onSelectedImagesChanged(selectedImages, numberOfSelectedImagesMarkedAsNotForUpload)
|
||||
}
|
||||
}
|
||||
}
|
||||
imageSelectListener.onSelectedImagesChanged(selectedImages, numberOfSelectedImagesMarkedAsNotForUpload)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -638,17 +638,20 @@ class CustomSelectorActivity :
|
|||
finishPickImages(arrayListOf())
|
||||
return
|
||||
}
|
||||
var i = 0
|
||||
while (i < selectedImages.size) {
|
||||
val path = selectedImages[i].path
|
||||
val file = File(path)
|
||||
if (!file.exists()) {
|
||||
selectedImages.removeAt(i)
|
||||
i--
|
||||
scope.launch(ioDispatcher) {
|
||||
val uniqueImages = selectedImages.distinctBy { image ->
|
||||
CustomSelectorUtils.getImageSHA1(
|
||||
image.uri,
|
||||
ioDispatcher,
|
||||
fileUtilsWrapper,
|
||||
contentResolver
|
||||
)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
finishPickImages(ArrayList(uniqueImages))
|
||||
}
|
||||
i++
|
||||
}
|
||||
finishPickImages(selectedImages)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -708,8 +708,17 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
GeoPoint point = new GeoPoint(
|
||||
nearbyBaseMarker.getPlace().location.getLatitude(),
|
||||
nearbyBaseMarker.getPlace().location.getLongitude());
|
||||
OverlayItem item = new OverlayItem(nearbyBaseMarker.getPlace().name, null,
|
||||
point);
|
||||
|
||||
Media markerMedia = this.getMediaFromImageURL(nearbyBaseMarker.getPlace().pic);
|
||||
String authorUser = null;
|
||||
if (markerMedia != null) {
|
||||
authorUser = markerMedia.getAuthorOrUser();
|
||||
// HTML text is sometimes part of the author string and needs to be removed
|
||||
authorUser = Html.fromHtml(authorUser, Html.FROM_HTML_MODE_LEGACY).toString();
|
||||
}
|
||||
|
||||
OverlayItem item = new OverlayItem(nearbyBaseMarker.getPlace().name,
|
||||
authorUser, point);
|
||||
item.setMarker(d);
|
||||
items.add(item);
|
||||
ItemizedOverlayWithFocus overlay = new ItemizedOverlayWithFocus(items,
|
||||
|
|
@ -740,13 +749,37 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specific Media object from the mediaList field.
|
||||
* @param url The specific Media's image URL.
|
||||
* @return The Media object that matches the URL or null if it could not be found.
|
||||
*/
|
||||
private Media getMediaFromImageURL(String url) {
|
||||
if (mediaList == null || url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mediaList.size(); i++) {
|
||||
if (mediaList.get(i) != null && mediaList.get(i).getImageUrl() != null
|
||||
&& mediaList.get(i).getImageUrl().equals(url)) {
|
||||
return mediaList.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a marker from the map based on the specified NearbyBaseMarker.
|
||||
*
|
||||
* @param nearbyBaseMarker The NearbyBaseMarker object representing the marker to be removed.
|
||||
*/
|
||||
private void removeMarker(BaseMarker nearbyBaseMarker) {
|
||||
Place place = nearbyBaseMarker.getPlace();
|
||||
if (nearbyBaseMarker == null || nearbyBaseMarker.getPlace().getName() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String target = nearbyBaseMarker.getPlace().getName();
|
||||
List<Overlay> overlays = binding.mapView.getOverlays();
|
||||
ItemizedOverlayWithFocus item;
|
||||
|
||||
|
|
@ -755,8 +788,7 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
|
|||
item = (ItemizedOverlayWithFocus) overlays.get(i);
|
||||
OverlayItem overlayItem = item.getItem(0);
|
||||
|
||||
if (place.location.getLatitude() == overlayItem.getPoint().getLatitude()
|
||||
&& place.location.getLongitude() == overlayItem.getPoint().getLongitude()) {
|
||||
if (overlayItem.getTitle().equals(target)) {
|
||||
binding.mapView.getOverlays().remove(i);
|
||||
binding.mapView.invalidate();
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class FooterAdapter(
|
|||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int,
|
||||
) = when (FooterItem.values()[viewType]) {
|
||||
) = when (FooterItem.entries[viewType]) {
|
||||
FooterItem.LoadingItem ->
|
||||
LoadingViewHolder(
|
||||
parent.inflate(R.layout.list_item_progress),
|
||||
|
|
|
|||
|
|
@ -153,7 +153,10 @@ public class Place implements Parcelable {
|
|||
.build(),
|
||||
item.getPic().getValue(),
|
||||
// Checking if the place exists or not
|
||||
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == ""), entityId);
|
||||
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == "")
|
||||
&& (item.getDateOfOfficialClosure().getValue() == "")
|
||||
&& (item.getPointInTime().getValue()==""),
|
||||
entityId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -103,4 +103,4 @@ class WikidataFeedback : BaseActivity() {
|
|||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,8 @@ class NearbyResultItem(
|
|||
@field:SerializedName("description") private val description: ResultTuple?,
|
||||
@field:SerializedName("endTime") private val endTime: ResultTuple?,
|
||||
@field:SerializedName("monument") private val monument: ResultTuple?,
|
||||
@field:SerializedName("dateOfOfficialClosure") private val dateOfOfficialClosure: ResultTuple?,
|
||||
@field:SerializedName("pointInTime") private val pointInTime: ResultTuple?,
|
||||
) {
|
||||
fun getItem(): ResultTuple = item ?: ResultTuple()
|
||||
|
||||
|
|
@ -41,6 +43,8 @@ class NearbyResultItem(
|
|||
|
||||
fun getDestroyed(): ResultTuple = destroyed ?: ResultTuple()
|
||||
|
||||
fun getDateOfOfficialClosure(): ResultTuple = dateOfOfficialClosure ?: ResultTuple()
|
||||
|
||||
fun getDescription(): ResultTuple = description ?: ResultTuple()
|
||||
|
||||
fun getEndTime(): ResultTuple = endTime ?: ResultTuple()
|
||||
|
|
@ -48,4 +52,7 @@ class NearbyResultItem(
|
|||
fun getAddress(): String = address?.value ?: ""
|
||||
|
||||
fun getMonument(): ResultTuple? = monument
|
||||
|
||||
fun getPointInTime(): ResultTuple = pointInTime ?: ResultTuple()
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import android.os.Bundle
|
|||
import android.provider.Settings
|
||||
import android.view.View
|
||||
import android.widget.CheckBox
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
|
|
@ -122,7 +123,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
/**
|
||||
* Set the value of the showPermissionDialog variable.
|
||||
*
|
||||
* @param showPermissionsDialog `true` to indicate to show
|
||||
* @property isShowPermissionsDialog `true` to indicate to show
|
||||
* Permissions Dialog if permissions are missing, `false` otherwise.
|
||||
*/
|
||||
/**
|
||||
|
|
@ -166,6 +167,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
private var _binding: ActivityUploadBinding? = null
|
||||
private val binding: ActivityUploadBinding get() = _binding!!
|
||||
|
||||
private lateinit var onBackPressedCallback: OnBackPressedCallback
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -173,6 +176,23 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
_binding = ActivityUploadBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
// Overrides the back button to make sure the user is prepared to lose their progress
|
||||
onBackPressedCallback = object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
showAlertDialog(
|
||||
this@UploadActivity,
|
||||
getString(R.string.back_button_warning),
|
||||
getString(R.string.back_button_warning_desc),
|
||||
getString(R.string.back_button_continue),
|
||||
getString(R.string.back_button_warning),
|
||||
null
|
||||
) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
|
||||
|
||||
/*
|
||||
If Configuration of device is changed then get the new fragments
|
||||
created by the system and populate the fragments ArrayList
|
||||
|
|
@ -187,7 +207,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
}
|
||||
|
||||
init()
|
||||
binding.rlContainerTitle.setOnClickListener { v: View? -> onRlContainerTitleClicked() }
|
||||
binding.rlContainerTitle.setOnClickListener { _: View? -> onRlContainerTitleClicked() }
|
||||
nearbyPopupAnswers = mutableMapOf()
|
||||
//getting the current dpi of the device and if it is less than 320dp i.e. overlapping
|
||||
//threshold, thumbnails automatically minimizes
|
||||
|
|
@ -201,7 +221,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
}
|
||||
locationManager!!.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER)
|
||||
locationManager!!.requestLocationUpdatesFromProvider(LocationManager.NETWORK_PROVIDER)
|
||||
store = BasicKvStore(this, storeNameForCurrentUploadImagesSize).apply {
|
||||
store = BasicKvStore(this, STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE).apply {
|
||||
clearAll()
|
||||
}
|
||||
checkStoragePermissions()
|
||||
|
|
@ -241,7 +261,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
|
||||
override fun onPageSelected(position: Int) {
|
||||
currentSelectedPosition = position
|
||||
if (position >= uploadableFiles!!.size) {
|
||||
if (position >= uploadableFiles.size) {
|
||||
binding.cvContainerTopCard.visibility = View.GONE
|
||||
} else {
|
||||
thumbnailsAdapter!!.notifyDataSetChanged()
|
||||
|
|
@ -274,7 +294,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.filter { result: Boolean? -> result!! }
|
||||
.subscribe { result: Boolean? ->
|
||||
.subscribe { _: Boolean? ->
|
||||
showAlertDialog(
|
||||
this,
|
||||
getString(R.string.block_notification_title),
|
||||
|
|
@ -284,7 +304,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
})
|
||||
}
|
||||
|
||||
fun checkStoragePermissions() {
|
||||
private fun checkStoragePermissions() {
|
||||
// Check if all required permissions are granted
|
||||
val hasAllPermissions = hasPermission(this, PERMISSIONS_STORAGE)
|
||||
val hasPartialAccess = hasPartialAccess(this)
|
||||
|
|
@ -355,7 +375,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
showLongToast(this, messageResourceId)
|
||||
}
|
||||
|
||||
override fun getUploadableFiles(): List<UploadableFile>? {
|
||||
override fun getUploadableFiles(): List<UploadableFile> {
|
||||
return uploadableFiles
|
||||
}
|
||||
|
||||
|
|
@ -367,6 +387,14 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
override fun onUploadMediaDeleted(index: Int) {
|
||||
fragments!!.removeAt(index) //Remove the corresponding fragment
|
||||
uploadableFiles.removeAt(index) //Remove the files from the list
|
||||
|
||||
val isMediaDetailFragment = fragments!!.getOrNull(currentSelectedPosition)?.let {
|
||||
it is UploadMediaDetailFragment
|
||||
} ?: false
|
||||
if(!isMediaDetailFragment) {
|
||||
// Should hide the top card current fragment is not the media detail fragment
|
||||
showHideTopCard(false)
|
||||
}
|
||||
thumbnailsAdapter!!.notifyItemRemoved(index) //Notify the thumbnails adapter
|
||||
uploadImagesAdapter!!.notifyDataSetChanged() //Notify the ViewPager
|
||||
}
|
||||
|
|
@ -375,8 +403,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
binding.tvTopCardTitle.text = resources
|
||||
.getQuantityString(
|
||||
R.plurals.upload_count_title,
|
||||
uploadableFiles!!.size,
|
||||
uploadableFiles!!.size
|
||||
uploadableFiles.size,
|
||||
uploadableFiles.size
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -444,15 +472,16 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
receiveInternalSharedItems()
|
||||
}
|
||||
|
||||
if (uploadableFiles == null || uploadableFiles!!.isEmpty()) {
|
||||
if (uploadableFiles.isEmpty()) {
|
||||
handleNullMedia()
|
||||
} else {
|
||||
//Show thumbnails
|
||||
if (uploadableFiles!!.size > 1) {
|
||||
if (!defaultKvStore.getBoolean("hasAlreadyLaunchedCategoriesDialog")) { //If there is only file, no need to show the image thumbnails
|
||||
if (uploadableFiles.size > 1) {
|
||||
if (!defaultKvStore.getBoolean("hasAlreadyLaunchedCategoriesDialog")) {
|
||||
// If there is only file, no need to show the image thumbnails
|
||||
showAlertDialogForCategories()
|
||||
}
|
||||
if (uploadableFiles!!.size > 3 &&
|
||||
if (uploadableFiles.size > 3 &&
|
||||
!defaultKvStore.getBoolean("hasAlreadyLaunchedBigMultiupload")
|
||||
) {
|
||||
showAlertForBattery()
|
||||
|
|
@ -464,8 +493,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
binding.tvTopCardTitle.text = resources
|
||||
.getQuantityString(
|
||||
R.plurals.upload_count_title,
|
||||
uploadableFiles!!.size,
|
||||
uploadableFiles!!.size
|
||||
uploadableFiles.size,
|
||||
uploadableFiles.size
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -474,7 +503,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
}
|
||||
|
||||
|
||||
for (uploadableFile in uploadableFiles!!) {
|
||||
for (uploadableFile in uploadableFiles) {
|
||||
val uploadMediaDetailFragment = UploadMediaDetailFragment()
|
||||
|
||||
if (!uploadIsOfAPlace) {
|
||||
|
|
@ -497,8 +526,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
object : UploadMediaDetailFragmentCallback {
|
||||
override fun deletePictureAtIndex(index: Int) {
|
||||
store!!.putInt(
|
||||
keyForCurrentUploadImagesSize,
|
||||
(store!!.getInt(keyForCurrentUploadImagesSize) - 1)
|
||||
KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE,
|
||||
(store!!.getInt(KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE) - 1)
|
||||
)
|
||||
presenter!!.deletePictureAtIndex(index)
|
||||
}
|
||||
|
|
@ -576,11 +605,11 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
fragments!!.add(mediaLicenseFragment!!)
|
||||
} else {
|
||||
for (i in 1 until fragments!!.size) {
|
||||
fragments!![i]!!.callback = object : UploadBaseFragment.Callback {
|
||||
fragments!![i].callback = object : UploadBaseFragment.Callback {
|
||||
override fun onNextButtonClicked(index: Int) {
|
||||
if (index < fragments!!.size - 1) {
|
||||
binding.vpUpload.setCurrentItem(index + 1, false)
|
||||
fragments!![index + 1]!!.onBecameVisible()
|
||||
fragments!![index + 1].onBecameVisible()
|
||||
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(
|
||||
if ((index > 0)) index - 1 else 0,
|
||||
|
|
@ -594,7 +623,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
override fun onPreviousButtonClicked(index: Int) {
|
||||
if (index != 0) {
|
||||
binding.vpUpload.setCurrentItem(index - 1, true)
|
||||
fragments!![index - 1]!!.onBecameVisible()
|
||||
fragments!![index - 1].onBecameVisible()
|
||||
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(
|
||||
if ((index > 3)) index - 2 else 0,
|
||||
|
|
@ -632,11 +661,12 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
binding.vpUpload.offscreenPageLimit = fragments!!.size
|
||||
}
|
||||
// Saving size of uploadableFiles
|
||||
store!!.putInt(keyForCurrentUploadImagesSize, uploadableFiles!!.size)
|
||||
store!!.putInt(KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE, uploadableFiles.size)
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes current image when one image upload is cancelled, to highlight next image in the top thumbnail.
|
||||
* Changes current image when one image upload is cancelled, to highlight next image in the top
|
||||
* thumbnail.
|
||||
* Fixes: [Issue](https://github.com/commons-app/apps-android-commons/issues/5511)
|
||||
*
|
||||
* @param index Index of image to be removed
|
||||
|
|
@ -771,7 +801,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
override fun onNextButtonClicked(index: Int) {
|
||||
if (index < fragments!!.size - 1) {
|
||||
binding.vpUpload.setCurrentItem(index + 1, false)
|
||||
fragments!![index + 1]!!.onBecameVisible()
|
||||
fragments!![index + 1].onBecameVisible()
|
||||
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(if ((index > 0)) index - 1 else 0, 0)
|
||||
if (index < fragments!!.size - 4) {
|
||||
|
|
@ -786,10 +816,10 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
override fun onPreviousButtonClicked(index: Int) {
|
||||
if (index != 0) {
|
||||
binding.vpUpload.setCurrentItem(index - 1, true)
|
||||
fragments!![index - 1]!!.onBecameVisible()
|
||||
fragments!![index - 1].onBecameVisible()
|
||||
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
|
||||
.scrollToPositionWithOffset(if ((index > 3)) index - 2 else 0, 0)
|
||||
if ((index != 1) && ((index - 1) < uploadableFiles!!.size)) {
|
||||
if ((index != 1) && ((index - 1) < uploadableFiles.size)) {
|
||||
// Shows the top card if it was hidden because of the last image being deleted and
|
||||
// now the user has hit previous button to go back to the media details
|
||||
showHideTopCard(true)
|
||||
|
|
@ -797,7 +827,10 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
}
|
||||
}
|
||||
|
||||
override fun onThumbnailDeleted(position: Int) = presenter!!.deletePictureAtIndex(position)
|
||||
override fun onThumbnailDeleted(position: Int) {
|
||||
presenter!!.deletePictureAtIndex(position)
|
||||
thumbnailsAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
/**
|
||||
* The adapter used to show image upload intermediate fragments
|
||||
|
|
@ -824,11 +857,11 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
}
|
||||
|
||||
|
||||
fun onRlContainerTitleClicked() {
|
||||
private fun onRlContainerTitleClicked() {
|
||||
binding.rvThumbnails.visibility =
|
||||
if (isTitleExpanded) View.GONE else View.VISIBLE
|
||||
isTitleExpanded = !isTitleExpanded
|
||||
binding.ibToggleTopCard.rotation = binding.ibToggleTopCard.rotation + 180
|
||||
binding.ibToggleTopCard.rotation += 180
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
@ -845,21 +878,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
if (uploadCategoriesFragment != null) {
|
||||
uploadCategoriesFragment!!.callback = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the back button to make sure the user is prepared to lose their progress
|
||||
*/
|
||||
@SuppressLint("MissingSuperCall")
|
||||
override fun onBackPressed() {
|
||||
showAlertDialog(
|
||||
this,
|
||||
getString(R.string.back_button_warning),
|
||||
getString(R.string.back_button_warning_desc),
|
||||
getString(R.string.back_button_continue),
|
||||
getString(R.string.back_button_warning),
|
||||
null
|
||||
) { finish() }
|
||||
onBackPressedCallback.remove()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -879,7 +898,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
.setView(view)
|
||||
.setTitle(getString(R.string.multiple_files_depiction_header))
|
||||
.setMessage(getString(R.string.multiple_files_depiction))
|
||||
.setPositiveButton("OK") { dialog: DialogInterface?, which: Int ->
|
||||
.setPositiveButton("OK") { _: DialogInterface?, _: Int ->
|
||||
if (checkBox.isChecked) {
|
||||
// Save the user's choice to not show the dialog again
|
||||
defaultKvStore.putBoolean("hasAlreadyLaunchedCategoriesDialog", true)
|
||||
|
|
@ -913,14 +932,14 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
getString(R.string.cancel),
|
||||
{
|
||||
/* Since opening the right settings page might be device dependent, using
|
||||
https://github.com/WaseemSabir/BatteryPermissionHelper
|
||||
directly appeared like a promising idea.
|
||||
However, this simply closed the popup and did not make
|
||||
the settings page appear on a Pixel as well as a Xiaomi device.
|
||||
Used the standard intent instead of using this library as
|
||||
it shows a list of all the apps on the device and allows users to
|
||||
turn battery optimisation off.
|
||||
*/
|
||||
https://github.com/WaseemSabir/BatteryPermissionHelper
|
||||
directly appeared like a promising idea.
|
||||
However, this simply closed the popup and did not make
|
||||
the settings page appear on a Pixel as well as a Xiaomi device.
|
||||
Used the standard intent instead of using this library as
|
||||
it shows a list of all the apps on the device and allows users to
|
||||
turn battery optimisation off.
|
||||
*/
|
||||
val batteryOptimisationSettingsIntent = Intent(
|
||||
Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
|
||||
)
|
||||
|
|
@ -958,7 +977,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
Also, location information is discarded if the difference between
|
||||
current location and location recorded just before capturing the image
|
||||
is greater than 100 meters */
|
||||
if (isLocationTagUnchecked || locationDifference > 100 || !defaultKvStore.getBoolean("inAppCameraLocationPref")
|
||||
if (isLocationTagUnchecked || locationDifference > 100
|
||||
|| !defaultKvStore.getBoolean("inAppCameraLocationPref")
|
||||
|| !isInAppCameraUpload
|
||||
) {
|
||||
currLocation = null
|
||||
|
|
@ -979,8 +999,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
|
|||
@JvmField
|
||||
var nearbyPopupAnswers: MutableMap<Place, Boolean>? = null
|
||||
|
||||
const val keyForCurrentUploadImagesSize: String = "CurrentUploadImagesSize"
|
||||
const val storeNameForCurrentUploadImagesSize: String = "CurrentUploadImageQualities"
|
||||
const val KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE: String = "CurrentUploadImagesSize"
|
||||
const val STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE: String = "CurrentUploadImageQualities"
|
||||
|
||||
/**
|
||||
* Sets the flag indicating whether the upload is of a specific place.
|
||||
|
|
|
|||
|
|
@ -146,34 +146,31 @@ class UploadPresenter @Inject internal constructor(
|
|||
|
||||
override fun deletePictureAtIndex(index: Int) {
|
||||
val uploadableFiles = view.getUploadableFiles()
|
||||
if (index == uploadableFiles!!.size - 1) {
|
||||
// If the next fragment to be shown is not one of the MediaDetailsFragment
|
||||
// lets hide the top card so that it doesn't appear on the other fragments
|
||||
view.showHideTopCard(false)
|
||||
}
|
||||
view.setImageCancelled(true)
|
||||
repository.deletePicture(uploadableFiles[index].getFilePath())
|
||||
if (uploadableFiles.size == 1) {
|
||||
view.showMessage(R.string.upload_cancelled)
|
||||
view.finish()
|
||||
return
|
||||
}
|
||||
|
||||
presenter.updateImageQualitiesJSON(uploadableFiles.size, index)
|
||||
view.onUploadMediaDeleted(index)
|
||||
if (index != uploadableFiles.size && index != 0) {
|
||||
// if the deleted image was not the last item to be uploaded, check quality of next
|
||||
repository.getUploadItem(index)?.let {
|
||||
presenter.checkImageQuality(it, index)
|
||||
uploadableFiles?.let {
|
||||
view.setImageCancelled(true)
|
||||
repository.deletePicture(uploadableFiles[index].getFilePath())
|
||||
if (uploadableFiles.size == 1) {
|
||||
view.showMessage(R.string.upload_cancelled)
|
||||
view.finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (uploadableFiles.size < 2) {
|
||||
view.showHideTopCard(false)
|
||||
}
|
||||
presenter.updateImageQualitiesJSON(uploadableFiles.size, index)
|
||||
view.onUploadMediaDeleted(index)
|
||||
if (index != uploadableFiles.size && index != 0) {
|
||||
// if the deleted image was not the last item to be uploaded, check quality of next
|
||||
repository.getUploadItem(index)?.let {
|
||||
presenter.checkImageQuality(it, index)
|
||||
}
|
||||
}
|
||||
|
||||
//In case lets update the number of uploadable media
|
||||
view.updateTopCardTitle()
|
||||
if (uploadableFiles.size < 2) {
|
||||
view.showHideTopCard(false)
|
||||
}
|
||||
|
||||
//In case lets update the number of uploadable media
|
||||
view.updateTopCardTitle()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachView(view: UploadContract.View) {
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
|||
basicKvStore!!.putBoolean(keyForShowingAlertDialog, false)
|
||||
if (isInternetConnectionEstablished(requireActivity())) {
|
||||
val sizeOfUploads = basicKvStore!!.getInt(
|
||||
UploadActivity.keyForCurrentUploadImagesSize
|
||||
UploadActivity.KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE
|
||||
)
|
||||
for (i in indexOfFragment until sizeOfUploads) {
|
||||
presenter.getImageQuality(
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ class UploadMediaPresenter @Inject constructor(
|
|||
private fun storeImageQuality(
|
||||
imageResult: Int, uploadItemIndex: Int, activity: Activity, uploadItem: UploadItem
|
||||
) {
|
||||
val store = BasicKvStore(activity, UploadActivity.storeNameForCurrentUploadImagesSize)
|
||||
val store = BasicKvStore(activity, UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE)
|
||||
val value = store.getString(UPLOAD_QUALITIES_KEY, null)
|
||||
try {
|
||||
val jsonObject = value.asJsonObject().apply {
|
||||
|
|
@ -339,8 +339,10 @@ class UploadMediaPresenter @Inject constructor(
|
|||
*/
|
||||
override fun checkImageQuality(uploadItem: UploadItem, index: Int) {
|
||||
if ((uploadItem.imageQuality != IMAGE_OK) && (uploadItem.imageQuality != IMAGE_KEEP)) {
|
||||
val value = basicKvStoreFactory?.let { it(UploadActivity.storeNameForCurrentUploadImagesSize) }
|
||||
|
||||
val value = basicKvStoreFactory?.let { it(UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE) }
|
||||
?.getString(UPLOAD_QUALITIES_KEY, null)
|
||||
|
||||
try {
|
||||
val imageQuality = value.asJsonObject()["UploadItem$index"] as Int
|
||||
view.showProgress(false)
|
||||
|
|
@ -363,8 +365,9 @@ class UploadMediaPresenter @Inject constructor(
|
|||
* @param index Index of the UploadItem which was deleted
|
||||
*/
|
||||
override fun updateImageQualitiesJSON(size: Int, index: Int) {
|
||||
val value = basicKvStoreFactory?.let { it(UploadActivity.storeNameForCurrentUploadImagesSize) }
|
||||
val value = basicKvStoreFactory?.let { it(UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE) }
|
||||
?.getString(UPLOAD_QUALITIES_KEY, null)
|
||||
|
||||
try {
|
||||
val jsonObject = value.asJsonObject().apply {
|
||||
for (i in index until (size - 1)) {
|
||||
|
|
@ -372,7 +375,8 @@ class UploadMediaPresenter @Inject constructor(
|
|||
}
|
||||
remove("UploadItem" + (size - 1))
|
||||
}
|
||||
basicKvStoreFactory?.let { it(UploadActivity.storeNameForCurrentUploadImagesSize) }
|
||||
|
||||
basicKvStoreFactory?.let { it(UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE) }
|
||||
?.putString(UPLOAD_QUALITIES_KEY, jsonObject.toString())
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@
|
|||
android:layout_marginEnd="@dimen/standard_gap"
|
||||
android:layout_marginRight="@dimen/standard_gap"
|
||||
android:layout_marginBottom="@dimen/standard_gap"
|
||||
android:hint="@string/_2fa_code"
|
||||
android:visibility="gone"
|
||||
app:passwordToggleEnabled="false"
|
||||
tools:visibility="visible">
|
||||
|
|
@ -154,9 +155,7 @@
|
|||
android:id="@+id/login_two_factor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/_2fa_code"
|
||||
android:imeOptions="flagNoExtractUi"
|
||||
android:inputType="number"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:weightSum="2">
|
||||
android:weightSum="3">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -65,24 +65,120 @@
|
|||
android:layout_marginTop="@dimen/dimen_0"
|
||||
app:srcCompat="@drawable/commons_logo" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/rl_container_upload_overlay"
|
||||
<!-- <RelativeLayout-->
|
||||
<!-- android:id="@+id/rl_container_upload_overlay"-->
|
||||
<!-- android:layout_width="match_parent"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_alignParentBottom="true"-->
|
||||
<!-- android:layout_gravity="center|bottom"-->
|
||||
<!-- android:background="#77000000"-->
|
||||
<!-- android:gravity="center"-->
|
||||
<!-- android:padding="@dimen/tiny_gap">-->
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tv_image_caption"-->
|
||||
<!-- style="?android:textAppearanceMedium"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:textColor="#FFFFFFFF" />-->
|
||||
|
||||
<!-- </RelativeLayout>-->
|
||||
|
||||
<!-- New Information Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_gravity="center|bottom"
|
||||
android:background="#77000000"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/tiny_gap">
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_image_caption"
|
||||
style="?android:textAppearanceMedium"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFFFFFFF" />
|
||||
android:text="Uploader"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
<!-- Vertical dividers -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:divider="?android:attr/dividerVertical"
|
||||
android:showDividers="middle"
|
||||
android:dividerPadding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUploaderName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="User:Filli99 (955 edits, age 959 days)"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSource"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="https://owlmaps.github.io/units/#/ruUnknown"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLicenseLink"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="License"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvChecksLink"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tineye . Google Lens . Bing . Yandex"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvGlobalEdits"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Globally: 11,027 edits (Not blocked anywhere)"
|
||||
android:paddingTop="8dp"/>
|
||||
|
||||
<!-- Link section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTalk"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="talk"
|
||||
android:paddingEnd="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUploads"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="uploads"
|
||||
android:paddingEnd="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvContributions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="contributions"
|
||||
android:paddingEnd="8dp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_review_image"
|
||||
|
|
@ -92,8 +188,96 @@
|
|||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- New Information Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Uploader"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
<!-- Vertical dividers -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:divider="?android:attr/dividerVertical"
|
||||
android:showDividers="middle"
|
||||
android:dividerPadding="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUploader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="955 edits, age 959 days"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvSourceLink"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="https://owlmaps.github.io/units/#/ruUnknown"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLicense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="License"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvChecks"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tineye . Google Lens . Bing . Yandex"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Link section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTalkPage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="talk"
|
||||
android:paddingEnd="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvUploadsPage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="uploads"
|
||||
android:paddingEnd="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvContributionsPage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="contributions"
|
||||
android:paddingEnd="8dp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<fr.free.nrw.commons.review.ReviewViewPager
|
||||
android:id="@+id/view_pager_review"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -101,6 +285,7 @@
|
|||
android:layout_weight="1"
|
||||
android:fadingEdge="none" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@
|
|||
android:layout_marginEnd="8dp"
|
||||
android:text="SEND"
|
||||
android:visibility="visible"
|
||||
android:textColor="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/textHeader"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:visibility="visible"
|
||||
app:backgroundTint="@color/main_background_light"
|
||||
app:backgroundTint="?attr/colorSurface"
|
||||
app:elevation="@dimen/dimen_6"
|
||||
app:fabSize="normal"
|
||||
app:srcCompat="@drawable/ic_my_location_black_24dp"
|
||||
app:tint="?attr/colorOnSurface"
|
||||
app:useCompatPadding="true" />
|
||||
|
||||
<View
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@
|
|||
<string name="login_failed_throttled">الكثير من المحاولات غير الناجحة. الرجاء المحاولة مرة أخرى في بضع دقائق.</string>
|
||||
<string name="login_failed_blocked">عذراً، لقد تم منع هذا المستخدم على كومنز</string>
|
||||
<string name="login_failed_2fa_needed">يجب توفير رمز التحقق المزدوج.</string>
|
||||
<string name="login_failed_email_auth_needed">تم إرسال رمز التحقق إلى بريدك الإلكتروني. يُرجى إدخال الرمز لتسجيل الدخول.</string>
|
||||
<string name="login_failed_generic">فشل تسجيل الدخول</string>
|
||||
<string name="share_upload_button">ارفع</string>
|
||||
<string name="multiple_share_base_title">اسم هذه المجموعة</string>
|
||||
|
|
@ -273,6 +274,7 @@
|
|||
<string name="become_a_tester_title">انضم لمختبري اصدارات Beta (بيتا)</string>
|
||||
<string name="become_a_tester_description">يمكنك الاشتراك في القناة التجريبية على جوجل بلاي والحصول على إمكانية الوصول المبكر إلى الميزات الجديدة وإصلاحات الأخطاء</string>
|
||||
<string name="_2fa_code">رمز التحقق المزدوج 2FA</string>
|
||||
<string name="email_auth_code">رمز التحقق من البريد الإلكتروني</string>
|
||||
<string name="logout_verification">أترغب فعلا في الخروج؟</string>
|
||||
<string name="mediaimage_failed">صورة الوسائط فشلت</string>
|
||||
<string name="no_subcategory_found">لم يتم العثور على تصنيفات فرعية.</string>
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@
|
|||
<string name="login_failed_throttled">For mange mislykkede forsøg. Prøv igen om et par minutter.</string>
|
||||
<string name="login_failed_blocked">Beklager, denne bruger er blevet blokeret på Commons</string>
|
||||
<string name="login_failed_2fa_needed">Du skal angive din tofaktorgodkendelseskode.</string>
|
||||
<string name="login_failed_email_auth_needed">En login-bekræftelseskode er blevet sendt til din e-mailadresse. Angiv koden for at logge ind.</string>
|
||||
<string name="login_failed_generic">Login mislykkedes</string>
|
||||
<string name="share_upload_button">Upload</string>
|
||||
<string name="multiple_share_base_title">Navngiv dette sæt</string>
|
||||
|
|
@ -224,6 +225,7 @@
|
|||
<string name="become_a_tester_title">Bliv betatester</string>
|
||||
<string name="become_a_tester_description">Registrer dig på vores betakanal på Google Play og få tidlig adgang til nye funktioner og fejlrettelser</string>
|
||||
<string name="_2fa_code">2FA-kode</string>
|
||||
<string name="email_auth_code">E-mail-bekræftelseskode</string>
|
||||
<string name="logout_verification">Ønsker du at logge ud?</string>
|
||||
<string name="mediaimage_failed">Mediebillede mislykkedes</string>
|
||||
<string name="no_subcategory_found">Ingen underkategorier fundet</string>
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@
|
|||
<string name="share_image_via">Resımi vıla kerê pê</string>
|
||||
<string name="no_achievements_yet" fuzzy="true">Hewna to iştirak nêkerdo</string>
|
||||
<string name="account_created">Hesab vıraziya!</string>
|
||||
<string name="text_copy">Metın kopyayê panoyi biyo</string>
|
||||
<string name="text_copy">Metın be panoyi ra kopya bi</string>
|
||||
<string name="notification_mark_read">Pêhesnayışi wanaye nışan bıkerê</string>
|
||||
<string name="some_error">Yew xeta biye!</string>
|
||||
<string name="place_state">Weziyetê cayi:</string>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
* Fitoschido
|
||||
* Gastonsaenz
|
||||
* Hasley
|
||||
* HylianAngel
|
||||
* Ihojose
|
||||
* JO777
|
||||
* Jack30
|
||||
|
|
@ -150,6 +151,7 @@
|
|||
<string name="menu_from_camera">Tomar una foto</string>
|
||||
<string name="menu_nearby">Cercanos</string>
|
||||
<string name="provider_contributions">Mis subidas</string>
|
||||
<string name="menu_copy_link">Copiar enlace</string>
|
||||
<string name="menu_share">Compartir</string>
|
||||
<string name="menu_view_file_page">Ver página del archivo</string>
|
||||
<string name="share_title_hint">Leyenda (requerido)</string>
|
||||
|
|
@ -413,7 +415,7 @@
|
|||
<string name="statistics_thanks">Agradecimientos recibidos</string>
|
||||
<string name="statistics_featured">Imágenes destacadas</string>
|
||||
<string name="statistics_wikidata_edits">Imágenes vía \"Sitios Cercanos\"</string>
|
||||
<string name="level" fuzzy="true">Nivel</string>
|
||||
<string name="level">Nivel %d</string>
|
||||
<string name="images_uploaded">Imágenes subidas</string>
|
||||
<string name="image_reverts">Imágenes no revertidas</string>
|
||||
<string name="images_used_by_wiki">Imágenes utilizadas</string>
|
||||
|
|
|
|||
|
|
@ -853,8 +853,14 @@
|
|||
<string name="usages_on_other_wikis_heading">Autres wikis</string>
|
||||
<string name="bullet_point">•</string>
|
||||
<string name="file_usages_container_heading">Utilisations du fichier</string>
|
||||
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
|
||||
<string name="account">Compte</string>
|
||||
<string name="vanish_account">Faire disparaître le compte</string>
|
||||
<string name="account_vanish_request_confirm_title">Avertissement de disparition du compte</string>
|
||||
<string name="account_vanish_request_confirm">La disparition est un <b>dernier recours</b> et ne devrait être <b>utilisée que quand vous voulez arrêter d’éditer pour toujours</b> et aussi pour cacher autant que possible vos associations passées.<br/><br/>La suppression de compte sur Wikimedia Commons se fait en changeant le nom de votre compte de sorte que les autres ne peuvent pas identifier vos contributions, lors d’un processus appelé disparition du compte. <b>La disparition ne garantit pas l’anonymat complet ni ne supprime les contributions de vos projets</b>.</string>
|
||||
<string name="caption">Légende</string>
|
||||
<string name="caption_copied_to_clipboard">Légende copiée dans le presse-papier</string>
|
||||
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Félicitations, toutes les images dans cet album ont été soit téléchargées soit marquées comme non téléchargeables.</string>
|
||||
<string name="show_in_explore">Afficher dans Explorer</string>
|
||||
<string name="show_in_nearby">Afficher à proximité</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -40,13 +40,13 @@
|
|||
<item quantity="one">(%1$d)</item>
|
||||
<item quantity="other">(%1$d)</item>
|
||||
</plurals>
|
||||
<plurals name="starting_multiple_uploads" fuzzy="true">
|
||||
<item quantity="one">Iniciando %1$d carga</item>
|
||||
<item quantity="other">Iniciando %1$d cargas</item>
|
||||
<plurals name="starting_multiple_uploads">
|
||||
<item quantity="one">Procesando %d carga</item>
|
||||
<item quantity="other">Procesando %d cargas</item>
|
||||
</plurals>
|
||||
<plurals name="multiple_uploads_title" fuzzy="true">
|
||||
<item quantity="one">%1$d carga</item>
|
||||
<item quantity="other">%1$d cargas</item>
|
||||
<plurals name="multiple_uploads_title">
|
||||
<item quantity="one">%d carga</item>
|
||||
<item quantity="other">%d cargas</item>
|
||||
</plurals>
|
||||
<plurals name="share_license_summary">
|
||||
<item quantity="one">Esta imaxe quedará baixo a licenza %1$s</item>
|
||||
|
|
@ -80,16 +80,16 @@
|
|||
<string name="updating_caption_title">A actualizar lendas e descricións</string>
|
||||
<string name="updating_caption_message">Agarde un chisco…</string>
|
||||
<string name="login_success">Accedeu correctamente!</string>
|
||||
<string name="login_failed">Erro durante o inició de sesión!</string>
|
||||
<string name="login_failed">Erro durante o inicio de sesión!</string>
|
||||
<string name="upload_failed">Ficheiro non atopado. Por favor, probe con outro.</string>
|
||||
<string name="retry_limit_reached">Alcanzouse o límite máximo de reintentos! Cancele o envío e ténteo de novo</string>
|
||||
<string name="unrestricted_battery_mode">Desactivar a optimización da batería?</string>
|
||||
<string name="authentication_failed">Fallou a autenticación. Inicie sesión de novo.</string>
|
||||
<string name="uploading_started">A carga comezou!</string>
|
||||
<string name="uploading_queued">Envío en cola (modo de conexión limitado activado)</string>
|
||||
<string name="upload_completed_notification_title">Cargouse \"%1$s\"!</string>
|
||||
<string name="upload_completed_notification_title">Subiuse \"%1$s\"!</string>
|
||||
<string name="upload_completed_notification_text">Prema para ollar a súa carga</string>
|
||||
<string name="upload_progress_notification_title_start">A enviar ficheiro: %s</string>
|
||||
<string name="upload_progress_notification_title_start">A subir o ficheiro: %s</string>
|
||||
<string name="upload_progress_notification_title_in_progress">Cargando \"%1$s\"</string>
|
||||
<string name="upload_progress_notification_title_finishing">Rematando a carga de \"%1$s\"</string>
|
||||
<string name="upload_failed_notification_title">Produciuse un erro ao enviar %1$s</string>
|
||||
|
|
@ -352,7 +352,7 @@
|
|||
<string name="statistics_thanks">Agradecementos recibidos</string>
|
||||
<string name="statistics_featured">Imaxes destacadas</string>
|
||||
<string name="statistics_wikidata_edits">Imaxes vía \"Lugares próximos\"</string>
|
||||
<string name="level" fuzzy="true">Nivel</string>
|
||||
<string name="level">Nivel %d</string>
|
||||
<string name="images_uploaded">Imaxes cargadas</string>
|
||||
<string name="image_reverts">Imaxes non revertidas</string>
|
||||
<string name="images_used_by_wiki">Imaxes usadas</string>
|
||||
|
|
@ -408,14 +408,14 @@
|
|||
<string name="never_ask_again">Non volver a preguntar isto nunca</string>
|
||||
<string name="display_location_permission_title">Solicitar permiso de localización</string>
|
||||
<string name="display_location_permission_explanation">Pedir permisos de localización cando sexa necesario para a funcionalidade de notificación de proximidade.</string>
|
||||
<string name="achievements_fetch_failed" fuzzy="true">Algo foi mal, non puidemos obter as túas achegas</string>
|
||||
<string name="achievements_fetch_failed">Algo foi mal e non puidemos obter os logros</string>
|
||||
<string name="ends_on">Finaliza o:</string>
|
||||
<string name="display_campaigns">Amosar campañas</string>
|
||||
<string name="display_campaigns_explanation">Ver as campañas en curso</string>
|
||||
<string name="option_allow">Permitir</string>
|
||||
<string name="option_dismiss">Descartar</string>
|
||||
<string name="nearby_campaign_dismiss_message">Xa non verá as campañas. Porén, pode volver habilitar esta notificación na configuración.</string>
|
||||
<string name="this_function_needs_network_connection" fuzzy="true">Esta función require conexión de rede, verifique a súa configuración de conexión.</string>
|
||||
<string name="this_function_needs_network_connection">Esta función necesita conexión de rede. Verifique a súa configuración de conexión.</string>
|
||||
<string name="error_processing_image">Houbo un erro ó procesar a imaxe. Por favor, ténteo de novoǃ</string>
|
||||
<string name="getting_edit_token">Obter un identificador para editar</string>
|
||||
<string name="check_category_adding_template">Engadir modelo para o control de categoría</string>
|
||||
|
|
@ -462,8 +462,8 @@
|
|||
<string name="delete_helper_show_deletion_title_failed">Fallou</string>
|
||||
<string name="delete_helper_show_deletion_message_else">Non foi posíbel solicitar a eliminación.</string>
|
||||
<string name="delete_helper_ask_spam_selfie">Un autorretrato que non se emprega en ningún artigo</string>
|
||||
<string name="delete_helper_ask_spam_blurry" fuzzy="true">Borrosa</string>
|
||||
<string name="delete_helper_ask_spam_nonsense" fuzzy="true">Sen sentido</string>
|
||||
<string name="delete_helper_ask_spam_blurry">completamente borrosa</string>
|
||||
<string name="delete_helper_ask_spam_nonsense">sen sentido, totalmente inusable en calquera artigo</string>
|
||||
<string name="delete_helper_ask_reason_copyright_press_photo">Foto de prensa</string>
|
||||
<string name="delete_helper_ask_reason_copyright_internet_photo">Foto aleatoria de internet</string>
|
||||
<string name="delete_helper_ask_reason_copyright_logo">Logo</string>
|
||||
|
|
|
|||
|
|
@ -385,8 +385,11 @@
|
|||
<string name="notifications">Avizi</string>
|
||||
<string name="read_notifications">Avizi (lektita)</string>
|
||||
<string name="display_nearby_notification">Montrez proxima avizo</string>
|
||||
<string name="display_nearby_notification_summary">Montrar avizo en utensilo \'\'app\'\' pri la maxim proxima loko qua bezonas pikturi</string>
|
||||
<string name="list_sheet">Listo</string>
|
||||
<string name="storage_permission">Permiso pri enmagazinigo</string>
|
||||
<string name="write_storage_permission_rationale_for_image_share">Ni bezonas vua permiso por acesar l\'extera enmagazinigado di vua utensilo, por sendar imaji.</string>
|
||||
<string name="nearby_notification_dismiss_message">Vu ne pluse vidos la maxim proxima loko qua bezonas fotografuro. Tamen, vu povas kapabligar itere ca avizo en Ajusti (\'\'Settings\'\'), se vu deziros.</string>
|
||||
<string name="step_count">Etapo %1$d de %2$d: %3$s</string>
|
||||
<string name="next">Sequanta</string>
|
||||
<string name="previous">Antea</string>
|
||||
|
|
@ -411,17 +414,32 @@
|
|||
<string name="no_depictions_selected">Nula deskripturo selektita</string>
|
||||
<string name="back_button_warning">Cesar kargajo</string>
|
||||
<string name="back_button_continue">Durar kargajo</string>
|
||||
<string name="upload_flow_all_images_in_set">(Por omna imaji en la grupo)</string>
|
||||
<string name="search_this_area">Serchez ca areo</string>
|
||||
<string name="nearby_card_permission_title">Permiso bezonata</string>
|
||||
<string name="nearby_card_permission_explanation">Ka vu deziras ke ni uzez vua nuna lokizo por montrar vicina loki qui bezonas imaji?</string>
|
||||
<string name="unable_to_display_nearest_place">Ne esas posibla montrar la maxim proxima loko qua bezonas imajo, se vu ne montros vua lokizo</string>
|
||||
<string name="never_ask_again">Ne pluse demandez to</string>
|
||||
<string name="display_location_permission_title">Demandar lokala permiso</string>
|
||||
<string name="display_location_permission_explanation">Demandez lokala permiso, kande bezonata por uzar karto montranta proximeso.</string>
|
||||
<string name="achievements_fetch_failed">Ulu faliis, ni ne povis montrar vua sucesi</string>
|
||||
<string name="achievements_fetch_failed_ultimate_achievement">Vu facis plu multa kontributaji, e nia kalkulo-utensilo ne povis kalkular li. To esis la maxim importanta suceso.</string>
|
||||
<string name="ends_on">Finas la:</string>
|
||||
<string name="display_campaigns">Montrez kampanii</string>
|
||||
<string name="display_campaigns_explanation">Videz la kampanii duranta</string>
|
||||
<string name="in_app_camera_location_access_explanation">Permisez ke l\'utensilo (\'\'app\'\') lokizez, se la kamero ne enrejistros la lokizo. Kelka kameri ne havas utensilo por enrejistrar lokizo. Cakaze, vua kontributado divenos plu utila se vu permisos ke l\'\'\'app\'\' prenez ed enrejistrez lokizi. Vu povos abrogar ca permiso irgatempe en Ajusti (\'\'Settings\'\')</string>
|
||||
<string name="option_allow">Permisar</string>
|
||||
<string name="option_dismiss">Eskartar</string>
|
||||
<string name="in_app_camera_needs_location">Voluntez kapabligar registrago di lokizo en \'\'Settings\'\', e probez itere.\n\nNoto: l\'arkivo sendanta povas ne havar informo pri lokizo, se l\'\'\'app\'\' ne povas rekuperar l\'informo pri lokizo en kurta intervalo.</string>
|
||||
<string name="getting_edit_token">Kaptanta \'\'token\'\' por redaktar.</string>
|
||||
<string name="check_category_adding_template">Adjuntanta shablono por verifikar kategorio</string>
|
||||
<string name="check_category_notification_title">Demandanta verifiko di kategorio por %1$s</string>
|
||||
<string name="check_category_edit_summary">Demandanta verifiko di kategorio</string>
|
||||
<string name="check_category_success_title">Verifiko di kategorio demandita</string>
|
||||
<string name="check_category_failure_title">Demando pri verifiko di kategorio ne funcionis</string>
|
||||
<string name="check_category_success_message">Dema%1$sndita verifiko di kategorio por %1$s</string>
|
||||
<string name="check_category_failure_message">Ne povis demandar verifiko di kategorio por %1$s</string>
|
||||
<string name="check_category_toast">Demandanta verifiko di kategorio por %1$s</string>
|
||||
<string name="nominate_for_deletion_done">Facita</string>
|
||||
<string name="send_thank_success_title">Sendanta danko: Suceso</string>
|
||||
<string name="send_thank_success_message">Danko sendita sucese a %1$s</string>
|
||||
|
|
@ -430,6 +448,7 @@
|
|||
<string name="send_thank_toast">Sendanta danko a %1$s</string>
|
||||
<string name="review_copyright">Ka to obedias la reguli pri autoroyuro?</string>
|
||||
<string name="review_category">Ka lua kategorio esas korekta?</string>
|
||||
<string name="review_spam">Ka to apartenas al skopo dil projeto?</string>
|
||||
<string name="review_thanks">Ka vu deziras dankar la kontributero?</string>
|
||||
<string name="review_spam_explanation">Kliktez NO por indikar ca imajo por efaco, se ol ne havas irga utileso.</string>
|
||||
<string name="review_no_category">Ho, to ne mem havas kategorio!</string>
|
||||
|
|
@ -452,9 +471,11 @@
|
|||
<string name="please_wait">Vartez...</string>
|
||||
<string name="copied_successfully">Kopiita</string>
|
||||
<string name="welcome_do_upload_content_description">Exempli pri bona imaji por sendar a Commons</string>
|
||||
<string name="welcome_dont_upload_content_description">Exempli pri imaji por NE SENDAR</string>
|
||||
<string name="skip_image">Saltez ca imajo</string>
|
||||
<string name="download_failed_we_cannot_download_the_file_without_storage_permission">Descharjo faliis!! Ni ne povis descharjar l\'arkivo sen permiso pri extera konservo.</string>
|
||||
<string name="manage_exif_tags">Administrar etiketi EXIF</string>
|
||||
<string name="manage_exif_tags_summary">Dum sendo di arkivi, selektez quala etiketi EXIF devas mantenesar</string>
|
||||
<string name="exif_tag_name_author">Autoro</string>
|
||||
<string name="exif_tag_name_copyright">Autoroyuro</string>
|
||||
<string name="exif_tag_name_location">Loko</string>
|
||||
|
|
@ -465,10 +486,14 @@
|
|||
<string name="image_info">Informo pri imajo</string>
|
||||
<string name="no_categories_found">Nula kategorio trovesis</string>
|
||||
<string name="default_description_language">implicita deskripto-linguo</string>
|
||||
<string name="delete_helper_show_deletion_title">Indikita por efaco</string>
|
||||
<string name="delete_helper_show_deletion_title_success">Suceso</string>
|
||||
<string name="delete_helper_show_deletion_message_if">Indikita %1$s por efaco.</string>
|
||||
<string name="delete_helper_show_deletion_title_failed">Faliis</string>
|
||||
<string name="delete_helper_show_deletion_message_else">Ne povis demandar efaco.</string>
|
||||
<string name="delete_helper_ask_spam_selfie">\'\'selfie\'\'-imajo qua ne uzesas en irga artiklo</string>
|
||||
<string name="delete_helper_ask_spam_blurry">komplete neklara</string>
|
||||
<string name="delete_helper_ask_spam_nonsense">sensencajo, qua ne povas uzesar en irga artiklo</string>
|
||||
<string name="delete_helper_ask_reason_copyright_press_photo">Fotografuro de komunikilaro</string>
|
||||
<string name="delete_helper_ask_reason_copyright_internet_photo">Hazarda imajo de Interreto</string>
|
||||
<string name="delete_helper_ask_reason_copyright_logo">Emblemo</string>
|
||||
|
|
@ -534,9 +559,13 @@
|
|||
<string name="theme_dark_name">Koloro obskura</string>
|
||||
<string name="theme_light_name">Koloro klara</string>
|
||||
<string name="load_more">Charjez pluse</string>
|
||||
<string name="add_picture_to_wikipedia_article_title">Adjuntar imajo a Wikipedio</string>
|
||||
<string name="add_picture_to_wikipedia_article_desc">Ka vu deziras adjuntar ca imajo al artiklo de Wikipedio en idiomo %1$s?</string>
|
||||
<string name="confirm">Konfirmez</string>
|
||||
<string name="instructions_title">Instrucioni</string>
|
||||
<string name="wikipedia_instructions_step_1">1. Uzez la sequanta wikitexto:</string>
|
||||
<string name="wikipedia_instructions_step_2">Kliktanta \"konfirmar\" (\'\'Confirm\'\') apertos l\'artiklo che Wikipedio</string>
|
||||
<string name="wikipedia_instructions_step_3">3. Trovez adequata fako dil artiklo por inkluzar vua imajo</string>
|
||||
<string name="pause">pauzar</string>
|
||||
<string name="resume">durigar</string>
|
||||
<string name="paused">Pauzita</string>
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@
|
|||
<string name="login_failed_throttled">יותר מדי ניסיונות כניסה כושלים. נא לנסות שוב בעוד כמה דקות.</string>
|
||||
<string name="login_failed_blocked">סליחה, החשבון הזה חסום בוויקישיתוף</string>
|
||||
<string name="login_failed_2fa_needed">יש לספק את קוד האימות הדו־שלבי שלך.</string>
|
||||
<string name="login_failed_email_auth_needed">נשלח קוד אימות כניסה לכתובת הדוא״ל שלך. נא לספק את הקוד כדי להיכנס.</string>
|
||||
<string name="login_failed_generic">הכניסה נכשלה</string>
|
||||
<string name="share_upload_button">העלאה</string>
|
||||
<string name="multiple_share_base_title">שם האוסף</string>
|
||||
|
|
@ -249,6 +250,7 @@
|
|||
<string name="become_a_tester_title">להפוך לבודק בטא</string>
|
||||
<string name="become_a_tester_description">להירשם לערוץ הבטא שלנו בחנות גוגל Play ולקבל גישה מוקדמת לאפשרויות חדשות ותיקוני באגים</string>
|
||||
<string name="_2fa_code">קוד אימות דו־שלבי</string>
|
||||
<string name="email_auth_code">קוד אימות בדוא״ל</string>
|
||||
<string name="logout_verification">האם באמת לצאת מהחשבון?</string>
|
||||
<string name="mediaimage_failed">תמונת המדיה נכשלה</string>
|
||||
<string name="no_subcategory_found">לא נמצאו תת־קטגוריות</string>
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@
|
|||
<string name="login_failed_network">ログインできません - ネットワークのエラーです</string>
|
||||
<string name="login_failed_throttled">失敗した回数が多すぎます。数分後にもう一度お試しください。</string>
|
||||
<string name="login_failed_blocked">申し訳ありませんが、この利用者はコモンズでブロックされています。</string>
|
||||
<string name="login_failed_2fa_needed">2段階認証コードを入力してください。</string>
|
||||
<string name="login_failed_2fa_needed">二要素認証コードを入力してください。</string>
|
||||
<string name="login_failed_generic">ログイン失敗</string>
|
||||
<string name="share_upload_button">アップロード</string>
|
||||
<string name="multiple_share_base_title">このセットに名前をつけてください</string>
|
||||
|
|
@ -221,7 +221,7 @@
|
|||
<string name="media_detail_coordinates_empty">情報なし</string>
|
||||
<string name="become_a_tester_title">ベータ版テスターになる</string>
|
||||
<string name="become_a_tester_description">Google Playのベータ版チャンネルにオプトインして、新機能やバグ修正プログラムに早期にアクセス</string>
|
||||
<string name="_2fa_code">2段階認証コード</string>
|
||||
<string name="_2fa_code">2FAコード</string>
|
||||
<string name="logout_verification">ログアウトしてもよろしいですか?</string>
|
||||
<string name="mediaimage_failed">メディアイメージが失敗しました</string>
|
||||
<string name="no_subcategory_found">下位カテゴリは見つかりませんでした</string>
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@
|
|||
<string name="menu_from_camera">Суратха ал</string>
|
||||
<string name="menu_nearby">Джуўукъда</string>
|
||||
<string name="provider_contributions">Джюклегенлерим</string>
|
||||
<string name="menu_copy_link">Джибериуню копия эт</string>
|
||||
<string name="menu_link_copied">Джибериу алмашдырыу буферге копия этилгенди</string>
|
||||
<string name="menu_share">Юлюшле</string>
|
||||
<string name="menu_view_file_page">Файлны бетине къара</string>
|
||||
<string name="share_title_hint">Тюб джазыу (Амалсыз)</string>
|
||||
|
|
@ -274,6 +276,7 @@
|
|||
<string name="copy_wikicode">Викитекстни алмашдырыу буферге копия эт</string>
|
||||
<string name="wikicode_copied">Викитекст алмашдырыу буферге копия этилди</string>
|
||||
<string name="nearby_location_not_available">Джууукъдагыла тюз ишлеялмайды, Локация хайырландырылалмайды.</string>
|
||||
<string name="nearby_showing_pins_offline">Интернет джетишмейди. Къуру кэш этилген джерле кёргюзюледиле.</string>
|
||||
<string name="upload_location_access_denied">Локациягъа джетишиу уналмады. Бу функцияны хайырланыр ючюн, тилейбиз, локациягъызны къолугъуз бла белгилегиз.</string>
|
||||
<string name="location_permission_rationale_nearby">Джууукъдагъы джерле тизмени кёргюзюр ючююн, эркинлик берирге керекди</string>
|
||||
<string name="location_permission_rationale_explore">Джууукъдагъы суратла тизмени кёргюзюр ючююн, эркинлик берирге керекди</string>
|
||||
|
|
@ -357,11 +360,13 @@
|
|||
<string name="delete">Кетер</string>
|
||||
<string name="Achievements">Джетишимле</string>
|
||||
<string name="Profile">Профиль</string>
|
||||
<string name="badges">Белгичикле</string>
|
||||
<string name="statistics">Статистика</string>
|
||||
<string name="statistics_thanks">Бюсюреуле Алындыла</string>
|
||||
<string name="statistics_featured">Сайланнган Суратла</string>
|
||||
<string name="statistics_wikidata_edits">\"Джууукъдагъы Джерле\" юсю бла суратла</string>
|
||||
<string name="level" fuzzy="true">Дараджа</string>
|
||||
<string name="level">Дараджа %d</string>
|
||||
<string name="profileLevel">%s (Дараджа %s)</string>
|
||||
<string name="images_uploaded">Суратла Джюклендиле</string>
|
||||
<string name="image_reverts">Суратла Кери Алынмадыла</string>
|
||||
<string name="images_used_by_wiki">Суратла Хайырландыла</string>
|
||||
|
|
@ -393,6 +398,7 @@
|
|||
<string name="map_application_missing">Девайсыгъызда келишген картография къошакъ табылмады. Тилейбиз, бу энчиликни хайырландырыр ючюн картография къошакъ джюклегиз.</string>
|
||||
<string name="title_page_bookmarks_pictures">Суратла</string>
|
||||
<string name="title_page_bookmarks_locations">Локацияла</string>
|
||||
<string name="title_page_bookmarks_categories">Категорияла</string>
|
||||
<string name="menu_bookmark">Китаб белгилени къош/къорат</string>
|
||||
<string name="provider_bookmarks">Китаб белгиле</string>
|
||||
<string name="bookmark_empty">Алкъын чырт китаб белги къошмадыгъыз</string>
|
||||
|
|
@ -794,4 +800,19 @@
|
|||
<string name="red_pin">Бу джерни сураты джокъду, хайда бирин эт!</string>
|
||||
<string name="green_pin">Бу джерни алайсыз да сураты барды.</string>
|
||||
<string name="grey_pin">Бу джерни сураты болуб-болмагъанын тинте турама.</string>
|
||||
<string name="error_while_loading">Джюкленнген заманда халат</string>
|
||||
<string name="no_usages_found">Бир хайырланыучу да табылмады</string>
|
||||
<string name="usages_on_commons_heading">Гёзен</string>
|
||||
<string name="usages_on_other_wikis_heading">Башха викиле</string>
|
||||
<string name="file_usages_container_heading">Файлны хайырланыулары</string>
|
||||
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
|
||||
<string name="account">Хыйсаб</string>
|
||||
<string name="vanish_account">Хыйсабны сюрт</string>
|
||||
<string name="account_vanish_request_confirm_title">Хыйсаб сюртюуню эсгертиую</string>
|
||||
<string name="account_vanish_request_confirm">Джокъ этиу — <b>ахыр амалды</b>, эмда аны <b>тюзетиуню тамамы бла тохтатыргъа излегесиз хайырланыргъа керекди</b>, неда эскиде ассоциацияланы бир мадар болуб аслам джашырыргъа излесегиз.<br/><br />Викигёзенде хыйсабны кетериу, башхала хыйсабны джокъ этиу атны джюрютген процессде сизни кошумугъузну танымазча, хыйсабыгъызны атын тюрлендириу бла этиледи.<b>Джокъ этиу толу анонимликни гарантия этмейди эмда проектде къошумларыгъызны къоратмайды</b>.</string>
|
||||
<string name="caption">Тюб джазыу</string>
|
||||
<string name="caption_copied_to_clipboard">Тюб джазыу алмашдырыу буферге копия этилгенди</string>
|
||||
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Алгъышлайбыз, бу альбомна бютеу сратла не джюкленнгендиле, неда джюкленирге джораланмагъанлача белгиленнгендиле.</string>
|
||||
<string name="show_in_explore">Explore-де кёргюз</string>
|
||||
<string name="show_in_nearby">Nearby-да кёргюз</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@
|
|||
<string name="statistics_thanks">Spasî Hate Wergirtin</string>
|
||||
<string name="statistics_featured">Wêneyên Bijartî</string>
|
||||
<string name="statistics_wikidata_edits">Wêneyên bi riya \"Cihên Nêz\"</string>
|
||||
<string name="level" fuzzy="true">Derece</string>
|
||||
<string name="level">Derece %d</string>
|
||||
<string name="images_uploaded">Wêneyên Barkirî</string>
|
||||
<string name="review_thanks_yes_button_text">Wêneyê din</string>
|
||||
<string name="review_thanks_no_button_text">Belê, çima na</string>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
<string name="authentication_failed">D\'Authentifizéierung huet net funktionéiert. Loggt Iech wgl. nach eng Kéier an.</string>
|
||||
<string name="uploading_started">D\'Eroplueden huet ugefaang!</string>
|
||||
<string name="upload_completed_notification_title">%1$s eropgelueden!</string>
|
||||
<string name="upload_completed_notification_text">Dréckt fir de Fichier ze gesinn deen Dir eropgelueden hutt</string>
|
||||
<string name="upload_completed_notification_text">Tippt fir de Fichier ze gesinn, deen Dir eropgelueden hutt</string>
|
||||
<string name="upload_progress_notification_title_start">Fichier eroplueden: %s</string>
|
||||
<string name="upload_progress_notification_title_in_progress">%1$s gëtt eropgelueden</string>
|
||||
<string name="upload_progress_notification_title_finishing">Eropluede vu(n) %1$s ofschléissen</string>
|
||||
|
|
@ -99,6 +99,7 @@
|
|||
<string name="login_failed_throttled">Ze dacks ouni Succès probéiert. Probéiert wgl. an e puer Minutten nach eng Kéier.</string>
|
||||
<string name="login_failed_blocked">Pardon, dëse Benotzer ass op Commons gespaart</string>
|
||||
<string name="login_failed_2fa_needed">Dir musst de Code vun Ärer Zwee-Facteur-Authentifizéierung uginn.</string>
|
||||
<string name="login_failed_email_auth_needed">Dir hutt ee Login-Verifikatiounscode per E-Mail geschéckt kritt. Gitt wgl. de Code an, fir Iech anzeloggen.</string>
|
||||
<string name="login_failed_generic">Aloggen huet net funktionéiert</string>
|
||||
<string name="share_upload_button">Eroplueden</string>
|
||||
<string name="multiple_share_base_title">Gitt dëser Biller een Numm</string>
|
||||
|
|
@ -192,6 +193,7 @@
|
|||
<string name="become_a_tester_title">Beta-Tester ginn</string>
|
||||
<string name="become_a_tester_description">Schreift Iech op GooglePlay a fir eise Beta-Kanal a kritt fréi Zougang zu neie Funktiounen a Verbesserunge vu Feeler</string>
|
||||
<string name="_2fa_code">2FA-Code</string>
|
||||
<string name="email_auth_code">E-Mail-Verifikatiounscode</string>
|
||||
<string name="logout_verification">Wëllt dir Iech wierklech ausloggen?</string>
|
||||
<string name="no_subcategory_found">Keng Ënnerkategorie fonnt</string>
|
||||
<string name="welcome_image_mount_zao">Bierg Zao</string>
|
||||
|
|
@ -274,6 +276,7 @@
|
|||
<string name="menu_search_button">Sichen</string>
|
||||
<string name="search_commons">Op Commons sichen</string>
|
||||
<string name="title_activity_search">Sichen</string>
|
||||
<string name="search_recent_header">Rezent gesicht:</string>
|
||||
<string name="search_tab_title_media">Medien</string>
|
||||
<string name="search_tab_title_categories">Kategorien</string>
|
||||
<string name="search_tab_title_depictions">Elementer</string>
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@
|
|||
<string name="login_failed_throttled">Направени се премногу неуспешни обиди. Обидете се пак за некоја минута.</string>
|
||||
<string name="login_failed_blocked">За жал, корисникот е блокиран на Ризницата</string>
|
||||
<string name="login_failed_2fa_needed">Мора да го укажете вашиот код за двочинителска заверка.</string>
|
||||
<string name="login_failed_email_auth_needed">На вашата е-поштенска адреса ви испративме потврден код за најава. Внесете го кодот за да се најавите.</string>
|
||||
<string name="login_failed_generic">Најавата не успеа</string>
|
||||
<string name="share_upload_button">Подигни</string>
|
||||
<string name="multiple_share_base_title">Дајте му име на овој комплет</string>
|
||||
|
|
@ -218,6 +219,7 @@
|
|||
<string name="become_a_tester_title">Станете бета-испробувач</string>
|
||||
<string name="become_a_tester_description">Пријавете се на нашиот бета-канал на Google Play и добивајте ран пристап до нови можности и исправки на грешки</string>
|
||||
<string name="_2fa_code">2ЧЗ-код</string>
|
||||
<string name="email_auth_code">Испрати го потврдниот код на е-пошта</string>
|
||||
<string name="logout_verification">Дали навистина сакате да се одјавите?</string>
|
||||
<string name="mediaimage_failed">Сликата не успеа</string>
|
||||
<string name="no_subcategory_found">Не пронајдов поткатегории</string>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
<string name="nearby_row_image">ਤਸਵੀਰ</string>
|
||||
<string name="nearby_all">ਸਾਰੇ</string>
|
||||
<string name="appwidget_img">ਦਿਨ ਦੀ ਤਸਵੀਰ</string>
|
||||
<plurals name="uploads_pending_notification_indicator" fuzzy="true">
|
||||
<plurals name="uploads_pending_notification_indicator">
|
||||
<item quantity="one">੧ ਫ਼ਾਈਲ ਚੜ੍ਹਾਈ ਜਾ ਰਹੀ ਹੈ</item>
|
||||
<item quantity="other">%1$d ਫ਼ਾਈਲਾਂ ਚੜ੍ਹਾਈਆਂ ਜਾ ਰਹੀਆਂ ਹਨ</item>
|
||||
</plurals>
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<string name="preference_category_general">ਆਮ</string>
|
||||
<string name="preference_category_feedback">ਸੁਝਾਅ</string>
|
||||
<string name="preference_category_privacy">ਪਰਦੇਦਾਰੀ</string>
|
||||
<string name="app_name" fuzzy="true">ਵਿਕੀਮੀਡੀਆ ਕਾਮਨਜ਼</string>
|
||||
<string name="app_name">ਵਿਕੀਮੀਡੀਆ ਸ਼ਾਮਲਾਟ</string>
|
||||
<string name="menu_settings">ਪਸੰਦਾਂ</string>
|
||||
<string name="upload_in_progress">ਚੜ੍ਹਾਉਣਾ ਜਾਰੀ ਐ</string>
|
||||
<string name="username">ਵਰਤੋਂਕਾਰ ਨਾਂ</string>
|
||||
|
|
@ -180,8 +180,11 @@
|
|||
<string name="media_detail_coordinates_empty">ਕੋਈ ਉਪਲਬਧ ਨਹੀਂ</string>
|
||||
<string name="_2fa_code">2FA ਕੋਡ</string>
|
||||
<string name="logout_verification">ਕੀ ਤੁਸੀਂ ਸੱਚੀਂ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
|
||||
<string name="welcome_image_llamas">ਲਾਮਾ</string>
|
||||
<string name="welcome_image_rainbow_bridge">ਸਤਰੰਗੀ ਪੁਲ</string>
|
||||
<string name="welcome_image_welcome_wikipedia">ਵਿਕੀਪੀਡੀਆ \'ਤੇ ਜੀ ਆਇਆਂ ਨੂੰ</string>
|
||||
<string name="welcome_image_welcome_copyright">ਜੀ ਆਇਆਂ ਨੂੰ ਕਾਪੀਰਾਈਟ</string>
|
||||
<string name="welcome_image_sydney_opera_house">ਸਿਡਨੀ ਓਪੇਰਾ ਹਾਊਸ</string>
|
||||
<string name="cancel">ਰੱਦ ਕਰੋ</string>
|
||||
<string name="navigation_drawer_open">ਖੋਲ੍ਹੋ</string>
|
||||
<string name="navigation_drawer_close">ਬੰਦ ਕਰੋ</string>
|
||||
|
|
@ -191,10 +194,13 @@
|
|||
<string name="navigation_item_about">ਬਾਰੇ</string>
|
||||
<string name="navigation_item_settings">ਤਰਜੀਹਾਂ</string>
|
||||
<string name="navigation_item_feedback">ਸੁਝਾਅ</string>
|
||||
<string name="navigation_item_feedback_github">ਗਿੱਟਹਬ (GitHub) ਰਾਹੀਂ ਸੁਝਾਅ</string>
|
||||
<string name="navigation_item_logout">ਬਾਹਰ ਆਉ</string>
|
||||
<string name="navigation_item_info">ਸਿਖਲਾਈ</string>
|
||||
<string name="navigation_item_notification">ਸੂਚਨਾਵਾਂ</string>
|
||||
<string name="navigation_item_review">ਪਰਖੋ</string>
|
||||
<string name="no_description_found">ਕੋਈ ਵੇਰਵਾ ਨਹੀਂ ਮਿਲਿਆ</string>
|
||||
<string name="nearby_info_menu_wikidata_article">ਵਿਕੀਡਾਟਾ ਵਸਤਾਂ</string>
|
||||
<string name="nearby_info_menu_wikipedia_article">ਵਿਕੀਪੀਡੀਆ ਲੇਖ</string>
|
||||
<string name="upload_problem_image_dark">ਤਸਵੀਰ ਬਹੁਤ ਗੂੜ੍ਹੀ ਹੈ।</string>
|
||||
<string name="upload_problem_image_blurry">ਤਸਵੀਰ ਧੁੰਦਲੀ ਹੈ।</string>
|
||||
|
|
@ -203,35 +209,76 @@
|
|||
<string name="navigation_item_login">ਦਾਖ਼ਲ ਹੋਵੋ</string>
|
||||
<string name="nearby_wikidata">ਵਿਕੀਡੇਟਾ</string>
|
||||
<string name="nearby_wikipedia">ਵਿਕੀਪੀਡੀਆ</string>
|
||||
<string name="about_rate_us">ਸਾਨੂੰ ਦਰਜਾ ਦਿਓ</string>
|
||||
<string name="about_faq">ਅਕਸਰ ਪੁੱਛੇ ਜਾਂਦੇ ਸੁਆਲ</string>
|
||||
<string name="user_guide">ਵਰਤੋਂਕਾਰ ਦਸਤਿਆਂ</string>
|
||||
<string name="welcome_skip_button">ਸਿਖਲਾਈ ਛੱਡੋ</string>
|
||||
<string name="about_translate">ਤਰਜਮਾ ਕਰੋ</string>
|
||||
<string name="about_translate_title">ਬੋਲੀਆਂ</string>
|
||||
<string name="about_translate_proceed">ਅੱਗੇ ਵਧੋ</string>
|
||||
<string name="about_translate_cancel">ਰੱਦ ਕਰੋ</string>
|
||||
<string name="retry">ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ</string>
|
||||
<string name="showcase_view_needs_photo">ਇਸ ਜਗ੍ਹਾ ਨੂੰ ਇੱਕ ਤਸਵੀਰ ਦੀ ਲੋੜ ਏ।</string>
|
||||
<string name="showcase_view_has_photo">ਇਸ ਜਗ੍ਹਾ \'ਤੇ ਪਹਿਲਾਂ ਹੀ ਇੱਕ ਤਸਵੀਰ ਏ।</string>
|
||||
<string name="showcase_view_no_longer_exists">ਇਹ ਜਗ੍ਹਾ ਹੁਣ ਮੌਜੂਦ ਨਹੀਂ ਏ।</string>
|
||||
<string name="no_images_found">ਕੋਈ ਤਸਵੀਰ ਨਹੀਂ ਲੱਭੀ!</string>
|
||||
<string name="error_loading_images">ਤਸਵੀਰ ਚੜਾਉਨ ਵੇਲੇ ਗਲਤੀ ਆਈ ਏ।</string>
|
||||
<string name="image_uploaded_by">%1$s: ਵੱਲੋਂ ਚੜ੍ਹਾਈ ਗਈ</string>
|
||||
<string name="block_notification_title">ਰੋਕ ਲਾਈ ਗਈ</string>
|
||||
<string name="app_widget_heading">ਦਿਨ ਦੀ ਤਸਵੀਰ</string>
|
||||
<string name="menu_search_button">ਲੱਭੋ</string>
|
||||
<string name="title_activity_search">ਲੱਭੋ</string>
|
||||
<string name="search_recent_header">ਹਾਲੀਆ ਖੋਜਾਂ:</string>
|
||||
<string name="provider_searches">ਹਾਲ ਦੀਆਂ ਪੁੱਛਗਿੱਛ ਖੋਜਾਂ</string>
|
||||
<string name="provider_recent_languages">ਹਾਲ ਹੀ ਵਿੱਚ ਬੋਲੀਆਂ ਬਾਰੇ ਪੁੱਛਗਿੱਛ</string>
|
||||
<string name="search_tab_title_categories">ਸ਼੍ਰੇਣੀਆਂ</string>
|
||||
<string name="search_tab_title_depictions">ਵਸਤਾਂ</string>
|
||||
<string name="explore_tab_title_map">ਨਕਸ਼ਾ</string>
|
||||
<string name="question">ਸਵਾਲ</string>
|
||||
<string name="result">ਨਤੀਜਾ</string>
|
||||
<string name="user_not_logged_in">ਤੁਹਾਡੇ ਦਾਖਲੇ ਦੀ ਮਿਆਦ ਪੁੱਗ ਗਈ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਮੁੜ ਦਾਖਲ ਹੋਵੋ।</string>
|
||||
<string name="continue_message">ਜਾਰੀ ਰੱਖੋ</string>
|
||||
<string name="correct">ਸਹੀ ਜਵਾਬ</string>
|
||||
<string name="wrong">ਗਲਤ ਜਵਾਬ</string>
|
||||
<string name="share_app_title">ਐਪ ਸਾਂਝਾ ਕਰੋ</string>
|
||||
<string name="rotate">ਘੁੰਮਾਓ</string>
|
||||
<string name="error_fetching_nearby_places">ਨੇੜਲੀਆਂ ਥਾਵਾਂ ਲੋਡ ਨਹੀਂ ਕੀਤੀਆਂ ਜਾ ਸਕੀਆਂ</string>
|
||||
<string name="no_pictures_in_this_area">ਇਸ ਖੇਤਰ ਵਿੱਚ ਕੋਈ ਤਸਵੀਰਾਂ ਨਹੀਂ ਹਨ।</string>
|
||||
<string name="no_nearby_places_around">ਆਲੇ-ਦੁਆਲੇ ਕੋਈ ਨੇੜਲੀ ਥਾਂ ਨਹੀਂ ਏ।</string>
|
||||
<string name="error_fetching_nearby_monuments">ਨੇਡ਼ਲੇ ਸਮਾਰਕਾਂ ਨੂੰ ਲਿਆਉਣ ਵਿੱਚ ਗਲਤੀ।</string>
|
||||
<string name="no_recent_searches">ਕੋਈ ਤਾਜ਼ਾ ਖੋਜ ਨਹੀਂ</string>
|
||||
<string name="delete_recent_searches_dialog">ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ ਉੱਤੇ ਆਪਣੇ ਖੋਜ ਇਤਿਹਾਸ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
|
||||
<string name="delete_search_dialog">ਕੀ ਤੁਸੀਂ ਇਸ ਖੋਜ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
|
||||
<string name="search_history_deleted">ਖੋਜ ਇਤਿਹਾਸ ਮਿਟਾਇਆ ਗਿਆ</string>
|
||||
<string name="nominate_delete">ਮਿਟਾਉਣ ਲਈ ਨਾਮਜ਼ਦ ਕਰੋ</string>
|
||||
<string name="delete">ਮਿਟਾਓ</string>
|
||||
<string name="Achievements">ਪ੍ਰਾਪਤੀਆਂ</string>
|
||||
<string name="Profile">ਪ੍ਰੋਫਾਈਲ</string>
|
||||
<string name="statistics">ਅੰਕੜੇ</string>
|
||||
<string name="statistics_thanks">ਧੰਨਵਾਦ ਪ੍ਰਾਪਤ ਹੋਏ</string>
|
||||
<string name="statistics_featured">ਵਿਸ਼ੇਸ਼ ਤਸਵੀਰ</string>
|
||||
<string name="statistics_wikidata_edits">\"ਨੇੜਲੀਆਂ ਥਾਵਾਂ\" ਰਾਹੀਂ ਤਸਵੀਰਾਂ</string>
|
||||
<string name="level">ਪੱਧਰ %d</string>
|
||||
<string name="images_uploaded">ਤਸਵੀਰਾਂ ਚੜ੍ਹਾਇਆਂ ਗਈਆਂ</string>
|
||||
<string name="image_reverts">ਤਸਵੀਰਾਂ ਵਾਪਸ ਨਹੀਂ ਕੀਤੀ ਗਈਆਂ</string>
|
||||
<string name="images_used_by_wiki">ਵਰਤੀ ਗਈਆਂ ਤਸਵੀਰਾਂ</string>
|
||||
<string name="achievements_share_message">ਆਪਣੀਆਂ ਪ੍ਰਾਪਤੀਆਂ ਨੂੰ ਆਪਣੇ ਦੋਸਤਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰੋ!</string>
|
||||
<string name="achievements_revert_limit_message">ਘੱਟੋ-ਘੱਟ ਲੋੜੀਂਦਾ:</string>
|
||||
<string name="error_occurred">ਗਲਤੀ ਆਈ!</string>
|
||||
<string name="contributions_fragment">ਯੋਗਦਾਨ</string>
|
||||
<string name="nearby_fragment">ਨੇੜੇ-ਤੇੜੇ</string>
|
||||
<string name="notifications">ਸੂਚਨਾਵਾਂ</string>
|
||||
<string name="read_notifications">ਸੂਚਨਾਵਾਂ (ਪੜ੍ਹਿਆਂ)</string>
|
||||
<string name="list_sheet">ਸੂਚੀ</string>
|
||||
<string name="next">ਅੱਗੇ</string>
|
||||
<string name="previous">ਪਿਛਲਾ</string>
|
||||
<string name="title_page_bookmarks_pictures">ਤਸਵੀਰਾਂ</string>
|
||||
<string name="title_page_bookmarks_locations">ਟਿਕਾਣਾ</string>
|
||||
<string name="title_page_bookmarks_categories">ਸ਼੍ਰੇਣੀਆਂ</string>
|
||||
<string name="search_this_area">ਇਸ ਖੇਤਰ ਵਿੱਚ ਖੋਜ ਕਰੋ</string>
|
||||
<string name="nearby_card_permission_title">ਇਜਾਜ਼ਤ ਦੀ ਬੇਨਤੀ</string>
|
||||
<string name="never_ask_again">ਇਹ ਮੁੜ ਕਦੇ ਨਾ ਪੁੱਛੋ</string>
|
||||
<string name="display_location_permission_title">ਟਿਕਾਣੇਂ ਦੀ ਆਗਿਆ ਮੰਗੋ</string>
|
||||
<string name="ends_on">ਨੂੰ ਮਿਆਦ ਪੁਗਦੀ</string>
|
||||
<string name="display_campaigns">ਮੁਹਿੰਮਾਂ ਵੇਖਾਓ</string>
|
||||
<string name="option_allow">ਇਜਾਜ਼ਤ ਦਿਓ</string>
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@
|
|||
<string name="login_failed_throttled">Tròpi tentativ falì. Për piasì, ch\'a preuva torna da-sì chèiche minute.</string>
|
||||
<string name="login_failed_blocked">An dëspias, s\'utent-sì a l\'é stàit blocà ansima a Commons</string>
|
||||
<string name="login_failed_2fa_needed">A dev fornì sò còdes d\'autentificassion a doi fator.</string>
|
||||
<string name="login_failed_email_auth_needed">Un còdes ëd verìfica ëd conession a l\'é stàit mandà a soa adrëssa ëd pòsta eletrònica. Për piasì, ch\'a anserissa col còdes për intré ant ël sistema.</string>
|
||||
<string name="login_failed_generic">Falì a rintré ant ël sistema</string>
|
||||
<string name="share_upload_button">Carié</string>
|
||||
<string name="multiple_share_base_title">Deje un nòm a s\'ansem</string>
|
||||
|
|
@ -216,6 +217,7 @@
|
|||
<string name="become_a_tester_title">Dventé në sperimentador Beta</string>
|
||||
<string name="become_a_tester_description">Anscriv-se a nòstr canal beta su Google Play a oten-e n\'acess antissipà a le neuve fonsionalità e coression ëd givo</string>
|
||||
<string name="_2fa_code">Còdes 2FA</string>
|
||||
<string name="email_auth_code">Mandé un còdes ëd verifica</string>
|
||||
<string name="logout_verification">Veul-lo për da bon seurte dal sistema?</string>
|
||||
<string name="mediaimage_failed">Faliment ëd la plancia dël mojen</string>
|
||||
<string name="no_subcategory_found">Gnun-e sot-categorìe trovà</string>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,14 @@
|
|||
<item quantity="one">%d upload</item>
|
||||
<item quantity="other">%d پورته کول</item>
|
||||
</plurals>
|
||||
<string name="share_license_summary" fuzzy="true">دا انځور به د %1$s په منښتليک سمبال وي.</string>
|
||||
<plurals name="share_license_summary">
|
||||
<item quantity="one">دا انځور به د منښتليک %1$s لاندې وي</item>
|
||||
<item quantity="other">دا انځورونه به د %1$s منښتليک لاندې وي</item>
|
||||
</plurals>
|
||||
<plurals name="upload_count_title">
|
||||
<item quantity="one">%1$d راپورته کول</item>
|
||||
<item quantity="other">%1$d راپورته کېدنې</item>
|
||||
</plurals>
|
||||
<string name="navigation_item_explore">سپړنه</string>
|
||||
<string name="preference_category_appearance">ښکارېدنه</string>
|
||||
<string name="preference_category_general">ټولګړی</string>
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@
|
|||
<string name="provider_bookmarks">Favoritos</string>
|
||||
<string name="bookmark_empty">Não adicionou nenhum favorito</string>
|
||||
<string name="provider_bookmarks_location">Favoritos</string>
|
||||
<string name="log_collection_started">A recolha de registos foi iniciada. REINICIE a aplicação, execute a operação que pretende registar e prima outra vez \"Enviar ficheiro de registos\"</string>
|
||||
<string name="log_collection_started">A coleta de registros foi iniciada. REINICIE o aplicativo, execute a operação que pretende registrar e toque em ‘Enviar arquivo de registros’ novamente</string>
|
||||
<string name="deletion_reason_uploaded_by_mistake">Eu fiz o carregamento por engano</string>
|
||||
<string name="deletion_reason_publicly_visible">Eu não sabia que seria publicamente visível</string>
|
||||
<string name="deletion_reason_bad_for_my_privacy">Eu percebi que é ruim para minha privacidade</string>
|
||||
|
|
@ -696,7 +696,7 @@
|
|||
<string name="place_state_wlm">WLM</string>
|
||||
<string name="wlm_upload_info">Essa imagem será enviada ao concurso Wiki Loves Monuments</string>
|
||||
<string name="display_monuments">Monumentos de exibição</string>
|
||||
<string name="wlm_month_message">Estamos no mês no Wiki Loves Monuments!</string>
|
||||
<string name="wlm_month_message">Chegou o mês do Wiki Loves Monuments!</string>
|
||||
<string name="learn_more">SABER MAIS</string>
|
||||
<string name="wlm_campaign_title">Wiki Loves Monuments</string>
|
||||
<string name="wlm_campaign_description">O Wiki Loves Monuments é um concurso internacional organizado pela Wikimedia sobre fotografias de monumentos</string>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Authors:
|
||||
* AguzulH
|
||||
* Brahim-essaidi
|
||||
* Hakim1bal
|
||||
-->
|
||||
|
|
@ -79,7 +80,7 @@
|
|||
<string name="Profile">ⵉⴼⵔⵙ</string>
|
||||
<string name="statistics">ⵉⵙⵉⴹⵏⵏ</string>
|
||||
<string name="title_app_shortcut_setting">ⵜⵉⵙⵖⴰⵍ</string>
|
||||
<string name="leaderboard_column_user">ⴰⵏⵙⵙⵎⵔⵙ</string>
|
||||
<string name="leaderboard_column_user">ⴰⵏⵙⵎⵔⴰⵙ</string>
|
||||
<string name="leaderboard_column_count">ⵙⵙⵉⴹⵏ</string>
|
||||
<string name="leaderboard_yearly">ⴰⵙⴳⵯⵙⴰⵏ</string>
|
||||
<string name="leaderboard_weekly">ⴰⵏⵎⵍⴰⵙⵙ</string>
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@
|
|||
<string name="login_failed_throttled">失敗次數過多。請於幾分鐘後重試。</string>
|
||||
<string name="login_failed_blocked">很抱歉,該使用者已被維基共享資源封禁</string>
|
||||
<string name="login_failed_2fa_needed">必須提供您的雙重驗證代碼。</string>
|
||||
<string name="login_failed_email_auth_needed">登入驗證碼已發送到您的電子郵件地址。請提供驗證碼以登入。</string>
|
||||
<string name="login_failed_generic">登入失敗</string>
|
||||
<string name="share_upload_button">上傳</string>
|
||||
<string name="multiple_share_base_title">給這個集合命名</string>
|
||||
|
|
@ -241,6 +242,7 @@
|
|||
<string name="become_a_tester_title">成為 Beta 測試員</string>
|
||||
<string name="become_a_tester_description">選擇加入我們在 Google Play 上的測試版頻道並儘早訪問新功能和錯誤修復</string>
|
||||
<string name="_2fa_code">2FA 代碼</string>
|
||||
<string name="email_auth_code">電子郵件驗證碼</string>
|
||||
<string name="logout_verification">您確定要登出嗎?</string>
|
||||
<string name="mediaimage_failed">媒體圖片失敗</string>
|
||||
<string name="no_subcategory_found">找不到子分類</string>
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@
|
|||
<string name="login_failed_throttled">Too many unsuccessful attempts. Please try again in a few minutes.</string>
|
||||
<string name="login_failed_blocked">Sorry, this user has been blocked on Commons</string>
|
||||
<string name="login_failed_2fa_needed">You must provide your two factor authentication code.</string>
|
||||
<string name="login_failed_email_auth_needed">A login verification code has been sent to your email address. Please provide the code to log in.</string>
|
||||
<string name="login_failed_generic">Log-in failed</string>
|
||||
<string name="share_upload_button">Upload</string>
|
||||
<string name="multiple_share_base_title">Name this set</string>
|
||||
|
|
@ -218,6 +219,7 @@
|
|||
<string name="become_a_tester_description">Opt-in to our beta channel on Google Play and get early access to new features and bug fixes</string>
|
||||
<string name="beta_opt_in_link">https://play.google.com/apps/testing/fr.free.nrw.commons</string>
|
||||
<string name="_2fa_code">2FA Code</string>
|
||||
<string name="email_auth_code">Email verification code</string>
|
||||
<string name="logout_verification">Do you really want to logout?</string>
|
||||
<string name="mediaimage_failed">Media Image Failed</string>
|
||||
<string name="no_subcategory_found">No subcategories found</string>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ SELECT
|
|||
(SAMPLE(?wikipediaArticle) AS ?wikipediaArticle)
|
||||
(SAMPLE(?commonsArticle) AS ?commonsArticle)
|
||||
(SAMPLE(?commonsCategory) AS ?commonsCategory)
|
||||
(SAMPLE(?dateOfOfficialClosure) AS ?dateOfOfficialClosure)
|
||||
(SAMPLE(?pointInTime) AS ?pointInTime)
|
||||
WHERE {
|
||||
SERVICE <https://query.wikidata.org/sparql> {
|
||||
values ?item {
|
||||
|
|
@ -45,6 +47,8 @@ WHERE {
|
|||
# Get existence
|
||||
OPTIONAL {?item wdt:P576 ?destroyed}
|
||||
OPTIONAL {?item wdt:P582 ?endTime}
|
||||
OPTIONAL {?item wdt:P3999 ?dateOfOfficialClosure}
|
||||
OPTIONAL {?item wdt:P585 ?pointInTime}
|
||||
|
||||
# Get Commons category
|
||||
OPTIONAL {?item wdt:P373 ?commonsCategory}
|
||||
|
|
|
|||
|
|
@ -262,15 +262,4 @@ class UploadActivityUnitTests {
|
|||
method.isAccessible = true
|
||||
method.invoke(activity)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun testOnBackPressed() {
|
||||
val method: Method =
|
||||
UploadActivity::class.java.getDeclaredMethod(
|
||||
"onBackPressed",
|
||||
)
|
||||
method.isAccessible = true
|
||||
method.invoke(activity)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue