Unbreak link previews in timelines (#2506)

This commit is contained in:
Levi Bard 2022-05-05 18:27:05 +02:00 committed by GitHub
parent db81ede04a
commit b4eda5ea65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 10 deletions

View file

@ -21,6 +21,7 @@ import com.keylesspalace.tusky.db.TimelineAccountEntity
import com.keylesspalace.tusky.db.TimelineStatusEntity
import com.keylesspalace.tusky.db.TimelineStatusWithAccount
import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.Card
import com.keylesspalace.tusky.entity.Emoji
import com.keylesspalace.tusky.entity.HashTag
import com.keylesspalace.tusky.entity.Poll
@ -96,7 +97,8 @@ fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity {
expanded = loading,
contentCollapsed = false,
contentShowing = false,
pinned = false
pinned = false,
card = null,
)
}
@ -136,7 +138,8 @@ fun Status.toEntity(
expanded = expanded,
contentShowing = contentShowing,
contentCollapsed = contentCollapsed,
pinned = actionableStatus.pinned == true
pinned = actionableStatus.pinned == true,
card = actionableStatus.card?.let(gson::toJson),
)
}
@ -151,6 +154,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson): StatusViewData {
val application = gson.fromJson(status.application, Status.Application::class.java)
val emojis: List<Emoji> = gson.fromJson(status.emojis, emojisListType) ?: emptyList()
val poll: Poll? = gson.fromJson(status.poll, Poll::class.java)
val card: Card? = gson.fromJson(status.card, Card::class.java)
val reblog = status.reblogServerId?.let { id ->
Status(
@ -178,7 +182,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson): StatusViewData {
pinned = false,
muted = status.muted,
poll = poll,
card = null
card = card,
)
}
val status = if (reblog != null) {
@ -235,7 +239,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson): StatusViewData {
pinned = status.pinned,
muted = status.muted,
poll = poll,
card = null
card = card,
)
}
return StatusViewData.Concrete(

View file

@ -31,7 +31,7 @@ import java.io.File;
*/
@Database(entities = { DraftEntity.class, AccountEntity.class, InstanceEntity.class, TimelineStatusEntity.class,
TimelineAccountEntity.class, ConversationEntity.class
}, version = 34)
}, version = 35)
public abstract class AppDatabase extends RoomDatabase {
public abstract AccountDao accountDao();
@ -534,4 +534,11 @@ public abstract class AppDatabase extends RoomDatabase {
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `notificationsUpdates` INTEGER NOT NULL DEFAULT 1");
}
};
public static final Migration MIGRATION_34_35 = new Migration(34, 35) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `TimelineStatusEntity` ADD COLUMN `card` TEXT");
}
};
}

View file

@ -36,7 +36,7 @@ SELECT s.serverId, s.url, s.timelineUserId,
s.authorServerId, s.inReplyToId, s.inReplyToAccountId, s.createdAt,
s.emojis, s.reblogsCount, s.favouritesCount, s.reblogged, s.favourited, s.bookmarked, s.sensitive,
s.spoilerText, s.visibility, s.mentions, s.tags, s.application, s.reblogServerId,s.reblogAccountId,
s.content, s.attachments, s.poll, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned,
s.content, s.attachments, s.poll, s.card, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned,
a.serverId as 'a_serverId', a.timelineUserId as 'a_timelineUserId',
a.localUsername as 'a_localUsername', a.username as 'a_username',
a.displayName as 'a_displayName', a.url as 'a_url', a.avatar as 'a_avatar',

View file

@ -78,7 +78,8 @@ data class TimelineStatusEntity(
val expanded: Boolean, // used as the "loading" attribute when this TimelineStatusEntity is a placeholder
val contentCollapsed: Boolean,
val contentShowing: Boolean,
val pinned: Boolean
val pinned: Boolean,
val card: String?,
)
@Entity(

View file

@ -63,7 +63,7 @@ class AppModule {
AppDatabase.Migration25_26(appContext.getExternalFilesDir("Tusky")),
AppDatabase.MIGRATION_26_27, AppDatabase.MIGRATION_27_28, AppDatabase.MIGRATION_28_29,
AppDatabase.MIGRATION_29_30, AppDatabase.MIGRATION_30_31, AppDatabase.MIGRATION_31_32,
AppDatabase.MIGRATION_32_33, AppDatabase.MIGRATION_33_34
AppDatabase.MIGRATION_32_33, AppDatabase.MIGRATION_33_34, AppDatabase.MIGRATION_34_35,
)
.build()
}

View file

@ -369,13 +369,36 @@ class TimelineDaoTest {
assertEquals("99", timelineDao.getTopPlaceholderId(1))
}
@Test
fun `preview card survives roundtrip`() = runBlocking {
val setOne = makeStatus(statusId = 3, cardUrl = "https://foo.bar")
for ((status, author, reblogger) in listOf(setOne)) {
timelineDao.insertAccount(author)
reblogger?.let {
timelineDao.insertAccount(it)
}
timelineDao.insertStatus(status)
}
val pagingSource = timelineDao.getStatuses(setOne.first.timelineUserId)
val loadResult = pagingSource.load(PagingSource.LoadParams.Refresh(null, 2, false))
val loadedStatuses = (loadResult as PagingSource.LoadResult.Page).data
assertEquals(1, loadedStatuses.size)
assertStatuses(listOf(setOne), loadedStatuses)
}
private fun makeStatus(
accountId: Long = 1,
statusId: Long = 10,
reblog: Boolean = false,
createdAt: Long = statusId,
authorServerId: String = "20",
domain: String = "mastodon.example"
domain: String = "mastodon.example",
cardUrl: String? = null,
): Triple<TimelineStatusEntity, TimelineAccountEntity, TimelineAccountEntity?> {
val author = TimelineAccountEntity(
serverId = authorServerId,
@ -403,6 +426,10 @@ class TimelineDaoTest {
)
} else null
val card = when (cardUrl) {
null -> null
else -> "{ url: \"$cardUrl\" }"
}
val even = accountId % 2 == 0L
val status = TimelineStatusEntity(
serverId = statusId.toString(),
@ -433,7 +460,8 @@ class TimelineDaoTest {
expanded = false,
contentCollapsed = false,
contentShowing = true,
pinned = false
pinned = false,
card = card,
)
return Triple(status, author, reblogAuthor)
}