Improve compatibility and add a shortcut for creating a post

This commit is contained in:
Matthieu 2022-06-21 18:19:54 +02:00
parent e2cdbb5717
commit 4a6795bc0e
23 changed files with 180 additions and 76 deletions

View File

@ -0,0 +1,15 @@
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="new_post"
android:enabled="true"
android:icon="@drawable/photo_camera"
android:shortcutShortLabel="@string/new_post_shortcut_short"
android:shortcutLongLabel="@string/new_post_shortcut_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="org.pixeldroid.app.debug"
android:targetClass="org.pixeldroid.app.postCreation.camera.CameraActivityShortcut" />
<categories android:name="android.shortcut.conversation" />
<capability-binding android:key="actions.intent.CREATE_MESSAGE" />
</shortcut>
</shortcuts>

View File

@ -35,7 +35,17 @@
android:configChanges="keyboardHidden|orientation|screenSize" android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="false" android:exported="false"
android:theme="@style/AppTheme.NoActionBar" /> android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".postCreation.camera.CameraActivity" /> <activity android:name=".postCreation.camera.CameraActivity"/>
<activity android:name=".postCreation.camera.CameraActivityShortcut"
android:exported = "true"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity " />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
</intent-filter>
</activity>
<activity <activity
android:name=".posts.ReportActivity" android:name=".posts.ReportActivity"
android:screenOrientation="sensorPortrait" android:screenOrientation="sensorPortrait"
@ -46,31 +56,12 @@
android:exported="true" android:exported="true"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" /> <data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" /> <data android:mimeType="video/*" />
</intent-filter> </intent-filter>
</activity> </activity>
@ -112,6 +103,8 @@
<meta-data <meta-data
android:name="android.app.default_searchable" android:name="android.app.default_searchable"
android:value="org.pixeldroid.app.searchDiscover.SearchActivity" /> android:value="org.pixeldroid.app.searchDiscover.SearchActivity" />
<meta-data android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity> </activity>
<activity <activity
android:name=".LoginActivity" android:name=".LoginActivity"

View File

@ -373,7 +373,7 @@ class MainActivity : BaseActivity() {
when(position){ when(position){
0 -> R.drawable.ic_home_white_24dp 0 -> R.drawable.ic_home_white_24dp
1 -> R.drawable.ic_search_white_24dp 1 -> R.drawable.ic_search_white_24dp
2 -> R.drawable.ic_photo_camera_white_24dp 2 -> R.drawable.photo_camera
3 -> R.drawable.ic_heart 3 -> R.drawable.ic_heart
4 -> R.drawable.ic_filter_black_24dp 4 -> R.drawable.ic_filter_black_24dp
else -> throw IllegalArgumentException() else -> throw IllegalArgumentException()

View File

@ -355,7 +355,7 @@ class PostCreationViewModel(application: Application, clipdata: ClipData? = null
} }
fun modifyAt(position: Int, data: Intent): Unit? { fun modifyAt(position: Int, data: Intent): Unit? {
val result: PhotoData = photoData.value?.get(position)?.run { val result: PhotoData = photoData.value?.getOrNull(position)?.run {
if (video) { if (video) {
val muted: Boolean = data.getBooleanExtra(VideoEditActivity.MUTED, false) val muted: Boolean = data.getBooleanExtra(VideoEditActivity.MUTED, false)
val videoStart: Float? = data.getFloatExtra(VideoEditActivity.VIDEO_START, -1f).let { val videoStart: Float? = data.getFloatExtra(VideoEditActivity.VIDEO_START, -1f).let {

View File

@ -1,8 +1,13 @@
package org.pixeldroid.app.postCreation.camera package org.pixeldroid.app.postCreation.camera
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import org.pixeldroid.app.utils.BaseActivity import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import org.pixeldroid.app.MainActivity
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.utils.BaseActivity
class CameraActivity : BaseActivity() { class CameraActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -20,4 +25,36 @@ class CameraActivity : BaseActivity() {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.add(R.id.camera_activity_fragment, cameraFragment).commit() .add(R.id.camera_activity_fragment, cameraFragment).commit()
} }
}
/**
* Launch without arguments so that it will open the
* [org.pixeldroid.app.postCreation.PostCreationActivity] instead of "returning" to a non-existent
* [org.pixeldroid.app.postCreation.PostCreationActivity]
*/
class CameraActivityShortcut : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setTitle(R.string.new_post_shortcut_long)
val cameraFragment = CameraFragment()
supportFragmentManager.beginTransaction()
.add(R.id.camera_activity_fragment, cameraFragment).commit()
}
//Start a new MainActivity when "going back" on this activity
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
super.startActivity(intent)
}
}
return true
}
} }

View File

@ -442,7 +442,7 @@ class CameraFragment : BaseFragment() {
.apply { .apply {
uris.forEach{ uris.forEach{
//Why are we using ClipData here? Because the FLAG_GRANT_READ_URI_PERMISSION //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 //needs to be applied to the URIs, and this flag only applies to the
//Intent's data and any URIs specified in its ClipData. //Intent's data and any URIs specified in its ClipData.
if(clipData == null){ if(clipData == null){
clipData = ClipData("", emptyArray(), ClipData.Item(it.toUri())) clipData = ClipData("", emptyArray(), ClipData.Item(it.toUri()))

View File

@ -91,7 +91,7 @@ class ImageCarousel(
} }
if (position != RecyclerView.NO_POSITION && field != position) { if (position != RecyclerView.NO_POSITION && field != position) {
val thisProgress = data?.get(position)?.encodeProgress val thisProgress = data?.getOrNull(position)?.encodeProgress
if (thisProgress != null) { if (thisProgress != null) {
binding.encodeProgress.visibility = VISIBLE binding.encodeProgress.visibility = VISIBLE
binding.encodeInfoText.visibility = VISIBLE binding.encodeInfoText.visibility = VISIBLE
@ -473,7 +473,7 @@ class ImageCarousel(
onScrollListener?.apply { onScrollListener?.apply {
val position = snapHelper.getSnapPosition(recyclerView.layoutManager) val position = snapHelper.getSnapPosition(recyclerView.layoutManager)
val carouselItem = data?.get(position) val carouselItem = data?.getOrNull(position)
onScrollStateChanged( onScrollStateChanged(
recyclerView, recyclerView,
@ -564,7 +564,7 @@ class ImageCarousel(
} }
fun updateProgress(progress: Int?, position: Int, error: Boolean){ fun updateProgress(progress: Int?, position: Int, error: Boolean){
data?.get(position)?.encodeProgress = progress data?.getOrNull(position)?.encodeProgress = progress
if(currentPosition == position) { if(currentPosition == position) {
if (progress == null) { if (progress == null) {
binding.encodeProgress.visibility = INVISIBLE binding.encodeProgress.visibility = INVISIBLE

View File

@ -356,7 +356,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
override fun onPermissionGranted(p0: PermissionGrantedResponse?) { override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
status?.downloadImage( status?.downloadImage(
binding.root.context, binding.root.context,
status?.media_attachments?.get(binding.postPager.currentItem)?.url status?.media_attachments?.getOrNull(binding.postPager.currentItem)?.url
?: "", ?: "",
binding.root binding.root
) )
@ -379,7 +379,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
override fun onPermissionGranted(p0: PermissionGrantedResponse?) { override fun onPermissionGranted(p0: PermissionGrantedResponse?) {
status?.downloadImage( status?.downloadImage(
binding.root.context, binding.root.context,
status?.media_attachments?.get(binding.postPager.currentItem)?.url status?.media_attachments?.getOrNull(binding.postPager.currentItem)?.url
?: "", ?: "",
binding.root, binding.root,
share = true, share = true,
@ -590,7 +590,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
class AlbumViewPagerAdapter( class AlbumViewPagerAdapter(
private val media_attachments: List<Attachment>, private var sensitive: Boolean?, private val media_attachments: List<Attachment>, private var sensitive: Boolean?,
private val opened: Boolean, //TODO if opened don't open again, and use PhotoView instead of shite private val opened: Boolean,
) : ) :
RecyclerView.Adapter<AlbumViewPagerAdapter.ViewHolder>() { RecyclerView.Adapter<AlbumViewPagerAdapter.ViewHolder>() {

View File

@ -103,10 +103,10 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
when (type) { when (type) {
Notification.NotificationType.mention, Notification.NotificationType.favourite, Notification.NotificationType.mention, Notification.NotificationType.favourite,
Notification.NotificationType.poll, Notification.NotificationType.reblog, Notification.NotificationType.poll, Notification.NotificationType.reblog,
Notification.NotificationType.comment -> { Notification.NotificationType.comment, Notification.NotificationType.status -> {
openPostFromNotification() openPostFromNotification()
} }
Notification.NotificationType.follow -> { Notification.NotificationType.follow, Notification.NotificationType.follow_request -> {
openAccountFromNotification() openAccountFromNotification()
} }
null -> return null -> return
@ -164,6 +164,16 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
) )
Notification.NotificationType.poll -> Notification.NotificationType.poll ->
getStringAndDrawable(context, R.string.poll_notification, R.drawable.poll) getStringAndDrawable(context, R.string.poll_notification, R.drawable.poll)
Notification.NotificationType.follow_request -> getStringAndDrawable(
context,
R.string.follow_request,
R.drawable.ic_follow
)
Notification.NotificationType.status -> getStringAndDrawable(
context,
R.string.status_notification,
R.drawable.ic_comment_empty
)
} }
textView.text = format.format(username) textView.text = format.format(username)
textView.setCompoundDrawablesWithIntrinsicBounds( textView.setCompoundDrawablesWithIntrinsicBounds(

View File

@ -19,6 +19,8 @@ import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import org.pixeldroid.app.R import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ActivityProfileBinding import org.pixeldroid.app.databinding.ActivityProfileBinding
@ -40,6 +42,8 @@ import org.pixeldroid.app.utils.openUrl
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.pixeldroid.app.databinding.ErrorLayoutBinding import org.pixeldroid.app.databinding.ErrorLayoutBinding
import org.pixeldroid.app.postCreation.carousel.dpToPx
import org.pixeldroid.app.utils.BlurHashDecoder
import org.pixeldroid.app.utils.api.objects.Attachment import org.pixeldroid.app.utils.api.objects.Attachment
import retrofit2.HttpException import retrofit2.HttpException
import java.io.IOException import java.io.IOException
@ -349,23 +353,39 @@ class ProfilePostsViewHolder(binding: FragmentProfilePostsBinding) : RecyclerVie
fun bind(post: Status) { fun bind(post: Status) {
if(post.sensitive!!) { if ((post.media_attachments?.size ?: 0) == 0){
ImageConverter.setSquareImageFromDrawable( //No media in this post, so put a little icon there
itemView, postPreview.scaleX = 0.3f
AppCompatResources.getDrawable(itemView.context, R.drawable.ic_sensitive), postPreview.scaleY = 0.3f
postPreview Glide.with(postPreview).load(R.drawable.ic_comment_empty).into(postPreview)
)
} else {
ImageConverter.setSquareImageFromURL(itemView, post.getPostPreviewURL(), postPreview)
}
if(post.media_attachments?.size ?: 0 > 1) {
albumIcon.visibility = View.VISIBLE
} else {
albumIcon.visibility = View.GONE albumIcon.visibility = View.GONE
if(post.media_attachments?.get(0)?.type == Attachment.AttachmentType.video) { videoIcon.visibility = View.GONE
videoIcon.visibility = View.VISIBLE } else {
} else videoIcon.visibility = View.GONE postPreview.scaleX = 1f
postPreview.scaleY = 1f
if (post.sensitive != false) {
Glide.with(postPreview)
.load(post.media_attachments?.firstOrNull()?.blurhash?.let {
BlurHashDecoder.blurHashBitmap(itemView.resources, it, 32, 32)
}
).placeholder(R.drawable.ic_sensitive).apply(RequestOptions().centerCrop())
.into(postPreview)
} else {
ImageConverter.setSquareImageFromURL(postPreview,
post.getPostPreviewURL(),
postPreview,
post.media_attachments?.firstOrNull()?.blurhash)
}
if ((post.media_attachments?.size ?: 0) > 1) {
albumIcon.visibility = View.VISIBLE
videoIcon.visibility = View.GONE
} else {
albumIcon.visibility = View.GONE
if (post.media_attachments?.getOrNull(0)?.type == Attachment.AttachmentType.video) {
videoIcon.visibility = View.VISIBLE
} else videoIcon.visibility = View.GONE
}
} }
postPreview.setOnClickListener { postPreview.setOnClickListener {

View File

@ -117,11 +117,11 @@ class SearchDiscoverFragment : BaseFragment() {
override fun onBindViewHolder(holder: ProfilePostViewHolder, position: Int) { override fun onBindViewHolder(holder: ProfilePostViewHolder, position: Int) {
val post = posts[position] val post = posts[position]
if(post?.media_attachments?.size ?: 0 > 1) { if((post?.media_attachments?.size ?: 0) > 1) {
holder.albumIcon.visibility = View.VISIBLE holder.albumIcon.visibility = View.VISIBLE
} else { } else {
holder.albumIcon.visibility = View.GONE holder.albumIcon.visibility = View.GONE
if(post?.media_attachments?.get(0)?.type == Attachment.AttachmentType.video) { if(post?.media_attachments?.getOrNull(0)?.type == Attachment.AttachmentType.video) {
holder.videoIcon.visibility = View.VISIBLE holder.videoIcon.visibility = View.VISIBLE
} else holder.videoIcon.visibility = View.GONE } else holder.videoIcon.visibility = View.GONE

View File

@ -42,6 +42,8 @@ data class Account(
val fields: List<Field>? = emptyList(), val fields: List<Field>? = emptyList(),
val bot: Boolean? = false, val bot: Boolean? = false,
val source: Source? = null, val source: Source? = null,
val suspended: Boolean? = null,
val mute_expires_at: Instant? = null, //ISO 8601 Datetime
) : Serializable, FeedContent { ) : Serializable, FeedContent {
companion object { companion object {
const val ACCOUNT_TAG = "AccountTag" const val ACCOUNT_TAG = "AccountTag"

View File

@ -10,14 +10,16 @@ data class Attachment(
val preview_url: String? = "", //URL val preview_url: String? = "", //URL
//Optional attributes //Optional attributes
val remote_url: String? = null, //URL val remote_url: String? = null, //URL
val text_url: String? = null, //URL
val meta: Meta?, val meta: Meta?,
val description: String? = null, val description: String? = null,
val blurhash: String? = null val blurhash: String? = null,
//Deprecated attributes
val text_url: String? = null, //URL
) : Serializable { ) : Serializable {
enum class AttachmentType { enum class AttachmentType: Serializable {
unknown, image, gifv, video, audio unknown, image, gifv, video, audio
} }

View File

@ -17,7 +17,8 @@ data class Card(
val width: Int? = null, val width: Int? = null,
val height: Int? = null, val height: Int? = null,
val image: String? = null, //URL val image: String? = null, //URL
val embed_url: String? = null //URL val embed_url: String? = null, //URL
val blurhash: String? = null,
) : Serializable { ) : Serializable {
enum class CardType { enum class CardType {
link, photo, video, rich link, photo, video, rich

View File

@ -1,6 +1,7 @@
package org.pixeldroid.app.utils.api.objects package org.pixeldroid.app.utils.api.objects
import org.pixeldroid.app.utils.validDomain import org.pixeldroid.app.utils.validDomain
import java.io.Serializable
/* /*
See https://nodeinfo.diaspora.software/schema.html and https://pixelfed.social/api/nodeinfo/2.0.json See https://nodeinfo.diaspora.software/schema.html and https://pixelfed.social/api/nodeinfo/2.0.json
@ -14,7 +15,7 @@ data class NodeInfo (
val protocols: List<String>?, val protocols: List<String>?,
val openRegistrations: Boolean?, val openRegistrations: Boolean?,
val metadata: PixelfedMetadata?, val metadata: PixelfedMetadata?,
){ ): Serializable {
/** /**
* Check if this NodeInfo has the fields we need or if we also need to look into the * Check if this NodeInfo has the fields we need or if we also need to look into the
* /api/v1/instance endpoint * /api/v1/instance endpoint
@ -31,16 +32,16 @@ data class NodeInfo (
data class Software( data class Software(
val name: String?, val name: String?,
val version: String? val version: String?
) ): Serializable
data class PixelfedMetadata( data class PixelfedMetadata(
val nodeName: String?, val nodeName: String?,
val software: Software?, val software: Software?,
val config: PixelfedConfig val config: PixelfedConfig
){ ): Serializable {
data class Software( data class Software(
val homepage: String?, val homepage: String?,
val repo: String? val repo: String?
) ): Serializable
} }
data class PixelfedConfig( data class PixelfedConfig(
val open_registration: Boolean?, val open_registration: Boolean?,
@ -48,8 +49,8 @@ data class NodeInfo (
val activitypub: ActivityPub?, val activitypub: ActivityPub?,
val features: Features?, val features: Features?,
val site: Site? val site: Site?
){ ): Serializable {
data class Uploader( data class Uploader (
val max_photo_size: String?, val max_photo_size: String?,
val max_caption_length: String?, val max_caption_length: String?,
val album_limit: String?, val album_limit: String?,
@ -58,35 +59,34 @@ data class NodeInfo (
val optimize_video: Boolean?, val optimize_video: Boolean?,
val media_types: String?, val media_types: String?,
val enforce_account_limit: Boolean? val enforce_account_limit: Boolean?
) ): Serializable
data class ActivityPub( data class ActivityPub(
val enabled: Boolean?, val enabled: Boolean?,
val remote_follow: Boolean? val remote_follow: Boolean?
) ): Serializable
data class Features( data class Features(
val mobile_apis: Boolean?, val mobile_apis: Boolean?,
val circles: Boolean?, val circles: Boolean?,
val stories: Boolean?, val stories: Boolean?,
val video: Boolean? val video: Boolean?
) ): Serializable
data class Site( data class Site(
val name: String?, val name: String?,
val domain: String?, val domain: String?,
val url: String?, val url: String?,
val description: String? val description: String?
) ): Serializable
} }
} }
data class NodeInfoJRD( data class NodeInfoJRD(
val links: List<Link> val links: List<Link>
){ ): Serializable {
data class Link( data class Link(
val rel: String?, val rel: String?,
val href: String? val href: String?
) ): Serializable
} }

View File

@ -36,8 +36,8 @@ data class Notification(
//TODO do we find this approach acceptable? Preferable to a semi-duplicate NotificationDataBaseEntity? //TODO do we find this approach acceptable? Preferable to a semi-duplicate NotificationDataBaseEntity?
override var user_id: String, override var user_id: String,
override var instance_uri: String, override var instance_uri: String,
): FeedContent, FeedContentDatabase { ): FeedContent, FeedContentDatabase, Serializable {
enum class NotificationType: Serializable { enum class NotificationType: Serializable {
follow, mention, reblog, favourite, poll, comment follow, follow_request, mention, reblog, favourite, poll, status, comment //comment is Pixelfed-specific?
} }
} }

View File

@ -18,5 +18,5 @@ data class Poll (
data class Option( data class Option(
val title: String?, val title: String?,
val votes_count: Int? //null if result not published yet val votes_count: Int? //null if result not published yet
) ): Serializable
} }

View File

@ -11,7 +11,8 @@ data class Tag(
val name: String, val name: String,
val url: String, val url: String,
//Optional attributes //Optional attributes
val history: List<History>? = emptyList()) : Serializable, FeedContent { val history: List<History>? = emptyList()
) : Serializable, FeedContent {
//needed to be a FeedContent, this inheritance is a bit fickle. Do not use. //needed to be a FeedContent, this inheritance is a bit fickle. Do not use.
override val id: String override val id: String
get() = "tag" get() = "tag"

View File

@ -1,9 +1,11 @@
package org.pixeldroid.app.utils.api.objects package org.pixeldroid.app.utils.api.objects
import java.io.Serializable
data class Token( data class Token(
val access_token: String?, val access_token: String?,
val refresh_token: String?, val refresh_token: String?,
val token_type: String?, val token_type: String?,
val scope: String?, val scope: String?,
val created_at: Int? val created_at: Int? //UNIX timestamp
) ): Serializable

View File

@ -172,11 +172,11 @@ class NotificationsWorker(
val builder = NotificationCompat.Builder(applicationContext, makeChannelId(uniqueUserId, notification.type)) val builder = NotificationCompat.Builder(applicationContext, makeChannelId(uniqueUserId, notification.type))
.setSmallIcon( .setSmallIcon(
when (notification.type) { when (notification.type) {
follow -> R.drawable.ic_follow follow, follow_request -> R.drawable.ic_follow
mention -> R.drawable.mention_at_24dp mention -> R.drawable.mention_at_24dp
reblog -> R.drawable.ic_reblog reblog -> R.drawable.ic_reblog
favourite -> R.drawable.ic_like_full favourite -> R.drawable.ic_like_full
comment -> R.drawable.ic_comment_empty comment, status -> R.drawable.ic_comment_empty
poll -> R.drawable.poll poll -> R.drawable.poll
null -> R.drawable.ic_comment_empty null -> R.drawable.ic_comment_empty
} }
@ -193,6 +193,8 @@ class NotificationsWorker(
favourite -> R.string.liked_notification favourite -> R.string.liked_notification
poll -> R.string.poll_notification poll -> R.string.poll_notification
null -> R.string.other_notification null -> R.string.other_notification
follow_request -> R.string.follow_request
status -> R.string.status_notification
} }
).format(username) ).format(username)
} }

View File

@ -1,4 +1,4 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0" android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/> <path android:fillColor="#FF000000" android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>

View File

@ -270,4 +270,8 @@ For more info about Pixelfed, you can check here: https://pixelfed.org"</string>
<string name="encode_progress">Encode %1$d%%</string> <string name="encode_progress">Encode %1$d%%</string>
<string name="select_video_range">Select what to keep of the video</string> <string name="select_video_range">Select what to keep of the video</string>
<string name="still_encoding">One or more videos are still encoding. Wait for them to finish before uploading</string> <string name="still_encoding">One or more videos are still encoding. Wait for them to finish before uploading</string>
<string name="new_post_shortcut_long">Create new post</string>
<string name="new_post_shortcut_short">New post</string>
<string name="follow_request">%1$s requests to follow you</string>
<string name="status_notification">%1$s created a post</string>
</resources> </resources>

View File

@ -0,0 +1,15 @@
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="new_post"
android:enabled="true"
android:icon="@drawable/photo_camera"
android:shortcutShortLabel="@string/new_post_shortcut_short"
android:shortcutLongLabel="@string/new_post_shortcut_long">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="org.pixeldroid.app"
android:targetClass="org.pixeldroid.app.postCreation.camera.CameraActivityShortcut" />
<categories android:name="android.shortcut.conversation" />
<capability-binding android:key="actions.intent.CREATE_MESSAGE" />
</shortcut>
</shortcuts>