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:
parent
83862569e2
commit
d823052862
19 changed files with 1041 additions and 18 deletions
|
@ -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) : "",
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue