Merge branch 'maintenance' into 'master'

Reduce technical debt and improve code, remove hardcoded strings

See merge request pixeldroid/PixelDroid!454
This commit is contained in:
Matthieu 2022-07-28 19:37:26 +00:00
commit 5158c2b1c0
38 changed files with 231 additions and 378 deletions

View File

@ -303,7 +303,6 @@ class LoginActivity : BaseThemedWithoutBarActivity() {
} }
} }
@OptIn(ExperimentalPagingApi::class)
private suspend fun storeUser(accessToken: String, refreshToken: String?, clientId: String, clientSecret: String, instance: String) { private suspend fun storeUser(accessToken: String, refreshToken: String?, clientId: String, clientSecret: String, instance: String) {
try { try {
val user = pixelfedAPI.verifyCredentials("Bearer $accessToken") val user = pixelfedAPI.verifyCredentials("Bearer $accessToken")

View File

@ -62,7 +62,6 @@ class MainActivity : BaseThemedWithoutBarActivity() {
companion object { companion object {
const val ADD_ACCOUNT_IDENTIFIER: Long = -13 const val ADD_ACCOUNT_IDENTIFIER: Long = -13
const val LOG_OUT_REQUESTED = "LOG_OUT_REQUESTED"
} }
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding

View File

@ -13,6 +13,7 @@ import android.util.Log
import android.view.View import android.view.View
import android.view.View.INVISIBLE import android.view.View.INVISIBLE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.View.GONE
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.ActivityResult import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
@ -195,7 +196,7 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
model.setImages(model.addPossibleImages(it)) model.setImages(model.addPossibleImages(it))
} }
} else if (result.resultCode != Activity.RESULT_CANCELED) { } else if (result.resultCode != Activity.RESULT_CANCELED) {
Toast.makeText(applicationContext, "Error while adding images", Toast.LENGTH_SHORT).show() Toast.makeText(applicationContext, R.string.add_images_error, Toast.LENGTH_SHORT).show()
} }
} }
@ -296,11 +297,11 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
private fun enableButton(enable: Boolean = true){ private fun enableButton(enable: Boolean = true){
binding.postCreationSendButton.isEnabled = enable binding.postCreationSendButton.isEnabled = enable
if(enable){ if(enable){
binding.postingProgressBar.visibility = View.GONE binding.postingProgressBar.visibility = GONE
binding.postCreationSendButton.visibility = View.VISIBLE binding.postCreationSendButton.visibility = VISIBLE
} else { } else {
binding.postingProgressBar.visibility = View.VISIBLE binding.postingProgressBar.visibility = VISIBLE
binding.postCreationSendButton.visibility = View.GONE binding.postCreationSendButton.visibility = GONE
} }
} }
@ -310,9 +311,9 @@ class PostCreationActivity : BaseThemedWithoutBarActivity() {
if (result?.resultCode == Activity.RESULT_OK && result.data != null) { if (result?.resultCode == Activity.RESULT_OK && result.data != null) {
val position: Int = result.data!!.getIntExtra(PhotoEditActivity.PICTURE_POSITION, 0) val position: Int = result.data!!.getIntExtra(PhotoEditActivity.PICTURE_POSITION, 0)
model.modifyAt(position, result.data!!) model.modifyAt(position, result.data!!)
?: Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show() ?: Toast.makeText(applicationContext, R.string.error_editing, Toast.LENGTH_SHORT).show()
} else if(result?.resultCode != Activity.RESULT_CANCELED){ } else if(result?.resultCode != Activity.RESULT_CANCELED){
Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show() Toast.makeText(applicationContext, R.string.error_editing, Toast.LENGTH_SHORT).show()
} }
} }

View File

@ -248,7 +248,8 @@ class PostCreationViewModel(application: Application, clipdata: ClipData? = null
return return
} }
val imagePart = ProgressRequestBody(imageInputStream, data.size) val type = imageUri.getMimeType(getApplication<PixelDroidApplication>().contentResolver)
val imagePart = ProgressRequestBody(imageInputStream, data.size, type)
val requestBody = MultipartBody.Builder() val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
.addFormDataPart("file", System.currentTimeMillis().toString(), imagePart) .addFormDataPart("file", System.currentTimeMillis().toString(), imagePart)

View File

@ -8,7 +8,7 @@ import okhttp3.RequestBody
import okio.BufferedSink import okio.BufferedSink
import java.io.* import java.io.*
class ProgressRequestBody(private val mFile: InputStream, private val length: Long) : RequestBody() { class ProgressRequestBody(private val mFile: InputStream, private val length: Long, private val type: String) : RequestBody() {
private val getProgressSubject: PublishSubject<Float> = PublishSubject.create() private val getProgressSubject: PublishSubject<Float> = PublishSubject.create()
@ -18,7 +18,7 @@ class ProgressRequestBody(private val mFile: InputStream, private val length: Lo
} }
override fun contentType(): MediaType? { override fun contentType(): MediaType? {
return "image/png".toMediaTypeOrNull() return type.toMediaTypeOrNull()
} }
@Throws(IOException::class) @Throws(IOException::class)

View File

@ -3,7 +3,6 @@ package org.pixeldroid.app.postCreation
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.RelativeLayout
internal class SquareLayout(context: Context, attrs: AttributeSet) : internal class SquareLayout(context: Context, attrs: AttributeSet) :
FrameLayout(context, attrs) { FrameLayout(context, attrs) {

View File

@ -25,14 +25,15 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.view.setPadding import androidx.core.view.setPadding
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.FragmentCameraBinding import org.pixeldroid.app.databinding.FragmentCameraBinding
import org.pixeldroid.app.postCreation.PostCreationActivity import org.pixeldroid.app.postCreation.PostCreationActivity
import org.pixeldroid.app.utils.BaseFragment
import java.io.File import java.io.File
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
@ -40,8 +41,6 @@ import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlin.properties.Delegates import kotlin.properties.Delegates
import org.pixeldroid.app.R
import org.pixeldroid.app.utils.BaseFragment
private const val ANIMATION_FAST_MILLIS = 50L private const val ANIMATION_FAST_MILLIS = 50L
private const val ANIMATION_SLOW_MILLIS = 100L private const val ANIMATION_SLOW_MILLIS = 100L

View File

@ -7,14 +7,12 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.SeekBar import android.widget.SeekBar
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.FragmentEditImageBinding
class EditImageFragment : Fragment(), SeekBar.OnSeekBarChangeListener { class EditImageFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
private var listener: PhotoEditActivity? = null private var listener: PhotoEditActivity? = null
private lateinit var binding: FragmentEditImageBinding
private lateinit var seekbarBrightness: SeekBar
private lateinit var seekbarSaturation: SeekBar
private lateinit var seekbarContrast: SeekBar
private var BRIGHTNESS_MAX = 200 private var BRIGHTNESS_MAX = 200
private var SATURATION_MAX = 20 private var SATURATION_MAX = 20
@ -26,32 +24,28 @@ class EditImageFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View {
// Inflate the layout for this fragment // Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_edit_image, container, false) binding = FragmentEditImageBinding.inflate(inflater, container, false)
seekbarBrightness = view.findViewById(R.id.seekbar_brightness) binding.seekbarBrightness.max = BRIGHTNESS_MAX
seekbarSaturation = view.findViewById(R.id.seekbar_saturation) binding.seekbarBrightness.progress = BRIGHTNESS_START
seekbarContrast = view.findViewById(R.id.seekbar_contrast)
seekbarBrightness.max = BRIGHTNESS_MAX binding.seekbarContrast.max = CONTRAST_MAX
seekbarBrightness.progress = BRIGHTNESS_START binding.seekbarContrast.progress = CONTRAST_START
seekbarContrast.max = CONTRAST_MAX binding.seekbarSaturation.max = SATURATION_MAX
seekbarContrast.progress = CONTRAST_START binding.seekbarSaturation.progress = SATURATION_START
seekbarSaturation.max = SATURATION_MAX
seekbarSaturation.progress = SATURATION_START
setOnSeekBarChangeListeners(this) setOnSeekBarChangeListeners(this)
return view return binding.root
} }
private fun setOnSeekBarChangeListeners(listener: EditImageFragment?){ private fun setOnSeekBarChangeListeners(listener: EditImageFragment?){
seekbarBrightness.setOnSeekBarChangeListener(listener) binding.seekbarBrightness.setOnSeekBarChangeListener(listener)
seekbarContrast.setOnSeekBarChangeListener(listener) binding.seekbarContrast.setOnSeekBarChangeListener(listener)
seekbarSaturation.setOnSeekBarChangeListener(listener) binding.seekbarSaturation.setOnSeekBarChangeListener(listener)
} }
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
@ -75,9 +69,9 @@ class EditImageFragment : Fragment(), SeekBar.OnSeekBarChangeListener {
// Make sure to ignore seekbar change events, since we don't want to have the reset cause // Make sure to ignore seekbar change events, since we don't want to have the reset cause
// filter applications due to the onProgressChanged calls // filter applications due to the onProgressChanged calls
setOnSeekBarChangeListeners(null) setOnSeekBarChangeListeners(null)
seekbarBrightness.progress = BRIGHTNESS_START binding.seekbarBrightness.progress = BRIGHTNESS_START
seekbarContrast.progress = CONTRAST_START binding.seekbarContrast.progress = CONTRAST_START
seekbarSaturation.progress = SATURATION_START binding.seekbarSaturation.progress = SATURATION_START
setOnSeekBarChangeListeners(this) setOnSeekBarChangeListeners(this)
} }

View File

@ -1,25 +0,0 @@
package org.pixeldroid.app.postCreation.photoEdit
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
class EditPhotoViewPagerAdapter (manager: FragmentManager):
FragmentPagerAdapter(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private val fragmentList = ArrayList<Fragment>()
private val fragmentTitleList = ArrayList<String>()
override fun getItem(position: Int) = fragmentList[position]
override fun getCount() = fragmentList.size
fun addFragment(fragment: Fragment, title: String) {
fragmentList.add(fragment)
fragmentTitleList.add(title)
}
override fun getPageTitle(position: Int): CharSequence {
return fragmentTitleList[position]
}
}

View File

@ -1,75 +1,64 @@
package org.pixeldroid.app.postCreation.photoEdit package org.pixeldroid.app.postCreation.photoEdit
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.ImageDecoder
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore
import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.pixeldroid.app.R
import com.zomato.photofilters.FilterPack import com.zomato.photofilters.FilterPack
import com.zomato.photofilters.imageprocessors.Filter import com.zomato.photofilters.imageprocessors.Filter
import com.zomato.photofilters.utils.ThumbnailItem import com.zomato.photofilters.utils.ThumbnailItem
import com.zomato.photofilters.utils.ThumbnailsManager import com.zomato.photofilters.utils.ThumbnailsManager
import kotlinx.coroutines.launch
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.FragmentFilterListBinding
import org.pixeldroid.app.utils.bitmapFromUri import org.pixeldroid.app.utils.bitmapFromUri
class FilterListFragment : Fragment() { class FilterListFragment : Fragment() {
private lateinit var recyclerView: RecyclerView private lateinit var binding: FragmentFilterListBinding
private var listener : PhotoEditActivity? = null
private var listener : ((Filter) -> Unit)? = null
internal lateinit var adapter: ThumbnailAdapter internal lateinit var adapter: ThumbnailAdapter
private lateinit var tbItemList: MutableList<ThumbnailItem> private lateinit var tbItemList: MutableList<ThumbnailItem>
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View {
// Inflate the layout for this fragment // Inflate the layout for this fragment
val view = inflater.inflate(R.layout.fragment_filter_list, container, false) binding = FragmentFilterListBinding.inflate(inflater, container, false)
tbItemList = ArrayList() tbItemList = ArrayList()
recyclerView = view.findViewById(R.id.recycler_view) binding.recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.HORIZONTAL, false)
recyclerView.itemAnimator = DefaultItemAnimator()
val space = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics).toInt()
recyclerView.addItemDecoration(SpaceItemDecoration(space))
adapter = ThumbnailAdapter(requireActivity(), tbItemList, this) adapter = ThumbnailAdapter(requireActivity(), tbItemList, this)
recyclerView.adapter = adapter binding.recyclerView.adapter = adapter
return view return binding.root
} }
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onViewCreated(view, savedInstanceState)
displayImage(null) displayImage()
} }
private fun displayImage(bitmap: Bitmap?) { private fun displayImage() {
val r = Runnable { viewLifecycleOwner.lifecycleScope.launch {
val tbImage: Bitmap = (if (bitmap == null) { viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) {
bitmapFromUri(requireActivity().contentResolver, PhotoEditActivity.imageUri) val tbImage: Bitmap = bitmapFromUri(requireActivity().contentResolver, PhotoEditActivity.imageUri)
} else { setupFilter(tbImage)
Bitmap.createScaledBitmap(bitmap, 100, 100, false)
})
?: return@Runnable
if(activity != null) setupFilter(tbImage) tbItemList.addAll(ThumbnailsManager.processThumbs(context))
adapter.notifyDataSetChanged()
if(context != null) tbItemList.addAll(ThumbnailsManager.processThumbs(context)) }
activity?.runOnUiThread{ adapter.notifyDataSetChanged() }
} }
Thread(r).start()
} }
private fun setupFilter(tbImage: Bitmap?) { private fun setupFilter(tbImage: Bitmap?) {
@ -95,14 +84,13 @@ class FilterListFragment : Fragment() {
fun resetSelectedFilter(){ fun resetSelectedFilter(){
adapter.resetSelected() adapter.resetSelected()
displayImage(null)
} }
fun onFilterSelected(filter: Filter) { fun onFilterSelected(filter: Filter) {
listener?.onFilterSelected(filter) listener?.invoke(filter)
} }
fun setListener(listFragmentListener: PhotoEditActivity) { fun setListener(listFragmentListener: (filter: Filter) -> Unit) {
this.listener = listFragmentListener this.listener = listFragmentListener
} }
} }

View File

@ -1,43 +0,0 @@
package org.pixeldroid.app.postCreation.photoEdit
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.animation.DecelerateInterpolator
import android.widget.Scroller
import androidx.viewpager.widget.ViewPager
class NonSwipeableViewPager: ViewPager {
constructor(context: Context):super(context) {
setMyScroller()
}
constructor(context: Context,attributeSet: AttributeSet): super(context, attributeSet) {
setMyScroller()
}
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
return false
}
override fun onTouchEvent(ev: MotionEvent?): Boolean {
return false
}
private fun setMyScroller() {
try {
val viewPager = ViewPager::class.java
val scroller = viewPager.getDeclaredField("mScroller")
scroller.isAccessible = true
scroller.set(this, FilterScroller(context))
} catch (e:Exception) {
e.printStackTrace()
}
}
}
class FilterScroller(context: Context): Scroller(context, DecelerateInterpolator()) {
override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int, duration: Int) {
super.startScroll(startX, startY, dx, dy, 400)
}
}

View File

@ -5,12 +5,10 @@ import android.app.AlertDialog
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Point import android.graphics.Point
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View.GONE import android.view.View.GONE
@ -18,9 +16,12 @@ import android.view.View.VISIBLE
import android.widget.Toast import android.widget.Toast
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayoutMediator
import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop
import com.zomato.photofilters.imageprocessors.Filter import com.zomato.photofilters.imageprocessors.Filter
import com.zomato.photofilters.imageprocessors.subfilters.BrightnessSubFilter import com.zomato.photofilters.imageprocessors.subfilters.BrightnessSubFilter
@ -115,7 +116,6 @@ class PhotoEditActivity : BaseThemedWithBarActivity() {
loadImage() loadImage()
setupViewPager(binding.viewPager) setupViewPager(binding.viewPager)
binding.tabs.setupWithViewPager(binding.viewPager)
} }
private fun loadImage() { private fun loadImage() {
@ -137,18 +137,36 @@ class PhotoEditActivity : BaseThemedWithBarActivity() {
return Bitmap.createScaledBitmap(image, (image.width * scale).toInt(), newY.toInt(), true) return Bitmap.createScaledBitmap(image, (image.width * scale).toInt(), newY.toInt(), true)
} }
private fun setupViewPager(viewPager: NonSwipeableViewPager?) { private fun setupViewPager(viewPager: ViewPager2) {
val adapter = EditPhotoViewPagerAdapter(supportFragmentManager)
filterListFragment = FilterListFragment() filterListFragment = FilterListFragment()
filterListFragment.setListener(this) filterListFragment.setListener(::onFilterSelected)
editImageFragment = EditImageFragment() editImageFragment = EditImageFragment()
editImageFragment.setListener(this) editImageFragment.setListener(this)
adapter.addFragment(filterListFragment, "FILTERS")
adapter.addFragment(editImageFragment, "EDIT")
viewPager!!.adapter = adapter val tabs: List<() -> Fragment> = listOf({ filterListFragment }, { editImageFragment })
// Keep both tabs loaded at all times because values are needed there
viewPager.offscreenPageLimit = 1
//Disable swiping in viewpager
viewPager.isUserInputEnabled = false
viewPager.adapter = object : FragmentStateAdapter(this) {
override fun createFragment(position: Int): Fragment {
return tabs[position]()
}
override fun getItemCount(): Int {
return tabs.size
}
}
TabLayoutMediator(binding.tabs, viewPager) { tab, position ->
tab.setText(when(position) {
0 -> R.string.tab_filters
else -> R.string.edit
})
}.attach()
} }
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {

View File

@ -1,22 +0,0 @@
package org.pixeldroid.app.postCreation.photoEdit
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class SpaceItemDecoration(private val space: Int): RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
if (parent.getChildAdapterPosition(view) == state.itemCount - 1) {
outRect.left = space
outRect.right = 0
} else {
outRect.left = 0
outRect.right = space
}
}
}

View File

@ -5,11 +5,10 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.zomato.photofilters.utils.ThumbnailItem
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ThumbnailListItemBinding import org.pixeldroid.app.databinding.ThumbnailListItemBinding
import com.zomato.photofilters.utils.ThumbnailItem
import org.pixeldroid.app.utils.getColorFromAttr import org.pixeldroid.app.utils.getColorFromAttr
class ThumbnailAdapter (private val context: Context, class ThumbnailAdapter (private val context: Context,

View File

@ -36,6 +36,6 @@ class AlbumActivity : BaseActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(false) supportActionBar?.setDisplayShowTitleEnabled(false)
supportActionBar?.setBackgroundDrawable(null) supportActionBar?.setBackgroundDrawable(null)
window.statusBarColor = ContextCompat.getColor(this,android.R.color.transparent); window.statusBarColor = ContextCompat.getColor(this,android.R.color.transparent)
} }
} }

View File

@ -7,7 +7,6 @@ import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
import android.text.style.ClickableSpan import android.text.style.ClickableSpan
import android.text.style.URLSpan import android.text.style.URLSpan
import android.util.Log
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import androidx.core.text.toSpanned import androidx.core.text.toSpanned
@ -22,7 +21,6 @@ import java.net.URI
import java.net.URISyntaxException import java.net.URISyntaxException
import java.text.ParseException import java.text.ParseException
import java.time.Instant import java.time.Instant
import java.time.ZoneOffset
import java.util.* import java.util.*
fun fromHtml(html: String): Spanned { fun fromHtml(html: String): Spanned {

View File

@ -38,7 +38,7 @@ class NestedScrollableHost(context: Context, attrs: AttributeSet? = null) :
} }
var images: ArrayList<Attachment> = ArrayList(); var images: ArrayList<Attachment> = ArrayList()
var doubleTapCallback: (() -> Unit)? = null var doubleTapCallback: (() -> Unit)? = null
private val child: View? get() = if (childCount > 0) getChildAt(0) else null private val child: View? get() = if (childCount > 0) getChildAt(0) else null

View File

@ -42,7 +42,6 @@ import org.pixeldroid.app.databinding.OpenedAlbumBinding
import org.pixeldroid.app.databinding.PostFragmentBinding import org.pixeldroid.app.databinding.PostFragmentBinding
import org.pixeldroid.app.posts.MediaViewerActivity.Companion.openActivity import org.pixeldroid.app.posts.MediaViewerActivity.Companion.openActivity
import org.pixeldroid.app.utils.BlurHashDecoder import org.pixeldroid.app.utils.BlurHashDecoder
import org.pixeldroid.app.utils.ImageConverter
import org.pixeldroid.app.utils.api.PixelfedAPI import org.pixeldroid.app.utils.api.PixelfedAPI
import org.pixeldroid.app.utils.api.objects.Attachment import org.pixeldroid.app.utils.api.objects.Attachment
import org.pixeldroid.app.utils.api.objects.Status import org.pixeldroid.app.utils.api.objects.Status
@ -51,6 +50,7 @@ import org.pixeldroid.app.utils.api.objects.Status.Companion.POST_TAG
import org.pixeldroid.app.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG import org.pixeldroid.app.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG
import org.pixeldroid.app.utils.db.AppDatabase import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.di.PixelfedAPIHolder import org.pixeldroid.app.utils.di.PixelfedAPIHolder
import org.pixeldroid.app.utils.setProfileImageFromURL
import retrofit2.HttpException import retrofit2.HttpException
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@ -132,10 +132,10 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
binding.root.context binding.root.context
) )
binding.postDomain.text = status?.getStatusDomain(domain) binding.postDomain.text = status?.getStatusDomain(domain, binding.postDomain.context)
//Setup images //Setup images
ImageConverter.setRoundImageFromURL( setProfileImageFromURL(
binding.root, binding.root,
status?.getProfilePicUrl(), status?.getProfilePicUrl(),
binding.profilePic binding.profilePic

View File

@ -6,7 +6,6 @@ import android.view.ViewGroup
import android.widget.ProgressBar import android.widget.ProgressBar
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.size
import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.LifecycleCoroutineScope
import androidx.paging.LoadState import androidx.paging.LoadState
import androidx.paging.LoadStateAdapter import androidx.paging.LoadStateAdapter
@ -14,14 +13,14 @@ import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ErrorLayoutBinding import org.pixeldroid.app.databinding.ErrorLayoutBinding
import org.pixeldroid.app.databinding.LoadStateFooterViewItemBinding import org.pixeldroid.app.databinding.LoadStateFooterViewItemBinding
import org.pixeldroid.app.posts.feeds.uncachedFeeds.FeedViewModel import org.pixeldroid.app.posts.feeds.uncachedFeeds.FeedViewModel
import org.pixeldroid.app.utils.api.objects.FeedContent import org.pixeldroid.app.utils.api.objects.FeedContent
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
/** /**

View File

@ -7,12 +7,15 @@ import android.view.ViewGroup
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.paging.* import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadState.* import androidx.paging.LoadState.NotLoading
import androidx.recyclerview.widget.LinearLayoutManager import androidx.paging.PagingDataAdapter
import androidx.paging.RemoteMediator
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filter
import org.pixeldroid.app.databinding.FragmentFeedBinding import org.pixeldroid.app.databinding.FragmentFeedBinding
import org.pixeldroid.app.posts.feeds.initAdapter import org.pixeldroid.app.posts.feeds.initAdapter
import org.pixeldroid.app.utils.BaseFragment import org.pixeldroid.app.utils.BaseFragment

View File

@ -7,18 +7,18 @@ import android.view.ViewGroup
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.paging.* import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadState
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import org.pixeldroid.app.posts.feeds.launch
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChangedBy import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.databinding.FragmentFeedBinding import org.pixeldroid.app.databinding.FragmentFeedBinding
import org.pixeldroid.app.utils.BaseFragment
import org.pixeldroid.app.posts.feeds.initAdapter import org.pixeldroid.app.posts.feeds.initAdapter
import org.pixeldroid.app.posts.feeds.launch
import org.pixeldroid.app.utils.BaseFragment
import org.pixeldroid.app.utils.api.objects.FeedContent import org.pixeldroid.app.utils.api.objects.FeedContent

View File

@ -4,11 +4,9 @@ import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager import androidx.paging.Pager
import androidx.paging.PagingConfig import androidx.paging.PagingConfig
import androidx.paging.PagingData import androidx.paging.PagingData
import org.pixeldroid.app.utils.api.PixelfedAPI
import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedContentRepository
import org.pixeldroid.app.utils.api.objects.FeedContent
import org.pixeldroid.app.utils.api.objects.Results
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedContentRepository
import org.pixeldroid.app.utils.api.PixelfedAPI
import org.pixeldroid.app.utils.api.objects.Status import org.pixeldroid.app.utils.api.objects.Status
import javax.inject.Inject import javax.inject.Inject

View File

@ -33,15 +33,12 @@ import org.pixeldroid.app.posts.feeds.uncachedFeeds.FeedViewModel
import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedContentRepository import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedContentRepository
import org.pixeldroid.app.posts.feeds.uncachedFeeds.profile.ProfileContentRepository import org.pixeldroid.app.posts.feeds.uncachedFeeds.profile.ProfileContentRepository
import org.pixeldroid.app.posts.parseHTMLText import org.pixeldroid.app.posts.parseHTMLText
import org.pixeldroid.app.utils.BaseThemedWithBarActivity import org.pixeldroid.app.utils.*
import org.pixeldroid.app.utils.BlurHashDecoder
import org.pixeldroid.app.utils.ImageConverter
import org.pixeldroid.app.utils.api.PixelfedAPI import org.pixeldroid.app.utils.api.PixelfedAPI
import org.pixeldroid.app.utils.api.objects.Account import org.pixeldroid.app.utils.api.objects.Account
import org.pixeldroid.app.utils.api.objects.Attachment import org.pixeldroid.app.utils.api.objects.Attachment
import org.pixeldroid.app.utils.api.objects.Status import org.pixeldroid.app.utils.api.objects.Status
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
import org.pixeldroid.app.utils.openUrl
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
@ -99,9 +96,9 @@ class ProfileActivity : BaseThemedWithBarActivity() {
} }
/** /**
* Shows or hides the error in the different FeedFragments * Shows or hides the error in the profile
*/ */
private fun showError(errorText: String = "Something went wrong while loading", show: Boolean = true){ private fun showError(errorText: String = getString(R.string.profile_error), show: Boolean = true){
if(show){ if(show){
binding.profileProgressBar.visibility = View.GONE binding.profileProgressBar.visibility = View.GONE
binding.motionLayout.transitionToEnd() binding.motionLayout.transitionToEnd()
@ -116,6 +113,7 @@ class ProfileActivity : BaseThemedWithBarActivity() {
if(account != null) { if(account != null) {
setViews(account) setViews(account)
} else { } else {
supportActionBar?.setTitle(R.string.menu_account)
lifecycleScope.launchWhenResumed { lifecycleScope.launchWhenResumed {
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setToCurrentUser() val api: PixelfedAPI = apiHolder.api ?: apiHolder.setToCurrentUser()
val myAccount: Account = try { val myAccount: Account = try {
@ -149,7 +147,7 @@ class ProfileActivity : BaseThemedWithBarActivity() {
*/ */
private fun setViews(account: Account) { private fun setViews(account: Account) {
val profilePicture = binding.profilePictureImageView val profilePicture = binding.profilePictureImageView
ImageConverter.setRoundImageFromURL( setProfileImageFromURL(
View(applicationContext), View(applicationContext),
account.anyAvatar(), account.anyAvatar(),
profilePicture profilePicture
@ -368,7 +366,7 @@ class ProfilePostsViewHolder(binding: FragmentProfilePostsBinding) : RecyclerVie
).placeholder(R.drawable.ic_sensitive).apply(RequestOptions().centerCrop()) ).placeholder(R.drawable.ic_sensitive).apply(RequestOptions().centerCrop())
.into(postPreview) .into(postPreview)
} else { } else {
ImageConverter.setSquareImageFromURL(postPreview, setSquareImageFromURL(postPreview,
post.getPostPreviewURL(), post.getPostPreviewURL(),
postPreview, postPreview,
post.media_attachments?.firstOrNull()?.blurhash) post.media_attachments?.firstOrNull()?.blurhash)

View File

@ -18,9 +18,9 @@ import org.pixeldroid.app.utils.api.PixelfedAPI
import org.pixeldroid.app.utils.api.objects.Status import org.pixeldroid.app.utils.api.objects.Status
import org.pixeldroid.app.posts.PostActivity import org.pixeldroid.app.posts.PostActivity
import org.pixeldroid.app.utils.BaseFragment import org.pixeldroid.app.utils.BaseFragment
import org.pixeldroid.app.utils.ImageConverter
import org.pixeldroid.app.utils.api.objects.Attachment import org.pixeldroid.app.utils.api.objects.Attachment
import org.pixeldroid.app.utils.bindingLifecycleAware import org.pixeldroid.app.utils.bindingLifecycleAware
import org.pixeldroid.app.utils.setSquareImageFromURL
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
@ -69,7 +69,7 @@ class SearchDiscoverFragment : BaseFragment() {
} }
} }
fun showError(@StringRes errorText: Int = R.string.loading_toast, show: Boolean = true){ private fun showError(@StringRes errorText: Int = R.string.loading_toast, show: Boolean = true){
binding.motionLayout.apply { binding.motionLayout.apply {
if(show){ if(show){
transitionToEnd() transitionToEnd()
@ -126,7 +126,7 @@ class SearchDiscoverFragment : BaseFragment() {
} else holder.videoIcon.visibility = View.GONE } else holder.videoIcon.visibility = View.GONE
} }
ImageConverter.setSquareImageFromURL(holder.postView, post?.getPostPreviewURL(), holder.postPreview, post?.media_attachments?.firstOrNull()?.blurhash) setSquareImageFromURL(holder.postView, post?.getPostPreviewURL(), holder.postPreview, post?.media_attachments?.firstOrNull()?.blurhash)
holder.postPreview.setOnClickListener { holder.postPreview.setOnClickListener {
val intent = Intent(holder.postView.context, PostActivity::class.java) val intent = Intent(holder.postView.context, PostActivity::class.java)
intent.putExtra(Status.POST_TAG, post) intent.putExtra(Status.POST_TAG, post)

View File

@ -29,7 +29,7 @@ object BlurHashDecoder {
) )
} }
fun decode(blurHash: String?, width: Int?, height: Int?, punch: Float = 1f): Bitmap? { private fun decode(blurHash: String?, width: Int?, height: Int?, punch: Float = 1f): Bitmap? {
if (blurHash == null || width == null || height == null || blurHash.length < 6) { if (blurHash == null || width == null || height == null || blurHash.length < 6) {
return null return null
} }

View File

@ -1,99 +1,30 @@
package org.pixeldroid.app.utils package org.pixeldroid.app.utils
import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import org.pixeldroid.app.R import org.pixeldroid.app.R
class ImageConverter { /**
companion object { * @brief Loads a given image (via url) as a round image into a given image view
/** * @param view, the view in which this is happening
* @brief Loads a given image (via url) into a given image view * @param url, the url of the image that will be loaded
* @param activity, the activity in which this is happening * @param image, the imageView into which we will load the image
* @param url, the url of the image that will be loaded */
* @param view, the imageView into which we will load the image fun setProfileImageFromURL(view : View, url : String?, image : ImageView) {
*/ Glide.with(view).load(url).apply(RequestOptions().circleCrop())
fun setImageViewFromURL(activity: AppCompatActivity, url : String?, view : ImageView) { .placeholder(R.drawable.ic_default_user).into(image)
Glide.with(activity).load(url).into(view) }
}
/** /**
* @brief Loads a given image (via url) into a given image view * @brief Loads a given image (via url) as a square image into a given image view
* @param fragment, the fragment in which this is happening * @param view, the view in which this is happening
* @param url, the url of the image that will be loaded * @param url, the url of the image that will be loaded
* @param view, the imageView into which we will load the image * @param image, the imageView into which we will load the image
*/ */
fun setImageViewFromURL(fragment: Fragment, url : String?, view : ImageView) { fun setSquareImageFromURL(view : View, url : String?, image : ImageView, blurhash: String? = null) {
Glide.with(fragment).load(url).into(view) Glide.with(view).load(url).placeholder(
} blurhash?.let { BlurHashDecoder.blurHashBitmap(view.resources, it, 32, 32) }
).apply(RequestOptions().centerCrop()).into(image)
/**
* @brief Loads a given image (via url) into a given image view
* @param fragmentActivity, the fragmentActivity in which this is happening
* @param url, the url of the image that will be loaded
* @param view, the imageView into which we will load the image
*/
fun setImageViewFromURL(fragmentActivity: FragmentActivity, url : String?, view : ImageView) {
Glide.with(fragmentActivity).load(url).into(view)
}
/**
* @brief Loads a given image (via url) into a given image view
* @param fragView, the view in which this is happening
* @param url, the url of the image that will be loaded
* @param view, the imageView into which we will load the image
*/
fun setImageViewFromURL(fragView: View, url : String?, view : ImageView) {
Glide.with(fragView).load(url).into(view)
}
/**
* @brief Loads a given image (via url) as a round image into a given image view
* @param view, the view in which this is happening
* @param url, the url of the image that will be loaded
* @param image, the imageView into which we will load the image
*/
fun setRoundImageFromURL(view : View, url : String?, image : ImageView) {
Glide.with(view).load(url).apply(RequestOptions().circleCrop())
.placeholder(R.drawable.ic_default_user).into(image)
}
/**
* @brief Loads a given image (via url) as a square image into a given image view
* @param view, the view in which this is happening
* @param url, the url of the image that will be loaded
* @param image, the imageView into which we will load the image
*/
fun setSquareImageFromURL(view : View, url : String?, image : ImageView, blurhash: String? = null) {
Glide.with(view).load(url).placeholder(
blurhash?.let { BlurHashDecoder.blurHashBitmap(view.resources, it, 32,32) }
).apply(RequestOptions().centerCrop()).into(image)
}
/**
* @brief Loads a given image (via url) as a square image into a given image view
* @param view, the view in which this is happening
* @param drawable, the drawable of the image
* @param image, the imageView into which we will load the image
*/
fun setSquareImageFromDrawable(view : View, drawable : Drawable?, image : ImageView) {
Glide.with(view).load(drawable).apply(RequestOptions().centerCrop()).into(image)
}
/**
* @brief Loads a default image into a given image view
* @param view, the view in which this is happening
* @param image, the imageView into which we will load the image
*/
fun setImageFromDrawable(view : View, image : ImageView, drawable : Int) {
Glide.with(view).load(drawable).into(image)
}
}
} }

View File

@ -3,9 +3,8 @@ package org.pixeldroid.app.utils
import android.app.Application import android.app.Application
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import org.pixeldroid.app.utils.di.*
import com.mikepenz.iconics.Iconics
import org.ligi.tracedroid.TraceDroid import org.ligi.tracedroid.TraceDroid
import org.pixeldroid.app.utils.di.*
class PixelDroidApplication: Application() { class PixelDroidApplication: Application() {

View File

@ -29,6 +29,7 @@ import com.arthenica.ffmpegkit.FFmpegKitConfig
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import okhttp3.HttpUrl import okhttp3.HttpUrl
import org.pixeldroid.app.R import org.pixeldroid.app.R
import java.util.*
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@ -65,7 +66,7 @@ fun Uri.getMimeType(contentResolver: ContentResolver, fallback: String = "image/
contentResolver.getType(this) contentResolver.getType(this)
} else { } else {
MimeTypeMap.getFileExtensionFromUrl(toString()) MimeTypeMap.getFileExtensionFromUrl(toString())
?.run { MimeTypeMap.getSingleton().getMimeTypeFromExtension(toLowerCase()) } ?.run { MimeTypeMap.getSingleton().getMimeTypeFromExtension(lowercase(Locale.getDefault())) }
} ?: fallback } ?: fallback
} }

View File

@ -73,7 +73,7 @@ data class Account(
fun getDisplayName() : String = when { fun getDisplayName() : String = when {
username.isNullOrBlank() && display_name.isNullOrBlank() -> "" username.isNullOrBlank() && display_name.isNullOrBlank() -> ""
display_name.isNullOrBlank() -> "@$username" display_name.isNullOrBlank() -> "@$username"
else -> display_name.orEmpty() else -> display_name
} }
fun anyAvatar(): String? = avatar_static ?: avatar fun anyAvatar(): String? = avatar_static ?: avatar

View File

@ -84,10 +84,10 @@ open class Status(
) )
} }
fun getStatusDomain(domain: String) : String { fun getStatusDomain(domain: String, context: Context) : String {
val accountDomain = getDomain(account!!.url) val accountDomain = getDomain(account!!.url)
return if(getDomain(domain) == accountDomain) "" return if(getDomain(domain) == accountDomain) ""
else " from $accountDomain" else context.getString(R.string.from_other_domain).format(accountDomain)
} }

View File

@ -6,7 +6,6 @@ import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Color
import android.os.Build import android.os.Build
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
@ -24,6 +23,7 @@ import org.pixeldroid.app.utils.api.objects.Status
import org.pixeldroid.app.utils.db.AppDatabase import org.pixeldroid.app.utils.db.AppDatabase
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
import org.pixeldroid.app.utils.di.PixelfedAPIHolder import org.pixeldroid.app.utils.di.PixelfedAPIHolder
import org.pixeldroid.app.utils.getColorFromAttr
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
import java.time.Instant import java.time.Instant
@ -171,7 +171,6 @@ class NotificationsWorker(
}.putExtra(USER_NOTIFICATION_TAG, user.user_id) }.putExtra(USER_NOTIFICATION_TAG, user.user_id)
.putExtra(INSTANCE_NOTIFICATION_TAG, user.instance_uri) .putExtra(INSTANCE_NOTIFICATION_TAG, user.instance_uri)
val builder = NotificationCompat.Builder(applicationContext, makeChannelId(uniqueUserId, notification.type)) val builder = NotificationCompat.Builder(applicationContext, makeChannelId(uniqueUserId, notification.type))
.setSmallIcon( .setSmallIcon(
when (notification.type) { when (notification.type) {
@ -184,7 +183,7 @@ class NotificationsWorker(
null -> R.drawable.ic_comment_empty null -> R.drawable.ic_comment_empty
} }
) )
.setColor(Color.parseColor("#6200EE")) .setColor(applicationContext.getColorFromAttr(R.attr.colorPrimary))
.setContentTitle( .setContentTitle(
notification.account?.username?.let { username -> notification.account?.username?.let { username ->
applicationContext.getString( applicationContext.getString(

View File

@ -26,7 +26,7 @@
android:scaleType="centerInside" android:scaleType="centerInside"
android:contentDescription="@string/image_preview" /> android:contentDescription="@string/image_preview" />
<org.pixeldroid.app.postCreation.photoEdit.NonSwipeableViewPager <androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager" android:id="@+id/viewPager"
app:layout_behavior="@string/appbar_scrolling_view_behavior" app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -1,70 +1,79 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
tools:context=".postCreation.photoEdit.EditImageFragment"> tools:context=".postCreation.photoEdit.EditImageFragment">
<LinearLayout
android:orientation="horizontal"
android:paddingBottom="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="@string/lbl_brightness"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<SeekBar
android:id="@+id/seekbar_brightness"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout <TextView
android:orientation="horizontal" android:id="@+id/label_brightness"
android:paddingBottom="8dp" android:layout_width="wrap_content"
android:paddingTop="8dp" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_marginStart="8dp"
android:layout_height="wrap_content"> android:gravity="center_horizontal"
android:text="@string/lbl_brightness"
app:layout_constraintBottom_toTopOf="@+id/label_contrast"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="spread" />
<TextView <TextView
android:text="@string/lbl_contrast" android:id="@+id/label_contrast"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:gravity="center_horizontal"
android:text="@string/lbl_contrast"
app:layout_constraintBottom_toTopOf="@+id/label_saturation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label_brightness" />
<SeekBar <TextView
android:id="@+id/seekbar_contrast" android:id="@+id/label_saturation"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_height="wrap_content" /> android:layout_marginStart="8dp"
android:gravity="center_horizontal"
android:text="@string/lbl_saturation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/label_contrast" />
</LinearLayout> <SeekBar
android:id="@+id/seekbar_brightness"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/label_brightness"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/label_barrier"
app:layout_constraintTop_toTopOf="@+id/label_brightness" />
<LinearLayout <SeekBar
android:orientation="horizontal" android:id="@+id/seekbar_saturation"
android:paddingTop="8dp" android:layout_width="0dp"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content"> app:layout_constraintBottom_toBottomOf="@+id/label_saturation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/seekbar_contrast"
app:layout_constraintTop_toTopOf="@+id/label_saturation" />
<TextView <SeekBar
android:text="@string/lbl_saturation" android:id="@+id/seekbar_contrast"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/label_contrast"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/seekbar_brightness"
app:layout_constraintTop_toTopOf="@+id/label_contrast" />
<SeekBar <androidx.constraintlayout.widget.Barrier
android:id="@+id/seekbar_saturation" android:id="@+id/label_barrier"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_width="0dp" android:layout_height="wrap_content"
android:layout_height="wrap_content" /> app:barrierDirection="right"
app:constraint_referenced_ids="label_brightness,label_contrast,label_saturation" />
</LinearLayout>
</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -58,7 +58,7 @@
app:layout_constraintTop_toBottomOf="@id/notification_type" app:layout_constraintTop_toBottomOf="@id/notification_type"
tools:src="@drawable/ic_default_user" tools:src="@drawable/ic_default_user"
tools:srcCompat="@tools:sample/backgrounds/scenic" tools:srcCompat="@tools:sample/backgrounds/scenic"
android:contentDescription="TODO" /> android:contentDescription="@string/notification_thumbnail" />
<TextView <TextView
android:id="@+id/notification_post_description" android:id="@+id/notification_post_description"

View File

@ -15,7 +15,7 @@
android:id="@+id/postPreview" android:id="@+id/postPreview"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:contentDescription="TODO" android:contentDescription="@string/post_preview"
android:padding="1dp" android:padding="1dp"
app:layout_columnWeight="1" app:layout_columnWeight="1"
app:layout_constraintDimensionRatio="H,1:1" app:layout_constraintDimensionRatio="H,1:1"

View File

@ -42,11 +42,12 @@
android:id="@+id/postDomain" android:id="@+id/postDomain"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="#b3b3b3" android:textColor="#b3b3b3"
app:layout_constraintBottom_toBottomOf="@+id/profilePic" app:layout_constraintBottom_toBottomOf="@+id/profilePic"
app:layout_constraintStart_toEndOf="@+id/username" app:layout_constraintStart_toEndOf="@+id/username"
app:layout_constraintTop_toTopOf="@+id/profilePic" app:layout_constraintTop_toTopOf="@+id/profilePic"
tools:text=" from domain.tld" /> tools:text="from domain.tld" />
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/postConstraint" android:id="@+id/postConstraint"

View File

@ -3,6 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:orientation="vertical"
android:padding="4dp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View File

@ -119,10 +119,10 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<!-- Post editing --> <!-- Post editing -->
<string name="lbl_brightness">BRIGHTNESS</string> <string name="lbl_brightness">Brightness</string>
<string name="lbl_contrast">CONTRAST</string> <string name="lbl_contrast">Contrast</string>
<string name="lbl_saturation">SATURATION</string> <string name="lbl_saturation">Saturation</string>
<string name="tab_filters">FILTERS</string> <string name="tab_filters">Filters</string>
<string name="edit">Edit</string> <string name="edit">Edit</string>
<string name="filter_thumbnail">Thumbnail of filter</string> <string name="filter_thumbnail">Thumbnail of filter</string>
<string name="normal_filter">Normal</string> <string name="normal_filter">Normal</string>
@ -133,6 +133,7 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="crop_button">Button to crop or rotate the image</string> <string name="crop_button">Button to crop or rotate the image</string>
<string name="save_before_returning">Save your edits?</string> <string name="save_before_returning">Save your edits?</string>
<string name="no_cancel_edit">No, cancel edit</string> <string name="no_cancel_edit">No, cancel edit</string>
<string name="error_editing">Error while editing</string>
<!-- Camera --> <!-- Camera -->
<string name="capture_button_alt">Capture</string> <string name="capture_button_alt">Capture</string>
@ -282,4 +283,12 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="accentColorSummary">Choose a color accent</string> <string name="accentColorSummary">Choose a color accent</string>
<string name="color_choice_button">Choose this color accent</string> <string name="color_choice_button">Choose this color accent</string>
<string name="color_chosen">Chosen color accent</string> <string name="color_chosen">Chosen color accent</string>
<string name="profile_error">Could not load profile</string>
<!-- Tells user what domain this user is from -->
<string name="from_other_domain">from %1$s</string>
<string name="add_images_error">Error while adding images</string>
<string name="notification_thumbnail">"Thumbnail of image in this notification's post"</string>
<string name="post_preview">Preview of a post</string>
</resources> </resources>