Merge branch 'master' into feature/upload-pictures

This commit is contained in:
Ulysse Widmer 2020-03-20 16:23:38 +09:00
commit ac9a9943ac
24 changed files with 539 additions and 62 deletions

View File

@ -67,6 +67,8 @@ dependencies {
def room_version = "2.2.4"
implementation "androidx.room:room-runtime:$room_version"
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"

File diff suppressed because one or more lines are too long

View File

@ -31,13 +31,13 @@ class SwipeTest {
ActivityScenario.launch(MainActivity::class.java)
}
fun swipingLeftOnSearchShowsCameraFragment() {
val tab: TabLayout = onView(withId(R.id.tabs))
onView(withId(R.id.main_activity_main_linear_layout))
.perform(swipeLeft())
onView(withId(R.id.camera_fragment_main_linear_layout)).check(matches(isDisplayed()))
}
// fun swipingLeftOnSearchShowsCameraFragment() {
// val tab: TabLayout = onView(withId(R.id.tabs))
//
// onView(withId(R.id.main_activity_main_linear_layout))
// .perform(swipeLeft())
// onView(withId(R.id.camera_fragment_main_linear_layout)).check(matches(isDisplayed()))
// }
@Test
fun swipingRightOnFavoriteShowsCameraFragment() {

View File

@ -19,6 +19,7 @@ import com.google.android.material.tabs.TabLayoutMediator
import com.h.pixeldroid.fragments.CameraFragment
import com.h.pixeldroid.fragments.HomeFragment
import com.h.pixeldroid.fragments.MyProfileFragment
import com.h.pixeldroid.fragments.NotificationsFragment
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
@ -44,9 +45,12 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
drawerLayout = findViewById(R.id.drawer_layout)
val navigationView: NavigationView = findViewById(R.id.nav_view)
navigationView.setNavigationItemSelectedListener(this)
val tabs =
arrayOf(HomeFragment(), Fragment(), CameraFragment(), Fragment(), MyProfileFragment())
val tabs = arrayOf(HomeFragment(),
Fragment(),
CameraFragment(),
NotificationsFragment(),
MyProfileFragment())
setupTabs(tabs)
}
@ -69,7 +73,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
0 -> tab.icon = getDrawable(R.drawable.ic_home_white_24dp)
1 -> tab.icon = getDrawable(R.drawable.ic_search_white_24dp)
2 -> tab.icon = getDrawable(R.drawable.ic_photo_camera_white_24dp)
3 -> tab.icon = getDrawable(R.drawable.ic_star_white_24dp)
3 -> tab.icon = getDrawable(R.drawable.ic_heart)
4 -> tab.icon = getDrawable(R.drawable.ic_person_white_24dp)
}
}.attach()

View File

@ -1,14 +1,12 @@
package com.h.pixeldroid
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.SurfaceControl
import android.view.View
import androidx.fragment.app.Fragment
import androidx.appcompat.app.AppCompatActivity
import com.h.pixeldroid.fragments.PostFragment
import com.h.pixeldroid.models.Post
import com.h.pixeldroid.models.Post.Companion.POST_TAG
class PostActivity : AppCompatActivity() {
lateinit var postFragment : PostFragment
@ -17,7 +15,11 @@ class PostActivity : AppCompatActivity() {
setContentView(R.layout.activity_post)
val post = intent.getSerializableExtra(POST_TAG) as Post
postFragment = PostFragment.newInstance(post)
postFragment = PostFragment()
val arguments = Bundle()
arguments.putSerializable(POST_TAG, post)
postFragment.arguments = arguments
supportFragmentManager.beginTransaction()
.add(R.id.postFragmentSingle, postFragment).commit()

View File

@ -1,14 +1,12 @@
package com.h.pixeldroid.api
import com.h.pixeldroid.objects.Account
import com.h.pixeldroid.objects.Application
import com.h.pixeldroid.objects.Status
import com.h.pixeldroid.objects.Token
import com.h.pixeldroid.objects.*
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
import retrofit2.http.Field
/*
@ -61,6 +59,23 @@ interface PixelfedAPI {
@Query("local") local: Boolean? = null
): Call<List<Status>>
/*
Note: as of 0.10.8, Pixelfed does not seem to respect the Mastodon API documentation,
you *need* to pass one of the so-called "optional" arguments. See:
https://github.com/pixelfed/pixelfed/blob/dev/app/Http/Controllers/Api/ApiV1Controller.php
An example that works: specify min_id as 1 (not 0 though)
*/
@GET("/api/v1/notifications")
fun notifications(
//The authorization header needs to be of the form "Bearer <token>"
@Header("Authorization") authorization: String,
@Query("max_id") max_id: String? = null,
@Query("since_id") since_id: String? = null,
@Query("min_id") min_id: String? = null,
@Query("exclude_types") limit: String? = null,
@Query("account_id") exclude_types: Boolean? = null
): Call<List<Notification>>
@GET("/api/v1/accounts/verify_credentials")
fun verifyCredentials(
//The authorization header needs to be of the form "Bearer <token>"

View File

@ -0,0 +1,99 @@
package com.h.pixeldroid.fragments
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import com.h.pixeldroid.BuildConfig
import com.h.pixeldroid.R
import com.h.pixeldroid.api.PixelfedAPI
import com.h.pixeldroid.objects.Notification
import kotlinx.android.synthetic.main.fragment_notifications_list.*
import kotlinx.android.synthetic.main.fragment_notifications_list.view.*
import kotlinx.android.synthetic.main.fragment_notifications_list.view.swipeRefreshLayout
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
/**
* A fragment representing a list of Items.
*/
class NotificationsFragment : Fragment() {
private lateinit var preferences: SharedPreferences
private lateinit var list : RecyclerView
private lateinit var adapter : NotificationsRecyclerViewAdapter
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
var notifications : List<Notification> = ArrayList()
private lateinit var pixelfedAPI: PixelfedAPI
private var accessToken: String? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_notifications_list, container, false)
preferences = activity!!.getSharedPreferences(
"${BuildConfig.APPLICATION_ID}.pref", Context.MODE_PRIVATE
)
pixelfedAPI = PixelfedAPI.create("${preferences.getString("domain", "")}")
accessToken = preferences.getString("accessToken", "")
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout)
list = swipeRefreshLayout.list
// Set the adapter
list.layoutManager = LinearLayoutManager(context)
adapter = NotificationsRecyclerViewAdapter()
list.adapter = adapter
swipeRefreshLayout.setOnRefreshListener {
doRequest()
}
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
doRequest()
}
fun setContent(notifications : ArrayList<Notification>) {
this.notifications = notifications
adapter.initializeWith(notifications)
}
private fun doRequest(){
val call = pixelfedAPI.notifications("Bearer $accessToken", min_id="1")
call.enqueue(object : Callback<List<Notification>> {
override fun onResponse(call: Call<List<Notification>>, response: Response<List<Notification>>) {
if (response.code() == 200) {
val notifications = response.body()!! as ArrayList<Notification>
setContent(notifications)
} else{
Toast.makeText(context,"Something went wrong while refreshing", Toast.LENGTH_SHORT).show()
}
swipeRefreshLayout.isRefreshing = false
}
override fun onFailure(call: Call<List<Notification>>, t: Throwable) {
Toast.makeText(context,"Could not get notifications", Toast.LENGTH_SHORT).show()
Log.e("Notifications", t.toString())
}
})
}
}

View File

@ -0,0 +1,136 @@
package com.h.pixeldroid.fragments
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.net.Uri
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.h.pixeldroid.PostActivity
import com.h.pixeldroid.R
import com.h.pixeldroid.models.Post
import com.h.pixeldroid.models.Post.Companion.POST_TAG
import com.h.pixeldroid.objects.Notification
import kotlinx.android.synthetic.main.fragment_notifications.view.*
/**
* [RecyclerView.Adapter] that can display a [Notification]
*/
class NotificationsRecyclerViewAdapter: RecyclerView.Adapter<NotificationsRecyclerViewAdapter.ViewHolder>() {
private val notifications: ArrayList<Notification> = arrayListOf()
private lateinit var context: Context
private val mOnClickListener: View.OnClickListener
init {
mOnClickListener = View.OnClickListener { v ->
val notification = v.tag as Notification
openActivity(notification)
}
}
private fun openActivity(notification: Notification){
val intent: Intent
when (notification.type){
Notification.NotificationType.mention, Notification.NotificationType.favourite-> {
intent = Intent(context, PostActivity::class.java)
intent.putExtra(POST_TAG, Post(notification.status))
}
Notification.NotificationType.reblog-> {
Toast.makeText(context,"Can't see shares yet, sorry!",Toast.LENGTH_SHORT).show()
return
}
Notification.NotificationType.follow -> {
val url = notification.status?.url ?: notification.account.url
intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
}
}
context.startActivity(intent)
}
fun initializeWith(newNotifications: List<Notification>){
notifications.clear()
notifications.addAll(newNotifications)
notifyDataSetChanged()
}
fun addNotifications(newNotifications: List<Notification>){
val oldSize = notifications.size
notifications.addAll(newNotifications)
notifyItemRangeInserted(oldSize, newNotifications.size)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.fragment_notifications, parent, false)
context = view.context
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val notification = notifications[position]
Glide.with(holder.mView).load(notification.account.avatar_static).apply(RequestOptions().circleCrop())
.placeholder(R.drawable.ic_default_user).into(holder.avatar)
val previewUrl = notification.status?.media_attachments?.get(0)?.preview_url
if(!previewUrl.isNullOrBlank()){
Glide.with(holder.mView).load(previewUrl)
.placeholder(R.drawable.ic_picture_fallback).into(holder.photoThumbnail)
} else{
holder.photoThumbnail.visibility = View.GONE
}
setNotificationType(notification.type, notification.account.username, holder.notificationType)
holder.postDescription.text = notification.status?.content ?: ""
with(holder.mView) {
tag = notification
setOnClickListener(mOnClickListener)
}
}
private fun setNotificationType(type: Notification.NotificationType, username: String,
textView: TextView){
val context = textView.context
val (format: String, drawable: Drawable?) = when(type) {
Notification.NotificationType.follow -> {
setNotificationTypeTextView(context, R.string.followed_notification, R.drawable.ic_follow)
}
Notification.NotificationType.mention -> {
setNotificationTypeTextView(context, R.string.mention_notification, R.drawable.ic_apenstaart)
}
Notification.NotificationType.reblog -> {
setNotificationTypeTextView(context, R.string.shared_notification, R.drawable.ic_share)
}
Notification.NotificationType.favourite -> {
setNotificationTypeTextView(context, R.string.liked_notification, R.drawable.ic_heart)
}
}
textView.text = format.format(username)
textView.setCompoundDrawablesWithIntrinsicBounds(
drawable,null,null,null
)
}
private fun setNotificationTypeTextView(context: Context, format: Int, drawable: Int): Pair<String, Drawable?> {
return Pair(context.getString(format), context.getDrawable(drawable))
}
override fun getItemCount(): Int = notifications.size
inner class ViewHolder(val mView: View) : RecyclerView.ViewHolder(mView) {
val notificationType: TextView = mView.notification_type
val postDescription: TextView = mView.notification_post_description
val avatar: ImageView = mView.notification_avatar
val photoThumbnail: ImageView = mView.notification_photo_thumbnail
}
}

View File

@ -12,16 +12,6 @@ import com.h.pixeldroid.models.Post.Companion.POST_TAG
class PostFragment : Fragment() {
companion object {
fun newInstance(post : Post) : PostFragment {
val postFragment = PostFragment()
val arguments = Bundle()
arguments.putSerializable(POST_TAG, post)
postFragment.arguments = arguments
return postFragment
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?

View File

@ -35,6 +35,9 @@ class Post(private val status: Status?) : Serializable {
}
return name!!
}
fun getUsernameDescription() : CharSequence {
return status?.account?.display_name ?: ""
}
fun getNLikes() : CharSequence {
val nLikes : Int = status?.favourites_count ?: 0
@ -53,7 +56,7 @@ class Post(private val status: Status?) : Serializable {
username.setTypeface(null, Typeface.BOLD)
val usernameDesc = rootView.findViewById<TextView>(R.id.usernameDesc)
usernameDesc.text = this.getUsername()
usernameDesc.text = this.getUsernameDescription()
usernameDesc.setTypeface(null, Typeface.BOLD)
val description = rootView.findViewById<TextView>(R.id.description)

View File

@ -0,0 +1,19 @@
package com.h.pixeldroid.objects
/*
Represents a notification of an event relevant to the user.
https://docs.joinmastodon.org/entities/notification/
*/
data class Notification (
//Required attributes
val id: String,
val type: NotificationType,
val created_at: String, //ISO 8601 Datetime
val account: Account,
//Optional attributes
val status: Status? = null
) {
enum class NotificationType {
follow, mention, reblog, favourite
}
}

View File

@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="48"
android:viewportWidth="48" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="m18.9609,24.1172q0,2.793 1.3867,4.3945 1.3867,1.582 3.8086,1.582 2.4023,0 3.7695,-1.6016 1.3867,-1.6016 1.3867,-4.375 0,-2.7344 -1.4063,-4.3359 -1.4063,-1.6211 -3.7891,-1.6211 -2.3633,0 -3.7695,1.6016 -1.3867,1.6016 -1.3867,4.3555zM29.6055,29.957q-1.1719,1.5039 -2.6953,2.2266 -1.5039,0.7031 -3.5156,0.7031 -3.3594,0 -5.4688,-2.4219 -2.0898,-2.4414 -2.0898,-6.3477 0,-3.9063 2.1094,-6.3477 2.1094,-2.4414 5.4492,-2.4414 2.0117,0 3.5352,0.7422 1.5234,0.7227 2.6758,2.207v-2.5586h2.793v14.375q2.8516,-0.4297 4.4531,-2.5977 1.6211,-2.1875 1.6211,-5.6445 0,-2.0898 -0.625,-3.9258 -0.6055,-1.8359 -1.8555,-3.3984 -2.0313,-2.5586 -4.9609,-3.9063 -2.9102,-1.3672 -6.3477,-1.3672 -2.4023,0 -4.6094,0.6445 -2.207,0.625 -4.082,1.875 -3.0664,1.9922 -4.8047,5.2344 -1.7188,3.2227 -1.7188,6.9922 0,3.1055 1.1133,5.8203 1.1328,2.7148 3.2617,4.7852 2.0508,2.0313 4.7461,3.0859 2.6953,1.0742 5.7617,1.0742 2.5195,0 4.9414,-0.8594 2.4414,-0.8398 4.4727,-2.4219l1.7578,2.168q-2.4414,1.8945 -5.332,2.8906 -2.8711,1.0156 -5.8398,1.0156 -3.6133,0 -6.8164,-1.2891 -3.2031,-1.2695 -5.7031,-3.7109 -2.5,-2.4414 -3.8086,-5.6445 -1.3086,-3.2227 -1.3086,-6.9141 0,-3.5547 1.3281,-6.7773 1.3281,-3.2227 3.7891,-5.6641 2.5195,-2.4805 5.8203,-3.7891 3.3008,-1.3281 6.9922,-1.3281 4.1406,0 7.6758,1.6992 3.5547,1.6992 5.957,4.8242 1.4648,1.9141 2.2266,4.1602 0.7813,2.2461 0.7813,4.6484 0,5.1367 -3.1055,8.1055 -3.1055,2.9688 -8.5742,3.0859z"/>
</vector>

View File

@ -3,23 +3,23 @@
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M24,4L24,4A20,20 0,0 1,44 24L44,24A20,20 0,0 1,24 44L24,44A20,20 0,0 1,4 24L4,24A20,20 0,0 1,24 4z"
android:strokeWidth="0.82808512"
android:fillColor="#d9d9e8"
android:fillAlpha="1"/>
<path
android:pathData="M24,4L24,4A20,20 0,0 1,44 24L44,24A20,20 0,0 1,24 44L24,44A20,20 0,0 1,4 24L4,24A20,20 0,0 1,24 4z"
android:strokeWidth="0.82808512"
android:fillColor="#d9d9e8"
android:fillAlpha="1"/>
<path
android:fillColor="#FF000000"
android:pathData="M24.0666,16.1964m-6.6463,0a6.6463,6.6463 0,1 1,13.2926 0a6.6463,6.6463 0,1 1,-13.2926 0"
android:strokeWidth="0.46640581"/>
<group>
<clip-path
android:pathData="M24,27.5161L24,27.5161A5.4669,13.0074 90,0 1,37.0074 32.983L37.0074,32.983A5.4669,13.0074 90,0 1,24 38.4498L24,38.4498A5.4669,13.0074 90,0 1,10.9926 32.983L10.9926,32.983A5.4669,13.0074 90,0 1,24 27.5161zM10.9926,32.983l26.0147,0l0,5.4669l-26.0147,0z"/>
<path
android:fillColor="#FF000000"
android:pathData="M24.0666,16.1964m-6.6463,0a6.6463,6.6463 0,1 1,13.2926 0a6.6463,6.6463 0,1 1,-13.2926 0"
android:strokeWidth="0.46640581"/>
<group>
<clip-path
android:pathData="M24,27.5161L24,27.5161A5.4669,13.0074 90,0 1,37.0074 32.983L37.0074,32.983A5.4669,13.0074 90,0 1,24 38.4498L24,38.4498A5.4669,13.0074 90,0 1,10.9926 32.983L10.9926,32.983A5.4669,13.0074 90,0 1,24 27.5161zM10.9926,32.983l26.0147,0l0,5.4669l-26.0147,0z"/>
<path
android:fillColor="#FF000000"
android:pathData="M24,27.5161L24,27.5161A5.4669,13.0074 90,0 1,37.0074 32.983L37.0074,32.983A5.4669,13.0074 90,0 1,24 38.4498L24,38.4498A5.4669,13.0074 90,0 1,10.9926 32.983L10.9926,32.983A5.4669,13.0074 90,0 1,24 27.5161z"/>
<path
android:fillColor="#FF000000"
android:pathData="M10.9926,32.983l26.0147,0l0,5.4669l-26.0147,0z"/>
</group>
</vector>
android:pathData="M24,27.5161L24,27.5161A5.4669,13.0074 90,0 1,37.0074 32.983L37.0074,32.983A5.4669,13.0074 90,0 1,24 38.4498L24,38.4498A5.4669,13.0074 90,0 1,10.9926 32.983L10.9926,32.983A5.4669,13.0074 90,0 1,24 27.5161z"/>
<path
android:fillColor="#FF000000"
android:pathData="M10.9926,32.983l26.0147,0l0,5.4669l-26.0147,0z"/>
</group>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM6,10L6,7L4,7v3L1,10v2h3v3h2v-3h3v-2L6,10zM15,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@ -0,0 +1,4 @@
<vector android:height="18dp" android:viewportHeight="512"
android:viewportWidth="512" android:width="18dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000000" android:pathData="M462.3,62.6C407.5,15.9 326,24.3 275.7,76.2L256,96.5l-19.7,-20.3C186.1,24.3 104.5,15.9 49.7,62.6c-62.8,53.6 -66.1,149.8 -9.9,207.9l193.5,199.8c12.5,12.9 32.8,12.9 45.3,0l193.5,-199.8c56.3,-58.1 53,-154.3 -9.8,-207.9z"/>
</vector>

View File

@ -0,0 +1,37 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:pathData="M1.6887,0.4744L46.3113,0.4744A1.6383,1.2144 90,0 1,47.5256 2.1127L47.5256,45.8873A1.6383,1.2144 90,0 1,46.3113 47.5256L1.6887,47.5256A1.6383,1.2144 90,0 1,0.4744 45.8873L0.4744,2.1127A1.6383,1.2144 90,0 1,1.6887 0.4744z"
android:fillColor="#d9d9e8"
android:fillAlpha="1"/>
<path
android:pathData="M24,23.8582L24,23.8582A0.1418,0.3781 90,0 1,24.3781 24L24.3781,24A0.1418,0.3781 90,0 1,24 24.1418L24,24.1418A0.1418,0.3781 90,0 1,23.6219 24L23.6219,24A0.1418,0.3781 90,0 1,24 23.8582z"
android:fillColor="#d9d9e8"
android:fillAlpha="1"/>
<group>
</group>
<path
android:pathData="M9.607,10.6332L38.393,10.6332A1.0187,1.3799 90,0 1,39.7729 11.6519L39.7729,36.3481A1.0187,1.3799 90,0 1,38.393 37.3668L9.607,37.3668A1.0187,1.3799 90,0 1,8.2271 36.3481L8.2271,11.6519A1.0187,1.3799 90,0 1,9.607 10.6332z"
android:strokeWidth="0.98549145"
android:fillColor="#000000"
android:fillAlpha="1"/>
<path
android:pathData="M10.5761,11.8696L37.4239,11.8696A1.3529,1.1794 90,0 1,38.6033 13.2225L38.6033,34.7775A1.3529,1.1794 90,0 1,37.4239 36.1304L10.5761,36.1304A1.3529,1.1794 90,0 1,9.3967 34.7775L9.3967,13.2225A1.3529,1.1794 90,0 1,10.5761 11.8696z"
android:fillColor="#ffffff"
android:fillAlpha="1"/>
<path
android:pathData="M14.1949,31.2335L33.4431,31.2335l-4.6116,-7.2181 -3.208,3.2749 -7.6191,-9.691z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="1"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="butt"/>
<path
android:pathData="M29.482,16.3441m-2.1387,0a2.1387,2.1387 0,1 1,4.2774 0a2.1387,2.1387 0,1 1,-4.2774 0"
android:fillColor="#000000"
android:fillAlpha="1"/>
</vector>

View File

@ -0,0 +1,4 @@
<vector android:height="19.2dp" android:viewportHeight="512"
android:viewportWidth="640" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M629.657,343.598L528.971,444.284c-9.373,9.372 -24.568,9.372 -33.941,0L394.343,343.598c-9.373,-9.373 -9.373,-24.569 0,-33.941l10.823,-10.823c9.562,-9.562 25.133,-9.34 34.419,0.492L480,342.118L480,160L292.451,160a24.005,24.005 0,0 1,-16.971 -7.029l-16,-16C244.361,121.851 255.069,96 276.451,96L520,96c13.255,0 24,10.745 24,24v222.118l40.416,-42.792c9.285,-9.831 24.856,-10.054 34.419,-0.492l10.823,10.823c9.372,9.372 9.372,24.569 -0.001,33.941zM364.519,359.029A23.999,23.999 0,0 0,347.548 352L160,352L160,169.881l40.416,42.792c9.286,9.831 24.856,10.054 34.419,0.491l10.822,-10.822c9.373,-9.373 9.373,-24.569 0,-33.941L144.971,67.716c-9.373,-9.373 -24.569,-9.373 -33.941,0L10.343,168.402c-9.373,9.373 -9.373,24.569 0,33.941l10.822,10.822c9.562,9.562 25.133,9.34 34.419,-0.491L96,169.881L96,392c0,13.255 10.745,24 24,24h243.549c21.382,0 32.09,-25.851 16.971,-40.971l-16.001,-16z"/>
</vector>

View File

@ -6,11 +6,10 @@
android:layout_height="match_parent"
tools:context=".PostActivity">
<fragment
<androidx.fragment.app.FragmentContainerView
android:id="@+id/postFragmentSingle"
android:name="com.h.pixeldroid.fragments.PostFragment"
android:layout_width="81dp"
android:layout_height="14dp"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@ -0,0 +1,66 @@
<?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:id="@+id/notification"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/notification_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:drawableStart="@drawable/ic_heart"
android:drawablePadding="6dp"
android:gravity="center_vertical"
android:paddingStart="38dp"
android:textColor="?android:textColorTertiary"
android:textStyle="bold"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintRight_toLeftOf="parent"
app:layout_constraintStart_toEndOf="@+id/notification_avatar"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlSymmetry"
tools:text="User liked your post"
tools:visibility="visible" />
<ImageView
android:id="@+id/notification_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="14dp"
android:layout_marginTop="14dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/notification_type"
tools:src="@drawable/ic_default_user" />
<ImageView
android:id="@+id/notification_photo_thumbnail"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="14dp"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/notification_type"
tools:src="@drawable/ic_default_user"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<TextView
android:id="@+id/notification_post_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/notification_photo_thumbnail"
app:layout_constraintHorizontal_bias="0.164"
app:layout_constraintStart_toEndOf="@+id/notification_avatar"
app:layout_constraintTop_toBottomOf="@+id/notification_type"
app:layout_constraintVertical_bias="0.408"
tools:text="Post description" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.recyclerview.widget.RecyclerView
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/list"
android:name="com.h.pixeldroid.fragments.NotificationsFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:context=".fragments.NotificationsFragment"
tools:listitem="@layout/fragment_notifications" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -38,11 +38,11 @@ tools:context=".fragments.PostFragment">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/profilePic"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.516" />
app:layout_constraintVertical_bias="0.516"
tools:text="TextView" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
@ -77,7 +77,7 @@ tools:context=".fragments.PostFragment">
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:layout_weight="50"
android:text="TextView" />
tools:text="TextView" />
<TextView
android:id="@+id/nshares"
@ -88,7 +88,7 @@ tools:context=".fragments.PostFragment">
android:layout_marginBottom="10dp"
android:layout_weight="50"
android:gravity="right"
android:text="TextView" />
tools:text="TextView" />
</LinearLayout>
<TextView
@ -97,7 +97,7 @@ tools:context=".fragments.PostFragment">
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="TextView" />
tools:text="TextView" />
<TextView
android:id="@+id/description"
@ -105,7 +105,7 @@ tools:context=".fragments.PostFragment">
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="TextView" />
tools:text="TextView" />
<androidx.constraintlayout.widget.ConstraintLayout

View File

@ -5,4 +5,6 @@
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="fab_margin">16dp</dimen>
</resources>
<dimen name="text_margin">16dp</dimen>
</resources>

View File

@ -59,5 +59,9 @@
<string name="start_login">Start Login</string>
<string name="no_username">No Username</string>
<string name="upload_a_picture">Upload a picture</string>
<string name="followed_notification">%1$s followed you</string>
<string name="mention_notification">%1$s mentioned you</string>
<string name="shared_notification">%1$s shared your post</string>
<string name="liked_notification">%1$s liked your post</string>
</resources>

View File

@ -34,7 +34,30 @@ class APIUnitTest {
tags= listOf(Tag(name="hiking", url="https://pixelfed.de/discover/tags/hiking", history=null), Tag(name="nature", url="https://pixelfed.de/discover/tags/nature", history=null), Tag(name="rotavicentina", url="https://pixelfed.de/discover/tags/rotavicentina", history=null)),
emojis= emptyList(), reblogs_count=0, favourites_count=0, replies_count=0, url="https://pixelfed.de/p/Miike/140364967936397312",
in_reply_to_id=null, in_reply_to_account=null, reblog=null, poll=null, card=null, language=null, text=null, favourited=false, reblogged=false, muted=false, bookmarked=false, pinned=false)
val sampleNotification = Notification("45723", Notification.NotificationType.favourite,
"2020-03-14T15:01:49+00:00",
Account("79574199701737472", "Spaziergaenger",
"Spaziergaenger", "https://pixelfed.de/Spaziergaenger",
"anonymous", "", "https://pixelfed.de/storage/avatars/007/957/419/970/173/747/2/KEg4YgCgsmzdgyVztszz_avatar.jpeg?v=d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35",
"https://pixelfed.de/storage/avatars/007/957/419/970/173/747/2/KEg4YgCgsmzdgyVztszz_avatar.jpeg?v=d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35",
locked=false, followers_count = 40, following_count = 0, statuses_count = 891, created_at = "1568728767", header = "", discoverable = true, emojis = emptyList(), header_static = ""),
Status("144456497894658048","https://pixelfed.de/p/dante/144456497894658048",
"https://pixelfed.de/p/dante/144456497894658048", in_reply_to_id = null,
in_reply_to_account = null, reblog = null,content = "Saturn V launch", emojis = emptyList(), reblogs_count = 0,
favourites_count = 1, reblogged = false, favourited = false, muted = false, sensitive = false,
spoiler_text = "", visibility = Status.Visibility.public, application = Application("web", null),
language = null, pinned = false, mentions = emptyList(), tags = emptyList(), replies_count = 0,
account = Account("136453537340198912", "dante", "dante", locked = false, following_count = 3,
followers_count = 1,statuses_count = 1, note = "", url = "https://pixelfed.de/dante",
avatar = "https://pixelfed.de/storage/avatars/default.png?v=5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9",
emojis = emptyList(), header_static = "", header = "", created_at = "1582289858", avatar_static = "https://pixelfed.de/storage/avatars/default.png?v=5feceb66ffc86f38d952786c6d696c79c2dbc239dd4e91b46729d73a27fb57e9",
discoverable = true, display_name = "Dante"), media_attachments = listOf(
Attachment("16583",Attachment.AttachmentType.image, "https://pixelfed.de/storage/m/113a3e2124a33b1f5511e531953f5ee48456e0c7/0fa8bbe19cc23442034913a7c97fbe4527c1d63a/vs2vouJ86OvzxhK9ewhPlfPf4Y9IoQ5CHfiBIqad.jpeg",
"https://pixelfed.de/storage/m/113a3e2124a33b1f5511e531953f5ee48456e0c7/0fa8bbe19cc23442034913a7c97fbe4527c1d63a/vs2vouJ86OvzxhK9ewhPlfPf4Y9IoQ5CHfiBIqad_thumb.jpeg",
null, null, null, null)
)
, bookmarked = false, card = null, poll = null, text= null,url= "https://pixelfed.de/p/dante/144456497894658048")
)
@get:Rule
public var wireMockRule = WireMockRule(8089)
/*@Test