feat(status/edit-history): display diff for text
Closes https://github.com/sk22/megalodon/issues/789
This commit is contained in:
@@ -16,14 +16,17 @@ import org.joinmastodon.android.ui.utils.InsetStatusItemDecoration;
|
|||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.grishka.appkit.api.SimpleCallback;
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
import name.fraser.neil.plaintext.diff_match_patch;
|
||||||
|
|
||||||
public class StatusEditHistoryFragment extends StatusListFragment{
|
public class StatusEditHistoryFragment extends StatusListFragment{
|
||||||
private String id, url;
|
private String id, url;
|
||||||
@@ -58,7 +61,7 @@ public class StatusEditHistoryFragment extends StatusListFragment{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<StatusDisplayItem> buildDisplayItems(Status s){
|
protected List<StatusDisplayItem> buildDisplayItems(Status s){
|
||||||
List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, null, StatusDisplayItem.FLAG_NO_FOOTER | StatusDisplayItem.FLAG_INSET | StatusDisplayItem.FLAG_NO_EMOJI_REACTIONS);
|
List<StatusDisplayItem> items=new ArrayList<>();
|
||||||
int idx=data.indexOf(s);
|
int idx=data.indexOf(s);
|
||||||
if(idx>=0){
|
if(idx>=0){
|
||||||
String date=UiUtils.DATE_TIME_FORMATTER.format(s.createdAt.atZone(ZoneId.systemDefault()));
|
String date=UiUtils.DATE_TIME_FORMATTER.format(s.createdAt.atZone(ZoneId.systemDefault()));
|
||||||
@@ -85,6 +88,8 @@ public class StatusEditHistoryFragment extends StatusListFragment{
|
|||||||
|
|
||||||
if(!Objects.equals(s.content, prev.content)){
|
if(!Objects.equals(s.content, prev.content)){
|
||||||
changes.add(StatusEditChangeType.TEXT_CHANGED);
|
changes.add(StatusEditChangeType.TEXT_CHANGED);
|
||||||
|
//update status content to display a diffs
|
||||||
|
s.content=createDiffText(prev.content, s.content);
|
||||||
}
|
}
|
||||||
if(!Objects.equals(s.spoilerText, prev.spoilerText)){
|
if(!Objects.equals(s.spoilerText, prev.spoilerText)){
|
||||||
if(s.spoilerText==null){
|
if(s.spoilerText==null){
|
||||||
@@ -147,6 +152,7 @@ public class StatusEditHistoryFragment extends StatusListFragment{
|
|||||||
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" "+sep+" "+date, Collections.emptyList(), 0, null, null, s));
|
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" "+sep+" "+date, Collections.emptyList(), 0, null, null, s));
|
||||||
items.add(1, new DummyStatusDisplayItem(s.id, this));
|
items.add(1, new DummyStatusDisplayItem(s.id, this));
|
||||||
}
|
}
|
||||||
|
items.addAll(StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, null, StatusDisplayItem.FLAG_NO_FOOTER|StatusDisplayItem.FLAG_INSET|StatusDisplayItem.FLAG_NO_EMOJI_REACTIONS));
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,4 +176,28 @@ public class StatusEditHistoryFragment extends StatusListFragment{
|
|||||||
public Uri getWebUri(Uri.Builder base) {
|
public Uri getWebUri(Uri.Builder base) {
|
||||||
return Uri.parse(url);
|
return Uri.parse(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String createDiffText(String original, String modified) {
|
||||||
|
diff_match_patch dmp = new diff_match_patch();
|
||||||
|
LinkedList<diff_match_patch.Diff> diffs = dmp.diff_main(original, modified);
|
||||||
|
dmp.diff_cleanupSemantic(diffs);
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for(diff_match_patch.Diff diff: diffs){
|
||||||
|
switch(diff.operation){
|
||||||
|
case DELETE -> {
|
||||||
|
stringBuilder.append("<edit_diff_removed>");
|
||||||
|
stringBuilder.append(diff.text);
|
||||||
|
stringBuilder.append("</edit_diff_removed>");
|
||||||
|
}
|
||||||
|
case INSERT -> {
|
||||||
|
stringBuilder.append("<edit_diff_added>");
|
||||||
|
stringBuilder.append(diff.text);
|
||||||
|
stringBuilder.append("</edit_diff_added>");
|
||||||
|
}
|
||||||
|
default -> stringBuilder.append(diff.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.joinmastodon.android.ui.text;
|
||||||
|
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.text.style.CharacterStyle;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
public class DiffRemovedSpan extends CharacterStyle {
|
||||||
|
|
||||||
|
private final String text;
|
||||||
|
|
||||||
|
public DiffRemovedSpan(String text){
|
||||||
|
this.text=text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint tp) {
|
||||||
|
tp.setStrikeThruText(true);
|
||||||
|
tp.setColor(0xFFCA5B63);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.joinmastodon.android.ui.text;
|
package org.joinmastodon.android.ui.text;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
@@ -171,6 +172,9 @@ public class HtmlParser{
|
|||||||
}
|
}
|
||||||
case "code", "pre" -> openSpans.add(new SpanInfo(new TypefaceSpan("monospace"), ssb.length(), el));
|
case "code", "pre" -> openSpans.add(new SpanInfo(new TypefaceSpan("monospace"), ssb.length(), el));
|
||||||
case "blockquote" -> openSpans.add(new SpanInfo(new LeadingMarginSpan.Standard(V.dp(10)), ssb.length(), el));
|
case "blockquote" -> openSpans.add(new SpanInfo(new LeadingMarginSpan.Standard(V.dp(10)), ssb.length(), el));
|
||||||
|
//fake elements for the edit history diff view
|
||||||
|
case "edit_diff_added" -> openSpans.add(new SpanInfo(new ForegroundColorSpan(UiUtils.isDarkTheme() ? 0xFF89bb9c : 0xFF5b8e63), ssb.length(), el));
|
||||||
|
case "edit_diff_removed" -> openSpans.add(new SpanInfo(new DiffRemovedSpan(el.text()), ssb.length(), el));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user