Add reporting and link sharing functionality, polish UI
This commit is contained in:
parent
a769d404a6
commit
50dd0bad51
|
@ -65,7 +65,7 @@ dependencies {
|
|||
* AndroidX dependencies:
|
||||
*/
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.core:core-ktx:1.3.1'
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.3.0'
|
||||
|
@ -80,6 +80,7 @@ dependencies {
|
|||
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
|
||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
|
||||
implementation "androidx.annotation:annotation:1.1.0"
|
||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
|
||||
// Use the most recent version of CameraX
|
||||
def camerax_version = '1.0.0-beta08'
|
||||
|
@ -104,8 +105,6 @@ dependencies {
|
|||
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
|
||||
implementation 'com.google.android:flexbox:2.0.1'
|
||||
|
||||
//Dagger (dependency injection)
|
||||
implementation 'com.google.dagger:dagger-android:2.28.3'
|
||||
implementation 'com.google.dagger:dagger-android-support:2.28.3'
|
||||
|
@ -138,13 +137,14 @@ dependencies {
|
|||
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
|
||||
implementation "com.mikepenz:materialdrawer:8.1.4"
|
||||
implementation "com.mikepenz:materialdrawer:8.1.5"
|
||||
// Add for NavController support
|
||||
implementation "com.mikepenz:materialdrawer-nav:8.0.3"
|
||||
implementation "com.mikepenz:materialdrawer-nav:8.1.5"
|
||||
|
||||
//iconics
|
||||
implementation "com.mikepenz:materialdrawer-iconics:8.1.4"
|
||||
implementation "com.mikepenz:iconics-views:5.0.2"
|
||||
implementation "com.mikepenz:iconics-core:5.0.3"
|
||||
implementation "com.mikepenz:materialdrawer-iconics:8.1.5"
|
||||
implementation "com.mikepenz:iconics-views:5.0.3"
|
||||
implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar'
|
||||
|
||||
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:replace="android:allowBackup">
|
||||
<activity android:name=".CameraActivity"></activity>
|
||||
<activity
|
||||
android:name=".PhotoEditActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
android:name=".ReportActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<activity android:name=".PhotoEditActivity" />
|
||||
<activity
|
||||
android:name=".PostCreationActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
|
@ -47,19 +50,24 @@
|
|||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/title_activity_settings2"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"
|
||||
android:parentActivityName=".MainActivity" />
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
android:theme="@style/AppTheme.Launcher"
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.default_searchable"
|
||||
android:value=".SearchActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".LoginActivity"
|
||||
|
@ -89,28 +97,23 @@
|
|||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity">
|
||||
<intent-filter>
|
||||
<action
|
||||
android:name="android.intent.action.SEARCH"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".AboutActivity"
|
||||
android:parentActivityName=".SettingsActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"
|
||||
android:parentActivityName=".SettingsActivity" />
|
||||
|
||||
<activity android:name=".LicenseActivity"
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
<activity
|
||||
android:name=".LicenseActivity"
|
||||
android:parentActivityName=".AboutActivity"
|
||||
android:screenOrientation="sensorPortrait"
|
||||
tools:ignore="LockedOrientationActivity"
|
||||
android:parentActivityName=".AboutActivity" />
|
||||
|
||||
tools:ignore="LockedOrientationActivity" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.h.pixeldroid.fragments.CameraFragment
|
||||
|
||||
class CameraActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_camera)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setTitle(R.string.add_photo)
|
||||
|
||||
val cameraFragment = CameraFragment()
|
||||
|
||||
val arguments = Bundle()
|
||||
arguments.putBoolean("CameraActivity", true)
|
||||
cameraFragment.arguments = arguments
|
||||
|
||||
supportFragmentManager.beginTransaction()
|
||||
.add(R.id.camera_activity_fragment, cameraFragment).commit()
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -88,7 +88,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun setupDrawer() {
|
||||
main_toolbar.setNavigationOnClickListener {
|
||||
main_drawer_button.setOnClickListener{
|
||||
drawer_layout.open()
|
||||
}
|
||||
|
||||
|
|
|
@ -103,11 +103,9 @@ class PhotoEditActivity : AppCompatActivity(), FilterListFragmentListener, EditI
|
|||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_photo_edit)
|
||||
|
||||
//TODO move to xml:
|
||||
setSupportActionBar(toolbar)
|
||||
supportActionBar!!.title = "Edit"
|
||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar!!.setHomeButtonEnabled(true)
|
||||
supportActionBar?.setTitle(R.string.toolbar_title_edit)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setHomeButtonEnabled(true)
|
||||
|
||||
val cropButton: FloatingActionButton = findViewById(R.id.cropImageButton)
|
||||
|
||||
|
@ -267,7 +265,11 @@ class PhotoEditActivity : AppCompatActivity(), FilterListFragmentListener, EditI
|
|||
private fun startCrop() {
|
||||
val file = File.createTempFile("temp_crop_img", ".png", cacheDir)
|
||||
|
||||
val uCrop: UCrop = UCrop.of(initialUri!!, Uri.fromFile(file))
|
||||
val options: UCrop.Options = UCrop.Options().apply {
|
||||
setStatusBarColor(resources.getColor(R.color.colorPrimaryDark, theme))
|
||||
setActiveControlsWidgetColor(resources.getColor(R.color.colorButtonBg, theme))
|
||||
}
|
||||
val uCrop: UCrop = UCrop.of(initialUri!!, Uri.fromFile(file)).withOptions(options)
|
||||
uCrop.start(this)
|
||||
}
|
||||
|
||||
|
@ -470,14 +472,19 @@ class PhotoEditActivity : AppCompatActivity(), FilterListFragmentListener, EditI
|
|||
if(!save) {
|
||||
sendBackImage(path)
|
||||
} else {
|
||||
MediaScannerConnection.scanFile(
|
||||
this,
|
||||
arrayOf(path.toUri().toFile().absolutePath),
|
||||
null
|
||||
if(path.startsWith("file")) {
|
||||
MediaScannerConnection.scanFile(
|
||||
this,
|
||||
arrayOf(path.toUri().toFile().absolutePath),
|
||||
null
|
||||
|
||||
) { path, uri ->
|
||||
if(uri == null) {
|
||||
Log.e("NEW IMAGE SCAN FAILED", "Tried to scan $path, but it failed")
|
||||
) { path, uri ->
|
||||
if (uri == null) {
|
||||
Log.e(
|
||||
"NEW IMAGE SCAN FAILED",
|
||||
"Tried to scan $path, but it failed"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Application
|
|||
import androidx.preference.PreferenceManager
|
||||
import com.h.pixeldroid.di.*
|
||||
import com.h.pixeldroid.utils.ThemeUtils
|
||||
import com.mikepenz.iconics.Iconics
|
||||
import org.ligi.tracedroid.TraceDroid
|
||||
|
||||
|
||||
|
@ -23,7 +24,9 @@ class Pixeldroid: Application() {
|
|||
.databaseModule(DatabaseModule(applicationContext))
|
||||
.aPIModule(APIModule())
|
||||
.build()
|
||||
mApplicationComponent.inject(this);
|
||||
mApplicationComponent.inject(this)
|
||||
|
||||
Iconics.init(applicationContext)
|
||||
}
|
||||
|
||||
fun getAppComponent(): ApplicationComponent {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
|
@ -26,7 +25,6 @@ import com.h.pixeldroid.interfaces.PostCreationListener
|
|||
import com.h.pixeldroid.objects.Attachment
|
||||
import com.h.pixeldroid.objects.Instance
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import com.h.pixeldroid.utils.ProgressRequestBody
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
@ -39,9 +37,11 @@ import retrofit2.Callback
|
|||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
||||
private val TAG = "Post Creation Activity"
|
||||
private val MORE_PICTURES_REQUEST_CODE = 0xffff
|
||||
|
||||
private val TAG = "Post Creation Activity"
|
||||
|
||||
class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
||||
|
||||
private lateinit var recycler : RecyclerView
|
||||
private lateinit var adapter : PostCreationAdapter
|
||||
|
@ -74,16 +74,19 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
|||
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
// load images
|
||||
posts = intent.getStringArrayListExtra("pictures_uri")!!
|
||||
|
||||
progressList = posts.map { 0 } as ArrayList<Int>
|
||||
muListOfIds = posts.map { "" }.toMutableList()
|
||||
// get image URIs
|
||||
if(intent.clipData != null) {
|
||||
val count = intent.clipData!!.itemCount
|
||||
for (i in 0 until count) {
|
||||
val imageUri: String = intent.clipData!!.getItemAt(i).uri.toString()
|
||||
posts.add(imageUri)
|
||||
}
|
||||
}
|
||||
|
||||
user = db.userDao().getActiveUser()
|
||||
|
||||
val instances = db.instanceDao().getAll()
|
||||
maxLength = if (user!=null){
|
||||
maxLength = if (user != null){
|
||||
val thisInstances =
|
||||
instances.filter { instanceDatabaseEntity ->
|
||||
instanceDatabaseEntity.uri.contains(user!!.instance_uri)
|
||||
|
@ -100,12 +103,14 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
|||
// TODO
|
||||
|
||||
//upload the picture and display progress while doing so
|
||||
muListOfIds = posts.map { "" }.toMutableList()
|
||||
progressList = posts.map { 0 } as ArrayList<Int>
|
||||
upload()
|
||||
|
||||
adapter = PostCreationAdapter(posts)
|
||||
adapter.listener = this
|
||||
recycler = findViewById(R.id.image_grid)
|
||||
recycler.layoutManager = GridLayoutManager(this, if (posts.size > 2) 2 else 1)
|
||||
recycler.layoutManager = GridLayoutManager(this, 3)
|
||||
recycler.adapter = adapter
|
||||
|
||||
// get the description and send the post
|
||||
|
@ -126,8 +131,8 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
|||
val textField = findViewById<TextInputEditText>(R.id.new_post_description_input_field)
|
||||
val content = textField.text.toString()
|
||||
if (content.length > maxLength) {
|
||||
// error, too much characters
|
||||
textField.error = "Description must contain $maxLength characters at most."
|
||||
// error, too many characters
|
||||
textField.error = getString(R.string.description_max_characters).format(maxLength)
|
||||
return false
|
||||
}
|
||||
// store the description
|
||||
|
@ -135,9 +140,26 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
|||
return true
|
||||
}
|
||||
|
||||
private fun upload() {
|
||||
for ((index, post) in posts.withIndex()) {
|
||||
val imageUri = Uri.parse(post)
|
||||
/**
|
||||
* Uploads the images that are in the [posts] array.
|
||||
* Keeps track of them in the [progressList] (for the upload progress), and the [muListOfIds]
|
||||
* (for the list of ids of the uploads).
|
||||
* @param newImagesStartingIndex is the index in the [posts] array we want to start uploading at.
|
||||
* Indices before this are already uploading, or done uploading, from before.
|
||||
* @param editedImage contains the index of the image that was edited. If set, other images are
|
||||
* not uploaded again: they should already be uploading, or be done uploading, from before.
|
||||
*/
|
||||
private fun upload(newImagesStartingIndex: Int = 0, editedImage: Int? = null) {
|
||||
enableButton(false)
|
||||
uploadProgressBar.visibility = View.VISIBLE
|
||||
upload_completed_textview.visibility = View.INVISIBLE
|
||||
|
||||
val range: IntRange = if(editedImage == null){
|
||||
newImagesStartingIndex until posts.size
|
||||
} else IntRange(editedImage, editedImage)
|
||||
|
||||
for (index in range) {
|
||||
val imageUri = Uri.parse(posts[index])
|
||||
val imageInputStream = contentResolver.openInputStream(imageUri)!!
|
||||
|
||||
val size =
|
||||
|
@ -237,7 +259,7 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
|||
if(enable){
|
||||
posting_progress_bar.visibility = View.GONE
|
||||
post_creation_send_button.visibility = View.VISIBLE
|
||||
} else{
|
||||
} else {
|
||||
posting_progress_bar.visibility = View.VISIBLE
|
||||
post_creation_send_button.visibility = View.GONE
|
||||
}
|
||||
|
@ -259,51 +281,85 @@ class PostCreationActivity : AppCompatActivity(), PostCreationListener {
|
|||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
posts[positionResult] = data.getStringExtra("result")!!
|
||||
adapter.notifyItemChanged(positionResult)
|
||||
muListOfIds.clear()
|
||||
upload()
|
||||
}
|
||||
else if(resultCode == Activity.RESULT_CANCELED){
|
||||
Toast.makeText(applicationContext, "Edition cancelled", Toast.LENGTH_SHORT).show()
|
||||
muListOfIds[positionResult] = ""
|
||||
progressList[positionResult] = 0
|
||||
upload(editedImage = positionResult)
|
||||
} else if(resultCode == Activity.RESULT_CANCELED){
|
||||
Toast.makeText(applicationContext, "Editing cancelled", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(applicationContext, "Error while editing", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
} else if (requestCode == MORE_PICTURES_REQUEST_CODE) {
|
||||
if (resultCode == Activity.RESULT_OK && data?.clipData != null) {
|
||||
|
||||
val count = data.clipData!!.itemCount
|
||||
for (i in 0 until count) {
|
||||
val imageUri: String = data.clipData!!.getItemAt(i).uri.toString()
|
||||
posts.add(imageUri)
|
||||
progressList.add(0)
|
||||
muListOfIds.add(i, "")
|
||||
}
|
||||
adapter.notifyDataSetChanged()
|
||||
upload(newImagesStartingIndex = posts.size - count)
|
||||
} else if(resultCode == Activity.RESULT_CANCELED){
|
||||
Toast.makeText(applicationContext, "Adding images", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(applicationContext, "Error while adding images", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PostCreationAdapter(private val posts: ArrayList<String>): RecyclerView.Adapter<PostCreationAdapter.ViewHolder>() {
|
||||
private var context: Context? = null
|
||||
inner class PostCreationAdapter(private val posts: ArrayList<String>): RecyclerView.Adapter<PostCreationAdapter.ViewHolder>() {
|
||||
var listener: PostCreationListener? = null
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
context = parent.context
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
val view =
|
||||
if(viewType == 0) LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.image_album_creation, parent, false)
|
||||
else LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.add_more_album_creation, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
Log.d("test", "binded")
|
||||
holder.bind()
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
if(position == posts.size) return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = posts.size
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
if(position != posts.size) {
|
||||
holder.bindImage()
|
||||
} else{
|
||||
holder.bindPlusButton()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = posts.size + 1
|
||||
|
||||
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
fun bind() {
|
||||
val image = Uri.parse(posts[adapterPosition])
|
||||
fun bindImage() {
|
||||
val image = Uri.parse(
|
||||
posts[adapterPosition]
|
||||
)
|
||||
// load image
|
||||
Glide.with(context!!)
|
||||
Glide.with(itemView.context)
|
||||
.load(image)
|
||||
.centerCrop()
|
||||
.into(itemView.galleryImage)
|
||||
|
||||
// adding click or tap handler for the image layout
|
||||
itemView.galleryImage.setOnClickListener {
|
||||
Log.d("test", "clicked")
|
||||
itemView.setOnClickListener {
|
||||
listener?.onClick(adapterPosition)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun bindPlusButton() {
|
||||
itemView.setOnClickListener {
|
||||
val intent = Intent(itemView.context, CameraActivity::class.java)
|
||||
this@PostCreationActivity.startActivityForResult(intent, MORE_PICTURES_REQUEST_CODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.di.PixelfedAPIHolder
|
||||
import com.h.pixeldroid.objects.Report
|
||||
import com.h.pixeldroid.objects.Status
|
||||
import kotlinx.android.synthetic.main.activity_report.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
import javax.inject.Inject
|
||||
|
||||
class ReportActivity : AppCompatActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
@Inject
|
||||
lateinit var apiHolder: PixelfedAPIHolder
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_report)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
supportActionBar?.setTitle(R.string.report)
|
||||
|
||||
val status = intent.getSerializableExtra(Status.POST_TAG) as Status?
|
||||
|
||||
(this.application as Pixeldroid).getAppComponent().inject(this)
|
||||
//get the currently active user
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
|
||||
report_target_textview.text = getString(R.string.report_target).format(status?.account?.acct)
|
||||
|
||||
|
||||
reportButton.setOnClickListener{
|
||||
reportButton.visibility = View.INVISIBLE
|
||||
reportProgressBar.visibility = View.VISIBLE
|
||||
|
||||
textInputLayout.editText?.isEnabled = false
|
||||
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
api.report("Bearer $accessToken", status?.account?.id!!, listOf(status), textInputLayout.editText?.text.toString())
|
||||
.enqueue(object : Callback<Report> {
|
||||
override fun onResponse(
|
||||
call: Call<Report>,
|
||||
response: Response<Report>
|
||||
) {
|
||||
if (response.body() == null || !response.isSuccessful) {
|
||||
textInputLayout.error = getString(R.string.report_error)
|
||||
reportButton.visibility = View.VISIBLE
|
||||
textInputLayout.editText?.isEnabled = true
|
||||
reportProgressBar.visibility = View.GONE
|
||||
} else {
|
||||
reportProgressBar.visibility = View.GONE
|
||||
reportButton.isEnabled = false
|
||||
reportButton.text = getString(R.string.reported)
|
||||
reportButton.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<Report>, t: Throwable) {
|
||||
Log.e("REPORT:", t.toString())
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -20,9 +20,15 @@ class SearchActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_search)
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
var query = ""
|
||||
if (Intent.ACTION_SEARCH == intent.action) {
|
||||
query = intent.getStringExtra(SearchManager.QUERY).orEmpty()
|
||||
}
|
||||
|
||||
var query = intent.getSerializableExtra("searchFeed") as String
|
||||
query = query.trim()
|
||||
supportActionBar?.title = query
|
||||
|
||||
val searchType = when {
|
||||
query.startsWith("#") -> {
|
||||
|
@ -41,6 +47,11 @@ class SearchActivity : AppCompatActivity() {
|
|||
setupTabs(tabs, searchType)
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun createSearchTabs(query: String): Array<Fragment>{
|
||||
|
||||
val searchFeedFragment =
|
||||
|
|
|
@ -54,13 +54,6 @@ class SettingsActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferen
|
|||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.root_preferences, rootKey)
|
||||
val button: Preference? = findPreference("about")
|
||||
button?.onPreferenceClickListener =
|
||||
Preference.OnPreferenceClickListener {
|
||||
val intent = Intent(context, AboutActivity::class.java)
|
||||
startActivity(intent)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -266,4 +266,15 @@ interface PixelfedAPI {
|
|||
fun discover(
|
||||
@Header("Authorization") authorization: String
|
||||
) : Call<DiscoverPosts>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/reports")
|
||||
fun report(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Field("account_id") account_id: String,
|
||||
@Field("status_ids") status_ids: List<Status>,
|
||||
@Field("comment") comment: String,
|
||||
@Field("forward") forward: Boolean = true
|
||||
) : Call<Report>
|
||||
|
||||
}
|
|
@ -24,6 +24,7 @@ interface ApplicationComponent {
|
|||
fun inject(activity: PostCreationActivity?)
|
||||
fun inject(activity: ProfileActivity?)
|
||||
fun inject(mainActivity: MainActivity?)
|
||||
fun inject(activity: ReportActivity?)
|
||||
fun inject(fragment: PostFragment)
|
||||
fun inject(fragment: SearchDiscoverFragment)
|
||||
fun inject(fragment: OfflineFeedFragment)
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.h.pixeldroid.fragments
|
|||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.ClipData
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
|
@ -23,13 +24,14 @@ import androidx.camera.view.PreviewView
|
|||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.setPadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.h.pixeldroid.PhotoEditActivity
|
||||
import com.h.pixeldroid.PostCreationActivity
|
||||
import com.h.pixeldroid.CameraActivity
|
||||
import com.h.pixeldroid.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -39,6 +41,7 @@ import java.util.concurrent.Executors
|
|||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
// This is an arbitrary number we are using to keep track of the permission
|
||||
// request. Where an app has multiple context for requesting permission,
|
||||
|
@ -54,7 +57,10 @@ class CameraFragment : Fragment() {
|
|||
|
||||
private lateinit var container: ConstraintLayout
|
||||
private lateinit var viewFinder: PreviewView
|
||||
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
private val REQUIRED_PERMISSIONS = arrayOf(
|
||||
Manifest.permission.CAMERA,
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
)
|
||||
private val PICK_IMAGE_REQUEST = 1
|
||||
private val CAPTURE_IMAGE_REQUEST = 2
|
||||
|
||||
|
@ -64,6 +70,8 @@ class CameraFragment : Fragment() {
|
|||
private var imageCapture: ImageCapture? = null
|
||||
private var camera: Camera? = null
|
||||
|
||||
private var inActivity by Delegates.notNull<Boolean>()
|
||||
|
||||
/** Blocking camera operations are performed using this executor */
|
||||
private lateinit var cameraExecutor: ExecutorService
|
||||
|
||||
|
@ -90,7 +98,8 @@ class CameraFragment : Fragment() {
|
|||
*/
|
||||
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
|
||||
ContextCompat.checkSelfPermission(
|
||||
requireContext(), it) == PackageManager.PERMISSION_GRANTED
|
||||
requireContext(), it
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -105,8 +114,12 @@ class CameraFragment : Fragment() {
|
|||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? =
|
||||
inflater.inflate(R.layout.fragment_camera, container, false)
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
inActivity = arguments?.getBoolean("CameraActivity") ?: false
|
||||
|
||||
return inflater.inflate(R.layout.fragment_camera, container, false)
|
||||
}
|
||||
|
||||
private fun setGalleryThumbnail(uri: String) {
|
||||
// Reference of the view that holds the gallery thumbnail
|
||||
|
@ -203,11 +216,12 @@ class CameraFragment : Fragment() {
|
|||
// A variable number of use-cases can be passed here -
|
||||
// camera provides access to CameraControl & CameraInfo
|
||||
camera = cameraProvider.bindToLifecycle(
|
||||
this, cameraSelector, preview, imageCapture)
|
||||
this, cameraSelector, preview, imageCapture
|
||||
)
|
||||
|
||||
// Attach the viewfinder's surface provider to preview use case
|
||||
preview?.setSurfaceProvider(viewFinder.createSurfaceProvider())
|
||||
} catch(exc: Exception) {
|
||||
} catch (exc: Exception) {
|
||||
Log.e(TAG, "Use case binding failed", exc)
|
||||
}
|
||||
|
||||
|
@ -246,7 +260,6 @@ class CameraFragment : Fragment() {
|
|||
|
||||
// In the background, load latest photo taken (if any) for gallery thumbnail
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
// Find the last picture
|
||||
// Find the last picture
|
||||
val projection = arrayOf(
|
||||
MediaStore.Images.ImageColumns._ID,
|
||||
|
@ -382,10 +395,29 @@ class CameraFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun startAlbumCreation(uris: ArrayList<String>) {
|
||||
startActivity(
|
||||
Intent(activity, PostCreationActivity::class.java)
|
||||
.putExtra("pictures_uri", uris)
|
||||
)
|
||||
|
||||
val intent = Intent(requireActivity(), PostCreationActivity::class.java)
|
||||
.apply {
|
||||
uris.forEach{
|
||||
//Why are we using ClipData here? Because the FLAG_GRANT_READ_URI_PERMISSION
|
||||
//needs to be applied to the URIs, and this flag flag only applies to the
|
||||
//Intent's data and any URIs specified in its ClipData.
|
||||
if(clipData == null){
|
||||
clipData = ClipData("", emptyArray(), ClipData.Item(it.toUri()))
|
||||
} else {
|
||||
clipData!!.addItem(ClipData.Item(it.toUri()))
|
||||
}
|
||||
}
|
||||
addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
|
||||
if(inActivity){
|
||||
requireActivity().setResult(Activity.RESULT_OK, intent)
|
||||
requireActivity().finish()
|
||||
} else {
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -50,11 +50,14 @@ class FilterListFragment : Fragment(), FilterListFragmentListener {
|
|||
recyclerView.addItemDecoration(SpaceItemDecoration(space))
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
displayImage(null)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
displayImage(null)
|
||||
}
|
||||
|
||||
private fun displayImage(bitmap: Bitmap?) {
|
||||
val r = Runnable {
|
||||
val tbImage: Bitmap = (if (bitmap == null) {
|
||||
|
@ -74,10 +77,10 @@ class FilterListFragment : Fragment(), FilterListFragmentListener {
|
|||
})
|
||||
?: return@Runnable
|
||||
|
||||
setupFilter(tbImage)
|
||||
if(activity != null) setupFilter(tbImage)
|
||||
|
||||
tbItemList.addAll(ThumbnailsManager.processThumbs(activity))
|
||||
requireActivity().runOnUiThread{ adapter.notifyDataSetChanged() }
|
||||
if(context != null) tbItemList.addAll(ThumbnailsManager.processThumbs(context))
|
||||
activity?.runOnUiThread{ adapter.notifyDataSetChanged() }
|
||||
}
|
||||
|
||||
Thread(r).start()
|
||||
|
@ -93,7 +96,7 @@ class FilterListFragment : Fragment(), FilterListFragmentListener {
|
|||
tbItem.filterName = tbItem.filter.name
|
||||
ThumbnailsManager.addThumb(tbItem)
|
||||
|
||||
val filters = FilterPack.getFilterPack(requireActivity())
|
||||
val filters = FilterPack.getFilterPack(context)
|
||||
|
||||
for (filter in filters) {
|
||||
val item = ThumbnailItem()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.h.pixeldroid.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
|
@ -9,18 +8,14 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.Toast
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.utils.ImageUtils
|
||||
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.android.synthetic.main.fragment_image.*
|
||||
|
||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||
private const val IMG_URL = "imgurl"
|
||||
private const val IMG_DESCRIPTION = "imgdescription"
|
||||
private const val RQST_BLDR = "rqstbldr"
|
||||
|
||||
/**
|
||||
|
@ -30,11 +25,13 @@ private const val RQST_BLDR = "rqstbldr"
|
|||
*/
|
||||
class ImageFragment : Fragment() {
|
||||
private lateinit var imgUrl: String
|
||||
private lateinit var imgDescription: String
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let {
|
||||
imgUrl = it.getString(IMG_URL)!!
|
||||
imgUrl = it.getString(IMG_URL)!!
|
||||
imgDescription = it.getString(IMG_DESCRIPTION)!!.ifEmpty { getString(R.string.no_description) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,49 +42,10 @@ class ImageFragment : Fragment() {
|
|||
val view = inflater.inflate(R.layout.fragment_image, container, false)
|
||||
|
||||
view.findViewById<ImageView>(R.id.imageImageView).setOnLongClickListener {
|
||||
PopupMenu(view.context, it).apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.image_popup_menu_save_to_gallery -> {
|
||||
Dexter.withContext(view.context)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(object: BasePermissionListener() {
|
||||
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
|
||||
Toast.makeText(view.context,
|
||||
view.context.getString(R.string.write_permission_download_pic),
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
|
||||
ImageUtils.downloadImage(requireActivity(), imgUrl)
|
||||
}
|
||||
}).check()
|
||||
true
|
||||
}
|
||||
R.id.image_popup_menu_share_picture -> {
|
||||
Dexter.withContext(view.context)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(object: BasePermissionListener() {
|
||||
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
|
||||
Toast.makeText(view.context,
|
||||
view.context.getString(R.string.write_permission_share_pic),
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
|
||||
ImageUtils.downloadImage(requireActivity(), imgUrl, share = true)
|
||||
}
|
||||
}).check()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
inflate(R.menu.image_popup_menu)
|
||||
show()
|
||||
}
|
||||
Snackbar.make(it, imgDescription, Snackbar.LENGTH_SHORT).show()
|
||||
true
|
||||
}
|
||||
|
||||
// Inflate the layout for this fragment
|
||||
return view
|
||||
}
|
||||
|
@ -100,6 +58,7 @@ class ImageFragment : Fragment() {
|
|||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
.load(imgUrl)
|
||||
.into(view.findViewById(R.id.imageImageView)!!)
|
||||
imageImageView.contentDescription = imgDescription
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -111,10 +70,11 @@ class ImageFragment : Fragment() {
|
|||
* @return A new instance of fragment ImageFragment.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun newInstance(imageUrl: String) =
|
||||
fun newInstance(imageUrl: String, imageDescription: String) =
|
||||
ImageFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(IMG_URL, imageUrl)
|
||||
putString(IMG_DESCRIPTION, imageDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,14 +39,6 @@ class PostFragment : Fragment() {
|
|||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
currentStatus?.setupPost(root, picRequest, this, statusDomain, true)
|
||||
|
||||
//Setup arguments needed for the onclicklisteners
|
||||
val holder = PostViewHolder(
|
||||
root,
|
||||
requireContext()
|
||||
)
|
||||
|
||||
(requireActivity().application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
@ -54,21 +46,17 @@ class PostFragment : Fragment() {
|
|||
val accessToken = user?.accessToken.orEmpty()
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
currentStatus?.setDescription(root, api, "Bearer $accessToken")
|
||||
currentStatus?.setupPost(root, picRequest, this, statusDomain, true)
|
||||
|
||||
//Activate onclickListeners
|
||||
currentStatus?.activateLiker(holder, api, "Bearer $accessToken",
|
||||
currentStatus.favourited ?: false
|
||||
val holder = PostViewHolder(
|
||||
root,
|
||||
root.context
|
||||
)
|
||||
currentStatus?.activateReblogger(holder, api, "Bearer $accessToken",
|
||||
currentStatus.reblogged ?: false
|
||||
)
|
||||
currentStatus?.activateCommenter(holder, api, "Bearer $accessToken")
|
||||
currentStatus?.showComments(holder, api, "Bearer $accessToken")
|
||||
|
||||
//Activate double tap liking
|
||||
currentStatus?.activateDoubleTapLiker(holder, api, "Bearer $accessToken")
|
||||
currentStatus?.activateButtons(holder, api, "Bearer $accessToken")
|
||||
|
||||
return root
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
package com.h.pixeldroid.fragments
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.*
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.google.android.material.textview.MaterialTextView
|
||||
import com.h.pixeldroid.Pixeldroid
|
||||
import com.h.pixeldroid.PostActivity
|
||||
import com.h.pixeldroid.R
|
||||
|
@ -26,6 +28,12 @@ import com.h.pixeldroid.objects.DiscoverPosts
|
|||
import com.h.pixeldroid.objects.Status
|
||||
import com.h.pixeldroid.utils.DBUtils
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.padding
|
||||
import com.mikepenz.iconics.utils.paddingDp
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.android.synthetic.main.fragment_search.*
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
@ -55,22 +63,30 @@ class SearchDiscoverFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_search, container, false)
|
||||
val button = view.findViewById<Button>(R.id.searchButton)
|
||||
val search = view.findViewById<EditText>(R.id.searchEditText)
|
||||
val search = view.findViewById<SearchView>(R.id.search)
|
||||
|
||||
(requireActivity().application as Pixeldroid).getAppComponent().inject(this)
|
||||
|
||||
button.setOnClickListener {
|
||||
val intent = Intent(context, SearchActivity::class.java)
|
||||
intent.putExtra("searchFeed", search.text.toString())
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
//Configure the search widget (see https://developer.android.com/guide/topics/search/search-dialog#ConfiguringWidget)
|
||||
val searchManager = requireActivity().getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||
search.setSearchableInfo(searchManager.getSearchableInfo(requireActivity().componentName))
|
||||
|
||||
search.isSubmitButtonEnabled = true
|
||||
|
||||
// Set posts RecyclerView as a grid with 3 columns
|
||||
recycler = view.findViewById(R.id.discoverList)
|
||||
recycler.layoutManager = GridLayoutManager(requireContext(), 3)
|
||||
adapter = DiscoverRecyclerViewAdapter()
|
||||
recycler.adapter = adapter
|
||||
|
||||
val discoverText = view.findViewById<TextView>(R.id.discoverText)
|
||||
|
||||
discoverText.setCompoundDrawables(IconicsDrawable(requireContext(), GoogleMaterial.Icon.gmd_explore).apply {
|
||||
sizeDp = 24
|
||||
paddingDp = 20
|
||||
}, null, null, null)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.h.pixeldroid.fragments.feeds
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
|
@ -43,7 +44,7 @@ open class AccountListFragment : FeedFragment() {
|
|||
|
||||
//RequestBuilder that is re-used for every image
|
||||
profilePicRequest = Glide.with(this)
|
||||
.asDrawable().apply(RequestOptions().circleCrop())
|
||||
.asDrawable().dontAnimate().apply(RequestOptions().circleCrop())
|
||||
.placeholder(R.drawable.ic_default_user)
|
||||
|
||||
adapter = AccountsRecyclerViewAdapter()
|
||||
|
@ -160,9 +161,11 @@ open class AccountListFragment : FeedFragment() {
|
|||
|
||||
override fun onBindViewHolder(holder : ViewHolder, position : Int) {
|
||||
val account = getItem(position) ?: return
|
||||
profilePicRequest.load(account.avatar_static).into(holder.avatar)
|
||||
profilePicRequest.load(account.avatar).into(holder.avatar)
|
||||
|
||||
holder.username.text = account.username
|
||||
@SuppressLint("SetTextI18n")
|
||||
holder.acct.text = "@${account.acct}"
|
||||
|
||||
holder.mView.setOnClickListener { account.openProfile(context) }
|
||||
}
|
||||
|
@ -170,6 +173,7 @@ open class AccountListFragment : FeedFragment() {
|
|||
inner class ViewHolder(val mView : View) : RecyclerView.ViewHolder(mView) {
|
||||
val avatar : ImageView = mView.account_entry_avatar
|
||||
val username : TextView = mView.account_entry_username
|
||||
val acct: TextView = mView.account_entry_acct
|
||||
}
|
||||
|
||||
override fun getPreloadItems(position : Int) : MutableList<Account> {
|
||||
|
|
|
@ -117,7 +117,7 @@ open class FeedFragment: Fragment() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Do nothing here, it is expected to pull to refresh to load newer notifications
|
||||
* Do nothing here, it is expected to pull to refresh to load newer items
|
||||
*/
|
||||
override fun loadBefore(params: LoadParams<ObjectId>, callback: LoadCallback<APIObject>) {}
|
||||
|
||||
|
|
|
@ -172,8 +172,8 @@ class OfflineFeedFragment: Fragment() {
|
|||
holder.itemView.postTabs.visibility = View.VISIBLE
|
||||
val tabs : ArrayList<ImageFragment> = ArrayList()
|
||||
//Fill the tabs with each mediaAttachment
|
||||
for(media in post.media_urls) {
|
||||
tabs.add(ImageFragment.newInstance(media))
|
||||
for((index, media) in post.media_urls.withIndex()) {
|
||||
tabs.add(ImageFragment.newInstance(media, "Photo $index"))
|
||||
}
|
||||
holder.itemView.postPager.adapter = object : FragmentStateAdapter(this@OfflineFeedFragment) {
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.Observer
|
||||
import androidx.paging.PagedList
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import at.connyduck.sparkbutton.SparkButton
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.ListPreloader
|
||||
|
@ -60,7 +61,7 @@ abstract class PostsFeedFragment : FeedFragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
val content = makeContent()
|
||||
content.observe(viewLifecycleOwner,
|
||||
Observer { c ->
|
||||
{ c ->
|
||||
adapter.submitList(c)
|
||||
//after a refresh is done we need to stop the pull to refresh spinner
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
|
@ -99,29 +100,12 @@ abstract class PostsFeedFragment : FeedFragment() {
|
|||
val post = getItem(position) ?: return
|
||||
val metrics = context.resources.displayMetrics
|
||||
//Limit the height of the different images
|
||||
holder.profilePic.maxHeight = metrics.heightPixels
|
||||
holder.postPic.maxHeight = metrics.heightPixels
|
||||
holder.postPic.maxHeight = metrics.heightPixels * 3/4
|
||||
|
||||
//Setup the post layout
|
||||
post.setupPost(holder.postView, picRequest, this@PostsFeedFragment, domain, false)
|
||||
|
||||
//Set the special HTML text
|
||||
post.setDescription(holder.postView, api, credential)
|
||||
|
||||
//Activate liker
|
||||
post.activateLiker(holder, api, credential, post.favourited ?: false)
|
||||
|
||||
//Activate double tap liking
|
||||
post.activateDoubleTapLiker(holder, api, credential)
|
||||
|
||||
//Show comments
|
||||
post.showComments(holder, api, credential)
|
||||
|
||||
//Activate Commenter
|
||||
post.activateCommenter(holder, api, credential)
|
||||
|
||||
//Activate Reblogger
|
||||
post.activateReblogger(holder, api ,credential, post.reblogged ?: false)
|
||||
post.activateButtons(holder, api, credential)
|
||||
}
|
||||
|
||||
override fun getPreloadItems(position: Int): MutableList<Status> {
|
||||
|
@ -160,4 +144,7 @@ class PostViewHolder(val postView: View, val context: android.content.Context) :
|
|||
val postDate : TextView = postView.findViewById(R.id.postDate)
|
||||
val postDomain : TextView = postView.findViewById(R.id.postDomain)
|
||||
val sensitiveW : TextView = postView.findViewById(R.id.sensitiveWarning)
|
||||
val postPager : ViewPager2 = postView.findViewById(R.id.postPager)
|
||||
|
||||
val more : ImageButton = postView.findViewById(R.id.status_more)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.h.pixeldroid.objects
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
data class Report(
|
||||
val id: String
|
||||
): Serializable
|
|
@ -1,29 +1,36 @@
|
|||
package com.h.pixeldroid.objects
|
||||
|
||||
import android.Manifest
|
||||
import android.app.DownloadManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.ColorMatrixColorFilter
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.text.Spanned
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.*
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.bumptech.glide.RequestBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.ReportActivity
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.ImageFragment
|
||||
import com.h.pixeldroid.fragments.feeds.postFeeds.PostViewHolder
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.getDomain
|
||||
import com.h.pixeldroid.utils.HtmlUtils.Companion.parseHTMLText
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import com.h.pixeldroid.utils.ImageUtils.Companion.downloadImage
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.censorColorMatrix
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.likePostCall
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.postComment
|
||||
|
@ -39,8 +46,9 @@ import com.karumi.dexter.listener.PermissionDeniedResponse
|
|||
import com.karumi.dexter.listener.PermissionGrantedResponse
|
||||
import com.karumi.dexter.listener.single.BasePermissionListener
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.*
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
import java.util.Date
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
/*
|
||||
|
@ -115,39 +123,70 @@ data class Status(
|
|||
return context.getString(R.string.shares).format(reblogs_count.toString())
|
||||
}
|
||||
|
||||
private fun getStatusDomain(domain : String) : String {
|
||||
private fun getStatusDomain(domain: String) : String {
|
||||
val accountDomain = getDomain(account!!.url)
|
||||
return if(getDomain(domain) == accountDomain) ""
|
||||
else " from $accountDomain"
|
||||
|
||||
}
|
||||
|
||||
private fun setupPostPics(rootView: View, request: RequestBuilder<Drawable>, homeFragment: Fragment) {
|
||||
private fun setupPostPics(
|
||||
rootView: View,
|
||||
request: RequestBuilder<Drawable>,
|
||||
homeFragment: Fragment
|
||||
) {
|
||||
|
||||
// Standard layout
|
||||
rootView.postPicture.visibility = VISIBLE
|
||||
rootView.postPager.visibility = GONE
|
||||
rootView.postTabs.visibility = GONE
|
||||
|
||||
if (sensitive!!) {
|
||||
setupSensitiveLayout(rootView, request, homeFragment)
|
||||
|
||||
if(media_attachments?.size == 1) {
|
||||
request.load(this.getPostUrl()).into(rootView.postPicture)
|
||||
val imgDescription = media_attachments[0].description.orEmpty().ifEmpty { rootView.context.getString(R.string.no_description) }
|
||||
rootView.postPicture.contentDescription = imgDescription
|
||||
|
||||
} else {
|
||||
rootView.sensitiveWarning.visibility = GONE
|
||||
|
||||
if(media_attachments?.size == 1) {
|
||||
request.load(this.getPostUrl()).into(rootView.postPicture)
|
||||
|
||||
} else if(media_attachments?.size!! > 1) {
|
||||
setupTabsLayout(rootView, request, homeFragment)
|
||||
rootView.postPicture.setOnLongClickListener {
|
||||
Snackbar.make(it, imgDescription, Snackbar.LENGTH_SHORT).show()
|
||||
true
|
||||
}
|
||||
|
||||
imagePopUpMenu(rootView, homeFragment.requireActivity())
|
||||
} else if(media_attachments?.size!! > 1) {
|
||||
setupTabsLayout(rootView, request, homeFragment)
|
||||
}
|
||||
|
||||
if (sensitive!!) {
|
||||
setupSensitiveLayout(rootView)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTabsLayout(rootView: View, request: RequestBuilder<Drawable>, homeFragment: Fragment) {
|
||||
private fun setupSensitiveLayout(view: View) {
|
||||
|
||||
// Set dark layout and warning message
|
||||
view.sensitiveWarning.visibility = VISIBLE
|
||||
view.postPicture.colorFilter = ColorMatrixColorFilter(censorColorMatrix())
|
||||
|
||||
fun uncensorPicture(view: View) {
|
||||
view.sensitiveWarning.visibility = GONE
|
||||
view.postPicture.colorFilter = ColorMatrixColorFilter(uncensorColorMatrix())
|
||||
}
|
||||
|
||||
|
||||
view.findViewById<TextView>(R.id.sensitiveWarning).setOnClickListener {
|
||||
uncensorPicture(view)
|
||||
}
|
||||
|
||||
view.findViewById<ImageView>(R.id.postPicture).setOnClickListener {
|
||||
uncensorPicture(view)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTabsLayout(
|
||||
rootView: View,
|
||||
request: RequestBuilder<Drawable>,
|
||||
homeFragment: Fragment
|
||||
) {
|
||||
//Only show the viewPager and tabs
|
||||
rootView.postPicture.visibility = GONE
|
||||
rootView.postPager.visibility = VISIBLE
|
||||
|
@ -157,7 +196,7 @@ data class Status(
|
|||
|
||||
//Fill the tabs with each mediaAttachment
|
||||
for(media in media_attachments!!) {
|
||||
tabs.add(ImageFragment.newInstance(media.url!!))
|
||||
tabs.add(ImageFragment.newInstance(media.url!!, media.description.orEmpty()))
|
||||
}
|
||||
|
||||
setupTabs(tabs, rootView, homeFragment)
|
||||
|
@ -185,8 +224,8 @@ data class Status(
|
|||
rootView: View,
|
||||
request: RequestBuilder<Drawable>,
|
||||
homeFragment: Fragment,
|
||||
domain : String,
|
||||
isActivity : Boolean
|
||||
domain: String,
|
||||
isActivity: Boolean
|
||||
) {
|
||||
//Setup username as a button that opens the profile
|
||||
rootView.findViewById<TextView>(R.id.username).apply {
|
||||
|
@ -233,10 +272,8 @@ data class Status(
|
|||
rootView.findViewById<LinearLayout>(R.id.commentIn).visibility = GONE
|
||||
}
|
||||
|
||||
fun setDescription(rootView: View, api : PixelfedAPI, credential: String) {
|
||||
val desc = rootView.findViewById<TextView>(R.id.description)
|
||||
|
||||
desc.apply {
|
||||
fun setDescription(rootView: View, api: PixelfedAPI, credential: String) {
|
||||
rootView.findViewById<TextView>(R.id.description).apply {
|
||||
if (content.isNullOrBlank()) {
|
||||
visibility = GONE
|
||||
} else {
|
||||
|
@ -246,11 +283,35 @@ data class Status(
|
|||
}
|
||||
}
|
||||
|
||||
fun activateButtons(holder: PostViewHolder, api: PixelfedAPI, credential: String){
|
||||
|
||||
//Set the special HTML text
|
||||
setDescription(holder.postView, api, credential)
|
||||
|
||||
//Activate onclickListeners
|
||||
activateLiker(
|
||||
holder, api, credential,
|
||||
this.favourited ?: false
|
||||
)
|
||||
activateReblogger(
|
||||
holder, api, credential,
|
||||
this.reblogged ?: false
|
||||
)
|
||||
activateCommenter(holder, api, credential)
|
||||
|
||||
showComments(holder, api, credential)
|
||||
|
||||
//Activate double tap liking
|
||||
activateDoubleTapLiker(holder, api, credential)
|
||||
|
||||
activateMoreButton(holder)
|
||||
}
|
||||
|
||||
fun activateReblogger(
|
||||
holder : PostViewHolder,
|
||||
api : PixelfedAPI,
|
||||
holder: PostViewHolder,
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
isReblogged : Boolean
|
||||
isReblogged: Boolean
|
||||
) {
|
||||
holder.reblogger.apply {
|
||||
//Set initial button state
|
||||
|
@ -271,8 +332,165 @@ data class Status(
|
|||
}
|
||||
}
|
||||
|
||||
fun downloadImage(context: Context, url: String, view: View, share: Boolean = false) {
|
||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
|
||||
val downloadUri = Uri.parse(url)
|
||||
|
||||
val title = url.substringAfterLast("/")
|
||||
val request = DownloadManager.Request(downloadUri).apply {
|
||||
setTitle(title)
|
||||
if(!share) {
|
||||
val directory = File(Environment.DIRECTORY_PICTURES)
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
setDestinationInExternalPublicDir(directory.toString(), title)
|
||||
}
|
||||
}
|
||||
val downloadId = downloadManager.enqueue(request)
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
|
||||
Thread {
|
||||
|
||||
var msg = ""
|
||||
var lastMsg = ""
|
||||
var downloading = true
|
||||
|
||||
while (downloading) {
|
||||
val cursor: Cursor = downloadManager.query(query)
|
||||
cursor.moveToFirst()
|
||||
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
== DownloadManager.STATUS_SUCCESSFUL
|
||||
) {
|
||||
downloading = false
|
||||
}
|
||||
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
if (!share) {
|
||||
msg = when (status) {
|
||||
DownloadManager.STATUS_FAILED ->
|
||||
context.getString(R.string.image_download_failed)
|
||||
DownloadManager.STATUS_RUNNING ->
|
||||
context.getString(R.string.image_download_downloading)
|
||||
DownloadManager.STATUS_SUCCESSFUL ->
|
||||
context.getString(R.string.image_download_success)
|
||||
else -> ""
|
||||
}
|
||||
if (msg != lastMsg && msg != "") {
|
||||
Snackbar.make(view, msg, Snackbar.LENGTH_SHORT).show()
|
||||
lastMsg = msg
|
||||
}
|
||||
} else if (status == DownloadManager.STATUS_SUCCESSFUL) {
|
||||
|
||||
val ext = url.substringAfterLast(".", "*")
|
||||
|
||||
val path = cursor.getString(
|
||||
cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
|
||||
)
|
||||
val file = path.toUri()
|
||||
|
||||
val shareIntent: Intent = Intent.createChooser(Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
putExtra(Intent.EXTRA_STREAM, file)
|
||||
data = file
|
||||
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
type = "image/$ext"
|
||||
}, null)
|
||||
|
||||
context.startActivity(shareIntent)
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun activateMoreButton(holder: PostViewHolder){
|
||||
holder.more.setOnClickListener {
|
||||
PopupMenu(it.context, it).apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.post_more_menu_report -> {
|
||||
val intent = Intent(it.context, ReportActivity::class.java)
|
||||
intent.putExtra(POST_TAG, this@Status)
|
||||
startActivity(it.context, intent, null)
|
||||
true
|
||||
}
|
||||
R.id.post_more_menu_share_link -> {
|
||||
val share = Intent.createChooser(Intent().apply {
|
||||
action = Intent.ACTION_SEND
|
||||
putExtra(Intent.EXTRA_TEXT, uri)
|
||||
|
||||
type = "text/plain"
|
||||
|
||||
putExtra(Intent.EXTRA_TITLE, content)
|
||||
}, null)
|
||||
startActivity(it.context, share, null)
|
||||
|
||||
true
|
||||
}
|
||||
R.id.post_more_menu_save_to_gallery -> {
|
||||
Dexter.withContext(holder.context)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(object : BasePermissionListener() {
|
||||
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
|
||||
Toast.makeText(
|
||||
holder.context,
|
||||
holder.context.getString(R.string.write_permission_download_pic),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
|
||||
downloadImage(
|
||||
holder.context,
|
||||
media_attachments?.get(holder.postPager.currentItem)?.url
|
||||
?: "",
|
||||
holder.postView
|
||||
)
|
||||
}
|
||||
}).check()
|
||||
true
|
||||
}
|
||||
R.id.post_more_menu_share_picture -> {
|
||||
Dexter.withContext(holder.context)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(object : BasePermissionListener() {
|
||||
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
|
||||
Toast.makeText(
|
||||
holder.context,
|
||||
holder.context.getString(R.string.write_permission_share_pic),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
|
||||
downloadImage(
|
||||
holder.context,
|
||||
media_attachments?.get(holder.postPager.currentItem)?.url
|
||||
?: "",
|
||||
holder.postView,
|
||||
share = true,
|
||||
)
|
||||
}
|
||||
}).check()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
inflate(R.menu.post_more_menu)
|
||||
if(media_attachments.isNullOrEmpty()) {
|
||||
//make sure to disable image-related things if there aren't any
|
||||
menu.setGroupVisible(R.id.post_more_group_picture, false)
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun activateDoubleTapLiker(
|
||||
holder : PostViewHolder,
|
||||
holder: PostViewHolder,
|
||||
api: PixelfedAPI,
|
||||
credential: String
|
||||
) {
|
||||
|
@ -305,7 +523,7 @@ data class Status(
|
|||
}
|
||||
|
||||
fun activateLiker(
|
||||
holder : PostViewHolder,
|
||||
holder: PostViewHolder,
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
isLiked: Boolean
|
||||
|
@ -332,7 +550,7 @@ data class Status(
|
|||
|
||||
|
||||
fun showComments(
|
||||
holder : PostViewHolder,
|
||||
holder: PostViewHolder,
|
||||
api: PixelfedAPI,
|
||||
credential: String
|
||||
) {
|
||||
|
@ -353,19 +571,23 @@ data class Status(
|
|||
}
|
||||
|
||||
fun activateCommenter(
|
||||
holder : PostViewHolder,
|
||||
holder: PostViewHolder,
|
||||
api: PixelfedAPI,
|
||||
credential: String
|
||||
) {
|
||||
//Toggle comment button
|
||||
toggleCommentInput(holder)
|
||||
|
||||
//Activate commenter
|
||||
//Activate commenterpostPicture
|
||||
holder.submitCmnt.setOnClickListener {
|
||||
val textIn = holder.comment.text
|
||||
//Open text input
|
||||
if(textIn.isNullOrEmpty()) {
|
||||
Toast.makeText(holder.context, holder.context.getString(R.string.empty_comment), Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(
|
||||
holder.context,
|
||||
holder.context.getString(R.string.empty_comment),
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
} else {
|
||||
|
||||
//Post the comment
|
||||
|
@ -377,78 +599,4 @@ data class Status(
|
|||
enum class Visibility : Serializable {
|
||||
public, unlisted, private, direct
|
||||
}
|
||||
|
||||
|
||||
private fun imagePopUpMenu(view: View, activity: FragmentActivity) {
|
||||
val anchor = view.findViewById<FrameLayout>(R.id.post_fragment_image_popup_menu_anchor)
|
||||
if (!media_attachments.isNullOrEmpty() && media_attachments.size == 1) {
|
||||
view.findViewById<ImageView>(R.id.postPicture).setOnLongClickListener {
|
||||
PopupMenu(view.context, anchor).apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.image_popup_menu_save_to_gallery -> {
|
||||
Dexter.withContext(view.context)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(object: BasePermissionListener() {
|
||||
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
|
||||
Toast.makeText(view.context, view.context.getString(R.string.write_permission_download_pic), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
|
||||
downloadImage(activity, getPostUrl()!!)
|
||||
}
|
||||
}).check()
|
||||
true
|
||||
}
|
||||
R.id.image_popup_menu_share_picture -> {
|
||||
Dexter.withContext(view.context)
|
||||
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.withListener(object: BasePermissionListener() {
|
||||
override fun onPermissionDenied(p0: PermissionDeniedResponse?) {
|
||||
Toast.makeText(view.context, view.context.getString(R.string.write_permission_share_pic), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
|
||||
downloadImage(activity, getPostUrl()!!, share = true)
|
||||
}
|
||||
}).check()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
inflate(R.menu.image_popup_menu)
|
||||
show()
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSensitiveLayout(view: View, request: RequestBuilder<Drawable>, homeFragment: Fragment) {
|
||||
|
||||
// Set dark layout and warning message
|
||||
view.sensitiveWarning.visibility = VISIBLE
|
||||
view.postPicture.colorFilter = ColorMatrixColorFilter(censorColorMatrix())
|
||||
|
||||
fun uncensorPicture(view: View) {
|
||||
if (!media_attachments.isNullOrEmpty()) {
|
||||
view.sensitiveWarning.visibility = GONE
|
||||
view.postPicture.colorFilter = ColorMatrixColorFilter(uncensorColorMatrix())
|
||||
|
||||
if (media_attachments.size > 1)
|
||||
setupTabsLayout(view, request, homeFragment)
|
||||
}
|
||||
imagePopUpMenu(view, homeFragment.requireActivity())
|
||||
}
|
||||
|
||||
|
||||
view.findViewById<TextView>(R.id.sensitiveWarning).setOnClickListener {
|
||||
uncensorPicture(view)
|
||||
}
|
||||
|
||||
view.findViewById<ImageView>(R.id.postPicture).setOnClickListener {
|
||||
uncensorPicture(view)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
package com.h.pixeldroid.utils
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.provider.MediaStore.Images
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.h.pixeldroid.R
|
||||
import java.io.File
|
||||
|
||||
|
||||
class ImageUtils {
|
||||
companion object {
|
||||
fun downloadImage(activity: FragmentActivity, url: String, share: Boolean = false) {
|
||||
val context = activity.applicationContext
|
||||
var msg = ""
|
||||
var lastMsg = ""
|
||||
val directory = File(Environment.DIRECTORY_PICTURES)
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs()
|
||||
}
|
||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE)
|
||||
as DownloadManager
|
||||
val downloadUri = Uri.parse(url)
|
||||
val title = url.substring(url.lastIndexOf("/") + 1)
|
||||
val ext = url.substring(url.lastIndexOf("."))
|
||||
val request = DownloadManager.Request(downloadUri).apply {
|
||||
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
|
||||
or DownloadManager.Request.NETWORK_MOBILE)
|
||||
setTitle(title)
|
||||
setDestinationInExternalPublicDir(directory.toString(), title)
|
||||
}
|
||||
val downloadId = downloadManager.enqueue(request)
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
|
||||
Thread(Runnable {
|
||||
var downloading = true
|
||||
while (downloading) {
|
||||
val cursor: Cursor = downloadManager.query(query)
|
||||
cursor.moveToFirst()
|
||||
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
== DownloadManager.STATUS_SUCCESSFUL) {
|
||||
downloading = false
|
||||
}
|
||||
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
|
||||
if(!share) {
|
||||
msg = when (status) {
|
||||
DownloadManager.STATUS_FAILED ->
|
||||
context.getString(R.string.image_download_failed)
|
||||
DownloadManager.STATUS_RUNNING ->
|
||||
context.getString(R.string.image_download_downloading)
|
||||
DownloadManager.STATUS_SUCCESSFUL ->
|
||||
context.getString(R.string.image_download_success)
|
||||
else -> ""
|
||||
}
|
||||
if (msg != lastMsg && msg != "") {
|
||||
activity.runOnUiThread {
|
||||
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
lastMsg = msg
|
||||
}
|
||||
} else if (status == DownloadManager.STATUS_SUCCESSFUL) {
|
||||
val icon: Bitmap = BitmapFactory.decodeFile(
|
||||
Uri.parse(cursor.getString(
|
||||
cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
|
||||
)).path
|
||||
)
|
||||
val intentShare = Intent(Intent.ACTION_SEND)
|
||||
intentShare.type = "image/$ext"
|
||||
val values = ContentValues()
|
||||
values.put(Images.Media.TITLE, title)
|
||||
values.put(Images.Media.MIME_TYPE, "image/$ext")
|
||||
val uri: Uri = context.contentResolver.insert(
|
||||
Images.Media.EXTERNAL_CONTENT_URI,
|
||||
values
|
||||
)!!
|
||||
try {
|
||||
val outstream = context.contentResolver.openOutputStream(uri)!!
|
||||
icon.compress(Bitmap.CompressFormat.JPEG, 100, outstream)
|
||||
outstream.close()
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
intentShare.putExtra(Intent.EXTRA_STREAM, uri)
|
||||
activity.startActivity(Intent.createChooser(intentShare, context.getString(R.string.share_image)))
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,7v2.99s-1.99,0.01 -2,0L17,7h-3s0.01,-1.99 0,-2h3L17,2h2v3h3v2h-3zM16,11L16,8h-3L13,5L5,5c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-8h-3zM5,19l3,-4 2,3 3,-4 4,5L5,19z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,7v2.99s-1.99,0.01 -2,0L17,7h-3s0.01,-1.99 0,-2h3L17,2h2v3h3v2h-3zM16,11L16,8h-3L13,5L5,5c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2v-8h-3zM5,19l3,-4 2,3 3,-4 4,5L5,19z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
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_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/account_entry_avatar"
|
||||
|
@ -11,20 +11,31 @@
|
|||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:contentDescription="TODO"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@drawable/ic_default_user"
|
||||
android:contentDescription="TODO" />
|
||||
tools:src="@drawable/ic_default_user" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/account_entry_username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="28dp"
|
||||
android:text="TextView"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintStart_toEndOf="@+id/account_entry_avatar"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="@+id/account_entry_avatar"
|
||||
tools:text="Username" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/account_entry_acct"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/account_entry_avatar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/account_entry_username"
|
||||
app:layout_constraintTop_toBottomOf="@id/account_entry_username"
|
||||
tools:text="\@username@domain.tld" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".CameraActivity">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/camera_activity_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -10,22 +10,27 @@
|
|||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/main_activity_main_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/main_toolbar"
|
||||
<LinearLayout
|
||||
android:id="@+id/main_activity_main_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorPrimaryTab"
|
||||
app:contentInsetStartWithNavigation="0dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:navigationContentDescription="Open drawer menu"
|
||||
app:navigationIcon="@drawable/ic_baseline_menu_24">
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/main_drawer_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorPrimaryTab"
|
||||
android:contentDescription="@string/open_drawer_menu"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_baseline_menu_24" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabs"
|
||||
|
@ -36,19 +41,17 @@
|
|||
app:tabMaxWidth="0dp"
|
||||
app:tabMode="fixed"
|
||||
app:tabUnboundedRipple="false" />
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/view_pager"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||
app:layout_constraintBottom_toTopOf="@+id/main_toolbar"
|
||||
app:layout_constraintBottom_toTopOf="@+id/main_activity_main_linear_layout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -84,14 +84,4 @@
|
|||
app:layout_constraintRight_toRightOf="@+id/right_guideline"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/bottom_guideline" />
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorPrimaryActionBar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -17,15 +17,19 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/postFragmentSingle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/postFragmentSingle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" >
|
||||
</androidx.fragment.app.FragmentContainerView>
|
||||
</ScrollView>
|
||||
|
||||
</androidx.fragment.app.FragmentContainerView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -42,17 +42,29 @@
|
|||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
<com.mikepenz.iconics.view.IconicsTextView
|
||||
android:id="@+id/upload_completed_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/media_upload_completed"
|
||||
android:textColor="@android:color/holo_green_light"
|
||||
android:textSize="16sp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/image_grid"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/postTextInputLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
>
|
||||
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
app:layout_constraintTop_toBottomOf="@id/upload_completed_textview" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/buttonConstraints"
|
||||
|
@ -61,7 +73,7 @@
|
|||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/textInputLayout2">
|
||||
app:layout_constraintTop_toTopOf="@id/postTextInputLayout">
|
||||
|
||||
<Button
|
||||
android:id="@+id/post_creation_send_button"
|
||||
|
@ -70,7 +82,7 @@
|
|||
android:backgroundTint="@color/colorButtonBg"
|
||||
android:enabled="false"
|
||||
android:visibility="gone"
|
||||
android:text="@string/send"
|
||||
android:text="@string/post"
|
||||
android:textColor="@color/colorButtonText"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -93,12 +105,12 @@
|
|||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@id/textInputLayout2"
|
||||
app:layout_constraintBottom_toTopOf="@id/postTextInputLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textInputLayout2"
|
||||
android:id="@+id/postTextInputLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/description"
|
||||
|
@ -121,16 +133,4 @@
|
|||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.mikepenz.iconics.view.IconicsTextView
|
||||
android:id="@+id/upload_completed_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="@string/media_upload_completed"
|
||||
android:textColor="@android:color/holo_green_light"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -6,7 +6,7 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context=".ProfileActivity">
|
||||
|
||||
<ScrollView
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
@ -165,10 +165,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="5dp"
|
||||
android:nestedScrollingEnabled="false"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
tools:context=".fragments.ProfileFragment"
|
||||
tools:listitem="@layout/fragment_profile_posts" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ReportActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/report_target_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/textInputLayout"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Reporting @user's post:" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textInputLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="1000"
|
||||
app:layout_constraintBottom_toTopOf="@+id/reportButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/optional_report_comment"
|
||||
android:inputType="text|textCapSentences|textMultiLine"
|
||||
android:lines="8" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<com.mikepenz.iconics.view.IconicsButton
|
||||
android:id="@+id/reportButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/report"
|
||||
android:textColor="@color/colorText"
|
||||
android:backgroundTint="@color/colorPrimary"
|
||||
app:iconGravity="end"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.75" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/reportProgressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/reportButton"
|
||||
app:layout_constraintEnd_toEndOf="@+id/reportButton"
|
||||
app:layout_constraintStart_toStartOf="@+id/reportButton"
|
||||
app:layout_constraintTop_toTopOf="@+id/reportButton" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.h.pixeldroid.utils.SquareLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/add_photo_alternate_black_24dp" />
|
||||
</com.h.pixeldroid.utils.SquareLayout>
|
|
@ -11,7 +11,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="TODO" />
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
|
||||
</FrameLayout>
|
|
@ -1,24 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.gridlayout.widget.GridLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:flexWrap="wrap"
|
||||
app:justifyContent="center">
|
||||
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="5dp">
|
||||
app:columnCount="3">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ImageView
|
||||
android:id="@+id/postPreview"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:contentDescription="TODO" />
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintDimensionRatio="H,1:1"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:contentDescription="TODO"
|
||||
android:padding="1dp"
|
||||
app:layout_gravity="fill"
|
||||
app:layout_rowWeight="1"
|
||||
app:layout_columnWeight="1"/>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.gridlayout.widget.GridLayout>
|
||||
|
||||
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
|
|
|
@ -1,50 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal">
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
<androidx.appcompat.widget.SearchView
|
||||
android:id="@+id/search"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dp"
|
||||
android:gravity="center"
|
||||
android:hint="@string/search"
|
||||
app:errorEnabled="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/searchButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/searchEditText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textUri" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/searchButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:backgroundTint="@color/colorButtonBg"
|
||||
android:text="@string/search"
|
||||
android:textColor="@color/colorButtonText"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/search"
|
||||
app:iconifiedByDefault="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/search" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:queryHint="@string/search" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/discoverProgressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -54,21 +32,33 @@
|
|||
android:id="@+id/discoverRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/discoverList"
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
app:layoutManager="com.google.android.flexbox.FlexboxLayoutManager"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search" />
|
||||
android:layout_height="match_parent">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/discoverText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/discover"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/discoverList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:nestedScrollingEnabled="false"/>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,23 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.h.pixeldroid.utils.SquareLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/container"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/galleryImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="centerCrop"/>
|
||||
android:padding="8dp"
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/ic_baseline_edit_24"/>
|
||||
</RelativeLayout>
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/circle_black_24dp"
|
||||
android:backgroundTint="#7A3E3C3C"
|
||||
android:foreground="@drawable/ic_baseline_edit_24"
|
||||
android:foregroundGravity="center"
|
||||
android:foregroundTint="#FFFFFF"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.h.pixeldroid.utils.SquareLayout>
|
|
@ -4,17 +4,10 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
xmlns:sparkbutton="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".fragments.PostFragment">
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -33,16 +26,18 @@
|
|||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/ic_default_user"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:contentDescription="@string/profile_picture" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/profilePic"
|
||||
app:layout_constraintStart_toEndOf="@+id/profilePic"
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"/>
|
||||
android:id="@+id/username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/profilePic"
|
||||
app:layout_constraintStart_toEndOf="@+id/profilePic"
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"
|
||||
tools:text="username" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/postDomain"
|
||||
|
@ -51,14 +46,14 @@
|
|||
android:textColor="#b3b3b3"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/profilePic"
|
||||
app:layout_constraintStart_toEndOf="@+id/username"
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"/>
|
||||
app:layout_constraintTop_toTopOf="@+id/profilePic"
|
||||
tools:text=" from domain.tld" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/postConstraint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:adjustViewBounds="true"
|
||||
app:layout_constraintTop_toBottomOf="@+id/profilePic">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
|
@ -87,7 +82,7 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@color/browser_actions_bg_grey"
|
||||
android:longClickable="true" />
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/post_fragment_image_popup_menu_anchor"
|
||||
|
@ -106,11 +101,13 @@
|
|||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:gravity="center|center_horizontal|center_vertical"
|
||||
android:longClickable="true"
|
||||
android:text="@string/cw_nsfw_hidden_media_n_click_to_show"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
|
||||
android:textColor="@color/ic_launcher_background"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/postPicture"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/postTabs"
|
||||
tools:src="@color/browser_actions_bg_grey" />
|
||||
|
||||
|
@ -121,7 +118,6 @@
|
|||
android:id="@+id/commenter"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="4dp"
|
||||
android:src="@drawable/ic_comment_empty"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/liker"
|
||||
|
@ -137,7 +133,6 @@
|
|||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:clipToPadding="false"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="4dp"
|
||||
sparkbutton:activeImage="@drawable/ic_like_full"
|
||||
sparkbutton:iconSize="28dp"
|
||||
|
@ -154,7 +149,6 @@
|
|||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:clipToPadding="false"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/commenter"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -166,6 +160,17 @@
|
|||
sparkbutton:primaryColor="@color/share_blue"
|
||||
sparkbutton:secondaryColor="@color/black"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/status_more"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:contentDescription="@string/status_more_options"
|
||||
android:padding="4dp"
|
||||
style="?android:attr/actionOverflowButtonStyle"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/postDomain"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/postDomain" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nlikes"
|
||||
|
@ -182,7 +187,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="50"
|
||||
android:gravity="right"
|
||||
android:gravity="end"
|
||||
app:layout_constraintEnd_toEndOf="@+id/reblogger"
|
||||
app:layout_constraintStart_toStartOf="@+id/reblogger"
|
||||
app:layout_constraintTop_toBottomOf="@+id/reblogger"
|
||||
|
@ -214,7 +219,7 @@
|
|||
android:textColor="#b3b3b3"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
tools:text="time" />
|
||||
tools:text="Yesterday" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/commentIn"
|
||||
|
@ -234,7 +239,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/comment"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="text" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
@ -262,15 +266,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
tools:text="TextView"/>
|
||||
tools:text="3 comments"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
|
||||
</FrameLayout>
|
|
@ -1,18 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/filter_name"
|
||||
android:text="FILTER_NAME"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
tools:text="FILTER_NAME" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/thumbnail"
|
||||
|
@ -20,5 +21,5 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:contentDescription="thumbnail of filter" />
|
||||
android:contentDescription="Thumbnail of filter" />
|
||||
</LinearLayout>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/image_popup_menu_save_to_gallery"
|
||||
android:title="@string/save_to_gallery"/>
|
||||
<item android:id="@+id/image_popup_menu_share_picture"
|
||||
android:title="@string/share_picture"/>
|
||||
</menu>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@+id/post_more_menu_report"
|
||||
android:title="@string/report" />
|
||||
<item android:id="@+id/post_more_menu_share_link"
|
||||
android:title="@string/share_link" />
|
||||
|
||||
|
||||
<!-- Group that should only be shown if there are pictures in the post -->
|
||||
<group android:id="@+id/post_more_group_picture">
|
||||
<item android:id="@+id/post_more_menu_share_picture"
|
||||
android:title="@string/share_picture"/>
|
||||
<item android:id="@+id/post_more_menu_save_to_gallery"
|
||||
android:title="@string/save_to_gallery"/>
|
||||
</group>
|
||||
</menu>
|
|
@ -15,7 +15,7 @@
|
|||
<string name="auth_failed">فشلت المصادقة</string>
|
||||
<string name="followed_notification">يتابعك %1$s</string>
|
||||
<string name="description">الوصف…</string>
|
||||
<string name="send">ارسل</string>
|
||||
<string name="post">ارسل</string>
|
||||
<string name="whats_an_instance">ماذا نعني بمثيل الخادم؟</string>
|
||||
<string name="logout">الخروج</string>
|
||||
<string name="tab_filters">الفلاتر</string>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<string name="save_to_gallery">Desar a la galeria…</string>
|
||||
<string name="logout">Tancar sessió</string>
|
||||
<string name="whats_an_instance">Què és una instància\?</string>
|
||||
<string name="send">enviar</string>
|
||||
<string name="post">enviar</string>
|
||||
<string name="description">Descripció…</string>
|
||||
<string name="liked_notification">%1$s ha dona\'t m\'agrada a la teva publicació</string>
|
||||
<string name="theme_title">Tema de l\'aplicació</string>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<string name="mention_notification">%1$s hat dich erwähnt</string>
|
||||
<string name="shared_notification">%1$s hat deinen Beitrag geteilt</string>
|
||||
<string name="liked_notification">%1$s hat deinen Beitrag favorisiert</string>
|
||||
<string name="send">senden</string>
|
||||
<string name="post">senden</string>
|
||||
<string name="whats_an_instance">Was ist eine Instanz\?</string>
|
||||
<string name="theme_title">Erscheinungsbild</string>
|
||||
<string name="description">Beschreibung…</string>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<string name="shared_notification">%1$s compartió tu publicación</string>
|
||||
<string name="liked_notification">%1$s le gustó tu publicación</string>
|
||||
<string name="description">Descripción…</string>
|
||||
<string name="send">enviar</string>
|
||||
<string name="post">enviar</string>
|
||||
<string name="whats_an_instance">¿Qué es una instancia\?</string>
|
||||
<string name="logout">Cerrar sesión</string>
|
||||
<string name="save_to_gallery">Guardar en la galería…</string>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<string name="save_to_gallery">Gorde galerian…</string>
|
||||
<string name="logout">Saioa Itxi</string>
|
||||
<string name="whats_an_instance">Zer da instantzia bat\?</string>
|
||||
<string name="send">bidali</string>
|
||||
<string name="post">bidali</string>
|
||||
<string name="description">Deskribapena…</string>
|
||||
<string name="mention_notification">%1$s erabiltzaileak aipatu zaitu</string>
|
||||
<string name="followed_notification">%1$s jarraitzen hasi zaizu</string>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<string name="shared_notification">%1$s مطلب شما را همرسانی کرد</string>
|
||||
<string name="liked_notification">%1$s مطلب شما را پسندید</string>
|
||||
<string name="description">توضیحات…</string>
|
||||
<string name="send">بفرست</string>
|
||||
<string name="post">بفرست</string>
|
||||
<string name="whats_an_instance">یک نمونه چیست؟</string>
|
||||
<string name="logout">خروج</string>
|
||||
<string name="lbl_brightness">روشنایی</string>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<string name="shared_notification">%1$s a partagé votre publication</string>
|
||||
<string name="liked_notification">%1$s a aimé votre publication</string>
|
||||
<string name="description">Description…</string>
|
||||
<string name="send">envoyer</string>
|
||||
<string name="post">envoyer</string>
|
||||
<string name="whats_an_instance">Qu\'est-ce qu\'une instance \?</string>
|
||||
<string name="logout">Se déconnecter</string>
|
||||
<string name="save_to_gallery">Sauvegarder dans la galerie…</string>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<string name="liked_notification">a %1$s gustoulle a publicación</string>
|
||||
<string name="shared_notification">%1$s comparteu a publicación</string>
|
||||
<string name="description">Descrición…</string>
|
||||
<string name="send">enviar</string>
|
||||
<string name="post">enviar</string>
|
||||
<string name="whats_an_instance">Que é unha instancia\?</string>
|
||||
<string name="logout">Saír</string>
|
||||
<string name="lbl_brightness">BRILLO</string>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<string name="mention_notification">%1$s ti ha menzionato</string>
|
||||
<string name="liked_notification">%1$s è piaciuto il tuo post</string>
|
||||
<string name="tab_filters">FILTRI</string>
|
||||
<string name="send">invia</string>
|
||||
<string name="post">invia</string>
|
||||
<string name="lbl_brightness">LUMINOSITÀ</string>
|
||||
<string name="description">Descrizione…</string>
|
||||
<string name="whats_an_instance">Cos\'è un\'istanza\?</string>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<string name="followed_notification">%1$s さんにフォローされました</string>
|
||||
<string name="liked_notification">%1$s さんがあなたの投稿をお気に入りに登録しました</string>
|
||||
<string name="description">説明…</string>
|
||||
<string name="send">送信</string>
|
||||
<string name="post">送信</string>
|
||||
<string name="whats_an_instance">インスタンスとは?</string>
|
||||
<string name="logout">ログアウト</string>
|
||||
<string name="lbl_brightness">輝度</string>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<string name="menu_account">Mijn profiel</string>
|
||||
<string name="logout">Log uit</string>
|
||||
<string name="whats_an_instance">Wat is een instance\?</string>
|
||||
<string name="send">stuur</string>
|
||||
<string name="post">stuur</string>
|
||||
<string name="description">Beschrijving…</string>
|
||||
<string name="liked_notification">%1$s vond je bericht leuk</string>
|
||||
<string name="shared_notification">%1$s heeft je bericht gedeeld</string>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<string name="lbl_brightness">BRILHO</string>
|
||||
<string name="logout">Sair</string>
|
||||
<string name="whats_an_instance">O que é uma instância\?</string>
|
||||
<string name="send">enviar</string>
|
||||
<string name="post">enviar</string>
|
||||
<string name="description">Descrição…</string>
|
||||
<string name="liked_notification">%1$s curtiu o seu post</string>
|
||||
<string name="shared_notification">%1$s compartilhou o seu post</string>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<string name="followed_notification">%1$s подписался(-лась) на вас</string>
|
||||
<string name="mention_notification">%1$s упомянул(а) вас</string>
|
||||
<string name="shared_notification">%1$s поделился(-лась) вашим постом</string>
|
||||
<string name="send">отправить</string>
|
||||
<string name="post">отправить</string>
|
||||
<string name="logout">Выйти</string>
|
||||
<string name="lbl_brightness">ЯРКОСТЬ</string>
|
||||
<string name="whats_an_instance">Что такое инстанс\?</string>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<string name="shared_notification">%1$s delande ditt inlägg</string>
|
||||
<string name="liked_notification">%1$s gillar ditt inlägg</string>
|
||||
<string name="description">Beskrivning…</string>
|
||||
<string name="send">skicka</string>
|
||||
<string name="post">skicka</string>
|
||||
<string name="whats_an_instance">Vad är en instans\?</string>
|
||||
<string name="logout">Logga ut</string>
|
||||
<string name="lbl_brightness">LJUSSTYRKA</string>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<string name="theme_header">Тема</string>
|
||||
<string name="mention_notification">%1$s згадав(-ла) вас</string>
|
||||
<string name="description">Опис…</string>
|
||||
<string name="send">відправити</string>
|
||||
<string name="post">відправити</string>
|
||||
<string name="lbl_brightness">Яскравість</string>
|
||||
<string name="lbl_contrast">Контраст</string>
|
||||
<string name="lbl_saturation">Насичення</string>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<string name="auth_failed">无法验证</string>
|
||||
<string name="token_error">获取验证令牌时出错</string>
|
||||
<string name="theme_header">主题</string>
|
||||
<string name="send">发送</string>
|
||||
<string name="post">发送</string>
|
||||
<string name="logout">注销</string>
|
||||
<string name="app_name">PixelDroid</string>
|
||||
<string name="title_activity_settings2">配置</string>
|
||||
|
|
|
@ -44,8 +44,9 @@
|
|||
<string name="upload_post_success">Post uploaded successfully</string>
|
||||
<string name="upload_post_error">Post upload failed</string>
|
||||
<string name="description">Description…</string>
|
||||
<string name="send">send</string>
|
||||
<!-- Post edition -->
|
||||
<string name="post">post</string>
|
||||
<string name="add_photo">Add a photo</string>
|
||||
<!-- Post editing -->
|
||||
<string name="lbl_brightness">BRIGHTNESS</string>
|
||||
<string name="lbl_contrast">CONTRAST</string>
|
||||
<string name="lbl_saturation">SATURATION</string>
|
||||
|
@ -121,6 +122,19 @@
|
|||
<string name="post_title">%1$s\'s post</string>
|
||||
<string name="followers_title">%1$s\'s followers</string>
|
||||
<string name="follows_title">%1$s\'s follows</string>
|
||||
<string name="search_empty_error">Search query can\'t be empty</string>
|
||||
<string name="status_more_options">More options</string>
|
||||
<string name="report">Report</string>
|
||||
<string name="share_link">Share Link</string>
|
||||
<string name="optional_report_comment">Optional message for mods/admins</string>
|
||||
<string name="report_target">Report @%1$s\'s post</string>
|
||||
<!-- Text on button, shown when report was successful. {gmd_check_circle} is an icon, position it as is appropriate in target language -->
|
||||
<string name="reported">Reported {gmd_check_circle}</string>
|
||||
<string name="report_error">Could not send report</string>
|
||||
<string name="toolbar_title_edit">Edit</string>
|
||||
<string name="profile_picture">Profile picture</string>
|
||||
<string name="open_drawer_menu">Open drawer menu</string>
|
||||
<string name="discover">DISCOVER</string>
|
||||
|
||||
|
||||
</resources>
|
|
@ -24,6 +24,5 @@
|
|||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<PreferenceCategory app:title="@string/theme_header">
|
||||
<ListPreference
|
||||
app:defaultValue="@string/default_theme"
|
||||
app:defaultValue="default"
|
||||
app:entries="@array/theme_entries"
|
||||
app:entryValues="@array/theme_values"
|
||||
app:key="theme"
|
||||
|
@ -13,5 +13,9 @@
|
|||
|
||||
<Preference android:title="@string/about"
|
||||
android:key="about"
|
||||
android:summary="@string/about_pixeldroid"/>
|
||||
android:summary="@string/about_pixeldroid">
|
||||
<intent
|
||||
android:targetPackage="com.h.pixeldroid"
|
||||
android:targetClass="com.h.pixeldroid.AboutActivity"/>
|
||||
</Preference>
|
||||
</PreferenceScreen>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:label="@string/app_name"
|
||||
android:hint="Search" >
|
||||
android:hint="@string/search" >
|
||||
</searchable>
|
||||
|
|
Loading…
Reference in New Issue