2020-03-04 18:04:55 +01:00
|
|
|
package com.h.pixeldroid.objects
|
|
|
|
|
2020-10-04 23:27:06 +02:00
|
|
|
import android.app.DownloadManager
|
2020-04-23 17:48:45 +02:00
|
|
|
import android.content.Context
|
2020-10-04 23:27:06 +02:00
|
|
|
import android.content.Intent
|
|
|
|
import android.database.Cursor
|
2020-05-16 23:47:18 +02:00
|
|
|
import android.graphics.ColorMatrixColorFilter
|
2020-10-04 23:27:06 +02:00
|
|
|
import android.net.Uri
|
|
|
|
import android.os.Environment
|
2020-04-23 17:48:45 +02:00
|
|
|
import android.text.Spanned
|
2020-03-21 18:12:00 +01:00
|
|
|
import android.view.View
|
2020-04-23 18:49:32 +02:00
|
|
|
import android.view.View.GONE
|
|
|
|
import android.view.View.VISIBLE
|
2020-11-27 17:02:52 +01:00
|
|
|
import android.widget.ImageView
|
|
|
|
import android.widget.TextView
|
2020-10-04 23:27:06 +02:00
|
|
|
import androidx.core.net.toUri
|
2020-11-27 17:02:52 +01:00
|
|
|
import androidx.room.Entity
|
|
|
|
import androidx.room.ForeignKey
|
|
|
|
import androidx.room.Index
|
2020-10-04 23:27:06 +02:00
|
|
|
import com.google.android.material.snackbar.Snackbar
|
Commenting & seeing comments on a post ( issues: #37 #77 ) (#87)
Comment and like buttons added + a few UI tweaks
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* removed wrong annotation in unit test
* removed an import that was breaking the build
* removed tests that broke from merge, will override with master
* added UI test for the post activity
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* layout changes
* refactoring
* refactoring
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* removed wrong annotation in unit test
* removed an import that was breaking the build
* removed tests that broke from merge, will override with master
* fixed merging errors
* trying my best to merge
* removed drawable definition in activity_post.xml
* Started converting Post to a fragment
* got a working feed
* WI
* removed non-valid test
* rebase on other branch
* moved the feed to the home page
* Add tests
* delete test for now
* Adapt test to changes (no more profile from drawer)
* Add unit test for api
* Add test for profile, refactor to allow testing, add exception to security policy to allow tests
* Adapt test to new situation
* Fix typo due to change
* refactor somewhat
* added a feed test
* WIP posts
* trying to add images
* WIP posts
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* removed wrong annotation in unit test
* removed an import that was breaking the build
* removed tests that broke from merge, will override with master
* added UI test for the post activity
* WIP posts
* trying to add images
* WIP posts
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* removed wrong annotation in unit test
* removed an import that was breaking the build
* removed tests that broke from merge, will override with master
* added UI test for the post activity
* fixed merging errors
* trying my best to merge
* removed drawable definition in activity_post.xml
* Started converting Post to a fragment
* got a working feed
* WI
* removed non-valid test
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* moved a test file
* refactoring
* refactoring
* refactoring
* refactoring
* removed wrong annotation in unit test
* WIP posts
* WIP posts
* WIP posts
* WIP posts
* trying to add images
* trying to add images
* trying to add images
* trying to add images
* Got posts working and linked them to the profile
* Got posts working and linked them to the profile
* added tests for Post
* layout changes
* layout changes
* moved a test file
* refactoring
* refactoring
* refactoring
* refactoring
* removed wrong annotation in unit test
* removed an import that was breaking the build
* removed an import that was breaking the build
* removed tests that broke from merge, will override with master
* removed tests that broke from merge, will override with master
* added UI test for the post activity
* fixed merging errors
* trying my best to merge
* removed drawable definition in activity_post.xml
* Started converting Post to a fragment
* got a working feed
* WI
* removed non-valid test
* rebase on other branch
* moved the feed to the home page
* added a feed test
* added a working feed test
* fixed broken test
* merged with master
* added a max height for images and made profile pictures round
* Added a default image for the post
* created a PostActivity to look a single posts
* fixed buggy postActivity
* Complete overhall of the feed UI
* removed test that didn't please Travis
* removed legacy test
* changed feedAdapter init location (outside of network callback)
* changed the feed from public timeline to home timeline
* Refactored myProfile page
* Converted profile picture to round image
* restored feed test
* I can like a post, but unlike is still a WIP
* Liking kind of works now and added tests
* fixed an error, now we can unlike as well
* fixed travis constraint error
* Display user's posts on profile page
* moved test to Mock server tests
* fixed test
* last resort debugging
* Changed fixed size of profile posts
* last resort debugging
* last resort debugging
* last resort debugging
* made post_activity profilepic round
* Total refactor of profile posts
* still have a weird bug with the comments: input is always null (WIP)
* still trying to fix coments
* removed annoying side margins in the home feed
* trying to fix comments
* fixed null comment
* converted all posts back to statuses and got rid of post
* Refactored recycler view
* Merged with my-profile
* Posts displayed on profile page
* Added links to profile activity where needed
* fixed comment posting
* finished implementing comments, but api is buggy so none are visible
* removed useless space in profile page
* fixed ci config bug
* trying to trigger ci hook (github was down last time)
* updated tests with master tests
* added tests for the comments
* added tests for the comments
* added first() matcher to fix comment test
* still trying to fix comment tests' null progress bar
* getting rid of that null progress bar
* added comment test
* fixed merge error
* added like button test
* added more post tests
* took pr coments into account
* added back an old test
* added mockServer response for comment test and fixed comment null pointer bug
* changed notification UI to better separate notifications
* added mockserver response for likes and corrected like toggling error
* added a test for posting comments
* fixed typo in test
* a gift for code climate
* refactored stuff
* fixed broken imports
* comment refactored as xml
Co-authored-by: Matthieu <61561059+Wv5twkFEKh54vo4tta9yu7dHa3@users.noreply.github.com>
Co-authored-by: mjaillot <marie.jaillot@epfl.ch>
2020-04-11 12:55:06 +02:00
|
|
|
import com.h.pixeldroid.R
|
|
|
|
import com.h.pixeldroid.api.PixelfedAPI
|
2020-11-27 17:02:52 +01:00
|
|
|
import com.h.pixeldroid.db.entities.UserDatabaseEntity
|
2020-05-01 10:39:25 +02:00
|
|
|
import com.h.pixeldroid.utils.HtmlUtils.Companion.getDomain
|
2020-04-23 17:48:45 +02:00
|
|
|
import com.h.pixeldroid.utils.HtmlUtils.Companion.parseHTMLText
|
2020-05-16 23:47:18 +02:00
|
|
|
import com.h.pixeldroid.utils.PostUtils.Companion.censorColorMatrix
|
|
|
|
import com.h.pixeldroid.utils.PostUtils.Companion.uncensorColorMatrix
|
|
|
|
import kotlinx.android.synthetic.main.post_fragment.view.*
|
2020-10-04 23:27:06 +02:00
|
|
|
import java.io.File
|
2020-05-01 10:39:25 +02:00
|
|
|
import java.io.Serializable
|
2020-10-04 23:27:06 +02:00
|
|
|
import java.util.*
|
2020-03-04 18:04:55 +01:00
|
|
|
|
2020-11-27 17:02:52 +01:00
|
|
|
/**
|
|
|
|
Represents a status posted by an account.
|
|
|
|
https://docs.joinmastodon.org/entities/status/
|
2020-03-04 18:04:55 +01:00
|
|
|
*/
|
2020-11-27 17:02:52 +01:00
|
|
|
|
|
|
|
open class Status(
|
2020-03-04 18:04:55 +01:00
|
|
|
//Base attributes
|
2020-11-27 17:02:52 +01:00
|
|
|
override val id: String,
|
2020-06-05 20:14:57 +02:00
|
|
|
val uri: String? = "",
|
2020-09-10 20:20:23 +02:00
|
|
|
val created_at: Date? = Date(0), //ISO 8601 Datetime
|
2020-06-05 20:14:57 +02:00
|
|
|
val account: Account?,
|
|
|
|
val content: String? = "", //HTML
|
|
|
|
val visibility: Visibility? = Visibility.public,
|
|
|
|
val sensitive: Boolean? = false,
|
|
|
|
val spoiler_text: String? = "",
|
2020-04-30 20:01:35 +02:00
|
|
|
val media_attachments: List<Attachment>? = null,
|
|
|
|
val application: Application? = null,
|
2020-03-04 18:04:55 +01:00
|
|
|
//Rendering attributes
|
2020-04-30 20:01:35 +02:00
|
|
|
val mentions: List<Mention>? = null,
|
|
|
|
val tags: List<Tag>? = null,
|
|
|
|
val emojis: List<Emoji>? = null,
|
2020-03-04 18:04:55 +01:00
|
|
|
//Informational attributes
|
2020-06-05 20:14:57 +02:00
|
|
|
val reblogs_count: Int? = 0,
|
|
|
|
val favourites_count: Int? = 0,
|
|
|
|
val replies_count: Int? = 0,
|
2020-03-04 18:04:55 +01:00
|
|
|
//Nullable attributes
|
2020-04-30 20:01:35 +02:00
|
|
|
val url: String? = null, //URL
|
|
|
|
val in_reply_to_id: String? = null,
|
|
|
|
val in_reply_to_account: String? = null,
|
|
|
|
val reblog: Status? = null,
|
|
|
|
val poll: Poll? = null,
|
|
|
|
val card: Card? = null,
|
|
|
|
val language: String? = null, //ISO 639 Part 1 two-letter language code
|
|
|
|
val text: String? = null,
|
2020-03-04 18:04:55 +01:00
|
|
|
//Authorized user attributes
|
2020-06-05 20:14:57 +02:00
|
|
|
val favourited: Boolean? = false,
|
|
|
|
val reblogged: Boolean? = false,
|
|
|
|
val muted: Boolean? = false,
|
|
|
|
val bookmarked: Boolean? = false,
|
2020-11-27 17:02:52 +01:00
|
|
|
val pinned: Boolean? = false,
|
|
|
|
) : Serializable, FeedContent
|
2020-03-04 18:04:55 +01:00
|
|
|
{
|
2020-03-21 18:12:00 +01:00
|
|
|
companion object {
|
|
|
|
const val POST_TAG = "postTag"
|
2020-05-01 10:39:25 +02:00
|
|
|
const val DOMAIN_TAG = "domainTag"
|
2020-05-03 14:30:01 +02:00
|
|
|
const val DISCOVER_TAG = "discoverTag"
|
2020-03-21 18:12:00 +01:00
|
|
|
}
|
|
|
|
|
2020-06-05 20:14:57 +02:00
|
|
|
fun getPostUrl() : String? = media_attachments?.firstOrNull()?.url
|
|
|
|
fun getProfilePicUrl() : String? = account?.avatar
|
|
|
|
fun getPostPreviewURL() : String? = media_attachments?.firstOrNull()?.preview_url
|
2020-03-21 18:12:00 +01:00
|
|
|
|
2020-04-23 17:48:45 +02:00
|
|
|
/**
|
|
|
|
* @brief returns the parsed version of the HTML description
|
|
|
|
*/
|
2020-06-05 20:14:57 +02:00
|
|
|
private fun getDescription(api: PixelfedAPI, context: Context, credential: String) : Spanned =
|
|
|
|
parseHTMLText(content ?: "", mentions, api, context, credential)
|
2020-04-23 17:48:45 +02:00
|
|
|
|
2020-05-21 15:22:57 +02:00
|
|
|
fun getNLikes(context: Context) : CharSequence {
|
|
|
|
return context.getString(R.string.likes).format(favourites_count.toString())
|
2020-03-21 18:12:00 +01:00
|
|
|
}
|
|
|
|
|
2020-05-21 15:22:57 +02:00
|
|
|
fun getNShares(context: Context) : CharSequence {
|
|
|
|
return context.getString(R.string.shares).format(reblogs_count.toString())
|
2020-03-21 18:12:00 +01:00
|
|
|
}
|
|
|
|
|
2020-11-27 17:02:52 +01:00
|
|
|
fun getStatusDomain(domain: String) : String {
|
2020-06-05 20:14:57 +02:00
|
|
|
val accountDomain = getDomain(account!!.url)
|
2020-05-01 10:39:25 +02:00
|
|
|
return if(getDomain(domain) == accountDomain) ""
|
|
|
|
else " from $accountDomain"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-11-27 17:02:52 +01:00
|
|
|
fun setupSensitiveLayout(view: View) {
|
2020-05-16 23:47:18 +02:00
|
|
|
|
2020-10-04 23:27:06 +02:00
|
|
|
// 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)
|
2020-04-23 18:49:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-04 23:27:06 +02:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2020-11-27 17:02:52 +01:00
|
|
|
enum class Visibility: Serializable {
|
2020-03-04 18:04:55 +01:00
|
|
|
public, unlisted, private, direct
|
|
|
|
}
|
|
|
|
}
|