diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/MainActivity.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/MainActivity.kt
index 5f8a90c78..3874f52f6 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/MainActivity.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/activity/MainActivity.kt
@@ -691,7 +691,7 @@ open class MainActivity : AppCompatActivity(), NavigationDrawerCallbacks, OnSect
2 -> {
mCompositeDisposable.add(InteractorFactory.createStoriesInteractor()
- .getStory(
+ .getStories(
Settings.get().accounts().current,
null
)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/adapters/FeedbackVKOfficialDtoAdapter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/adapters/FeedbackVKOfficialDtoAdapter.kt
index 2f6c28e7c..262b72fea 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/adapters/FeedbackVKOfficialDtoAdapter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/adapters/FeedbackVKOfficialDtoAdapter.kt
@@ -56,10 +56,15 @@ class FeedbackVKOfficialDtoAdapter :
val dto = FeedbackVKOfficial()
if (hasObject(root_item, "action")) {
val action_item = root_item["action"]?.jsonObject
- if ("authorize" == optString(action_item, "type") || "custom" == optString(
+ if ("authorize" == optString(action_item, "type")) {
+ dto.action = ActionBrowserURL(optString(action_item, "url"))
+ } else if ("custom" == optString(
action_item,
"type"
- ) && optString(root_item, "icon_type") == "friend_found"
+ ) && optString(
+ root_item,
+ "icon_type"
+ ) == "friend_found"
) {
dto.action = ActionURL(optString(action_item, "url"))
} else if ("message_open" == optString(
@@ -182,6 +187,13 @@ class FeedbackVKOfficialDtoAdapter :
kJson.decodeFromJsonElement(ImageAdditional.serializer(), s)
dto.images?.add(imgh)
}
+
+ if (hasObject(additional_item, "action")) {
+ val action_item = additional_item["action"]?.jsonObject
+ if ("custom" == optString(action_item, "type")) {
+ dto.images_action = ActionURL(optString(action_item, "url"))
+ }
+ }
}
if ("photo" == optString(additional_item, "type")) {
attachments.add(
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/StoriesShortVideosApi.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/StoriesShortVideosApi.kt
index f33a83c02..56f84ce4d 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/StoriesShortVideosApi.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/impl/StoriesShortVideosApi.kt
@@ -9,8 +9,8 @@ import dev.ragnarok.fenrir.api.model.Items
import dev.ragnarok.fenrir.api.model.VKApiNarratives
import dev.ragnarok.fenrir.api.model.VKApiStory
import dev.ragnarok.fenrir.api.model.response.ShortVideosResponse
+import dev.ragnarok.fenrir.api.model.response.StoriesResponse
import dev.ragnarok.fenrir.api.model.response.StoryGetResponse
-import dev.ragnarok.fenrir.api.model.response.StoryResponse
import dev.ragnarok.fenrir.api.model.response.ViewersListResponse
import dev.ragnarok.fenrir.api.model.server.VKApiStoryUploadServer
import dev.ragnarok.fenrir.api.services.IStoriesShortVideosService
@@ -19,10 +19,14 @@ import io.reactivex.rxjava3.core.Single
internal class StoriesShortVideosApi(accountId: Long, provider: IServiceProvider) :
AbsApi(accountId, provider), IStoriesShortVideosApi {
- override fun getStory(owner_id: Long?, extended: Int?, fields: String?): Single {
+ override fun getStories(
+ owner_id: Long?,
+ extended: Int?,
+ fields: String?
+ ): Single {
return provideService(IStoriesShortVideosService(), TokenType.USER, TokenType.COMMUNITY)
.flatMap { service ->
- service.getStory(owner_id, extended, fields)
+ service.getStories(owner_id, extended, fields)
.map(extractResponseWithErrorHandling())
}
}
@@ -67,16 +71,16 @@ internal class StoriesShortVideosApi(accountId: Long, provider: IServiceProvider
}
}
- override fun searchStory(
+ override fun searchStories(
q: String?,
mentioned_id: Long?,
count: Int?,
extended: Int?,
fields: String?
- ): Single {
+ ): Single {
return provideService(IStoriesShortVideosService(), TokenType.USER, TokenType.COMMUNITY)
.flatMap { service ->
- service.searchStory(q, mentioned_id, count, extended, fields)
+ service.searchStories(q, mentioned_id, count, extended, fields)
.map(extractResponseWithErrorHandling())
}
}
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/interfaces/IStoriesShortVideosApi.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/interfaces/IStoriesShortVideosApi.kt
index 45a2ee2ca..fc1144d25 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/interfaces/IStoriesShortVideosApi.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/interfaces/IStoriesShortVideosApi.kt
@@ -6,8 +6,8 @@ import dev.ragnarok.fenrir.api.model.Items
import dev.ragnarok.fenrir.api.model.VKApiNarratives
import dev.ragnarok.fenrir.api.model.VKApiStory
import dev.ragnarok.fenrir.api.model.response.ShortVideosResponse
+import dev.ragnarok.fenrir.api.model.response.StoriesResponse
import dev.ragnarok.fenrir.api.model.response.StoryGetResponse
-import dev.ragnarok.fenrir.api.model.response.StoryResponse
import dev.ragnarok.fenrir.api.model.response.ViewersListResponse
import dev.ragnarok.fenrir.api.model.server.VKApiStoryUploadServer
import io.reactivex.rxjava3.core.Single
@@ -40,7 +40,7 @@ interface IStoriesShortVideosApi {
fun stories_save(upload_results: String?): Single>
@CheckResult
- fun getStory(owner_id: Long?, extended: Int?, fields: String?): Single
+ fun getStories(owner_id: Long?, extended: Int?, fields: String?): Single
@CheckResult
fun getNarratives(owner_id: Long, offset: Int?, count: Int?): Single>
@@ -53,13 +53,13 @@ interface IStoriesShortVideosApi {
): Single
@CheckResult
- fun searchStory(
+ fun searchStories(
q: String?,
mentioned_id: Long?,
count: Int?,
extended: Int?,
fields: String?
- ): Single
+ ): Single
@CheckResult
fun getShortVideos(
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/model/response/StoryResponse.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/model/response/StoriesResponse.kt
similarity index 95%
rename from app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/model/response/StoryResponse.kt
rename to app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/model/response/StoriesResponse.kt
index 386c8e43f..9b7cf18ca 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/model/response/StoryResponse.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/model/response/StoriesResponse.kt
@@ -6,7 +6,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
-class StoryResponse {
+class StoriesResponse {
@SerialName("items")
var items: List? = null
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/services/IStoriesShortVideosService.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/services/IStoriesShortVideosService.kt
index 4e7af1ded..7aa0fe0b6 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/services/IStoriesShortVideosService.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/api/services/IStoriesShortVideosService.kt
@@ -5,8 +5,8 @@ import dev.ragnarok.fenrir.api.model.VKApiNarratives
import dev.ragnarok.fenrir.api.model.VKApiStory
import dev.ragnarok.fenrir.api.model.response.BaseResponse
import dev.ragnarok.fenrir.api.model.response.ShortVideosResponse
+import dev.ragnarok.fenrir.api.model.response.StoriesResponse
import dev.ragnarok.fenrir.api.model.response.StoryGetResponse
-import dev.ragnarok.fenrir.api.model.response.StoryResponse
import dev.ragnarok.fenrir.api.model.response.ViewersListResponse
import dev.ragnarok.fenrir.api.model.server.VKApiStoryUploadServer
import dev.ragnarok.fenrir.api.rest.IServiceRest
@@ -82,17 +82,17 @@ class IStoriesShortVideosService : IServiceRest() {
)
}
- fun getStory(
+ fun getStories(
owner_id: Long?,
extended: Int?,
fields: String?
- ): Single> {
+ ): Single> {
return rest.request(
"stories.get", form(
"owner_id" to owner_id,
"extended" to extended,
"fields" to fields
- ), base(StoryResponse.serializer())
+ ), base(StoriesResponse.serializer())
)
}
@@ -124,13 +124,13 @@ class IStoriesShortVideosService : IServiceRest() {
)
}
- fun searchStory(
+ fun searchStories(
q: String?,
mentioned_id: Long?,
count: Int?,
extended: Int?,
fields: String?
- ): Single> {
+ ): Single> {
return rest.request(
"stories.search", form(
"q" to q,
@@ -138,7 +138,7 @@ class IStoriesShortVideosService : IServiceRest() {
"count" to count,
"extended" to extended,
"fields" to fields
- ), base(StoryResponse.serializer())
+ ), base(StoriesResponse.serializer())
)
}
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/IStoriesShortVideosInteractor.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/IStoriesShortVideosInteractor.kt
index 20519c43a..83502a716 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/IStoriesShortVideosInteractor.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/IStoriesShortVideosInteractor.kt
@@ -16,8 +16,8 @@ interface IStoriesShortVideosInteractor {
offset: Int
): Single>>
- fun searchStory(accountId: Long, q: String?, mentioned_id: Long?): Single>
- fun getStory(accountId: Long, owner_id: Long?): Single>
+ fun searchStories(accountId: Long, q: String?, mentioned_id: Long?): Single>
+ fun getStories(accountId: Long, owner_id: Long?): Single>
fun stories_delete(accountId: Long, owner_id: Long, story_id: Int): Single
fun getNarratives(
accountId: Long,
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/impl/StoriesShortVideosInteractor.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/impl/StoriesShortVideosInteractor.kt
index 4d3f58ca4..a0f6db391 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/impl/StoriesShortVideosInteractor.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/domain/impl/StoriesShortVideosInteractor.kt
@@ -121,10 +121,10 @@ class StoriesShortVideosInteractor(
.stories().stories_delete(owner_id, story_id)
}
- override fun getStory(accountId: Long, owner_id: Long?): Single> {
+ override fun getStories(accountId: Long, owner_id: Long?): Single> {
return networker.vkDefault(accountId)
.stories()
- .getStory(owner_id, 1, Fields.FIELDS_BASE_OWNER)
+ .getStories(owner_id, 1, Fields.FIELDS_BASE_OWNER)
.flatMap { story ->
val dtos_multy = listEmptyIfNull(story.items)
val dtos: MutableList = ArrayList()
@@ -156,14 +156,14 @@ class StoriesShortVideosInteractor(
}
}
- override fun searchStory(
+ override fun searchStories(
accountId: Long,
q: String?,
mentioned_id: Long?
): Single> {
return networker.vkDefault(accountId)
.stories()
- .searchStory(q, mentioned_id, 1000, 1, Fields.FIELDS_BASE_OWNER)
+ .searchStories(q, mentioned_id, 1000, 1, Fields.FIELDS_BASE_OWNER)
.flatMap { story ->
val dtos_multy = listEmptyIfNull(story.items)
val dtos: MutableList = ArrayList()
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialAdapter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialAdapter.kt
index 725a67d39..a311025f8 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialAdapter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialAdapter.kt
@@ -231,9 +231,15 @@ class FeedbackVKOfficialAdapter(
holder.time.text = AppTextUtils.getDateFromUnixTime(context, Page.time)
val Img = Page.getImage(256)
if (Img == null) {
+ holder.additional.setOnClickListener { }
holder.additional.visibility = View.GONE
with().cancelRequest(holder.additional)
} else {
+ holder.additional.setOnClickListener {
+ Page.images_action.requireNonNull { sc ->
+ clickListener?.openAction(sc)
+ }
+ }
holder.additional.visibility = View.VISIBLE
with()
.load(Img.url)
@@ -297,7 +303,7 @@ class FeedbackVKOfficialAdapter(
}
}
Page.action.ifNonNull({
- if (it.getActionType() == FeedbackVKOfficial.Action_Types.URL) {
+ if (it.getActionType() == FeedbackVKOfficial.Action_Types.URL || it.getActionType() == FeedbackVKOfficial.Action_Types.BROWSER_URL) {
holder.actionButton.setText(R.string.more_info)
} else {
holder.actionButton.setText(R.string.open)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialFragment.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialFragment.kt
index fcf8a22f7..616b4c080 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialFragment.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/feedback/feedbackvkofficial/FeedbackVKOfficialFragment.kt
@@ -24,6 +24,7 @@ import dev.ragnarok.fenrir.listener.EndlessRecyclerOnScrollListener
import dev.ragnarok.fenrir.listener.OnSectionResumeCallback
import dev.ragnarok.fenrir.listener.PicassoPauseOnScrollListener
import dev.ragnarok.fenrir.model.FeedbackVKOfficial
+import dev.ragnarok.fenrir.model.FeedbackVKOfficial.ActionBrowserURL
import dev.ragnarok.fenrir.model.FeedbackVKOfficial.ActionMessage
import dev.ragnarok.fenrir.model.FeedbackVKOfficial.ActionURL
import dev.ragnarok.fenrir.model.FeedbackVKOfficialList
@@ -154,16 +155,32 @@ class FeedbackVKOfficialFragment :
}
override fun openAction(action: FeedbackVKOfficial.Action) {
- if (action.getActionType() == FeedbackVKOfficial.Action_Types.URL) {
- LinkHelper.openLinkInBrowser(requireActivity(), (action as ActionURL).getUrl())
- } else if (action.getActionType() == FeedbackVKOfficial.Action_Types.MESSAGE) {
- val msg = action as ActionMessage
- getMessagesLookupPlace(
- Settings.get().accounts().current,
- msg.getPeerId(),
- msg.getMessageId(),
- null
- ).tryOpenWith(requireActivity())
+ when (action.getActionType()) {
+ FeedbackVKOfficial.Action_Types.BROWSER_URL -> {
+ LinkHelper.openLinkInBrowser(
+ requireActivity(),
+ (action as ActionBrowserURL).getUrl()
+ )
+ }
+
+ FeedbackVKOfficial.Action_Types.URL -> {
+ LinkHelper.openUrl(
+ requireActivity(),
+ Settings.get().accounts().current,
+ (action as ActionURL).getUrl(),
+ false
+ )
+ }
+
+ FeedbackVKOfficial.Action_Types.MESSAGE -> {
+ val msg = action as ActionMessage
+ getMessagesLookupPlace(
+ Settings.get().accounts().current,
+ msg.getPeerId(),
+ msg.getMessageId(),
+ null
+ ).tryOpenWith(requireActivity())
+ }
}
}
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/AbsWallPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/AbsWallPresenter.kt
index 27ce19d7f..cb643b2d2 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/AbsWallPresenter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/AbsWallPresenter.kt
@@ -472,7 +472,7 @@ abstract class AbsWallPresenter internal constructor(
cacheCompositeDisposable.clear()
requestWall(0)
if (!Settings.get().other().isDisable_history) {
- appendDisposable(storiesInteractor.getStory(
+ appendDisposable(storiesInteractor.getStories(
accountId,
if (accountId == ownerId) null else ownerId
)
@@ -904,7 +904,7 @@ abstract class AbsWallPresenter internal constructor(
storiesInteractor = InteractorFactory.createStoriesInteractor()
loadWallCachedData()
if (!Settings.get().other().isDisable_history) {
- appendDisposable(storiesInteractor.getStory(
+ appendDisposable(storiesInteractor.getStories(
accountId,
if (accountId == ownerId) null else ownerId
)
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/groupwall/GroupWallPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/groupwall/GroupWallPresenter.kt
index 1f637aa91..0786d997f 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/groupwall/GroupWallPresenter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/groupwall/GroupWallPresenter.kt
@@ -573,7 +573,7 @@ class GroupWallPresenter(
}
override fun searchStory(ByName: Boolean) {
- appendDisposable(storiesInteractor.searchStory(
+ appendDisposable(storiesInteractor.searchStories(
accountId,
if (ByName) community.fullName else null,
if (ByName) null else ownerId
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/userwall/UserWallPresenter.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/userwall/UserWallPresenter.kt
index 7952bb960..6047d3d3f 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/userwall/UserWallPresenter.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/fragment/wall/userwall/UserWallPresenter.kt
@@ -749,7 +749,7 @@ class UserWallPresenter(
}
override fun searchStory(ByName: Boolean) {
- appendDisposable(storiesInteractor.searchStory(
+ appendDisposable(storiesInteractor.searchStories(
accountId,
if (ByName) user.fullName else null,
if (ByName) null else ownerId
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/LinkHelper.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/LinkHelper.kt
index e30f52eec..761f1d1a6 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/LinkHelper.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/LinkHelper.kt
@@ -13,6 +13,7 @@ import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsService
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dev.ragnarok.fenrir.R
+import dev.ragnarok.fenrir.api.model.AccessIdPair
import dev.ragnarok.fenrir.domain.InteractorFactory
import dev.ragnarok.fenrir.fragment.fave.FaveTabsFragment
import dev.ragnarok.fenrir.fragment.photos.vkphotos.IVKPhotosView
@@ -23,6 +24,7 @@ import dev.ragnarok.fenrir.link.types.*
import dev.ragnarok.fenrir.link.types.FaveLink
import dev.ragnarok.fenrir.media.music.MusicPlaybackService.Companion.startForPlayList
import dev.ragnarok.fenrir.model.*
+import dev.ragnarok.fenrir.place.PlaceFactory
import dev.ragnarok.fenrir.place.PlaceFactory.getArtistPlace
import dev.ragnarok.fenrir.place.PlaceFactory.getAudiosInAlbumPlace
import dev.ragnarok.fenrir.place.PlaceFactory.getAudiosPlace
@@ -352,6 +354,19 @@ object LinkHelper {
}) { e -> createCustomToast(context).showToastThrowable(e) }
}
+ AbsLink.STORY -> {
+ val storyLink = link as StoryLink
+ InteractorFactory.createStoriesInteractor().getStoryById(
+ accountId,
+ listOf(AccessIdPair(storyLink.storyId, storyLink.ownerId, storyLink.access_key))
+ )
+ .fromIOToMain()
+ .subscribe({
+ PlaceFactory.getHistoryVideoPreviewPlace(accountId, ArrayList(it), 0)
+ .tryOpenWith(context)
+ }) { e -> createCustomToast(context).showToastThrowable(e) }
+ }
+
else -> return false
}
return true
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/VKLinkParser.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/VKLinkParser.kt
index 2b22d887b..450451ae4 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/VKLinkParser.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/VKLinkParser.kt
@@ -41,6 +41,7 @@ object VKLinkParser {
val PATTERN_PLAYLIST_ALT: Pattern =
Pattern.compile("vk\\.com/.+(?:act=|z=)audio_playlist(-?\\d*)_(\\d*)(?:&access_hash=(\\w+))?")
val PATTERN_DOC: Pattern = Pattern.compile("vk\\.com/doc(-?\\d*)_(\\d*)") //+
+ val PATTERN_STORY: Pattern = Pattern.compile("vk\\.com/story(-?\\d*)_(\\d*)") //+
val PATTERN_TOPIC: Pattern = Pattern.compile("vk\\.com/topic-(\\d*)_(\\d*)") //+
val PATTERN_FAVE: Pattern = Pattern.compile("vk\\.com/fave")
val PATTERN_GROUP_ID: Pattern = Pattern.compile("vk\\.com/(club|event|public)(\\d+)$") //+
@@ -252,6 +253,10 @@ object VKLinkParser {
if (vkLink != null) {
return vkLink
}
+ vkLink = parseStory(string)
+ if (vkLink != null) {
+ return vkLink
+ }
vkLink = parsePhotos(string)
if (vkLink != null) {
return vkLink
@@ -664,6 +669,25 @@ object VKLinkParser {
return null
}
+ private fun parseStory(string: String): AbsLink? {
+ val matcher = patterns.PATTERN_STORY.matcher(string)
+ try {
+ if (matcher.find()) {
+ return matcher.group(1)?.let {
+ matcher.group(2)?.let { it1 ->
+ StoryLink(
+ it.toLong(),
+ it1.toInt(),
+ parseAccessKey(string)
+ )
+ }
+ }
+ }
+ } catch (ignored: Exception) {
+ }
+ return null
+ }
+
private fun parseWall(string: String): AbsLink? {
val matcher = patterns.PATTERN_WALL.matcher(string)
return if (!matcher.find()) {
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/AbsLink.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/AbsLink.kt
index 4b096c6b9..565713d39 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/AbsLink.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/AbsLink.kt
@@ -34,6 +34,7 @@ abstract class AbsLink(val type: Int) {
const val VIDEOS = 26
const val APP_LINK = 27
const val ARTICLE_LINK = 28
- const val CATALOG_V2_SECTION_LINK = 29
+ const val STORY = 29
+ const val CATALOG_V2_SECTION_LINK = 30
}
}
\ No newline at end of file
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/StoryLink.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/StoryLink.kt
new file mode 100644
index 000000000..81b72a8f2
--- /dev/null
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/link/types/StoryLink.kt
@@ -0,0 +1,11 @@
+package dev.ragnarok.fenrir.link.types
+
+class StoryLink(val ownerId: Long, val storyId: Int, val access_key: String?) : AbsLink(STORY) {
+ override fun toString(): String {
+ return "StoryLink{" +
+ "ownerId=" + ownerId +
+ ", storyId=" + storyId +
+ ", Access_Key=" + access_key +
+ '}'
+ }
+}
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/model/FeedbackVKOfficial.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/model/FeedbackVKOfficial.kt
index 8e98f7aad..a82062e99 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/model/FeedbackVKOfficial.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/model/FeedbackVKOfficial.kt
@@ -19,6 +19,7 @@ class FeedbackVKOfficial {
var hide_query: String? = null
var time: Long = 0
var images: ArrayList? = null
+ var images_action: Action? = null
var attachments: ArrayList? = null
var action: Action? = null
fun getImage(prefSize: Int): ImageAdditional? {
@@ -36,12 +37,13 @@ class FeedbackVKOfficial {
return result
}
- @IntDef(Action_Types.MESSAGE, Action_Types.URL)
+ @IntDef(Action_Types.MESSAGE, Action_Types.BROWSER_URL, Action_Types.URL)
@Retention(AnnotationRetention.SOURCE)
annotation class Action_Types {
companion object {
const val MESSAGE = 0
- const val URL = 1
+ const val BROWSER_URL = 1
+ const val URL = 2
}
}
@@ -82,6 +84,19 @@ class FeedbackVKOfficial {
}
}
+ @Keep
+ @Serializable
+ @SerialName("action_browser_url")
+ class ActionBrowserURL(private val url: String?) : Action() {
+ fun getUrl(): String? {
+ return url
+ }
+
+ override fun getActionType(): Int {
+ return Action_Types.BROWSER_URL
+ }
+ }
+
@Keep
@Serializable
class ImageAdditional {
diff --git a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/push/message/LikeFCMMessage.kt b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/push/message/LikeFCMMessage.kt
index 32b910e4d..3cfb96766 100644
--- a/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/push/message/LikeFCMMessage.kt
+++ b/app_fenrir/src/main/kotlin/dev/ragnarok/fenrir/push/message/LikeFCMMessage.kt
@@ -150,6 +150,7 @@ class LikeFCMMessage {
.setSmallIcon(R.drawable.heart)
.setContentTitle(context.getString(R.string.like_title))
.setContentText(title)
+ .setStyle(NotificationCompat.BigTextStyle().bigText(title))
.setNumber(badge)
.setAutoCancel(true)
builder.priority = NotificationCompat.PRIORITY_HIGH
diff --git a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt
index eea1647d6..60da9a43b 100644
--- a/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt
+++ b/app_filegallery/src/main/kotlin/dev/ragnarok/filegallery/fragment/PreferencesFragment.kt
@@ -797,6 +797,12 @@ class PreferencesFragment : AbsPreferencesFragment(), PreferencesAdapter.OnScree
).absolutePath || sel.absolutePath == File(
Environment.getExternalStorageDirectory(),
".sstmp"
+ ).absolutePath || sel.absolutePath == File(
+ Environment.getExternalStorageDirectory(),
+ ".SLOGAN"
+ ).absolutePath || sel.absolutePath == File(
+ Environment.getExternalStorageDirectory(),
+ ".OplusOS"
).absolutePath || sel.absolutePath == File(
Environment.getExternalStorageDirectory(),
".time"
diff --git a/build.gradle b/build.gradle
index 9042bd015..6754a633e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,18 +13,18 @@ buildscript {
ext.appFileGalleryVersionName = "1.999"
//androidx libraries
- ext.activityVersion = "1.7.1"
+ ext.activityVersion = "1.7.2"
ext.annotationVersion = "1.6.0"
ext.appcompatVersion = "1.6.1"
ext.biometricVersion = "1.2.0-alpha05"
ext.browserVersion = "1.5.0"
- ext.cameraVersion = "1.2.2"
+ ext.cameraVersion = "1.2.3"
ext.cardviewVersion = "1.0.0"
ext.collectionVersion = "1.3.0-alpha04"
ext.concurentVersion = "1.2.0-alpha01"
- ext.constraintlayoutVersion = "2.2.0-alpha09"
+ ext.constraintlayoutVersion = "2.2.0-alpha10"
ext.coordinatorlayoutVersion = "1.2.0"
- ext.coreVersion = "1.10.1"
+ ext.coreVersion = "1.11.0-beta01"
ext.customviewVersion = "1.2.0-alpha02"
ext.customviewPoolingcontainerVersion = "1.0.0"
ext.drawerlayoutVersion = "1.2.0"
@@ -35,10 +35,10 @@ buildscript {
ext.loaderVersion = "1.1.0"
ext.mediaVersion = "1.7.0-alpha01"
ext.media3Version = "1.1.0-alpha01"
- ext.recyclerviewVersion = "1.3.0"
+ ext.recyclerviewVersion = "1.3.1-rc01"
ext.savedStateVersion = "1.2.1"
ext.swiperefreshlayoutVersion = "1.2.0-alpha01"
- ext.tracingVersion = "1.2.0-beta04"
+ ext.tracingVersion = "1.2.0-rc01"
ext.transitionVersion = "1.4.1"
ext.vectordrawableVersion = "1.2.0-beta01"
ext.webkitVersion = "1.7.0-rc01"
@@ -58,12 +58,12 @@ buildscript {
//common libraries
ext.kotlin_version = "1.8.21"
- ext.kotlin_coroutines = "1.7.0"
+ ext.kotlin_coroutines = "1.7.1"
ext.kotlin_serializer = "1.5.1"
ext.okhttpLibraryVersion = "5.0.0-alpha.11"
ext.okioVersion = "3.3.0"
ext.rxJavaVersion = "3.1.6"
- ext.guavaVersion = "31.1-android"
+ ext.guavaVersion = "32.0.0-android"
ext.errorproneVersion = "2.15.0"
ext.checkerCompatQualVersion = "2.5.5"
ext.checkerQualAndroidVersion = "3.34.0"
@@ -91,7 +91,7 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath "com.android.tools.build:gradle:8.0.1"
+ classpath "com.android.tools.build:gradle:8.0.2"
classpath "com.google.gms:google-services:4.3.15"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
diff --git a/camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 64494281d..a7b28fbd5 100644
--- a/camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -631,7 +631,7 @@ public void onUseCaseReset(@NonNull UseCase useCase) {
mExecutor.execute(() -> {
debugLog("Use case " + useCaseId + " RESET");
mUseCaseAttachState.updateUseCase(useCaseId, sessionConfig, useCaseConfig);
-
+ addOrRemoveMeteringRepeatingUseCase();
resetCaptureSession(/*abortInFlightCaptures=*/false);
updateCaptureSessionConfig();
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_neon.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_neon.cc
index d734b817c..b653765cc 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/row_neon.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/row_neon.cc
@@ -725,12 +725,12 @@ void DetileToYUY2_NEON(const uint8_t* src_y,
void UnpackMT2T_NEON(const uint8_t* src, uint16_t* dst, size_t size) {
asm volatile(
"1: \n"
- "vld1.8 q14, [%0]! \n" // Load lower bits.
- "vld1.8 q9, [%0]! \n" // Load upper bits row
+ "vld1.8 {q14}, [%0]! \n" // Load lower bits.
+ "vld1.8 {q9}, [%0]! \n" // Load upper bits row
// by row.
- "vld1.8 q11, [%0]! \n"
- "vld1.8 q13, [%0]! \n"
- "vld1.8 q15, [%0]! \n"
+ "vld1.8 {q11}, [%0]! \n"
+ "vld1.8 {q13}, [%0]! \n"
+ "vld1.8 {q15}, [%0]! \n"
"vshl.u8 q8, q14, #6 \n" // Shift lower bit data
// appropriately.
"vshl.u8 q10, q14, #4 \n"
@@ -804,7 +804,7 @@ void SplitRGBRow_NEON(const uint8_t* src_rgb,
"+r"(dst_b), // %3
"+r"(width) // %4
: // Input registers
- : "cc", "memory", "d0", "d1", "d2" // Clobber List
+ : "cc", "memory", "q0", "q1", "q2" // Clobber List
);
}
@@ -3845,7 +3845,7 @@ void SplitUVRow_16_NEON(const uint16_t* src_uv,
"+r"(dst_v), // %2
"+r"(width) // %3
: "r"(shift) // %4
- : "cc", "memory", "q0", "q1", "q2", "q3", "q4");
+ : "cc", "memory", "q0", "q1", "q2");
}
void MergeUVRow_16_NEON(const uint16_t* src_u,
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc b/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc
index 893333216..be4c4a309 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/row_rvv.cc
@@ -28,20 +28,20 @@ extern "C" {
// Fill YUV -> RGB conversion constants into vectors
// NOTE: To match behavior on other platforms, vxrm (fixed-point rounding mode
-// register) is set to round-down mode(2).
+// register) is set to round-to-nearest-up mode(0).
#define YUVTORGB_SETUP(yuvconst, vl, v_ub, v_vr, v_ug, v_vg, v_yg, v_bb, v_bg, \
v_br) \
{ \
- asm volatile("csrwi vxrm, 2"); \
+ asm volatile("csrwi vxrm, 0"); \
vl = __riscv_vsetvl_e8m1(w); \
v_ub = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[0], vl); \
v_vr = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[1], vl); \
v_ug = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[2], vl); \
v_vg = __riscv_vmv_v_x_u8m1(yuvconst->kUVCoeff[3], vl); \
v_yg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[0], vl); \
- v_bb = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[1], vl); \
- v_bg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[2], vl); \
- v_br = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[3], vl); \
+ v_bb = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[1] + 32, vl); \
+ v_bg = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[2] - 32, vl); \
+ v_br = __riscv_vmv_v_x_u16m2(yuvconst->kRGBCoeffBias[3] + 32, vl); \
}
// Read [VLEN/8] Y, [VLEN/(8 * 2)] U and [VLEN/(8 * 2)] V from 422
@@ -485,23 +485,21 @@ void I400ToARGBRow_RVV(const uint8_t* src_y,
vuint16m4_t v_yb;
vuint16m4_t v_yg = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[0], vl);
// To match behavior on other platforms, vxrm (fixed-point rounding mode
- // register) sets to round-down mode(2).
- asm volatile("csrwi vxrm, 2");
+ // register) sets to round-to-nearest-up mode(0).
+ asm volatile("csrwi vxrm, 0");
if (is_yb_positive) {
- v_yb = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[4], vl);
+ v_yb = __riscv_vmv_v_x_u16m4(yuvconstants->kRGBCoeffBias[4] - 32, vl);
} else {
- v_yb = __riscv_vmv_v_x_u16m4(-yuvconstants->kRGBCoeffBias[4], vl);
+ v_yb = __riscv_vmv_v_x_u16m4(-yuvconstants->kRGBCoeffBias[4] + 32, vl);
}
do {
vuint8m2_t v_y, v_out;
vuint16m4_t v_y_16, v_tmp0, v_tmp1, v_tmp2;
- vuint32m8_t v_y1;
vl = __riscv_vsetvl_e8m2(w);
v_y = __riscv_vle8_v_u8m2(src_y, vl);
v_y_16 = __riscv_vwaddu_vx_u16m4(v_y, 0, vl);
v_tmp0 = __riscv_vmul_vx_u16m4(v_y_16, 0x0101, vl); // 257 * v_y
- v_y1 = __riscv_vwmulu_vv_u32m8(v_tmp0, v_yg, vl);
- v_tmp1 = __riscv_vnsrl_wx_u16m4(v_y1, 16, vl);
+ v_tmp1 = __riscv_vmulhu_vv_u16m4(v_tmp0, v_yg, vl);
if (is_yb_positive) {
v_tmp2 = __riscv_vsaddu_vv_u16m4(v_tmp1, v_yb, vl);
} else {
diff --git a/libfenrir/src/main/jni/animation/libyuv/source/scale.cc b/libfenrir/src/main/jni/animation/libyuv/source/scale.cc
index 90abaefe8..591a6a938 100644
--- a/libfenrir/src/main/jni/animation/libyuv/source/scale.cc
+++ b/libfenrir/src/main/jni/animation/libyuv/source/scale.cc
@@ -820,9 +820,10 @@ static void ScaleAddCols2_C(int dst_width,
int ix = x >> 16;
x += dx;
boxwidth = MIN1((x >> 16) - ix);
- assert(((boxwidth - minboxwidth) == 0) || ((boxwidth - minboxwidth) == 1));
+ int scaletbl_index = boxwidth - minboxwidth;
+ assert((scaletbl_index == 0) || (scaletbl_index == 1));
*dst_ptr++ = (uint8_t)(SumPixels(boxwidth, src_ptr + ix) *
- scaletbl[boxwidth - minboxwidth] >>
+ scaletbl[scaletbl_index] >>
16);
}
}
@@ -843,10 +844,10 @@ static void ScaleAddCols2_16_C(int dst_width,
int ix = x >> 16;
x += dx;
boxwidth = MIN1((x >> 16) - ix);
- assert(((boxwidth - minboxwidth) == 0) || ((boxwidth - minboxwidth) == 1));
- *dst_ptr++ = SumPixels_16(boxwidth, src_ptr + ix) *
- scaletbl[boxwidth - minboxwidth] >>
- 16;
+ int scaletbl_index = boxwidth - minboxwidth;
+ assert((scaletbl_index == 0) || (scaletbl_index == 1));
+ *dst_ptr++ =
+ SumPixels_16(boxwidth, src_ptr + ix) * scaletbl[scaletbl_index] >> 16;
}
}
diff --git a/libfenrir/src/main/jni/rlottie/rlottie-master.zip b/libfenrir/src/main/jni/rlottie/rlottie-master.zip
index 4e879b73c..9366bf958 100644
Binary files a/libfenrir/src/main/jni/rlottie/rlottie-master.zip and b/libfenrir/src/main/jni/rlottie/rlottie-master.zip differ
diff --git a/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.cpp b/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.cpp
index 0c97fea4e..be036bb22 100644
--- a/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.cpp
+++ b/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.cpp
@@ -168,6 +168,28 @@ bool renderer::Composition::render(const rlottie::Surface &surface, bool clear)
painter.setDrawRegion(
VRect(int(surface.drawRegionPosX()), int(surface.drawRegionPosY()),
int(surface.drawRegionWidth()), int(surface.drawRegionHeight())));
+
+ // layer surface should be created if it is not created already or its size
+ // is changed.
+ bool isLayerSurfaceCreated = mSurfaceCache.is_layer_surface_created();
+ bool isLayerSurfaceSizeChanged =
+ isLayerSurfaceCreated &&
+ (mSurfaceCache.get_layer_surface()->width() != surface.width() ||
+ mSurfaceCache.get_layer_surface()->height() != surface.height());
+
+ if (!isLayerSurfaceCreated || isLayerSurfaceSizeChanged) {
+ if (isLayerSurfaceCreated && isLayerSurfaceSizeChanged)
+ mSurfaceCache.delete_layer_surface();
+
+ mSurfaceCache.create_layer_surface(surface.width(), surface.height(),
+ VBitmap::Format::ARGB32_Premultiplied);
+
+ // set layer draw region
+ mSurfaceCache.get_layer_painter()->setDrawRegion(
+ VRect(int(surface.drawRegionPosX()), int(surface.drawRegionPosY()),
+ int(surface.drawRegionWidth()), int(surface.drawRegionHeight())));
+ }
+
mRootLayer->render(&painter, {}, {}, mSurfaceCache);
painter.end();
return true;
@@ -217,7 +239,7 @@ void renderer::Mask::preprocess(const VRect &clip)
}
void renderer::Layer::render(VPainter *painter, const VRle &inheritMask,
- const VRle &matteRle, SurfaceCache &)
+ const VRle &matteRle, SurfaceCache &cache)
{
auto renderlist = renderList();
@@ -233,31 +255,42 @@ void renderer::Layer::render(VPainter *painter, const VRle &inheritMask,
mask = inheritMask;
}
+ VPainter *usedPainter = painter;
+
+ if (cache.get_layer_painter() != nullptr) {
+ usedPainter = cache.get_layer_painter();
+ usedPainter->begin(cache.get_layer_surface(), true);
+ }
+
for (auto &i : renderlist) {
- painter->setBrush(i->mBrush);
+ usedPainter->setBrush(i->mBrush);
VRle rle = i->rle();
if (matteRle.empty()) {
if (mask.empty()) {
// no mask no matte
- painter->drawRle(VPoint(), rle);
+ usedPainter->drawRle(VPoint(), rle);
} else {
// only mask
- painter->drawRle(rle, mask);
+ usedPainter->drawRle(rle, mask);
}
-
} else {
if (!mask.empty()) rle = rle & mask;
if (rle.empty()) continue;
if (matteType() == model::MatteType::AlphaInv) {
rle = rle - matteRle;
- painter->drawRle(VPoint(), rle);
+ usedPainter->drawRle(VPoint(), rle);
} else {
// render with matteRle as clip.
- painter->drawRle(rle, matteRle);
+ usedPainter->drawRle(rle, matteRle);
}
}
}
+
+ if (cache.get_layer_painter() != nullptr) {
+ usedPainter->end();
+ painter->drawBitmap(VPoint(), *cache.get_layer_surface(), mCombinedAlpha * 255.0f);
+ }
}
void renderer::LayerMask::preprocess(const VRect &clip)
@@ -977,7 +1010,7 @@ void renderer::Group::update(int frameNo, const VMatrix &parentMatrix,
mMatrix = m;
- alpha = parentAlpha * mModel.transform()->opacity(frameNo);
+ alpha = mModel.transform()->opacity(frameNo);
if (!vCompare(alpha, parentAlpha)) {
newFlag |= DirtyFlagBit::Alpha;
}
@@ -1303,9 +1336,9 @@ renderer::Stroke::Stroke(model::Stroke *data)
static vthread_local std::vector Dash_Vector;
bool renderer::Stroke::updateContent(int frameNo, const VMatrix &matrix,
- float alpha)
+ float)
{
- auto combinedAlpha = alpha * mModel.opacity(frameNo);
+ auto combinedAlpha = mModel.opacity(frameNo);
auto color = mModel.color(frameNo).toColor(combinedAlpha);
VBrush brush(color);
diff --git a/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.h b/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.h
index 1be7694b1..0628bdc9f 100644
--- a/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.h
+++ b/libfenrir/src/main/jni/rlottie/src/lottie/lottieitem.h
@@ -106,9 +106,31 @@ class SurfaceCache {
}
void release_surface(VBitmap &surface) { mCache.push_back(surface); }
+ bool is_layer_surface_created() const { return mIsLayerBitmapCreated; }
+ void create_layer_surface(size_t width, size_t height, VBitmap::Format format)
+ {
+ if (mIsLayerBitmapCreated) return;
+
+ mLayerBitmap = std::make_unique(width, height, format);
+ mBitmapPainter = std::make_unique(mLayerBitmap.get(), true);
+ mIsLayerBitmapCreated = true;
+ }
+ void delete_layer_surface()
+ {
+ if (!mIsLayerBitmapCreated) return;
+
+ mLayerBitmap.reset();
+ mBitmapPainter.reset();
+ mIsLayerBitmapCreated = false;
+ }
+ VPainter* get_layer_painter() const { return mBitmapPainter.get(); }
+ VBitmap* get_layer_surface() const { return mLayerBitmap.get(); }
private:
std::vector mCache;
+ std::unique_ptr mLayerBitmap{nullptr};
+ std::unique_ptr mBitmapPainter{nullptr};
+ bool mIsLayerBitmapCreated{false};
};
class Drawable final : public VDrawable {
diff --git a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
index cf658a6ab..59a83ab06 100644
--- a/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
+++ b/libfenrir/src/main/jni/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
@@ -94,7 +94,7 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u
auto h = static_cast(region.max.y - region.min.y);
auto w = static_cast(region.max.x - region.min.x);
- auto ialpha = 255 - static_cast(_alpha(color));
+ uint32_t ialpha = 255 - a;
auto avxColor = _mm_set1_epi32(color);
auto avxIalpha = _mm_set1_epi8(ialpha);
@@ -148,7 +148,7 @@ static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, ui
if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage);
else src = color;
- auto ialpha = 255 - static_cast(_alpha(src));
+ auto ialpha = _ialpha(src);
//1. fill the not aligned memory (for 128-bit registers a 16-bytes alignment is required)
auto notAligned = ((uintptr_t)dst & 0xf) / 4;
diff --git a/viewpager2/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java b/viewpager2/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java
index 7a102fdba..ccd9cfae6 100644
--- a/viewpager2/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java
+++ b/viewpager2/src/main/java/androidx/recyclerview/widget/AsyncDifferConfig.java
@@ -50,6 +50,7 @@ public final class AsyncDifferConfig {
mDiffCallback = diffCallback;
}
+ /** @hide */
@SuppressWarnings("WeakerAccess")
@RestrictTo(RestrictTo.Scope.LIBRARY)
@Nullable
@@ -93,6 +94,7 @@ public Builder(@NonNull DiffUtil.ItemCallback diffCallback) {
* @param executor The executor which can run tasks in the UI thread.
* @return this
*
+ * @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
@NonNull
diff --git a/viewpager2/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java b/viewpager2/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
index 1534330c0..84d11622e 100644
--- a/viewpager2/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
+++ b/viewpager2/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
@@ -17,7 +17,6 @@
import android.content.Context;
import android.graphics.Rect;
-import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseIntArray;
@@ -26,7 +25,6 @@
import android.widget.GridView;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import java.util.Arrays;
@@ -42,7 +40,6 @@ public class GridLayoutManager extends LinearLayoutManager {
private static final boolean DEBUG = false;
private static final String TAG = "GridLayoutManager";
public static final int DEFAULT_SPAN_COUNT = -1;
-
/**
* Span size have been changed but we've not done a new layout calculation.
*/
@@ -122,7 +119,7 @@ public void setStackFromEnd(boolean stackFromEnd) {
public int getRowCountForAccessibility(RecyclerView.Recycler recycler,
RecyclerView.State state) {
if (mOrientation == HORIZONTAL) {
- return Math.min(mSpanCount, getItemCount());
+ return mSpanCount;
}
if (state.getItemCount() < 1) {
return 0;
@@ -136,7 +133,7 @@ public int getRowCountForAccessibility(RecyclerView.Recycler recycler,
public int getColumnCountForAccessibility(RecyclerView.Recycler recycler,
RecyclerView.State state) {
if (mOrientation == VERTICAL) {
- return Math.min(mSpanCount, getItemCount());
+ return mSpanCount;
}
if (state.getItemCount() < 1) {
return 0;
@@ -177,57 +174,6 @@ public void onInitializeAccessibilityNodeInfo(@NonNull RecyclerView.Recycler rec
info.setClassName(GridView.class.getName());
}
- @Override
- boolean performAccessibilityAction(int action, @Nullable Bundle args) {
- if (action == android.R.id.accessibilityActionScrollToPosition) {
- final int noRow = -1;
- final int noColumn = -1;
- if (args != null) {
- int rowArg = args.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_ROW_INT,
- noRow);
- int columnArg = args.getInt(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT,
- noColumn);
-
- if (rowArg == noRow || columnArg == noColumn) {
- return false;
- }
-
- int itemCount = mRecyclerView.mAdapter.getItemCount();
-
- int position = -1;
- for (int i = 0; i < itemCount; i++) {
- // Corresponds to a column value if the orientation is VERTICAL and a row value
- // if the orientation is HORIZONTAL
- int spanIndex = getSpanIndex(mRecyclerView.mRecycler, mRecyclerView.mState, i);
-
- // Corresponds to a row value if the orientation is VERTICAL and a column value
- // if the orientation is HORIZONTAL
- int spanGroupIndex = getSpanGroupIndex(mRecyclerView.mRecycler,
- mRecyclerView.mState, i);
-
- if (mOrientation == VERTICAL) {
- if (spanIndex == columnArg && spanGroupIndex == rowArg) {
- position = i;
- break;
- }
- } else { // horizontal
- if (spanIndex == rowArg && spanGroupIndex == columnArg) {
- position = i;
- break;
- }
- }
- }
-
- if (position > -1) {
- scrollToPositionWithOffset(position, 0);
- return true;
- }
- return false;
- }
- }
- return super.performAccessibilityAction(action, args);
- }
-
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
if (state.isPreLayout()) {
@@ -1018,9 +964,6 @@ int getCachedSpanGroupIndex(int position, int spanCount) {
/**
* Returns the final span index of the provided position.
*
- * If {@link #getOrientation()} is {@link #VERTICAL}, this is a column value.
- * If {@link #getOrientation()} is {@link #HORIZONTAL}, this is a row value.
- *
* If you have a faster way to calculate span index for your items, you should override
* this method. Otherwise, you should enable span index cache
* ({@link #setSpanIndexCacheEnabled(boolean)}) for better performance. When caching is
@@ -1097,9 +1040,6 @@ static int findFirstKeyLessThan(SparseIntArray cache, int position) {
/**
* Returns the index of the group this position belongs.
*
- * If {@link #getOrientation()} is {@link #VERTICAL}, this is a row value.
- * If {@link #getOrientation()} is {@link #HORIZONTAL}, this is a column value.
- *
* For example, if grid has 3 columns and each item occupies 1 span, span group index
* for item 1 will be 0, item 5 will be 1.
*
@@ -1506,4 +1446,5 @@ public int getSpanSize() {
return mSpanSize;
}
}
-}
\ No newline at end of file
+
+}
diff --git a/viewpager2/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java b/viewpager2/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java
index 3a3f1728e..b28479f0c 100644
--- a/viewpager2/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java
+++ b/viewpager2/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java
@@ -19,8 +19,6 @@
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.PointF;
-import android.os.Build;
-import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
@@ -29,10 +27,7 @@
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import androidx.tracing.Trace;
import java.util.List;
@@ -261,56 +256,6 @@ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
}
}
- @Override
- public void onInitializeAccessibilityNodeInfo(@NonNull RecyclerView.Recycler recycler,
- @NonNull RecyclerView.State state, @NonNull AccessibilityNodeInfoCompat info) {
- super.onInitializeAccessibilityNodeInfo(recycler, state, info);
- // TODO(b/251823537)
- if (mRecyclerView.mAdapter != null && mRecyclerView.mAdapter.getItemCount() > 0) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- info.addAction(AccessibilityActionCompat.ACTION_SCROLL_TO_POSITION);
- }
- }
- }
-
- @Override
- boolean performAccessibilityAction(int action, @Nullable Bundle args) {
- if (super.performAccessibilityAction(action, args)) {
- return true;
- }
-
- if (action == android.R.id.accessibilityActionScrollToPosition && args != null) {
- int position = -1;
-
- if (mOrientation == VERTICAL) {
- final int rowArg = args.getInt(
- AccessibilityNodeInfoCompat.ACTION_ARGUMENT_ROW_INT, -1);
- if (rowArg < 0) {
- return false;
- }
- position = Math.min(rowArg, getRowCountForAccessibility(mRecyclerView.mRecycler,
- mRecyclerView.mState) - 1);
- } else { // horizontal
- final int columnArg = args.getInt(
- AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT, -1);
- if (columnArg < 0) {
- return false;
- }
- position = Math.min(columnArg,
- getColumnCountForAccessibility(mRecyclerView.mRecycler,
- mRecyclerView.mState) - 1);
- }
- if (position >= 0) {
- // We want the target element to be the first on screen. That way, a
- // screenreader like Talkback can directly focus on it as part of its default focus
- // logic.
- scrollToPositionWithOffset(position, 0);
- return true;
- }
- }
- return false;
- }
-
@Override
@SuppressLint("UnknownNullness") // b/240775049: Cannot annotate properly
public Parcelable onSaveInstanceState() {
diff --git a/viewpager2/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/viewpager2/src/main/java/androidx/recyclerview/widget/RecyclerView.java
index e1264963a..42e95d456 100644
--- a/viewpager2/src/main/java/androidx/recyclerview/widget/RecyclerView.java
+++ b/viewpager2/src/main/java/androidx/recyclerview/widget/RecyclerView.java
@@ -283,20 +283,9 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
*/
private static final float FLING_DESTRETCH_FACTOR = 4f;
- /**
- * A {@link android.content.pm.PackageManager} feature specifying if a device's rotary encoder
- * has low resolution. Low resolution rotary encoders produce small number of
- * {@link MotionEvent}s per a 360 degree rotation, meaning that each {@link MotionEvent} has
- * large scroll values, which make {@link #scrollBy(int, int)} calls feel broken (due to the
- * fact that each event produces large scrolls, and scrolling with large pixels causes a visible
- * jump that does not feel smooth). As such, we will try adjusting our handling of generic
- * motion caused by such low resolution rotary encoders differently to make the scrolling
- * experience smooth.
- */
- static final String LOW_RES_ROTARY_ENCODER_FEATURE = "android.hardware.rotaryencoder.lowres";
-
static final boolean DISPATCH_TEMP_DETACH = false;
+ /** @hide */
@RestrictTo(LIBRARY_GROUP_PREFIX)
@IntDef({HORIZONTAL, VERTICAL})
@Retention(RetentionPolicy.SOURCE)
@@ -695,12 +684,6 @@ public void run() {
private int mLastAutoMeasureNonExactMeasuredWidth = 0;
private int mLastAutoMeasureNonExactMeasuredHeight = 0;
- /**
- * Whether or not the device has {@link #LOW_RES_ROTARY_ENCODER_FEATURE}. Computed once and
- * cached, since it's a static value that would not change on consecutive calls.
- */
- @VisibleForTesting boolean mLowResRotaryEncoderFeature;
-
/**
* The callback to convert view info diffs into animations.
*/
@@ -811,9 +794,6 @@ public RecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int
}
a.recycle();
- mLowResRotaryEncoderFeature =
- context.getPackageManager().hasSystemFeature(LOW_RES_ROTARY_ENCODER_FEATURE);
-
// Create the layoutManager if specified.
createLayoutManager(context, layoutManagerName, attrs, defStyleAttr, 0);
@@ -2184,12 +2164,6 @@ boolean scrollByInternal(int x, int y, MotionEvent ev, int type) {
if (getOverScrollMode() != View.OVER_SCROLL_NEVER) {
if (ev != null && !MotionEventCompat.isFromSource(ev, InputDevice.SOURCE_MOUSE)) {
pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY);
- // For rotary encoders, we release stretch EdgeEffects after they are pulled, to
- // avoid the effects being stuck pulled.
- if (Build.VERSION.SDK_INT >= 31
- && MotionEventCompat.isFromSource(ev, InputDevice.SOURCE_ROTARY_ENCODER)) {
- releaseGlows();
- }
}
considerReleasingGlowsOnScroll(x, y);
}
@@ -2284,7 +2258,7 @@ private int releaseVerticalGlow(int deltaY, float x) {
/**
*
Compute the horizontal offset of the horizontal scrollbar's thumb within the horizontal
- * range. This value is used to compute the position of the thumb within the scrollbar's track.
+ * range. This value is used to compute the length of the thumb within the scrollbar's track.
*
*
* The range is expressed in arbitrary units that must be the same as the units used by
@@ -2345,7 +2319,7 @@ public int computeHorizontalScrollExtent() {
* {@link RecyclerView.LayoutManager#computeHorizontalScrollRange(RecyclerView.State)} in your
* LayoutManager.
*
- * @return The total horizontal range represented by the horizontal scrollbar
+ * @return The total horizontal range represented by the vertical scrollbar
* @see RecyclerView.LayoutManager#computeHorizontalScrollRange(RecyclerView.State)
*/
@Override
@@ -2358,7 +2332,7 @@ public int computeHorizontalScrollRange() {
/**
* Compute the vertical offset of the vertical scrollbar's thumb within the vertical range.
- * This value is used to compute the position of the thumb within the scrollbar's track.
+ * This value is used to compute the length of the thumb within the scrollbar's track.
*
* The range is expressed in arbitrary units that must be the same as the units used by
* {@link #computeVerticalScrollRange()} and {@link #computeVerticalScrollExtent()}.
@@ -3960,8 +3934,6 @@ public boolean onGenericMotionEvent(MotionEvent event) {
if (mLayoutSuppressed) {
return false;
}
-
- boolean useSmoothScroll = false;
if (event.getAction() == MotionEvent.ACTION_SCROLL) {
final float vScroll, hScroll;
if ((event.getSource() & InputDeviceCompat.SOURCE_CLASS_POINTER) != 0) {
@@ -3991,25 +3963,14 @@ public boolean onGenericMotionEvent(MotionEvent event) {
vScroll = 0f;
hScroll = 0f;
}
- // Use smooth scrolling for low resolution rotary encoders to avoid the visible
- // pixel jumps that would be caused by doing regular scrolling.
- useSmoothScroll = mLowResRotaryEncoderFeature;
} else {
vScroll = 0f;
hScroll = 0f;
}
- int scaledVScroll = (int) (vScroll * mScaledVerticalScrollFactor);
- int scaledHScroll = (int) (hScroll * mScaledHorizontalScrollFactor);
- if (useSmoothScroll) {
- OverScroller overScroller = mViewFlinger.mOverScroller;
- // Account for any remaining scroll from a previous generic motion event.
- scaledVScroll += overScroller.getFinalY() - overScroller.getCurrY();
- scaledHScroll += overScroller.getFinalX() - overScroller.getCurrX();
- smoothScrollBy(scaledHScroll, scaledVScroll, /* interpolator= */ null,
- UNDEFINED_DURATION, /* withNestedScrolling= */ true);
- } else {
- nestedScrollByInternal(scaledHScroll, scaledVScroll, event, TYPE_NON_TOUCH);
+ if (vScroll != 0 || hScroll != 0) {
+ nestedScrollByInternal((int) (hScroll * mScaledHorizontalScrollFactor),
+ (int) (vScroll * mScaledVerticalScrollFactor), event, TYPE_NON_TOUCH);
}
}
return false;
@@ -4976,7 +4937,7 @@ void markItemDecorInsetsDirty() {
}
@Override
- public void draw(@NonNull Canvas c) {
+ public void draw(Canvas c) {
super.draw(c);
final int count = mItemDecorations.size();
@@ -5037,7 +4998,7 @@ public void draw(@NonNull Canvas c) {
}
@Override
- public void onDraw(@NonNull Canvas c) {
+ public void onDraw(Canvas c) {
super.onDraw(c);
final int count = mItemDecorations.size();
@@ -5577,7 +5538,7 @@ public View findChildViewUnder(float x, float y) {
}
@Override
- public boolean drawChild(@NonNull Canvas canvas, View child, long drawingTime) {
+ public boolean drawChild(Canvas canvas, View child, long drawingTime) {
return super.drawChild(canvas, child, drawingTime);
}
@@ -11015,7 +10976,7 @@ public int computeHorizontalScrollOffset(@NonNull State state) {
* Default implementation returns 0.
*
* @param state Current State of RecyclerView where you can find total item count
- * @return The total horizontal range represented by the horizontal scrollbar
+ * @return The total horizontal range represented by the vertical scrollbar
* @see RecyclerView#computeHorizontalScrollRange()
*/
public int computeHorizontalScrollRange(@NonNull State state) {
@@ -11299,12 +11260,6 @@ void onInitializeAccessibilityNodeInfoForItem(View host, AccessibilityNodeInfoCo
public void onInitializeAccessibilityNodeInfoForItem(@NonNull Recycler recycler,
@NonNull State state, @NonNull View host,
@NonNull AccessibilityNodeInfoCompat info) {
- int rowIndexGuess = canScrollVertically() ? getPosition(host) : 0;
- int columnIndexGuess = canScrollHorizontally() ? getPosition(host) : 0;
- final AccessibilityNodeInfoCompat.CollectionItemInfoCompat itemInfo =
- AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(rowIndexGuess, 1,
- columnIndexGuess, 1, false, false);
- info.setCollectionItemInfo(itemInfo);
}
/**
@@ -11353,10 +11308,7 @@ public int getSelectionModeForAccessibility(@NonNull Recycler recycler,
* @return The number of rows in LayoutManager for accessibility.
*/
public int getRowCountForAccessibility(@NonNull Recycler recycler, @NonNull State state) {
- if (mRecyclerView == null || mRecyclerView.mAdapter == null) {
- return 1;
- }
- return canScrollVertically() ? mRecyclerView.mAdapter.getItemCount() : 1;
+ return -1;
}
/**
@@ -11373,10 +11325,7 @@ public int getRowCountForAccessibility(@NonNull Recycler recycler, @NonNull Stat
*/
public int getColumnCountForAccessibility(@NonNull Recycler recycler,
@NonNull State state) {
- if (mRecyclerView == null || mRecyclerView.mAdapter == null) {
- return 1;
- }
- return canScrollHorizontally() ? mRecyclerView.mAdapter.getItemCount() : 1;
+ return -1;
}
/**
@@ -13298,6 +13247,7 @@ public void notifyItemMoved(int fromPosition, int toPosition) {
/**
* This is public so that the CREATOR can be accessed on cold launch.
*
+ * @hide
*/
@RestrictTo(LIBRARY)
public static class SavedState extends AbsSavedState {
diff --git a/viewpager2/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java b/viewpager2/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java
index 63ce8e4fb..19e5f832e 100644
--- a/viewpager2/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java
+++ b/viewpager2/src/main/java/androidx/recyclerview/widget/StaggeredGridLayoutManager.java
@@ -32,7 +32,6 @@
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.core.view.ViewCompat;
-import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -1283,36 +1282,6 @@ public Parcelable onSaveInstanceState() {
return state;
}
- @Override
- public void onInitializeAccessibilityNodeInfo(@NonNull RecyclerView.Recycler recycler,
- @NonNull RecyclerView.State state, @NonNull AccessibilityNodeInfoCompat info) {
- super.onInitializeAccessibilityNodeInfo(recycler, state, info);
- // Setting the classname allows accessibility services to set a role for staggered grids
- // and ensures that they are treated distinctly from canonical grids with clear row/column
- // semantics.
- info.setClassName("androidx.recyclerview.widget.StaggeredGridLayoutManager");
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfoForItem(@NonNull RecyclerView.Recycler recycler,
- @NonNull RecyclerView.State state, @NonNull View host,
- @NonNull AccessibilityNodeInfoCompat info) {
- ViewGroup.LayoutParams lp = host.getLayoutParams();
- if (!(lp instanceof LayoutParams)) {
- super.onInitializeAccessibilityNodeInfoForItem(host, info);
- return;
- }
- LayoutParams sglp = (LayoutParams) lp;
- if (mOrientation == HORIZONTAL) {
- info.setCollectionItemInfo(AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(
- sglp.getSpanIndex(), sglp.mFullSpan ? mSpanCount : 1,
- -1, -1, false, false));
- } else { // VERTICAL
- info.setCollectionItemInfo(AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(
- -1, -1,
- sglp.getSpanIndex(), sglp.mFullSpan ? mSpanCount : 1, false, false));
- }
- }
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
@@ -1345,24 +1314,6 @@ int findFirstVisibleItemPositionInt() {
return first == null ? RecyclerView.NO_POSITION : getPosition(first);
}
- @Override
- public int getRowCountForAccessibility(@NonNull RecyclerView.Recycler recycler,
- @NonNull RecyclerView.State state) {
- if (mOrientation == HORIZONTAL) {
- return Math.min(mSpanCount, state.getItemCount());
- }
- return -1;
- }
-
- @Override
- public int getColumnCountForAccessibility(@NonNull RecyclerView.Recycler recycler,
- @NonNull RecyclerView.State state) {
- if (mOrientation == VERTICAL) {
- return Math.min(mSpanCount, state.getItemCount());
- }
- return -1;
- }
-
/**
* This is for internal use. Not necessarily the child closest to start but the first child
* we find that matches the criteria.
@@ -2120,6 +2071,7 @@ public void scrollToPositionWithOffset(int position, int offset) {
requestLayout();
}
+ /** @hide */
@Override
@RestrictTo(LIBRARY)
public void collectAdjacentPrefetchPositions(int dx, int dy, RecyclerView.State state,