Status: Display indicators of edited posts (#2935)

* Add editedAt field to Status

* Status: Display indicators of edited posts

* Annotate edited posts in the Status description

* Cache info that post has been edited
This commit is contained in:
fruyek 2022-12-03 12:15:54 +01:00 committed by GitHub
commit d823052862
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 1041 additions and 18 deletions

View file

@ -307,19 +307,25 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
}
protected void setCreatedAt(Date createdAt, StatusDisplayOptions statusDisplayOptions) {
protected void setCreatedAt(Date createdAt, Date editedAt, StatusDisplayOptions statusDisplayOptions) {
String timestampText;
if (statusDisplayOptions.useAbsoluteTime()) {
timestampInfo.setText(absoluteTimeFormatter.format(createdAt, true));
timestampText = absoluteTimeFormatter.format(createdAt, true);
} else {
if (createdAt == null) {
timestampInfo.setText("?m");
timestampText = "?m";
} else {
long then = createdAt.getTime();
long now = System.currentTimeMillis();
String readout = TimestampUtils.getRelativeTimeSpanString(timestampInfo.getContext(), then, now);
timestampInfo.setText(readout);
timestampText = readout;
}
}
if (editedAt != null) {
timestampText = timestampInfo.getContext().getString(R.string.post_timestamp_with_edited_indicator, timestampText);
}
timestampInfo.setText(timestampText);
}
private CharSequence getCreatedAtDescription(Date createdAt,
@ -700,7 +706,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
Status actionable = status.getActionable();
setDisplayName(actionable.getAccount().getName(), actionable.getAccount().getEmojis(), statusDisplayOptions);
setUsername(status.getUsername());
setCreatedAt(actionable.getCreatedAt(), statusDisplayOptions);
setCreatedAt(actionable.getCreatedAt(), actionable.getEditedAt(), statusDisplayOptions);
setIsReply(actionable.getInReplyToId() != null);
setReplyCount(actionable.getRepliesCount());
setAvatar(actionable.getAccount().getAvatar(), status.getRebloggedAvatar(),
@ -752,7 +758,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (payloads instanceof List)
for (Object item : (List<?>) payloads) {
if (Key.KEY_CREATED.equals(item)) {
setCreatedAt(status.getActionable().getCreatedAt(), statusDisplayOptions);
setCreatedAt(status.getActionable().getCreatedAt(), status.getActionable().getEditedAt(), statusDisplayOptions);
}
}
@ -778,6 +784,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
getContentWarningDescription(context, status),
(TextUtils.isEmpty(status.getSpoilerText()) || !actionable.getSensitive() || status.isExpanded() ? status.getContent() : ""),
getCreatedAtDescription(actionable.getCreatedAt(), statusDisplayOptions),
actionable.getEditedAt() != null ? context.getString(R.string.description_post_edited) : "",
getReblogDescription(context, status),
status.getUsername(),
actionable.getReblogged() ? context.getString(R.string.description_post_reblogged) : "",

View file

@ -1,6 +1,8 @@
package com.keylesspalace.tusky.adapter;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.TextView;
@ -18,7 +20,9 @@ import com.keylesspalace.tusky.util.StatusDisplayOptions;
import com.keylesspalace.tusky.viewdata.StatusViewData;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class StatusDetailedViewHolder extends StatusBaseViewHolder {
private final TextView reblogs;
@ -33,13 +37,17 @@ public class StatusDetailedViewHolder extends StatusBaseViewHolder {
}
@Override
protected void setCreatedAt(Date createdAt, StatusDisplayOptions statusDisplayOptions) {
if (createdAt == null) {
timestampInfo.setText("");
} else {
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT);
timestampInfo.setText(dateFormat.format(createdAt));
protected void setCreatedAt(Date createdAt, Date editedAt, StatusDisplayOptions statusDisplayOptions) {
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT);
Context context = timestampInfo.getContext();
List<String> list = new ArrayList<>();
if (createdAt != null) {
list.add(dateFormat.format(createdAt));
}
if (editedAt != null) {
list.add(context.getString(R.string.post_edited, dateFormat.format(editedAt)));
}
timestampInfo.setText(TextUtils.join(context.getString(R.string.timestamp_joiner), list));
}
private void setReblogAndFavCount(int reblogCount, int favCount, StatusActionListener listener) {

View file

@ -80,6 +80,7 @@ data class ConversationStatusEntity(
val account: ConversationAccountEntity,
val content: String,
val createdAt: Date,
val editedAt: Date?,
val emojis: List<Emoji>,
val favouritesCount: Int,
val repliesCount: Int,
@ -109,6 +110,7 @@ data class ConversationStatusEntity(
content = content,
reblog = null,
createdAt = createdAt,
editedAt = editedAt,
emojis = emojis,
reblogsCount = 0,
favouritesCount = favouritesCount,
@ -159,6 +161,7 @@ fun Status.toEntity(
account = account.toEntity(),
content = content,
createdAt = createdAt,
editedAt = editedAt,
emojis = emojis,
favouritesCount = favouritesCount,
repliesCount = repliesCount,

View file

@ -71,6 +71,7 @@ fun StatusViewData.Concrete.toConversationStatusEntity(
account = status.account.toEntity(),
content = status.content,
createdAt = status.createdAt,
editedAt = status.editedAt,
emojis = status.emojis,
favouritesCount = status.favouritesCount,
repliesCount = status.repliesCount,

View file

@ -83,7 +83,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
setDisplayName(account.getDisplayName(), account.getEmojis(), statusDisplayOptions);
setUsername(account.getUsername());
setCreatedAt(status.getCreatedAt(), statusDisplayOptions);
setCreatedAt(status.getCreatedAt(), status.getEditedAt(), statusDisplayOptions);
setIsReply(status.getInReplyToId() != null);
setFavourited(status.getFavourited());
setBookmarked(status.getBookmarked());
@ -121,7 +121,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
if (payloads instanceof List) {
for (Object item : (List<?>) payloads) {
if (Key.KEY_CREATED.equals(item)) {
setCreatedAt(status.getCreatedAt(), statusDisplayOptions);
setCreatedAt(status.getCreatedAt(), status.getEditedAt(), statusDisplayOptions);
}
}
}

View file

@ -77,6 +77,7 @@ fun Placeholder.toEntity(timelineUserId: Long): TimelineStatusEntity {
inReplyToAccountId = null,
content = null,
createdAt = 0L,
editedAt = 0L,
emojis = null,
reblogsCount = 0,
favouritesCount = 0,
@ -120,6 +121,7 @@ fun Status.toEntity(
inReplyToAccountId = actionableStatus.inReplyToAccountId,
content = actionableStatus.content,
createdAt = actionableStatus.createdAt.time,
editedAt = actionableStatus.editedAt?.time,
emojis = actionableStatus.emojis.let(gson::toJson),
reblogsCount = actionableStatus.reblogsCount,
favouritesCount = actionableStatus.favouritesCount,
@ -170,6 +172,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson): StatusViewData {
reblog = null,
content = status.content.orEmpty(),
createdAt = Date(status.createdAt),
editedAt = status.editedAt?.let { Date(it) },
emojis = emojis,
reblogsCount = status.reblogsCount,
favouritesCount = status.favouritesCount,
@ -201,6 +204,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson): StatusViewData {
reblog = reblog,
content = "",
createdAt = Date(status.createdAt), // lie but whatever?
editedAt = null,
emojis = listOf(),
reblogsCount = 0,
favouritesCount = 0,
@ -231,6 +235,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson): StatusViewData {
reblog = null,
content = status.content.orEmpty(),
createdAt = Date(status.createdAt),
editedAt = status.editedAt?.let { Date(it) },
emojis = emojis,
reblogsCount = status.reblogsCount,
favouritesCount = status.favouritesCount,

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 = 44)
}, version = 45)
public abstract class AppDatabase extends RoomDatabase {
public abstract AccountDao accountDao();
@ -624,4 +624,12 @@ public abstract class AppDatabase extends RoomDatabase {
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `notificationsReports` INTEGER NOT NULL DEFAULT 1");
}
};
public static final Migration MIGRATION_44_45 = new Migration(44, 45) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `TimelineStatusEntity` ADD COLUMN `editedAt` INTEGER");
database.execSQL("ALTER TABLE `ConversationEntity` ADD COLUMN `s_editedAt` INTEGER");
}
};
}

View file

@ -33,7 +33,7 @@ abstract class TimelineDao {
@Query(
"""
SELECT s.serverId, s.url, s.timelineUserId,
s.authorServerId, s.inReplyToId, s.inReplyToAccountId, s.createdAt,
s.authorServerId, s.inReplyToId, s.inReplyToAccountId, s.createdAt, s.editedAt,
s.emojis, s.reblogsCount, s.favouritesCount, s.repliesCount, 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.card, s.muted, s.expanded, s.contentShowing, s.contentCollapsed, s.pinned, s.language,

View file

@ -58,6 +58,7 @@ data class TimelineStatusEntity(
val inReplyToAccountId: String?,
val content: String?,
val createdAt: Long,
val editedAt: Long?,
val emojis: String?,
val reblogsCount: Int,
val favouritesCount: Int,

View file

@ -67,6 +67,7 @@ class AppModule {
AppDatabase.MIGRATION_35_36, AppDatabase.MIGRATION_36_37, AppDatabase.MIGRATION_37_38,
AppDatabase.MIGRATION_38_39, AppDatabase.MIGRATION_39_40, AppDatabase.MIGRATION_40_41,
AppDatabase.MIGRATION_41_42, AppDatabase.MIGRATION_42_43, AppDatabase.MIGRATION_43_44,
AppDatabase.MIGRATION_44_45,
)
.build()
}

View file

@ -31,6 +31,7 @@ data class Status(
val reblog: Status?,
val content: String,
@SerializedName("created_at") val createdAt: Date,
@SerializedName("edited_at") val editedAt: Date?,
val emojis: List<Emoji>,
@SerializedName("reblogs_count") val reblogsCount: Int,
@SerializedName("favourites_count") val favouritesCount: Int,