Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • circles/circles-android
1 result
Show changes
Commits on Source (4)
...@@ -57,10 +57,12 @@ android { ...@@ -57,10 +57,12 @@ android {
buildTypes { buildTypes {
named("debug") { named("debug") {
isMinifyEnabled = false isMinifyEnabled = false
manifestPlaceholders["crashlyticsEnabled"] = false
} }
named("release") { named("release") {
signingConfig = signingConfigs.getByName("release") signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true isMinifyEnabled = true
manifestPlaceholders["crashlyticsEnabled"] = true
proguardFiles( proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro" "proguard-rules.pro"
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
android:theme="@style/Theme.Circles" android:theme="@style/Theme.Circles"
tools:ignore="DataExtractionRules" tools:ignore="DataExtractionRules"
tools:targetApi="tiramisu"> tools:targetApi="tiramisu">
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="${crashlyticsEnabled}" />
<activity <activity
android:name=".settings.feature.active_sessions.verify.qr.QrScannerActivity" android:name=".settings.feature.active_sessions.verify.qr.QrScannerActivity"
android:exported="false" /> android:exported="false" />
......
...@@ -19,8 +19,8 @@ import org.futo.circles.core.extensions.withConfirmation ...@@ -19,8 +19,8 @@ import org.futo.circles.core.extensions.withConfirmation
import org.futo.circles.core.feature.share.ShareProvider import org.futo.circles.core.feature.share.ShareProvider
import org.futo.circles.core.model.PostContent import org.futo.circles.core.model.PostContent
import org.futo.circles.databinding.DialogFragmentDmTimelineBinding import org.futo.circles.databinding.DialogFragmentDmTimelineBinding
import org.futo.circles.feature.direct.timeline.list.DMTimelineAdapter
import org.futo.circles.feature.timeline.list.PostOptionsListener import org.futo.circles.feature.timeline.list.PostOptionsListener
import org.futo.circles.feature.timeline.list.TimelineAdapter
import org.futo.circles.feature.timeline.post.create.PostSentListener import org.futo.circles.feature.timeline.post.create.PostSentListener
import org.futo.circles.feature.timeline.post.emoji.EmojiPickerListener import org.futo.circles.feature.timeline.post.emoji.EmojiPickerListener
import org.futo.circles.feature.timeline.post.menu.PostMenuListener import org.futo.circles.feature.timeline.post.menu.PostMenuListener
...@@ -43,7 +43,7 @@ class DMTimelineDialogFragment : ...@@ -43,7 +43,7 @@ class DMTimelineDialogFragment :
private val navigator by lazy { DMTimelineNavigator(this) } private val navigator by lazy { DMTimelineNavigator(this) }
private val listAdapter by lazy { private val listAdapter by lazy {
TimelineAdapter(this, false, videoPlayer).apply { DMTimelineAdapter(this, videoPlayer).apply {
setHasStableIds(true) setHasStableIds(true)
} }
} }
......
package org.futo.circles.feature.direct.timeline.list
import androidx.media3.exoplayer.ExoPlayer
import androidx.recyclerview.widget.RecyclerView
import org.futo.circles.core.base.list.BaseRvAdapter
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostListItem
import org.futo.circles.feature.timeline.list.OnVideoPlayBackStateListener
import org.futo.circles.feature.timeline.list.holder.PostViewHolder
import org.futo.circles.feature.timeline.list.holder.VideoPostViewHolder
import org.futo.circles.model.PostItemPayload
abstract class BaseTimelineAdapter<VH : RecyclerView.ViewHolder>(
private val videoPlayer: ExoPlayer
) : BaseRvAdapter<PostListItem, VH>(
PayloadIdEntityCallback { old, new ->
if (new is Post && old is Post)
PostItemPayload(
readByCount = new.readByCount,
repliesCount = new.repliesCount,
reactions = new.reactionsData,
needToUpdateFullItem = new.content != old.content || new.postInfo != old.postInfo
)
else null
}), OnVideoPlayBackStateListener {
private var currentPlayingVideoHolder: VideoPostViewHolder? = null
override fun getItemId(position: Int): Long = getItem(position).id.hashCode().toLong()
override fun onBindViewHolder(holder: VH, position: Int) {
holder.bind(getItem(position))
}
override fun onBindViewHolder(
holder: VH,
position: Int,
payloads: MutableList<Any>
) {
(holder as? PostViewHolder) ?: run {
super.onBindViewHolder(holder, position, payloads)
return
}
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads)
} else {
payloads.forEach {
val payload = (it as? PostItemPayload) ?: return@forEach
if (payload.needToUpdateFullItem) holder.bind(getItem(position))
else holder.bindPayload(payload)
}
}
}
override fun onViewDetachedFromWindow(holder: VH) {
super.onViewDetachedFromWindow(holder)
if (holder == currentPlayingVideoHolder) stopVideoPlayback()
}
override fun onVideoPlaybackStateChanged(holder: VideoPostViewHolder, isPlaying: Boolean) {
currentPlayingVideoHolder = if (isPlaying) {
stopVideoPlayback(false)
holder
} else null
}
fun stopVideoPlayback(shouldNotify: Boolean = true) {
currentPlayingVideoHolder?.stopVideo(shouldNotify)
}
}
\ No newline at end of file
package org.futo.circles.feature.direct.timeline.list package org.futo.circles.feature.direct.timeline.list
class DMTimelineAdapter { import android.view.ViewGroup
import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostContentType
import org.futo.circles.core.model.TimelineLoadingItem
import org.futo.circles.feature.timeline.list.PostOptionsListener
import org.futo.circles.feature.timeline.list.holder.OtherEventPostViewHolder
import org.futo.circles.feature.timeline.list.holder.PostListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.TimelineLoadingViewHolder
private enum class DmTimelineViewType {
MY_TEXT, OTHER_TEXT,
MY_IMAGE, OTHER_IMAGE,
MY_VIDEO, OTHER_VIDEO,
OTHER, LOADING
}
class DMTimelineAdapter(
private val postOptionsListener: PostOptionsListener,
videoPlayer: ExoPlayer
) : BaseTimelineAdapter<PostListItemViewHolder>(videoPlayer) {
override fun getItemViewType(position: Int): Int = when (val item = getItem(position)) {
is Post -> {
val isMyMessage = item.isMyPost()
when (item.content.type) {
PostContentType.TEXT_CONTENT -> if (isMyMessage) DmTimelineViewType.MY_TEXT.ordinal
else DmTimelineViewType.OTHER_TEXT.ordinal
PostContentType.IMAGE_CONTENT -> if (isMyMessage) DmTimelineViewType.MY_IMAGE.ordinal
else DmTimelineViewType.OTHER_IMAGE.ordinal
PostContentType.VIDEO_CONTENT -> if (isMyMessage) DmTimelineViewType.MY_VIDEO.ordinal
else DmTimelineViewType.OTHER_VIDEO.ordinal
else -> DmTimelineViewType.OTHER.ordinal
}
}
is TimelineLoadingItem -> DmTimelineViewType.LOADING.ordinal
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostListItemViewHolder {
return when (DmTimelineViewType.entries[viewType]) {
// TimelineViewType.TEXT -> TextPostViewHolder(
// parent, postOptionsListener, isThread
// )
//
// TimelineViewType.IMAGE -> ImagePostViewHolder(parent, postOptionsListener, isThread)
//
// TimelineViewType.VIDEO -> VideoPostViewHolder(
// parent,
// postOptionsListener,
// isThread,
// videoPlayer,
// this
// )
DmTimelineViewType.MY_TEXT -> TODO()
DmTimelineViewType.OTHER_TEXT -> TODO()
DmTimelineViewType.MY_IMAGE -> TODO()
DmTimelineViewType.OTHER_IMAGE -> TODO()
DmTimelineViewType.MY_VIDEO -> TODO()
DmTimelineViewType.OTHER_VIDEO -> TODO()
DmTimelineViewType.OTHER -> OtherEventPostViewHolder(parent, postOptionsListener)
DmTimelineViewType.LOADING -> TimelineLoadingViewHolder(parent)
}
}
} }
\ No newline at end of file
...@@ -2,20 +2,17 @@ package org.futo.circles.feature.timeline.list ...@@ -2,20 +2,17 @@ package org.futo.circles.feature.timeline.list
import android.view.ViewGroup import android.view.ViewGroup
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import org.futo.circles.core.base.list.BaseRvAdapter
import org.futo.circles.core.model.Post import org.futo.circles.core.model.Post
import org.futo.circles.core.model.PostContentType import org.futo.circles.core.model.PostContentType
import org.futo.circles.core.model.PostListItem
import org.futo.circles.core.model.TimelineLoadingItem import org.futo.circles.core.model.TimelineLoadingItem
import org.futo.circles.feature.direct.timeline.list.BaseTimelineAdapter
import org.futo.circles.feature.timeline.list.holder.ImagePostViewHolder import org.futo.circles.feature.timeline.list.holder.ImagePostViewHolder
import org.futo.circles.feature.timeline.list.holder.OtherEventPostViewHolder import org.futo.circles.feature.timeline.list.holder.OtherEventPostViewHolder
import org.futo.circles.feature.timeline.list.holder.PollPostViewHolder import org.futo.circles.feature.timeline.list.holder.PollPostViewHolder
import org.futo.circles.feature.timeline.list.holder.PostListItemViewHolder import org.futo.circles.feature.timeline.list.holder.PostListItemViewHolder
import org.futo.circles.feature.timeline.list.holder.PostViewHolder
import org.futo.circles.feature.timeline.list.holder.TextPostViewHolder import org.futo.circles.feature.timeline.list.holder.TextPostViewHolder
import org.futo.circles.feature.timeline.list.holder.TimelineLoadingViewHolder import org.futo.circles.feature.timeline.list.holder.TimelineLoadingViewHolder
import org.futo.circles.feature.timeline.list.holder.VideoPostViewHolder import org.futo.circles.feature.timeline.list.holder.VideoPostViewHolder
import org.futo.circles.model.PostItemPayload
private enum class TimelineViewType { TEXT, IMAGE, VIDEO, POLL, OTHER, LOADING } private enum class TimelineViewType { TEXT, IMAGE, VIDEO, POLL, OTHER, LOADING }
...@@ -23,20 +20,8 @@ class TimelineAdapter( ...@@ -23,20 +20,8 @@ class TimelineAdapter(
private val postOptionsListener: PostOptionsListener, private val postOptionsListener: PostOptionsListener,
private val isThread: Boolean, private val isThread: Boolean,
private val videoPlayer: ExoPlayer private val videoPlayer: ExoPlayer
) : BaseRvAdapter<PostListItem, PostListItemViewHolder>(PayloadIdEntityCallback { old, new -> ) : BaseTimelineAdapter<PostListItemViewHolder>(videoPlayer) {
if (new is Post && old is Post)
PostItemPayload(
readByCount = new.readByCount,
repliesCount = new.repliesCount,
reactions = new.reactionsData,
needToUpdateFullItem = new.content != old.content || new.postInfo != old.postInfo
)
else null
}), OnVideoPlayBackStateListener {
private var currentPlayingVideoHolder: VideoPostViewHolder? = null
override fun getItemId(position: Int): Long = getItem(position).id.hashCode().toLong()
override fun getItemViewType(position: Int): Int = when (val item = getItem(position)) { override fun getItemViewType(position: Int): Int = when (val item = getItem(position)) {
is Post -> when (item.content.type) { is Post -> when (item.content.type) {
...@@ -75,46 +60,4 @@ class TimelineAdapter( ...@@ -75,46 +60,4 @@ class TimelineAdapter(
TimelineViewType.LOADING -> TimelineLoadingViewHolder(parent) TimelineViewType.LOADING -> TimelineLoadingViewHolder(parent)
} }
} }
override fun onBindViewHolder(holder: PostListItemViewHolder, position: Int) {
holder.bind(getItem(position))
}
override fun onBindViewHolder(
holder: PostListItemViewHolder,
position: Int,
payloads: MutableList<Any>
) {
(holder as? PostViewHolder) ?: run {
super.onBindViewHolder(holder, position, payloads)
return
}
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads)
} else {
payloads.forEach {
val payload = (it as? PostItemPayload) ?: return@forEach
if (payload.needToUpdateFullItem) holder.bind(getItem(position))
else holder.bindPayload(payload)
}
}
}
override fun onViewDetachedFromWindow(holder: PostListItemViewHolder) {
super.onViewDetachedFromWindow(holder)
if (holder == currentPlayingVideoHolder) stopVideoPlayback()
}
override fun onVideoPlaybackStateChanged(holder: VideoPostViewHolder, isPlaying: Boolean) {
currentPlayingVideoHolder = if (isPlaying) {
stopVideoPlayback(false)
holder
} else null
}
fun stopVideoPlayback(shouldNotify: Boolean = true) {
currentPlayingVideoHolder?.stopVideo(shouldNotify)
}
} }
\ No newline at end of file
<?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_marginStart="36dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/ivBackground"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/chip_selected_color"
app:layout_constraintBottom_toBottomOf="@id/tvTime"
app:layout_constraintEnd_toEndOf="@id/tvMessage"
app:layout_constraintStart_toStartOf="@id/tvMessage"
app:layout_constraintTop_toTopOf="@id/tvMessage"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Message.My" />
<TextView
android:id="@+id/tvMessage"
style="@style/body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:autoLink="web"
android:padding="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
<TextView
android:id="@+id/tvTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:paddingBottom="4dp"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvMessage"
tools:text="sadasdasdasdasdasdasdasdasdasd" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
...@@ -12,12 +12,12 @@ ...@@ -12,12 +12,12 @@
android:id="@+id/ivBackground" android:id="@+id/ivBackground"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:background="@color/chip_selected_color" android:background="@color/post_card_background_color"
app:layout_constraintBottom_toBottomOf="@id/tvTime" app:layout_constraintBottom_toBottomOf="@id/tvTime"
app:layout_constraintEnd_toEndOf="@id/tvMessage" app:layout_constraintEnd_toEndOf="@id/tvMessage"
app:layout_constraintStart_toStartOf="@id/tvMessage" app:layout_constraintStart_toStartOf="@id/tvMessage"
app:layout_constraintTop_toTopOf="@id/tvMessage" app:layout_constraintTop_toTopOf="@id/tvMessage"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Message" /> app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Message.Other" />
<TextView <TextView
android:id="@+id/tvMessage" android:id="@+id/tvMessage"
......
...@@ -105,11 +105,18 @@ ...@@ -105,11 +105,18 @@
<item name="android:windowExitAnimation">@anim/slide_out</item> <item name="android:windowExitAnimation">@anim/slide_out</item>
</style> </style>
<style name="ShapeAppearanceOverlay.App.Message" parent=""> <style name="ShapeAppearanceOverlay.App.Message.Other" parent="">
<item name="cornerSizeTopRight">10dp</item> <item name="cornerSizeTopRight">10dp</item>
<item name="cornerSizeBottomRight">10dp</item> <item name="cornerSizeBottomRight">10dp</item>
<item name="cornerSizeTopLeft">10dp</item> <item name="cornerSizeTopLeft">10dp</item>
<item name="cornerFamilyTopRight">rounded</item> <item name="cornerFamilyTopRight">rounded</item>
</style> </style>
<style name="ShapeAppearanceOverlay.App.Message.My" parent="">
<item name="cornerSizeBottomLeft">10dp</item>
<item name="cornerSizeTopRight">10dp</item>
<item name="cornerSizeTopLeft">10dp</item>
<item name="cornerFamilyTopRight">rounded</item>
</style>
</resources> </resources>
\ No newline at end of file