Implement redraft feature. (#1190)
* Implement "Delete and Edit" feature * Some changes to ComposeActivity Support for uploaded medias, sensitive option. Fix typo. Change names of some extra keys. * Use Glide instead of Picasso * Pass ArrayList instead of json * Change wording for re-draft * Fix test
This commit is contained in:
parent
49ede9183d
commit
60d6927af6
@ -60,13 +60,32 @@ import android.widget.PopupMenu;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.view.inputmethod.InputConnectionCompat;
|
||||
import androidx.core.view.inputmethod.InputContentInfoCompat;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.TransitionManager;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.keylesspalace.tusky.adapter.EmojiAdapter;
|
||||
import com.keylesspalace.tusky.adapter.ComposeAutoCompleteAdapter;
|
||||
import com.keylesspalace.tusky.adapter.EmojiAdapter;
|
||||
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener;
|
||||
import com.keylesspalace.tusky.db.AccountEntity;
|
||||
import com.keylesspalace.tusky.db.AppDatabase;
|
||||
@ -81,10 +100,10 @@ import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.network.MastodonApi;
|
||||
import com.keylesspalace.tusky.network.ProgressRequestBody;
|
||||
import com.keylesspalace.tusky.service.SendTootService;
|
||||
import com.keylesspalace.tusky.util.ComposeTokenizer;
|
||||
import com.keylesspalace.tusky.util.CountUpDownLatch;
|
||||
import com.keylesspalace.tusky.util.DownsizeImageTask;
|
||||
import com.keylesspalace.tusky.util.ListUtils;
|
||||
import com.keylesspalace.tusky.util.ComposeTokenizer;
|
||||
import com.keylesspalace.tusky.util.SaveTootHelper;
|
||||
import com.keylesspalace.tusky.util.SpanUtilsKt;
|
||||
import com.keylesspalace.tusky.util.StringUtils;
|
||||
@ -114,24 +133,6 @@ import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.core.view.inputmethod.InputConnectionCompat;
|
||||
import androidx.core.view.inputmethod.InputContentInfoCompat;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.transition.TransitionManager;
|
||||
import at.connyduck.sparkbutton.helpers.Utils;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleObserver;
|
||||
@ -171,16 +172,18 @@ public final class ComposeActivity
|
||||
private static final int PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1;
|
||||
|
||||
private static final String SAVED_TOOT_UID_EXTRA = "saved_toot_uid";
|
||||
private static final String SAVED_TOOT_TEXT_EXTRA = "saved_toot_text";
|
||||
private static final String TOOT_TEXT_EXTRA = "toot_text";
|
||||
private static final String SAVED_JSON_URLS_EXTRA = "saved_json_urls";
|
||||
private static final String SAVED_JSON_DESCRIPTIONS_EXTRA = "saved_json_descriptions";
|
||||
private static final String SAVED_TOOT_VISIBILITY_EXTRA = "saved_toot_visibility";
|
||||
private static final String TOOT_VISIBILITY_EXTRA = "toot_visibility";
|
||||
private static final String IN_REPLY_TO_ID_EXTRA = "in_reply_to_id";
|
||||
private static final String REPLY_VISIBILITY_EXTRA = "reply_visibilty";
|
||||
private static final String REPLY_VISIBILITY_EXTRA = "reply_visibility";
|
||||
private static final String CONTENT_WARNING_EXTRA = "content_warning";
|
||||
private static final String MENTIONED_USERNAMES_EXTRA = "netnioned_usernames";
|
||||
private static final String MENTIONED_USERNAMES_EXTRA = "mentioned_usernames";
|
||||
private static final String REPLYING_STATUS_AUTHOR_USERNAME_EXTRA = "replying_author_nickname_extra";
|
||||
private static final String REPLYING_STATUS_CONTENT_EXTRA = "replying_status_content";
|
||||
private static final String MEDIA_ATTACHMENTS_EXTRA = "media_attachments";
|
||||
private static final String SENSITIVE_EXTRA = "sensitive";
|
||||
// Mastodon only counts URLs as this long in terms of status character limits
|
||||
static final int MAXIMUM_URL_LENGTH = 23;
|
||||
// https://github.com/tootsuite/mastodon/blob/1656663/app/models/media_attachment.rb#L94
|
||||
@ -409,6 +412,7 @@ public final class ComposeActivity
|
||||
String[] mentionedUsernames = null;
|
||||
ArrayList<String> loadedDraftMediaUris = null;
|
||||
ArrayList<String> loadedDraftMediaDescriptions = null;
|
||||
ArrayList<Attachment> mediaAttachments = null;
|
||||
inReplyToId = null;
|
||||
if (intent != null) {
|
||||
|
||||
@ -432,14 +436,13 @@ public final class ComposeActivity
|
||||
}
|
||||
}
|
||||
|
||||
// If come from SavedTootActivity
|
||||
String savedTootText = intent.getStringExtra(SAVED_TOOT_TEXT_EXTRA);
|
||||
if (!TextUtils.isEmpty(savedTootText)) {
|
||||
startingText = savedTootText;
|
||||
textEditor.setText(savedTootText);
|
||||
String tootText = intent.getStringExtra(TOOT_TEXT_EXTRA);
|
||||
if (!TextUtils.isEmpty(tootText)) {
|
||||
textEditor.setText(tootText);
|
||||
}
|
||||
|
||||
// try to redo a list of media
|
||||
// If come from SavedTootActivity
|
||||
String savedJsonUrls = intent.getStringExtra(SAVED_JSON_URLS_EXTRA);
|
||||
String savedJsonDescriptions = intent.getStringExtra(SAVED_JSON_DESCRIPTIONS_EXTRA);
|
||||
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
||||
@ -452,15 +455,20 @@ public final class ComposeActivity
|
||||
new TypeToken<ArrayList<String>>() {
|
||||
}.getType());
|
||||
}
|
||||
// If come from redraft
|
||||
mediaAttachments = intent.getParcelableArrayListExtra(MEDIA_ATTACHMENTS_EXTRA);
|
||||
|
||||
int savedTootUid = intent.getIntExtra(SAVED_TOOT_UID_EXTRA, 0);
|
||||
if (savedTootUid != 0) {
|
||||
this.savedTootUid = savedTootUid;
|
||||
|
||||
// If come from SavedTootActivity
|
||||
startingText = tootText;
|
||||
}
|
||||
|
||||
int savedTootVisibility = intent.getIntExtra(SAVED_TOOT_VISIBILITY_EXTRA, Status.Visibility.UNKNOWN.getNum());
|
||||
if (savedTootVisibility != Status.Visibility.UNKNOWN.getNum()) {
|
||||
startingVisibility = Status.Visibility.byNum(savedTootVisibility);
|
||||
int tootVisibility = intent.getIntExtra(TOOT_VISIBILITY_EXTRA, Status.Visibility.UNKNOWN.getNum());
|
||||
if (tootVisibility != Status.Visibility.UNKNOWN.getNum()) {
|
||||
startingVisibility = Status.Visibility.byNum(tootVisibility);
|
||||
}
|
||||
|
||||
if (intent.hasExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA)) {
|
||||
@ -491,6 +499,8 @@ public final class ComposeActivity
|
||||
if (intent.hasExtra(REPLYING_STATUS_CONTENT_EXTRA)) {
|
||||
replyContentTextView.setText(intent.getStringExtra(REPLYING_STATUS_CONTENT_EXTRA));
|
||||
}
|
||||
|
||||
statusMarkSensitive = intent.getBooleanExtra(SENSITIVE_EXTRA, false);
|
||||
}
|
||||
|
||||
// After the starting state is finalised, the interface can be set to reflect this state.
|
||||
@ -575,6 +585,25 @@ public final class ComposeActivity
|
||||
}
|
||||
pickMedia(uri, mediaSize, description);
|
||||
}
|
||||
} else if (!ListUtils.isEmpty(mediaAttachments)) {
|
||||
for (int mediaIndex =0; mediaIndex < mediaAttachments.size(); ++mediaIndex) {
|
||||
Attachment media = mediaAttachments.get(mediaIndex);
|
||||
QueuedMedia.Type type;
|
||||
switch (media.getType()) {
|
||||
case UNKNOWN:
|
||||
case IMAGE:
|
||||
default: {
|
||||
type = QueuedMedia.Type.IMAGE;
|
||||
break;
|
||||
}
|
||||
case VIDEO:
|
||||
case GIFV: {
|
||||
type = QueuedMedia.Type.VIDEO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
addMediaToQueue(media.getId(), type, media.getPreviewUrl(), media.getDescription());
|
||||
}
|
||||
} else if (savedMediaQueued != null) {
|
||||
for (SavedQueuedMedia item : savedMediaQueued) {
|
||||
Bitmap preview = getImageThumbnail(getContentResolver(), item.uri, thumbnailViewSize);
|
||||
@ -1111,6 +1140,11 @@ public final class ComposeActivity
|
||||
addMediaToQueue(null, type, preview, uri, mediaSize, null, description);
|
||||
}
|
||||
|
||||
private void addMediaToQueue(String id, QueuedMedia.Type type, String previewUrl, @Nullable String description) {
|
||||
addMediaToQueue(id, type, null, Uri.parse(previewUrl), 0,
|
||||
QueuedMedia.ReadyStage.UPLOADED, description);
|
||||
}
|
||||
|
||||
private void addMediaToQueue(@Nullable String id, QueuedMedia.Type type, Bitmap preview, Uri uri,
|
||||
long mediaSize, QueuedMedia.ReadyStage readyStage, @Nullable String description) {
|
||||
final QueuedMedia item = new QueuedMedia(type, uri, new ProgressImageView(this),
|
||||
@ -1126,7 +1160,14 @@ public final class ComposeActivity
|
||||
layoutParams.setMargins(margin, 0, margin, marginBottom);
|
||||
view.setLayoutParams(layoutParams);
|
||||
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
if (preview != null) {
|
||||
view.setImageBitmap(preview);
|
||||
} else {
|
||||
Glide.with(this)
|
||||
.load(uri)
|
||||
.placeholder(null)
|
||||
.into(view);
|
||||
}
|
||||
view.setOnClickListener(v -> onMediaClick(item, v));
|
||||
view.setContentDescription(getString(R.string.action_delete));
|
||||
mediaPreviewBar.addView(view);
|
||||
@ -1782,7 +1823,7 @@ public final class ComposeActivity
|
||||
@Nullable
|
||||
private Integer savedTootUid;
|
||||
@Nullable
|
||||
private String savedTootText;
|
||||
private String tootText;
|
||||
@Nullable
|
||||
private String savedJsonUrls;
|
||||
@Nullable
|
||||
@ -1794,21 +1835,25 @@ public final class ComposeActivity
|
||||
@Nullable
|
||||
private Status.Visibility replyVisibility;
|
||||
@Nullable
|
||||
private Status.Visibility savedVisibility;
|
||||
private Status.Visibility visibility;
|
||||
@Nullable
|
||||
private String contentWarning;
|
||||
@Nullable
|
||||
private String replyingStatusAuthor;
|
||||
@Nullable
|
||||
private String replyingStatusContent;
|
||||
@Nullable
|
||||
private ArrayList<Attachment> mediaAttachments;
|
||||
private boolean sensitive = false;
|
||||
|
||||
|
||||
public IntentBuilder savedTootUid(int uid) {
|
||||
this.savedTootUid = uid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder savedTootText(String savedTootText) {
|
||||
this.savedTootText = savedTootText;
|
||||
public IntentBuilder tootText(String tootText) {
|
||||
this.tootText = tootText;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1822,8 +1867,8 @@ public final class ComposeActivity
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder savedVisibility(Status.Visibility savedVisibility) {
|
||||
this.savedVisibility = savedVisibility;
|
||||
public IntentBuilder visibility(Status.Visibility visibility) {
|
||||
this.visibility = visibility;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1857,14 +1902,24 @@ public final class ComposeActivity
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder mediaAttachments(ArrayList<Attachment> mediaAttachments) {
|
||||
this.mediaAttachments = mediaAttachments;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder sensitive(boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Intent build(Context context) {
|
||||
Intent intent = new Intent(context, ComposeActivity.class);
|
||||
|
||||
if (savedTootUid != null) {
|
||||
intent.putExtra(SAVED_TOOT_UID_EXTRA, (int) savedTootUid);
|
||||
}
|
||||
if (savedTootText != null) {
|
||||
intent.putExtra(SAVED_TOOT_TEXT_EXTRA, savedTootText);
|
||||
if (tootText != null) {
|
||||
intent.putExtra(TOOT_TEXT_EXTRA, tootText);
|
||||
}
|
||||
if (savedJsonUrls != null) {
|
||||
intent.putExtra(SAVED_JSON_URLS_EXTRA, savedJsonUrls);
|
||||
@ -1882,8 +1937,8 @@ public final class ComposeActivity
|
||||
if (replyVisibility != null) {
|
||||
intent.putExtra(REPLY_VISIBILITY_EXTRA, replyVisibility.getNum());
|
||||
}
|
||||
if (savedVisibility != null) {
|
||||
intent.putExtra(SAVED_TOOT_VISIBILITY_EXTRA, savedVisibility.getNum());
|
||||
if (visibility != null) {
|
||||
intent.putExtra(TOOT_VISIBILITY_EXTRA, visibility.getNum());
|
||||
}
|
||||
if (contentWarning != null) {
|
||||
intent.putExtra(CONTENT_WARNING_EXTRA, contentWarning);
|
||||
@ -1894,6 +1949,10 @@ public final class ComposeActivity
|
||||
if (replyingStatusAuthor != null) {
|
||||
intent.putExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA, replyingStatusAuthor);
|
||||
}
|
||||
if (mediaAttachments != null) {
|
||||
intent.putParcelableArrayListExtra(MEDIA_ATTACHMENTS_EXTRA, mediaAttachments);
|
||||
}
|
||||
intent.putExtra(SENSITIVE_EXTRA, sensitive);
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
@ -155,14 +155,14 @@ public final class SavedTootActivity extends BaseActivity implements SavedTootAd
|
||||
public void click(int position, TootEntity item) {
|
||||
Intent intent = new ComposeActivity.IntentBuilder()
|
||||
.savedTootUid(item.getUid())
|
||||
.savedTootText(item.getText())
|
||||
.tootText(item.getText())
|
||||
.contentWarning(item.getContentWarning())
|
||||
.savedJsonUrls(item.getUrls())
|
||||
.savedJsonDescriptions(item.getDescriptions())
|
||||
.inReplyToId(item.getInReplyToId())
|
||||
.replyingStatusAuthor(item.getInReplyToUsername())
|
||||
.replyingStatusContent(item.getInReplyToText())
|
||||
.savedVisibility(item.getVisibility())
|
||||
.visibility(item.getVisibility())
|
||||
.build(this);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ data class ConversationStatusEntity(
|
||||
val favourited: Boolean,
|
||||
val sensitive: Boolean,
|
||||
val spoilerText: String,
|
||||
val attachments: List<Attachment>,
|
||||
val attachments: ArrayList<Attachment>,
|
||||
val mentions: Array<Status.Mention>,
|
||||
val showingHiddenContent: Boolean,
|
||||
val expanded: Boolean,
|
||||
|
@ -95,8 +95,8 @@ class Converters {
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun jsonToAttachmentList(attachmentListJson: String?): List<Attachment>? {
|
||||
return gson.fromJson(attachmentListJson, object : TypeToken<List<Attachment>>() {}.type)
|
||||
fun jsonToAttachmentList(attachmentListJson: String?): ArrayList<Attachment>? {
|
||||
return gson.fromJson(attachmentListJson, object : TypeToken<ArrayList<Attachment>>() {}.type)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
|
@ -36,7 +36,7 @@ data class Status(
|
||||
var sensitive: Boolean,
|
||||
@SerializedName("spoiler_text") val spoilerText: String,
|
||||
val visibility: Visibility,
|
||||
@SerializedName("media_attachments") var attachments: List<Attachment>,
|
||||
@SerializedName("media_attachments") var attachments: ArrayList<Attachment>,
|
||||
val mentions: Array<Mention>,
|
||||
val application: Application?,
|
||||
var pinned: Boolean?
|
||||
|
@ -21,17 +21,25 @@ import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.app.ActivityOptionsCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.keylesspalace.tusky.BaseActivity;
|
||||
import com.keylesspalace.tusky.BottomSheetActivity;
|
||||
import com.keylesspalace.tusky.ComposeActivity;
|
||||
@ -56,13 +64,6 @@ import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.app.ActivityOptionsCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
/* Note from Andrew on Jan. 22, 2017: This class is a design problem for me, so I left it with an
|
||||
* awkward name. TimelineFragment and NotificationFragment have significant overlap but the nature
|
||||
* of that is complicated by how they're coupled with Status and Notification and the corresponding
|
||||
@ -274,6 +275,10 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
showConfirmDeleteDialog(id, position);
|
||||
return true;
|
||||
}
|
||||
case R.id.status_delete_and_redraft: {
|
||||
showConfirmEditDialog(id, position, status);
|
||||
return true;
|
||||
}
|
||||
case R.id.pin: {
|
||||
timelineCases.pin(status, !status.isPinned());
|
||||
return true;
|
||||
@ -343,6 +348,46 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showConfirmEditDialog(final String id, final int position, Status status) {
|
||||
if (getActivity() == null) {
|
||||
return;
|
||||
}
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.dialog_redraft_toot_warning)
|
||||
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||
timelineCases.delete(id);
|
||||
removeItem(position);
|
||||
|
||||
Intent intent = new ComposeActivity.IntentBuilder()
|
||||
.tootText(getEditableText(status.getContent(), status.getMentions()))
|
||||
.inReplyToId(status.getInReplyToId())
|
||||
.visibility(status.getVisibility())
|
||||
.contentWarning(status.getSpoilerText())
|
||||
.mediaAttachments(status.getAttachments())
|
||||
.sensitive(status.getSensitive())
|
||||
.build(getContext());
|
||||
startActivity(intent);
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private String getEditableText(Spanned content, Status.Mention[] mentions) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(content);
|
||||
for (URLSpan span : content.getSpans(0, content.length(), URLSpan.class)) {
|
||||
String url = span.getURL();
|
||||
for (Status.Mention mention : mentions) {
|
||||
if (url.equals(mention.getUrl())) {
|
||||
int start = builder.getSpanStart(span);
|
||||
int end = builder.getSpanEnd(span);
|
||||
builder.replace(start, end, '@' + mention.getUsername());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private void openAsAccount(String statusUrl, AccountEntity account) {
|
||||
accountManager.setActiveAccount(account);
|
||||
Intent intent = new Intent(getContext(), MainActivity.class);
|
||||
|
@ -11,12 +11,16 @@ import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.DISK
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode.NETWORK
|
||||
import com.keylesspalace.tusky.util.*
|
||||
import com.keylesspalace.tusky.util.Either
|
||||
import com.keylesspalace.tusky.util.HtmlConverter
|
||||
import com.keylesspalace.tusky.util.dec
|
||||
import com.keylesspalace.tusky.util.inc
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
data class Placeholder(val id: String)
|
||||
|
||||
@ -191,8 +195,8 @@ class TimelineRepositoryImpl(
|
||||
return Either.Left(Placeholder(this.status.serverId))
|
||||
}
|
||||
|
||||
val attachments: List<Attachment> = gson.fromJson(status.attachments,
|
||||
object : TypeToken<List<Attachment>>() {}.type) ?: listOf()
|
||||
val attachments: ArrayList<Attachment> = gson.fromJson(status.attachments,
|
||||
object : TypeToken<List<Attachment>>() {}.type) ?: ArrayList()
|
||||
val mentions: Array<Status.Mention> = gson.fromJson(status.mentions,
|
||||
Array<Status.Mention>::class.java) ?: arrayOf()
|
||||
val application = gson.fromJson(status.application, Status.Application::class.java)
|
||||
@ -242,7 +246,7 @@ class TimelineRepositoryImpl(
|
||||
sensitive = false,
|
||||
spoilerText = "",
|
||||
visibility = status.visibility!!,
|
||||
attachments = listOf(),
|
||||
attachments = ArrayList(),
|
||||
mentions = arrayOf(),
|
||||
application = null,
|
||||
pinned = false
|
||||
|
@ -29,4 +29,7 @@
|
||||
<item
|
||||
android:id="@+id/status_delete"
|
||||
android:title="@string/action_delete" />
|
||||
<item
|
||||
android:id="@+id/status_delete_and_redraft"
|
||||
android:title="@string/action_delete_and_redraft" />
|
||||
</menu>
|
@ -74,6 +74,7 @@
|
||||
<string name="action_show_reblogs">ブーストを表示</string>
|
||||
<string name="action_report">通報</string>
|
||||
<string name="action_delete">削除</string>
|
||||
<string name="action_delete_and_redraft">削除して編集</string>
|
||||
<string name="action_send">トゥート</string>
|
||||
<string name="action_send_public">トゥート!</string>
|
||||
<string name="action_retry">再試行</string>
|
||||
|
@ -83,6 +83,7 @@
|
||||
<string name="action_show_reblogs">Show boosts</string>
|
||||
<string name="action_report">Report</string>
|
||||
<string name="action_delete">Delete</string>
|
||||
<string name="action_delete_and_redraft">Delete and re-draft</string>
|
||||
<string name="action_send">TOOT</string>
|
||||
<string name="action_send_public">TOOT!</string>
|
||||
<string name="action_retry">Retry</string>
|
||||
@ -179,6 +180,7 @@
|
||||
<string name="dialog_message_cancel_follow_request">Revoke the follow request?</string>
|
||||
<string name="dialog_unfollow_warning">Unfollow this account?</string>
|
||||
<string name="dialog_delete_toot_warning">Delete this toot?</string>
|
||||
<string name="dialog_redraft_toot_warning">Delete and re-draft this toot?</string>
|
||||
|
||||
<string name="visibility_public">Public: Post to public timelines</string>
|
||||
<string name="visibility_unlisted">Unlisted: Do not show in public timelines</string>
|
||||
|
@ -81,7 +81,7 @@ class BottomSheetActivityTest {
|
||||
false,
|
||||
"",
|
||||
Status.Visibility.PUBLIC,
|
||||
listOf(),
|
||||
ArrayList(),
|
||||
arrayOf(),
|
||||
null,
|
||||
pinned = false
|
||||
|
@ -30,6 +30,7 @@ import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class TimelineRepositoryTest {
|
||||
@Mock
|
||||
@ -297,7 +298,7 @@ class TimelineRepositoryTest {
|
||||
spoilerText = "",
|
||||
reblogged = true,
|
||||
favourited = false,
|
||||
attachments = listOf(),
|
||||
attachments = ArrayList(),
|
||||
mentions = arrayOf(),
|
||||
application = null,
|
||||
inReplyToAccountId = null,
|
||||
|
Loading…
Reference in New Issue
Block a user