Merge branch 'fix_share_and_save' into 'master'

Fix sharing and saving images & album crash on older Android versions

Closes #369, #371, and #372

See merge request pixeldroid/PixelDroid!562
This commit is contained in:
Matthieu 2024-01-03 15:44:38 +00:00
commit e108d08916
43 changed files with 138 additions and 996 deletions

View File

@ -27,7 +27,7 @@ android {
}
defaultConfig {
minSdkVersion 23
versionCode 25
versionCode 26
targetSdkVersion 34
versionName "1.0.beta" + versionCode
@ -221,9 +221,6 @@ dependencies {
implementation 'com.mikepenz:iconics-views:5.4.0'
implementation 'com.mikepenz:google-material-typeface:4.0.0.2-kotlin@aar'
implementation 'com.karumi:dexter:6.2.3'
implementation 'com.github.ligi:tracedroid:4.1'
implementation 'me.relex:circleindicator:2.1.6'

View File

@ -5,9 +5,9 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-feature
android:name="android.hardware.camera.any"

View File

@ -598,8 +598,8 @@ class PostCreationViewModel(
addPhotoButtonEnabled = (photoData.value?.size ?: 0) < (newMaxEntries ?: 0),
)
// Carousel off if in story mode
if (storyMode) newUiState = newUiState.copy(isCarousel = false)
// Carousel on if in story mode
if (storyMode) newUiState = newUiState.copy(isCarousel = true)
// If switching to story, and there are too many pictures, keep the first and backup the rest
if (storyMode && (photoData.value?.size ?: 0) > 1){

View File

@ -18,6 +18,9 @@ import androidx.recyclerview.widget.*
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ImageCarouselBinding
import me.relex.circleindicator.CircleIndicator2
import org.pixeldroid.common.dpToPx
import org.pixeldroid.common.getSnapPosition
import org.pixeldroid.common.spToPx
class ImageCarousel(
context: Context,

View File

@ -1,52 +0,0 @@
package org.pixeldroid.app.postCreation.carousel
import android.content.Context
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SnapHelper
/**
* This method converts device specific pixels to density independent pixels.
*/
fun Int.pxToDp(context: Context): Int {
return (this / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)).toInt()
}
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*/
fun Int.dpToPx(context: Context): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
this.toFloat(),
context.resources.displayMetrics
).toInt()
}
/**
* This method converts sp unit to equivalent pixels, depending on device density.
*/
fun Int.spToPx(context: Context): Int {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP,
this.toFloat(),
context.resources.displayMetrics
).toInt()
}
/**
* Get current snap item position of a recyclerView.
*
* @param layoutManager Target recyclerView
* @return Position of the item or RecyclerView.NO_POSITION (-1)
*/
fun SnapHelper.getSnapPosition(layoutManager: RecyclerView.LayoutManager?): Int {
if (layoutManager == null) {
return RecyclerView.NO_POSITION
}
val snapView: View = this.findSnapView(layoutManager) ?: return RecyclerView.NO_POSITION
return layoutManager.getPosition(snapView)
}

View File

@ -1,11 +1,13 @@
package org.pixeldroid.app.posts
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import org.pixeldroid.app.databinding.ActivityAlbumBinding
import org.pixeldroid.app.utils.api.objects.Attachment
class AlbumActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -36,4 +38,17 @@ class AlbumActivity : AppCompatActivity() {
supportActionBar?.setDisplayShowTitleEnabled(false)
supportActionBar?.setBackgroundDrawable(null)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
// Handle up arrow manually,
// since "up" isn't defined for this activity
onBackPressedDispatcher.onBackPressed()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}

View File

@ -5,7 +5,9 @@ import android.util.Log
import android.view.View
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ActivityPostBinding
import org.pixeldroid.app.posts.feeds.uncachedFeeds.comments.CommentFragment
@ -43,7 +45,10 @@ class PostActivity : BaseActivity() {
val holder = StatusViewHolder(binding.postFragmentSingle)
holder.bind(status, apiHolder, db, lifecycleScope, displayDimensionsInPx(), isActivity = true)
holder.bind(
status, apiHolder, db, lifecycleScope, displayDimensionsInPx(),
requestPermissionDownloadPic, isActivity = true
)
activateCommenter()
initCommentsFragment(domain = user?.instance_uri.orEmpty())
@ -60,6 +65,17 @@ class PostActivity : BaseActivity() {
}
}
private val requestPermissionDownloadPic =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (!isGranted) {
MaterialAlertDialogBuilder(this)
.setMessage(R.string.write_permission_download_pic)
.setNegativeButton(android.R.string.ok) { _, _ -> }
.show()
}
}
private fun activateCommenter() {
//Activate commenter
binding.submitComment.setOnClickListener {

View File

@ -1,14 +1,16 @@
package org.pixeldroid.app.posts
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.ClipData
import android.content.Intent
import android.content.pm.PackageManager.PERMISSION_DENIED
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.graphics.Typeface
import android.graphics.drawable.AnimatedVectorDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.os.Looper
import android.text.method.LinkMovementMethod
import android.util.Log
@ -17,6 +19,7 @@ import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
@ -36,10 +39,6 @@ import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.karumi.dexter.Dexter
import com.karumi.dexter.listener.PermissionDeniedResponse
import com.karumi.dexter.listener.PermissionGrantedResponse
import com.karumi.dexter.listener.single.BasePermissionListener
import kotlinx.coroutines.launch
import okhttp3.*
import okio.BufferedSink
@ -75,7 +74,11 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
private var status: Status? = null
fun bind(status: Status?, pixelfedAPI: PixelfedAPIHolder, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope, displayDimensionsInPx: Pair<Int, Int>, isActivity: Boolean = false) {
fun bind(
status: Status?, pixelfedAPI: PixelfedAPIHolder, db: AppDatabase,
lifecycleScope: LifecycleCoroutineScope, displayDimensionsInPx: Pair<Int, Int>,
requestPermissionDownloadPic: ActivityResultLauncher<String>, isActivity: Boolean = false
) {
this.itemView.visibility = View.VISIBLE
this.status = status
@ -104,7 +107,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
setupPost(picRequest, user.instance_uri, isActivity)
activateButtons(pixelfedAPI, db, lifecycleScope, isActivity)
activateButtons(pixelfedAPI, db, lifecycleScope, isActivity, requestPermissionDownloadPic)
}
@ -232,6 +235,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
db: AppDatabase,
lifecycleScope: LifecycleCoroutineScope,
isActivity: Boolean,
requestPermissionDownloadPic: ActivityResultLauncher<String>,
){
//Set the special HTML text
setDescription(apiHolder, lifecycleScope)
@ -261,7 +265,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
showComments(lifecycleScope, isActivity)
activateMoreButton(apiHolder, db, lifecycleScope)
activateMoreButton(apiHolder, db, lifecycleScope, requestPermissionDownloadPic)
}
private fun activateReblogger(
@ -363,7 +367,12 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
return null
}
private fun activateMoreButton(apiHolder: PixelfedAPIHolder, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope){
private fun activateMoreButton(
apiHolder: PixelfedAPIHolder,
db: AppDatabase,
lifecycleScope: LifecycleCoroutineScope,
requestPermissionDownloadPic: ActivityResultLauncher<String>
){
var bookmarked: Boolean? = null
binding.statusMore.setOnClickListener {
PopupMenu(it.context, it).apply {
@ -401,50 +410,29 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
true
}
R.id.post_more_menu_save_to_gallery -> {
Dexter.withContext(binding.root.context)
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(object : BasePermissionListener() {
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.write_permission_download_pic),
Toast.LENGTH_SHORT
).show()
}
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
status?.downloadImage(
binding.root.context,
status?.media_attachments?.getOrNull(binding.postPager.currentItem)?.url
?: "",
binding.root
)
}
}).check()
// Check permissions on old Android versions: on new versions it is not
// needed when storing a file.
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(binding.root.context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PERMISSION_DENIED) {
requestPermissionDownloadPic.launch(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
} else {
status?.downloadImage(
binding.root.context,
status?.media_attachments?.getOrNull(binding.postPager.currentItem)?.url
?: "",
binding.root
)
}
true
}
R.id.post_more_menu_share_picture -> {
Dexter.withContext(binding.root.context)
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(object : BasePermissionListener() {
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.write_permission_share_pic),
Toast.LENGTH_SHORT
).show()
}
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
status?.downloadImage(
binding.root.context,
status?.media_attachments?.getOrNull(binding.postPager.currentItem)?.url
?: "",
binding.root,
share = true,
)
}
}).check()
R.id.post_more_menu_share_picture -> {
status?.downloadImage(
binding.root.context,
status?.media_attachments?.getOrNull(binding.postPager.currentItem)?.url
?: "",
binding.root,
share = true,
)
true
}
R.id.post_more_menu_delete -> {

View File

@ -74,6 +74,7 @@ class PostFeedFragment<T: FeedContentDatabase>: CachedFeedFragment<T>() {
return view
}
inner class PostsAdapter(private val displayDimensionsInPx: Pair<Int, Int>) : PagingDataAdapter<T, RecyclerView.ViewHolder>(
object : DiffUtil.ItemCallback<T>() {
override fun areItemsTheSame (oldItem: T, newItem: T): Boolean = oldItem.id == newItem.id
@ -94,7 +95,9 @@ class PostFeedFragment<T: FeedContentDatabase>: CachedFeedFragment<T>() {
)
val uiModel = getItem(position) as Status?
uiModel?.let {
(holder as StatusViewHolder).bind(it, apiHolder, db, lifecycleScope, displayDimensionsInPx)
(holder as StatusViewHolder).bind(
it, apiHolder, db, lifecycleScope, displayDimensionsInPx, requestPermissionDownloadPic
)
}
}
}

View File

@ -85,7 +85,9 @@ class UncachedPostsFragment : UncachedFeedFragment<Status>() {
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
getItem(position)?.let {
(holder as StatusViewHolder).bind(it, apiHolder, db, lifecycleScope, displayDimensionsInPx)
(holder as StatusViewHolder).bind(
it, apiHolder, db, lifecycleScope, displayDimensionsInPx, requestPermissionDownloadPic
)
}
}
}

View File

@ -178,8 +178,10 @@ class ProfileFeedFragment : UncachedFeedFragment<FeedContent>() {
deleteFromCollection
)
} else {
(holder as StatusViewHolder).bind(it as Status, apiHolder, db,
lifecycleScope, requireContext().displayDimensionsInPx())
(holder as StatusViewHolder).bind(
it as Status, apiHolder, db, lifecycleScope,
requireContext().displayDimensionsInPx(), requestPermissionDownloadPic
)
}
}

View File

@ -1,7 +1,10 @@
package org.pixeldroid.app.utils
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.pixeldroid.app.R
import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.di.PixelfedAPIHolder
import javax.inject.Inject
@ -22,4 +25,18 @@ open class BaseFragment: Fragment() {
(requireActivity().application as PixelDroidApplication).getAppComponent().inject(this)
}
internal val requestPermissionDownloadPic =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (!isGranted) {
context?.let {
MaterialAlertDialogBuilder(it)
.setMessage(R.string.write_permission_download_pic)
.setNegativeButton(android.R.string.ok) { _, _ -> }
.show()
}
}
}
}

View File

@ -1,8 +1,10 @@
package org.pixeldroid.app.utils.api.objects
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.DownloadManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.database.Cursor
import android.net.Uri
import android.os.Environment
@ -11,6 +13,7 @@ import androidx.core.net.toUri
import com.google.android.material.snackbar.Snackbar
import org.pixeldroid.app.R
import org.pixeldroid.app.posts.getDomain
import org.pixeldroid.app.utils.getMimeType
import java.io.File
import java.io.Serializable
import java.time.Instant
@ -148,11 +151,13 @@ open class Status(
)
val file = path.toUri()
val shareIntent: Intent = Intent.createChooser(Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, file)
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
type = "image/$ext"
type = file.getMimeType(context.contentResolver)
}, null)
context.startActivity(shareIntent)

View File

@ -1,8 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="201.8771"
android:viewportHeight="218.8104"
android:width="254dp"
android:height="275dp">
android:viewportWidth="403.75"
android:viewportHeight="437.6"
android:width="100dp"
android:height="108dp">
<group android:translateX="100"
android:translateY="115">
<group
android:translateX="-1.41459"
android:translateY="-24.00768">
@ -808,4 +811,5 @@
android:strokeColor="#000000"
android:strokeWidth="1.32292"
android:strokeLineCap="round" />
</group>
</vector>

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,9 @@
<ImageView
android:id="@+id/mascotImage"
android:layout_width="match_parent"
android:layout_width="508dp"
android:layout_marginTop="-130dp"
android:adjustViewBounds="true"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:contentDescription="@string/mascot_description"
@ -30,6 +32,7 @@
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/login_activity_instance_input_layout"
android:layout_width="250dp"
android:layout_marginTop="-130dp"
android:layout_height="wrap_content"
android:gravity="center"
android:hint="@string/domain_of_your_instance"

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@drawable/mascot" />

View File

@ -52,7 +52,6 @@
<string name="comment_posted">التعليق: تم نشر%1$s!</string>
<string name="comment_error">خطأ في التعليق!</string>
<string name="share_image">مشاركة الصورة</string>
<string name="write_permission_share_pic">يجب عليك منح تصريح للكتابة قصد مشاركة الصور!</string>
<string name="write_permission_download_pic">تحتاج إلى منح إذن الكتابة لتنزيل الصور!</string>
<string name="empty_comment">لا يجب ان يكون التعليق فارغًا!</string>
<string name="posted_on">نُشِر في %1$s</string>

View File

@ -60,7 +60,6 @@
<string name="comment_posted">Comentari: %1$s publicat!</string>
<string name="comment_error">Error de comentari!</string>
<string name="share_image">Compartir imatge</string>
<string name="write_permission_share_pic">Necessites concedir permís descriptura per compartir imatges!</string>
<string name="write_permission_download_pic">Has de concedir permís descriptura per baixar imatges!</string>
<string name="empty_comment">El comentari no ha de estar buit!</string>
<string name="posted_on">Publica\'t el %1$s</string>

View File

@ -69,7 +69,6 @@
<string name="posted_on">Zveřejněno na %1$s</string>
<string name="NoCommentsToShow">U tohoto příspěvku nejsou žádné komentáře…</string>
<string name="empty_comment">Komentář nesmí být prázdný!</string>
<string name="write_permission_share_pic">Pro sdílení obrázků musíte udělit práva k zápisu!</string>
<string name="share_image">Sdílet obrázek</string>
<string name="comment_error">Chyba komentáře!</string>
<string name="comment_posted">Komentář: %1$s zveřejněn!</string>

View File

@ -79,7 +79,6 @@
<string name="feed_failed">Feed konnte nicht geladen werden</string>
<string name="posted_on">Erstellt am %1$s</string>
<string name="write_permission_download_pic">Für das Herunterladen von Bildern müssen Sie eine Schreibgenehmigung erteilen!</string>
<string name="write_permission_share_pic">Für die Teilen von Bildern müssen Sie eine Schreibgenehmigung erteilen!</string>
<string name="follow_status_failed">Konnte den Folgestatus nicht erhalten</string>
<string name="retry">Wiederholen</string>
<string name="nothing_to_see_here">Hier gibt\'s nichts zu sehen!</string>

View File

@ -64,7 +64,6 @@
<string name="comment_posted">¡Comentario: %1$s publicado!</string>
<string name="comment_error">¡Error al comentar!</string>
<string name="share_image">Compartir imagen</string>
<string name="write_permission_share_pic">¡Tienes que dar permiso de escritura para compartir fotos!</string>
<string name="write_permission_download_pic">¡Tienes que dar permiso de escritura para descargar fotos!</string>
<string name="empty_comment">¡Los comentarios no deben estar vacíos!</string>
<string name="posted_on">Publicado en %1$s</string>

View File

@ -76,7 +76,6 @@
<string name="follow_button_failed">Ezin izan da jarraipen-botoia erakutsi</string>
<string name="follow_status_failed">Ezin izan da segimendu-egoera lortu</string>
<string name="comment">Iruzkin</string>
<string name="write_permission_share_pic">Idazteko baimena eman behar duzu argazkiak partekatzeko!</string>
<string name="posted_on">%1$s(e)n argitaratua</string>
<string name="hashtags">TRAOLAK</string>
<string name="accounts">KONTUAK</string>

View File

@ -56,7 +56,6 @@
<string name="posted_on">منتشر شده در %1$s</string>
<string name="empty_comment">نظر نمی‌تواند خالی باشد!</string>
<string name="write_permission_download_pic">برای بارگیری تصاویر بایستی مجوز نوشتن را بدهید!</string>
<string name="write_permission_share_pic">برای هم‌رسانی تصاویر باید مجوز نوشتن را بدهید!</string>
<string name="share_image">هم‌رسانی تصویر</string>
<string name="comment_error">خطا در درج نظر!</string>
<string name="comment_posted">نظر: %1$s منتشر کرد!</string>

View File

@ -49,8 +49,7 @@
<string name="upload_post_success">Téléversement de la publication avec succès</string>
<string name="posted_on">Publié le %1$s</string>
<string name="empty_comment">Le commentaire ne doit pas être vide !</string>
<string name="write_permission_share_pic">Vous devez accorder une autorisation d\'écriture pour partager des photos !</string>
<string name="default_nfollowers">-
<string name="default_nfollowers">-
\nAbonné·e·s</string>
<string name="upload_post_error">Le téléversement de la publication a échoué</string>
<string name="loading_toast">Une erreur s\'est produite lors du chargement</string>

View File

@ -61,7 +61,6 @@
<string name="comment_posted">Comentario: %1$s publicado!</string>
<string name="comment_error">Fallo ao comentar!</string>
<string name="share_image">Compartir Imaxe</string>
<string name="write_permission_share_pic">Tes que dar permiso de escritura para compartir fotos!</string>
<string name="write_permission_download_pic">Tes que conceder permiso de escritura para descargar fotos!</string>
<string name="empty_comment">O comentario non debe quedar baleiro!</string>
<string name="posted_on">Publicado o %1$s</string>

View File

@ -106,7 +106,6 @@
<string name="comment_posted">Hozzászólás: %1$s közzétéve!</string>
<string name="comment_error">Hozzászólási hiba!</string>
<string name="share_image">Kép megosztása</string>
<string name="write_permission_share_pic">Írási engedélyt kell adnia a képek megosztásához!</string>
<string name="write_permission_download_pic">Írási engedélyt kell adnia a képek letöltéséhez!</string>
<string name="empty_comment">A hozzászólás nem lehet üres!</string>
<string name="NoCommentsToShow">Nincsenek hozzászólások a bejegyzésnél…</string>

View File

@ -53,7 +53,6 @@
<string name="no_description">Nessuna descrizione</string>
<string name="posted_on">Postato su %1$s</string>
<string name="empty_comment">Il commento non deve essere vuoto!</string>
<string name="write_permission_share_pic">È necessario concedere i permessi di scrittura per condividere le immagini!</string>
<string name="share_image">Condividi immagine</string>
<string name="comment_error">Errore nel commento!</string>
<string name="comment_posted">Commento: %1$s postato!</string>

View File

@ -39,7 +39,6 @@
<string name="instance_error">インスタンス情報が取得できませんでした</string>
<string name="posted_on">%1$s の投稿</string>
<string name="accounts">アカウント</string>
<string name="write_permission_share_pic">画像を共有するためには書き込みの権限を更新する必要があります</string>
<string name="write_permission_download_pic">画像をダウンロードするには書き込みの権限を更新する必要があります</string>
<string name="empty_comment">コメントは空欄にできません</string>
<string name="comment_posted">コメント: %1$s が投稿されました</string>

View File

@ -100,7 +100,6 @@
<string name="api_not_enabled_dialog">എപിഐ ഈ ഇൻസ്റ്റൻസിൽ സജീവമല്ലാ.ഇത് സജീവമാക്കാൻ നിങ്ങളുടെ അഡ്മിനിസ്ട്രേറ്ററെ ബന്ധപ്പെടുക.</string>
<string name="feed_failed">ഫീഡ് ലഭ്യമാക്കാൻ സാധിച്ചില്ല</string>
<string name="write_permission_download_pic">ചിത്രങ്ങൾ ഡൗൺലോഡ് ചെയ്യാൻ നിങ്ങൾ എഴുത്ത് അനുമതി നൽകണം!</string>
<string name="write_permission_share_pic">ചിത്രങ്ങൾ പങ്കിടാൻ നിങ്ങൾ എഴുത്ത് അനുമതി നൽകണം!</string>
<plurals name="number_comments">
<item quantity="one">%d</item>
<item quantity="other"></item>

View File

@ -70,7 +70,6 @@
<string name="comment_posted">Commentaar: %1$s gepost!</string>
<string name="comment_error">Fout met commentaar!</string>
<string name="share_image">Afbeelding delen</string>
<string name="write_permission_share_pic">Je moet schrijven toestaan om afbeeldingen te delen!</string>
<string name="write_permission_download_pic">Je moet schrijven toestaan om afbeeldingen te downloaden!</string>
<string name="follow_status_failed">Kon volgstatus niet ophalen</string>
<string name="follow_error">Kon niet volgen</string>

View File

@ -40,7 +40,6 @@
<string name="no_description">Bez opisu</string>
<string name="posted_on">Opublikowano %1$s</string>
<string name="empty_comment">Komentarz nie może być pusty!</string>
<string name="write_permission_share_pic">Musisz nadać uprawnienia do zapisu, aby móc udostępniać obrazki!</string>
<string name="share_image">Udostępnij</string>
<string name="comment_error">Błąd komentarza!</string>
<string name="comment_posted">Komentarz: %1$s opublikowany!</string>

View File

@ -146,7 +146,6 @@
<string name="switch_to_grid">Mudar para visualização em grade</string>
<string name="comment_posted">Comentário: %1$s publicado!</string>
<string name="comment_error">Erro no comentário!</string>
<string name="write_permission_share_pic">Você precisa conceder permissão de gravação para compartilhar imagens!</string>
<string name="language">Idioma</string>
<string name="delete_dialog">Excluir esta publicação\?</string>
<string name="something_went_wrong">Algo deu errado…</string>

View File

@ -84,7 +84,6 @@
<string name="share_image">Partilhar imagem</string>
<string name="comment_error">Erro ao comentar!</string>
<string name="write_permission_download_pic">Precisa adicionar a permissão para transferir imagens!</string>
<string name="write_permission_share_pic">Precisa adicionar permissão para partilhar imagens!</string>
<string name="comment_posted">Comentário: %1$s publicou!</string>
<string name="comment">Comentário</string>
<string name="add_comment">Adicionar um comentário</string>

View File

@ -42,7 +42,6 @@
<string name="comment_error">Ошибка комментирования!</string>
<string name="share_image">Поделиться изображением</string>
<string name="write_permission_download_pic">Вам необходимо предоставить разрешение на запись чтобы скачивать фотографии!</string>
<string name="write_permission_share_pic">Вы должны дать разрешение на запись чтобы делиться фотографиями!</string>
<string name="empty_comment">Комментарий не должен быть пустым!</string>
<string name="posted_on">Опубликовано в %1$s</string>
<string name="no_description">Описание отсутствует</string>

View File

@ -64,7 +64,6 @@
<string name="comment_posted">Kommentar: %1$s inlagd!</string>
<string name="comment_error">Kommentarsfel!</string>
<string name="share_image">Dela bild</string>
<string name="write_permission_share_pic">Du måste tillåta skrivrättigheter för att dela bilder!</string>
<string name="write_permission_download_pic">Du måste tillåta skrivrättigheter för att ladda ned bilder!</string>
<string name="empty_comment">Kommentaren får inte vara tom!</string>
<string name="posted_on">Inlagt på %1$s</string>

View File

@ -165,7 +165,6 @@
<string name="share_image">Поширити зображення</string>
<string name="liked_notification">%1$s хвалить ваш допис</string>
<string name="file_not_found">Файлу %1$s не знайдено</string>
<string name="write_permission_share_pic">Для поширення зображень потрібен дозвіл на запис!</string>
<string name="picture_format_error">Помилка вивантаження: хибний формат зображення.</string>
<string name="unfollow">Відписатись</string>
<string name="media_upload_failed">Не вдалося вивантажити медіа, повторіть спробу чи перевірте мережне з\'єднання</string>

View File

@ -64,7 +64,6 @@
<string name="comment_posted">评论: %1$s 已发布!</string>
<string name="comment_error">评论错误!</string>
<string name="share_image">分享图像</string>
<string name="write_permission_share_pic">您需要允许读写权限才能共享图片!</string>
<string name="write_permission_download_pic">您需要允许读写权限才能下载图片!</string>
<string name="empty_comment">评论不能为空!</string>
<string name="posted_on">发表于 %1$s</string>

View File

@ -150,7 +150,6 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="NoCommentsToShow">No comments on this post…</string>
<string name="empty_comment">Comment must not be empty!</string>
<string name="write_permission_download_pic">You need to grant write permission to download pictures!</string>
<string name="write_permission_share_pic">You need to grant write permission to share pictures!</string>
<string name="share_image">Share Image</string>
<string name="comment_error">Comment error!</string>
<string name="comment_posted">"Comment: %1$s posted!"</string>

View File

@ -1,14 +1,12 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<resources>
<!-- Splash screen theme. -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<!-- Set the splash screen background, animated icon, and animation duration. -->
<item name="windowSplashScreenBackground">?android:attr/colorBackground</item>
<!-- Use windowSplashScreenAnimatedIcon to add either a drawable or an
animated drawable. One of these is required. -->
<!-- TODO get rid of duplicated mascot/mascot_small somehow -->
<item name="windowSplashScreenAnimatedIcon">@drawable/mascot_small</item>
animated drawable. One of these is required.-->
<item name="windowSplashScreenAnimatedIcon">@drawable/mascot</item>
<!-- Set the theme of the Activity that directly follows your splash screen. -->
<!-- Required -->
@ -16,35 +14,4 @@
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.PopupOverlay" parent="Theme.Material3.Light" />
<style name="AppTheme.ActionBar.Transparent" parent="Theme.Material3.Dark">
<item name="android:windowLayoutInDisplayCutoutMode" tools:targetApi="o_mr1">always</item>
<item name="colorPrimary">@android:color/transparent</item>
<item name="colorPrimaryDark">@android:color/transparent</item>
<item name="colorPrimaryVariant">@android:color/transparent</item>
<item name="colorAccent">@android:color/transparent</item>
<item name="colorSecondary">@android:color/transparent</item>
<item name="statusBarForeground">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:toolbarStyle">@style/ToolbarTransparent</item>
<item name="toolbarStyle">@style/ToolbarTransparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="statusBarBackground">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
<style name="ToolbarTransparent" parent="Widget.Material3.Toolbar">
<item name="android:background">@android:color/transparent</item>
<item name="background">@android:color/transparent</item>
</style>
</resources>

View File

@ -53,7 +53,12 @@
android:targetPackage="@string/application_id"
android:targetClass="org.pixeldroid.common.AboutActivity">
<extra android:name="buildVersion" android:value="@string/versionName" />
<extra android:name="appImage" android:value="@drawable/mascot" />
<extra android:name="appImage" android:value="mascot" />
<extra android:name="appImageWidth" android:value="508" />
<extra android:name="appImageTopMargin" android:value="-130" />
<extra android:name="appImageBottomMargin" android:value="-130" />
<extra android:name="appImageLeftMargin" android:value="0" />
<extra android:name="appImageRightMargin" android:value="0" />
<extra android:name="appName" android:value="@string/app_name" />
<extra android:name="aboutAppDescription" android:value="@string/license_info" />
<extra android:name="website" android:value="@string/project_website" />

View File

@ -0,0 +1 @@
Bug fixes & improvements ;)

@ -1 +1 @@
Subproject commit 037995fc3c9a40c30ab22b199cdc4b7d43ca1976
Subproject commit a390dc0685eba3dfe18f57fd878f15fda52cc95b