Merge branch 'maintenance'
This commit is contained in:
commit
e2acc418d4
|
@ -17,8 +17,8 @@ buildscript {
|
||||||
allprojects {
|
allprojects {
|
||||||
ext {
|
ext {
|
||||||
projectGroupId = 'org.mariotaku.twidere'
|
projectGroupId = 'org.mariotaku.twidere'
|
||||||
projectVersionCode = 509
|
projectVersionCode = 510
|
||||||
projectVersionName = '4.1.0'
|
projectVersionName = '4.1.1'
|
||||||
|
|
||||||
globalCompileSdkVersion = 29
|
globalCompileSdkVersion = 29
|
||||||
globalBuildToolsVersion = "29.0.3"
|
globalBuildToolsVersion = "29.0.3"
|
||||||
|
|
|
@ -185,8 +185,6 @@ dependencies {
|
||||||
implementation 'com.commonsware.cwac:layouts:0.4.3'
|
implementation 'com.commonsware.cwac:layouts:0.4.3'
|
||||||
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
|
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
|
||||||
implementation 'com.pnikosis:materialish-progress:1.7'
|
implementation 'com.pnikosis:materialish-progress:1.7'
|
||||||
implementation "com.github.mariotaku:MessageBubbleView:${libVersions['MessageBubbleView']}"
|
|
||||||
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
|
||||||
implementation 'com.github.uucky:ColorPicker-Android:0.9.7@aar'
|
implementation 'com.github.uucky:ColorPicker-Android:0.9.7@aar'
|
||||||
implementation "pl.droidsonroids.gif:android-gif-drawable:${libVersions['AndroidGIFDrawable']}"
|
implementation "pl.droidsonroids.gif:android-gif-drawable:${libVersions['AndroidGIFDrawable']}"
|
||||||
implementation 'com.sprylab.android.texturevideoview:texturevideoview:1.2.1'
|
implementation 'com.sprylab.android.texturevideoview:texturevideoview:1.2.1'
|
||||||
|
@ -216,7 +214,8 @@ dependencies {
|
||||||
|
|
||||||
|
|
||||||
/** Custom dependencies **/
|
/** Custom dependencies **/
|
||||||
implementation 'com.github.mariotaku:MessageBubbleView:1.6'
|
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
||||||
|
implementation "com.github.mariotaku:MessageBubbleView:${libVersions['MessageBubbleView']}"
|
||||||
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
implementation 'com.github.mariotaku:DragSortListView:0.6.1'
|
||||||
implementation "com.github.mariotaku.MediaViewerLibrary:base:${libVersions['MediaViewerLibrary']}"
|
implementation "com.github.mariotaku.MediaViewerLibrary:base:${libVersions['MediaViewerLibrary']}"
|
||||||
implementation "com.github.mariotaku.MediaViewerLibrary:subsample-image-view:${libVersions['MediaViewerLibrary']}"
|
implementation "com.github.mariotaku.MediaViewerLibrary:subsample-image-view:${libVersions['MediaViewerLibrary']}"
|
||||||
|
|
|
@ -1032,6 +1032,12 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener,
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.copy_url -> {
|
||||||
|
val uri = LinkCreator.getUserWebLink(user)
|
||||||
|
ClipboardUtils.setText(context, uri.toString())
|
||||||
|
Toast.makeText(context, R.string.message_toast_link_copied_to_clipboard, Toast.LENGTH_SHORT).show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
R.id.qr_code -> {
|
R.id.qr_code -> {
|
||||||
executeAfterFragmentResumed {
|
executeAfterFragmentResumed {
|
||||||
val df = UserQrDialogFragment()
|
val df = UserQrDialogFragment()
|
||||||
|
|
|
@ -38,7 +38,6 @@ import org.mariotaku.twidere.extension.atto.filter
|
||||||
import org.mariotaku.twidere.extension.atto.firstElementOrNull
|
import org.mariotaku.twidere.extension.atto.firstElementOrNull
|
||||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||||
import org.mariotaku.twidere.extension.model.isOfficial
|
|
||||||
import org.mariotaku.twidere.extension.model.makeOriginal
|
import org.mariotaku.twidere.extension.model.makeOriginal
|
||||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||||
import org.mariotaku.twidere.model.AccountDetails
|
import org.mariotaku.twidere.model.AccountDetails
|
||||||
|
@ -153,39 +152,34 @@ class ConversationLoader(
|
||||||
}
|
}
|
||||||
if (loadReplies || noSinceMaxId || sinceId != null && sinceSortId > status.sort_id) {
|
if (loadReplies || noSinceMaxId || sinceId != null && sinceSortId > status.sort_id) {
|
||||||
// Load replies
|
// Load replies
|
||||||
var repliesLoaded = false
|
try {
|
||||||
// try {
|
|
||||||
// if (details.type == AccountType.TWITTER) {
|
|
||||||
// if (noSinceMaxId) {
|
|
||||||
// statuses.addAll(loadTwitterWebReplies(details, twitter))
|
|
||||||
// }
|
|
||||||
// repliesLoaded = true
|
|
||||||
// }
|
|
||||||
// } catch (e: MicroBlogException) {
|
|
||||||
// // Ignore
|
|
||||||
// }
|
|
||||||
if (!repliesLoaded) {
|
|
||||||
val query = SearchQuery()
|
|
||||||
query.count(100)
|
|
||||||
if (details.type == AccountType.TWITTER) {
|
if (details.type == AccountType.TWITTER) {
|
||||||
query.query("to:${status.user_screen_name} since_id:${status.id}")
|
// try to load thread
|
||||||
} else {
|
statuses.addAll(loadTwitterWebReplies(details, twitter))
|
||||||
query.query("@${status.user_screen_name}")
|
|
||||||
}
|
}
|
||||||
query.sinceId(sinceId ?: status.id)
|
} catch (e: MicroBlogException) {
|
||||||
try {
|
// Ignore
|
||||||
val queryResult = twitter.search(query)
|
}
|
||||||
val firstId = queryResult.firstOrNull()?.id
|
val query = SearchQuery()
|
||||||
if (firstId != null) {
|
query.count(100)
|
||||||
nextPagination = SinceMaxPagination.sinceId(firstId, 0)
|
if (details.type == AccountType.TWITTER) {
|
||||||
}
|
query.query("to:${status.user_screen_name} since_id:${status.id}")
|
||||||
queryResult.filterTo(statuses) { it.inReplyToStatusId == status.id }
|
} else {
|
||||||
} catch (e: MicroBlogException) {
|
query.query("@${status.user_screen_name}")
|
||||||
// Ignore for now
|
}
|
||||||
|
query.sinceId(sinceId ?: status.id)
|
||||||
|
try {
|
||||||
|
val queryResult = twitter.search(query)
|
||||||
|
val firstId = queryResult.firstOrNull()?.id
|
||||||
|
if (firstId != null) {
|
||||||
|
nextPagination = SinceMaxPagination.sinceId(firstId, 0)
|
||||||
}
|
}
|
||||||
|
queryResult.filterTo(statuses) { it.inReplyToStatusId == status.id }
|
||||||
|
} catch (e: MicroBlogException) {
|
||||||
|
// Ignore for now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return statuses.mapTo(PaginatedArrayList()) {
|
return statuses.distinctBy { it.id }.mapTo(PaginatedArrayList()) {
|
||||||
it.toParcelable(details, profileImageSize)
|
it.toParcelable(details, profileImageSize)
|
||||||
}.apply {
|
}.apply {
|
||||||
this.nextPage = nextPagination
|
this.nextPage = nextPagination
|
||||||
|
|
|
@ -60,6 +60,7 @@ import org.mariotaku.twidere.util.DataStoreUtils
|
||||||
import org.mariotaku.twidere.util.UriUtils
|
import org.mariotaku.twidere.util.UriUtils
|
||||||
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
import org.mariotaku.twidere.util.content.ContentResolverUtils
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.collections.component1
|
import kotlin.collections.component1
|
||||||
import kotlin.collections.component2
|
import kotlin.collections.component2
|
||||||
import kotlin.collections.filter
|
import kotlin.collections.filter
|
||||||
|
@ -171,19 +172,27 @@ class GetMessagesTask(
|
||||||
}.filter { it.sender != null && it.recipient != null }
|
}.filter { it.sender != null && it.recipient != null }
|
||||||
|
|
||||||
val insertMessages = arrayListOf<ParcelableMessage>()
|
val insertMessages = arrayListOf<ParcelableMessage>()
|
||||||
val conversations = hashMapOf<String, ParcelableMessageConversation>()
|
|
||||||
|
|
||||||
val conversationIds = hashSetOf<String>()
|
val conversationIds = result.map {
|
||||||
result.forEach {
|
if (it.senderId == details.key.id) {
|
||||||
conversationIds.add(ParcelableMessageUtils.incomingConversationId(it.senderId, it.recipientId))
|
ParcelableMessageUtils.outgoingConversationId(it.senderId, it.recipientId)
|
||||||
}
|
} else {
|
||||||
|
ParcelableMessageUtils.incomingConversationId(it.senderId, it.recipientId)
|
||||||
|
}
|
||||||
|
}.distinct().toHashSet()
|
||||||
|
|
||||||
|
val conversations = hashMapOf<String, ParcelableMessageConversation>()
|
||||||
conversations.addLocalConversations(context, accountKey, conversationIds)
|
conversations.addLocalConversations(context, accountKey, conversationIds)
|
||||||
|
// remove duplicate conversations upgrade from version 4.0.9
|
||||||
|
val distinct = distinctLocalConversations(context, accountKey, result.map { it.id }.toSet())
|
||||||
|
.distinct()
|
||||||
|
.filter { !it.startsWith(details.key.id) || it == details.key.id }
|
||||||
|
|
||||||
result.forEachIndexed { i, dm ->
|
result.forEachIndexed { i, dm ->
|
||||||
addConversationMessage(insertMessages, conversations, details, dm, i, list.size,
|
addConversationMessage(insertMessages, conversations, details, dm, i, list.size,
|
||||||
false, profileImageSize, updateLastRead)
|
dm.senderId == details.key.id, profileImageSize, updateLastRead)
|
||||||
}
|
}
|
||||||
return DatabaseUpdateData(conversations.values, insertMessages)
|
return DatabaseUpdateData(conversations.values, insertMessages, distinct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -490,6 +499,26 @@ class GetMessagesTask(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun distinctLocalConversations(context: Context, accountKey: UserKey, messageIds: Set<String>): ArrayList<String> {
|
||||||
|
val where = Expression.and(Expression.inArgs(Messages.MESSAGE_ID, messageIds.size),
|
||||||
|
Expression.equalsArgs(Conversations.ACCOUNT_KEY)).sql
|
||||||
|
val whereArgs = messageIds.toTypedArray() + accountKey.toString()
|
||||||
|
val result = arrayListOf<String>()
|
||||||
|
context.contentResolver.queryReference(Messages.CONTENT_URI, Messages.COLUMNS,
|
||||||
|
where, whereArgs, null)?.use { (cur) ->
|
||||||
|
val indices = ObjectCursor.indicesFrom(cur, ParcelableMessage::class.java)
|
||||||
|
cur.moveToFirst()
|
||||||
|
while (!cur.isAfterLast) {
|
||||||
|
val conversationId = cur.getString(indices[Messages.CONVERSATION_ID])
|
||||||
|
result.add(conversationId)
|
||||||
|
indices.newObject(cur)
|
||||||
|
cur.moveToNext()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
internal fun MutableMap<String, ParcelableMessageConversation>.addLocalConversations(context: Context,
|
internal fun MutableMap<String, ParcelableMessageConversation>.addLocalConversations(context: Context,
|
||||||
accountKey: UserKey, conversationIds: Set<String>) {
|
accountKey: UserKey, conversationIds: Set<String>) {
|
||||||
val newIds = conversationIds.filterNot { it in this.keys }
|
val newIds = conversationIds.filterNot { it in this.keys }
|
||||||
|
|
|
@ -86,6 +86,10 @@
|
||||||
android:id="@id/open_in_browser"
|
android:id="@id/open_in_browser"
|
||||||
android:icon="@drawable/ic_action_web"
|
android:icon="@drawable/ic_action_web"
|
||||||
android:title="@string/action_open_in_browser"/>
|
android:title="@string/action_open_in_browser"/>
|
||||||
|
<item
|
||||||
|
android:id="@id/copy_url"
|
||||||
|
android:icon="@drawable/ic_action_copy"
|
||||||
|
android:title="@android:string/copyUrl"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/add_to_home_screen_submenu"
|
android:id="@+id/add_to_home_screen_submenu"
|
||||||
android:icon="@drawable/ic_action_home"
|
android:icon="@drawable/ic_action_home"
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
<!-- Window attributes -->
|
<!-- Window attributes -->
|
||||||
<item name="android:windowBackground">@android:color/transparent</item>
|
<item name="android:windowBackground">@android:color/transparent</item>
|
||||||
<item name="android:windowIsTranslucent">true</item>
|
<item name="android:windowIsTranslucent">true</item>
|
||||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
|
||||||
|
|
||||||
<item name="windowActionBarOverlay">true</item>
|
<item name="windowActionBarOverlay">true</item>
|
||||||
<item name="actionBarStyle">@style/Widget.Twidere.Viewer.ActionBar</item>
|
<item name="actionBarStyle">@style/Widget.Twidere.Viewer.ActionBar</item>
|
||||||
|
|
Loading…
Reference in New Issue