Media description improvements (#898)
* Enforce 420-character limit on media descriptions in the UI * Persist media descriptions with drafts * Defer media description update until after upload finishes * Make description field 2 lines for better visibility of hint text * Reuse Gson instance * Force retranslation of modified string "hint_describe_for_visually_impaired" * Add bounds check when reading serialized media descriptions
This commit is contained in:
parent
026292122d
commit
690e612f8b
30 changed files with 103 additions and 48 deletions
|
@ -61,6 +61,7 @@ import android.support.v7.widget.GridLayoutManager;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.Editable;
|
||||
import android.text.InputFilter;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
|
@ -172,6 +173,7 @@ public final class ComposeActivity
|
|||
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 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 IN_REPLY_TO_ID_EXTRA = "in_reply_to_id";
|
||||
private static final String REPLY_VISIBILITY_EXTRA = "reply_visibilty";
|
||||
|
@ -181,6 +183,8 @@ public final class ComposeActivity
|
|||
private static final String REPLYING_STATUS_CONTENT_EXTRA = "replying_status_content";
|
||||
// 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
|
||||
private static final int MEDIA_DESCRIPTION_CHARACTER_LIMIT = 420;
|
||||
|
||||
@Inject
|
||||
public MastodonApi mastodonApi;
|
||||
|
@ -226,6 +230,7 @@ public final class ComposeActivity
|
|||
private @Px int thumbnailViewSize;
|
||||
|
||||
private SaveTootHelper saveTootHelper;
|
||||
private Gson gson = new Gson();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -396,6 +401,7 @@ public final class ComposeActivity
|
|||
|
||||
String[] mentionedUsernames = null;
|
||||
ArrayList<String> loadedDraftMediaUris = null;
|
||||
ArrayList<String> loadedDraftMediaDescriptions = null;
|
||||
inReplyToId = null;
|
||||
if (intent != null) {
|
||||
|
||||
|
@ -428,10 +434,16 @@ public final class ComposeActivity
|
|||
textEditor.setText(savedTootText);
|
||||
}
|
||||
|
||||
String savedJsonUrls = intent.getStringExtra(SAVED_JSON_URLS_EXTRA);
|
||||
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
||||
// try to redo a list of media
|
||||
loadedDraftMediaUris = new Gson().fromJson(savedJsonUrls,
|
||||
String savedJsonUrls = intent.getStringExtra(SAVED_JSON_URLS_EXTRA);
|
||||
String savedJsonDescriptions = intent.getStringExtra(SAVED_JSON_DESCRIPTIONS_EXTRA);
|
||||
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
||||
loadedDraftMediaUris = gson.fromJson(savedJsonUrls,
|
||||
new TypeToken<ArrayList<String>>() {
|
||||
}.getType());
|
||||
}
|
||||
if (!TextUtils.isEmpty(savedJsonDescriptions)) {
|
||||
loadedDraftMediaDescriptions = gson.fromJson(savedJsonDescriptions,
|
||||
new TypeToken<ArrayList<String>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
@ -550,10 +562,14 @@ public final class ComposeActivity
|
|||
|
||||
// These can only be added after everything affected by the media queue is initialized.
|
||||
if (!ListUtils.isEmpty(loadedDraftMediaUris)) {
|
||||
for (String uriString : loadedDraftMediaUris) {
|
||||
Uri uri = Uri.parse(uriString);
|
||||
for (int mediaIndex = 0; mediaIndex < loadedDraftMediaUris.size(); ++mediaIndex) {
|
||||
Uri uri = Uri.parse(loadedDraftMediaUris.get(mediaIndex));
|
||||
long mediaSize = getMediaSize(getContentResolver(), uri);
|
||||
pickMedia(uri, mediaSize);
|
||||
String description = null;
|
||||
if (loadedDraftMediaDescriptions != null && mediaIndex < loadedDraftMediaDescriptions.size()) {
|
||||
description = loadedDraftMediaDescriptions.get(mediaIndex);
|
||||
}
|
||||
pickMedia(uri, mediaSize, description);
|
||||
}
|
||||
} else if (savedMediaQueued != null) {
|
||||
for (SavedQueuedMedia item : savedMediaQueued) {
|
||||
|
@ -593,7 +609,7 @@ public final class ComposeActivity
|
|||
}
|
||||
for (Uri uri : uriList) {
|
||||
long mediaSize = getMediaSize(getContentResolver(), uri);
|
||||
pickMedia(uri, mediaSize);
|
||||
pickMedia(uri, mediaSize, null);
|
||||
}
|
||||
} else if (type.equals("text/plain")) {
|
||||
String action = intent.getAction();
|
||||
|
@ -610,6 +626,9 @@ public final class ComposeActivity
|
|||
}
|
||||
}
|
||||
}
|
||||
for (QueuedMedia item : mediaQueued) {
|
||||
item.preview.setChecked(!TextUtils.isEmpty(item.description));
|
||||
}
|
||||
|
||||
textEditor.requestFocus();
|
||||
}
|
||||
|
@ -880,7 +899,7 @@ public final class ComposeActivity
|
|||
} else {
|
||||
mediaSize = MEDIA_SIZE_UNKNOWN;
|
||||
}
|
||||
pickMedia(uri, mediaSize);
|
||||
pickMedia(uri, mediaSize, null);
|
||||
|
||||
currentInputContentInfo = inputContentInfo;
|
||||
currentFlags = flags;
|
||||
|
@ -892,13 +911,15 @@ public final class ComposeActivity
|
|||
String spoilerText) {
|
||||
ArrayList<String> mediaIds = new ArrayList<>();
|
||||
ArrayList<Uri> mediaUris = new ArrayList<>();
|
||||
ArrayList<String> mediaDescriptions = new ArrayList<>();
|
||||
for (QueuedMedia item : mediaQueued) {
|
||||
mediaIds.add(item.id);
|
||||
mediaUris.add(item.uri);
|
||||
mediaDescriptions.add(item.description);
|
||||
}
|
||||
|
||||
Intent sendIntent = SendTootService.sendTootIntent(this, content, spoilerText,
|
||||
visibility, sensitive, mediaIds, mediaUris, inReplyToId,
|
||||
visibility, sensitive, mediaIds, mediaUris, mediaDescriptions, inReplyToId,
|
||||
getIntent().getStringExtra(REPLYING_STATUS_CONTENT_EXTRA),
|
||||
getIntent().getStringExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA),
|
||||
getIntent().getStringExtra(SAVED_JSON_URLS_EXTRA),
|
||||
|
@ -1051,8 +1072,8 @@ public final class ComposeActivity
|
|||
colorActive ? android.R.attr.textColorTertiary : R.attr.compose_media_button_disabled_tint);
|
||||
}
|
||||
|
||||
private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize) {
|
||||
addMediaToQueue(null, type, preview, uri, mediaSize, null, null);
|
||||
private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize, @Nullable String description) {
|
||||
addMediaToQueue(null, type, preview, uri, mediaSize, null, description);
|
||||
}
|
||||
|
||||
private void addMediaToQueue(@Nullable String id, QueuedMedia.Type type, Bitmap preview, Uri uri,
|
||||
|
@ -1161,16 +1182,17 @@ public final class ComposeActivity
|
|||
((LinearLayout.LayoutParams) imageView.getLayoutParams()).setMargins(0, margin, 0, 0);
|
||||
|
||||
EditText input = new EditText(this);
|
||||
input.setHint(R.string.hint_describe_for_visually_impaired);
|
||||
input.setHint(getString(R.string.hint_describe_for_visually_impaired, MEDIA_DESCRIPTION_CHARACTER_LIMIT));
|
||||
dialogLayout.addView(input);
|
||||
((LinearLayout.LayoutParams) input.getLayoutParams()).setMargins(margin, margin, margin, margin);
|
||||
input.setLines(1);
|
||||
input.setLines(2);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
|
||||
input.setText(item.description);
|
||||
input.setFilters(new InputFilter[] { new InputFilter.LengthFilter(MEDIA_DESCRIPTION_CHARACTER_LIMIT) });
|
||||
|
||||
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
||||
mastodonApi.updateMedia(item.id, input.getText().toString())
|
||||
.enqueue(new Callback<Attachment>() {
|
||||
Runnable updateDescription = () -> {
|
||||
mastodonApi.updateMedia(item.id, input.getText().toString()).enqueue(new Callback<Attachment>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<Attachment> call, @NonNull Response<Attachment> response) {
|
||||
Attachment attachment = response.body();
|
||||
|
@ -1181,15 +1203,25 @@ public final class ComposeActivity
|
|||
} else {
|
||||
showFailedCaptionMessage();
|
||||
}
|
||||
item.updateDescription = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
|
||||
showFailedCaptionMessage();
|
||||
item.updateDescription = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (item.readyStage == QueuedMedia.ReadyStage.UPLOADED) {
|
||||
updateDescription.run();
|
||||
} else {
|
||||
// media is still uploading, queue description update for when it finishes
|
||||
item.updateDescription = updateDescription;
|
||||
}
|
||||
};
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||
.setView(dialogLayout)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
|
@ -1301,6 +1333,9 @@ public final class ComposeActivity
|
|||
public void onResponse(@NonNull Call<Attachment> call, @NonNull retrofit2.Response<Attachment> response) {
|
||||
if (response.isSuccessful()) {
|
||||
onUploadSuccess(item, response.body());
|
||||
if (item.updateDescription != null) {
|
||||
item.updateDescription.run();
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Upload request failed. " + response.message());
|
||||
onUploadFailure(item, call.isCanceled());
|
||||
|
@ -1311,6 +1346,7 @@ public final class ComposeActivity
|
|||
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
|
||||
Log.d(TAG, "Upload request failed. " + t.getMessage());
|
||||
onUploadFailure(item, call.isCanceled());
|
||||
item.updateDescription = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1355,15 +1391,15 @@ public final class ComposeActivity
|
|||
if (resultCode == RESULT_OK && requestCode == MEDIA_PICK_RESULT && intent != null) {
|
||||
Uri uri = intent.getData();
|
||||
long mediaSize = getMediaSize(getContentResolver(), uri);
|
||||
pickMedia(uri, mediaSize);
|
||||
pickMedia(uri, mediaSize, null);
|
||||
} else if (resultCode == RESULT_OK && requestCode == MEDIA_TAKE_PHOTO_RESULT) {
|
||||
long mediaSize = getMediaSize(getContentResolver(), photoUploadUri);
|
||||
pickMedia(photoUploadUri, mediaSize);
|
||||
pickMedia(photoUploadUri, mediaSize, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void pickMedia(Uri uri, long mediaSize) {
|
||||
private void pickMedia(Uri uri, long mediaSize, String description) {
|
||||
if (mediaSize == MEDIA_SIZE_UNKNOWN) {
|
||||
displayTransientError(R.string.error_media_upload_opening);
|
||||
return;
|
||||
|
@ -1385,7 +1421,7 @@ public final class ComposeActivity
|
|||
}
|
||||
Bitmap bitmap = getVideoThumbnail(this, uri, thumbnailViewSize);
|
||||
if (bitmap != null) {
|
||||
addMediaToQueue(QueuedMedia.Type.VIDEO, bitmap, uri, mediaSize);
|
||||
addMediaToQueue(QueuedMedia.Type.VIDEO, bitmap, uri, mediaSize, description);
|
||||
} else {
|
||||
displayTransientError(R.string.error_media_upload_opening);
|
||||
}
|
||||
|
@ -1394,7 +1430,7 @@ public final class ComposeActivity
|
|||
case "image": {
|
||||
Bitmap bitmap = getImageThumbnail(contentResolver, uri, thumbnailViewSize);
|
||||
if (bitmap != null) {
|
||||
addMediaToQueue(QueuedMedia.Type.IMAGE, bitmap, uri, mediaSize);
|
||||
addMediaToQueue(QueuedMedia.Type.IMAGE, bitmap, uri, mediaSize, description);
|
||||
} else {
|
||||
displayTransientError(R.string.error_media_upload_opening);
|
||||
}
|
||||
|
@ -1466,14 +1502,17 @@ public final class ComposeActivity
|
|||
|
||||
private void saveDraftAndFinish() {
|
||||
ArrayList<String> mediaUris = new ArrayList<>();
|
||||
ArrayList<String> mediaDescriptions = new ArrayList<>();
|
||||
for (QueuedMedia item : mediaQueued) {
|
||||
mediaUris.add(item.uri.toString());
|
||||
mediaDescriptions.add(item.description);
|
||||
}
|
||||
|
||||
saveTootHelper.saveToot(textEditor.getText().toString(),
|
||||
contentWarningEditor.getText().toString(),
|
||||
getIntent().getStringExtra("saved_json_urls"),
|
||||
mediaUris,
|
||||
mediaDescriptions,
|
||||
savedTootUid,
|
||||
inReplyToId,
|
||||
getIntent().getStringExtra(REPLYING_STATUS_CONTENT_EXTRA),
|
||||
|
@ -1543,6 +1582,7 @@ public final class ComposeActivity
|
|||
ReadyStage readyStage;
|
||||
long mediaSize;
|
||||
String description;
|
||||
Runnable updateDescription;
|
||||
|
||||
QueuedMedia(Type type, Uri uri, ProgressImageView preview, long mediaSize,
|
||||
String description) {
|
||||
|
@ -1628,6 +1668,8 @@ public final class ComposeActivity
|
|||
@Nullable
|
||||
private String savedJsonUrls;
|
||||
@Nullable
|
||||
private String savedJsonDescriptions;
|
||||
@Nullable
|
||||
private Collection<String> mentionedUsernames;
|
||||
@Nullable
|
||||
private String inReplyToId;
|
||||
|
@ -1657,6 +1699,11 @@ public final class ComposeActivity
|
|||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder savedJsonDescriptions(String jsonDescriptions) {
|
||||
this.savedJsonDescriptions = jsonDescriptions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IntentBuilder savedVisibility(Status.Visibility savedVisibility) {
|
||||
this.savedVisibility = savedVisibility;
|
||||
return this;
|
||||
|
@ -1704,6 +1751,9 @@ public final class ComposeActivity
|
|||
if (savedJsonUrls != null) {
|
||||
intent.putExtra(SAVED_JSON_URLS_EXTRA, savedJsonUrls);
|
||||
}
|
||||
if (savedJsonDescriptions != null) {
|
||||
intent.putExtra(SAVED_JSON_DESCRIPTIONS_EXTRA, savedJsonDescriptions);
|
||||
}
|
||||
if (mentionedUsernames != null) {
|
||||
String[] usernames = mentionedUsernames.toArray(new String[0]);
|
||||
intent.putExtra(MENTIONED_USERNAMES_EXTRA, usernames);
|
||||
|
|
|
@ -163,6 +163,7 @@ public final class SavedTootActivity extends BaseActivity implements SavedTootAd
|
|||
.savedTootText(item.getText())
|
||||
.contentWarning(item.getContentWarning())
|
||||
.savedJsonUrls(item.getUrls())
|
||||
.savedJsonDescriptions(item.getDescriptions())
|
||||
.inReplyToId(item.getInReplyToId())
|
||||
.repyingStatusAuthor(item.getInReplyToUsername())
|
||||
.replyingStatusContent(item.getInReplyToText())
|
||||
|
|
|
@ -70,7 +70,7 @@ public class TuskyApplication extends Application implements HasActivityInjector
|
|||
appDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "tuskyDB")
|
||||
.allowMainThreadQueries()
|
||||
.addMigrations(AppDatabase.MIGRATION_2_3, AppDatabase.MIGRATION_3_4, AppDatabase.MIGRATION_4_5,
|
||||
AppDatabase.MIGRATION_5_6, AppDatabase.MIGRATION_6_7, AppDatabase.MIGRATION_7_8)
|
||||
AppDatabase.MIGRATION_5_6, AppDatabase.MIGRATION_6_7, AppDatabase.MIGRATION_7_8, AppDatabase.MIGRATION_8_9)
|
||||
.build();
|
||||
accountManager = new AccountManager(appDatabase);
|
||||
serviceLocator = new ServiceLocator() {
|
||||
|
|
|
@ -25,7 +25,7 @@ import android.support.annotation.NonNull;
|
|||
* DB version & declare DAO
|
||||
*/
|
||||
|
||||
@Database(entities = {TootEntity.class, AccountEntity.class, InstanceEntity.class}, version = 8, exportSchema = false)
|
||||
@Database(entities = {TootEntity.class, AccountEntity.class, InstanceEntity.class}, version = 9, exportSchema = false)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
|
||||
public abstract TootDao tootDao();
|
||||
|
@ -98,4 +98,11 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `emojis` TEXT NOT NULL DEFAULT '[]'");
|
||||
}
|
||||
};
|
||||
|
||||
public static final Migration MIGRATION_8_9 = new Migration(8, 9) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `TootEntity` ADD COLUMN `descriptions` TEXT DEFAULT '[]'");
|
||||
}
|
||||
};
|
||||
}
|
|
@ -40,6 +40,9 @@ public class TootEntity {
|
|||
@ColumnInfo(name = "urls")
|
||||
private final String urls;
|
||||
|
||||
@ColumnInfo(name = "descriptions")
|
||||
private final String descriptions;
|
||||
|
||||
@ColumnInfo(name = "contentWarning")
|
||||
private final String contentWarning;
|
||||
|
||||
|
@ -57,12 +60,13 @@ public class TootEntity {
|
|||
@ColumnInfo(name = "visibility")
|
||||
private final Status.Visibility visibility;
|
||||
|
||||
public TootEntity(int uid, String text, String urls, String contentWarning, String inReplyToId,
|
||||
public TootEntity(int uid, String text, String urls, String descriptions, String contentWarning, String inReplyToId,
|
||||
@Nullable String inReplyToText, @Nullable String inReplyToUsername,
|
||||
Status.Visibility visibility) {
|
||||
this.uid = uid;
|
||||
this.text = text;
|
||||
this.urls = urls;
|
||||
this.descriptions = descriptions;
|
||||
this.contentWarning = contentWarning;
|
||||
this.inReplyToId = inReplyToId;
|
||||
this.inReplyToText = inReplyToText;
|
||||
|
@ -86,6 +90,10 @@ public class TootEntity {
|
|||
return urls;
|
||||
}
|
||||
|
||||
public String getDescriptions() {
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
public String getInReplyToId() {
|
||||
return inReplyToId;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
|||
false,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
citedStatusId,
|
||||
null,
|
||||
null,
|
||||
|
|
|
@ -238,6 +238,7 @@ class SendTootService : Service(), Injectable {
|
|||
toot.warningText,
|
||||
toot.savedJsonUrls,
|
||||
toot.mediaUris,
|
||||
toot.mediaDescriptions,
|
||||
toot.savedTootUid,
|
||||
toot.inReplyToId,
|
||||
toot.replyingStatusContent,
|
||||
|
@ -274,6 +275,7 @@ class SendTootService : Service(), Injectable {
|
|||
sensitive: Boolean,
|
||||
mediaIds: List<String>,
|
||||
mediaUris: List<Uri>,
|
||||
mediaDescriptions: List<String>,
|
||||
inReplyToId: String?,
|
||||
replyingStatusContent: String?,
|
||||
replyingStatusAuthorUsername: String?,
|
||||
|
@ -291,6 +293,7 @@ class SendTootService : Service(), Injectable {
|
|||
sensitive,
|
||||
mediaIds,
|
||||
mediaUris.map { it.toString() },
|
||||
mediaDescriptions,
|
||||
inReplyToId,
|
||||
replyingStatusContent,
|
||||
replyingStatusAuthorUsername,
|
||||
|
@ -332,6 +335,7 @@ data class TootToSend(val text: String,
|
|||
val sensitive: Boolean,
|
||||
val mediaIds: List<String>,
|
||||
val mediaUris: List<String>,
|
||||
val mediaDescriptions: List<String>,
|
||||
val inReplyToId: String?,
|
||||
val replyingStatusContent: String?,
|
||||
val replyingStatusAuthorUsername: String?,
|
||||
|
|
|
@ -32,6 +32,7 @@ public final class SaveTootHelper {
|
|||
|
||||
private TootDao tootDao;
|
||||
private Context context;
|
||||
private Gson gson = new Gson();
|
||||
|
||||
public SaveTootHelper(@NonNull TootDao tootDao, @NonNull Context context) {
|
||||
this.tootDao = tootDao;
|
||||
|
@ -43,6 +44,7 @@ public final class SaveTootHelper {
|
|||
@NonNull String contentWarning,
|
||||
@Nullable String savedJsonUrls,
|
||||
@NonNull List<String> mediaUris,
|
||||
@NonNull List<String> mediaDescriptions,
|
||||
int savedTootUid,
|
||||
@Nullable String inReplyToId,
|
||||
@Nullable String replyingStatusContent,
|
||||
|
@ -56,28 +58,31 @@ public final class SaveTootHelper {
|
|||
// Get any existing file's URIs.
|
||||
ArrayList<String> existingUris = null;
|
||||
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
||||
existingUris = new Gson().fromJson(savedJsonUrls,
|
||||
existingUris = gson.fromJson(savedJsonUrls,
|
||||
new TypeToken<ArrayList<String>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
String mediaUrlsSerialized = null;
|
||||
String mediaDescriptionsSerialized = null;
|
||||
|
||||
if (!ListUtils.isEmpty(mediaUris)) {
|
||||
List<String> savedList = saveMedia(mediaUris, existingUris);
|
||||
if (!ListUtils.isEmpty(savedList)) {
|
||||
mediaUrlsSerialized = new Gson().toJson(savedList);
|
||||
mediaUrlsSerialized = gson.toJson(savedList);
|
||||
if (!ListUtils.isEmpty(existingUris)) {
|
||||
deleteMedia(setDifference(existingUris, savedList));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
mediaDescriptionsSerialized = gson.toJson(mediaDescriptions);
|
||||
} else if (!ListUtils.isEmpty(existingUris)) {
|
||||
/* If there were URIs in the previous draft, but they've now been removed, those files
|
||||
* can be deleted. */
|
||||
deleteMedia(existingUris);
|
||||
}
|
||||
final TootEntity toot = new TootEntity(savedTootUid, content, mediaUrlsSerialized, contentWarning,
|
||||
final TootEntity toot = new TootEntity(savedTootUid, content, mediaUrlsSerialized, mediaDescriptionsSerialized, contentWarning,
|
||||
inReplyToId,
|
||||
replyingStatusContent,
|
||||
replyingStatusAuthorUsername,
|
||||
|
@ -102,7 +107,7 @@ public final class SaveTootHelper {
|
|||
|
||||
public void deleteDraft(@NonNull TootEntity item){
|
||||
// Delete any media files associated with the status.
|
||||
ArrayList<String> uris = new Gson().fromJson(item.getUrls(),
|
||||
ArrayList<String> uris = gson.fromJson(item.getUrls(),
|
||||
new TypeToken<ArrayList<String>>() {}.getType());
|
||||
if (uris != null) {
|
||||
for (String uriString : uris) {
|
||||
|
|
|
@ -265,7 +265,6 @@
|
|||
<string name="compose_active_account_description">النشر بواسطة حساب %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">تعذرت عملية إضافة الشرح</string>
|
||||
<string name="hint_describe_for_visually_impaired">وصف للمعاقين بصريًا</string>
|
||||
<string name="action_set_caption">إضافة شرح</string>
|
||||
<string name="action_remove_media">حذف</string>
|
||||
<string name="lock_account_label">تجميد الحساب</string>
|
||||
|
|
|
@ -305,7 +305,6 @@
|
|||
<string name="compose_active_account_description">Yn postio â chyfrif %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Methu gosod pennawd</string>
|
||||
<string name="hint_describe_for_visually_impaired">Disgrifiad i bobl â nam ar y golwg</string>
|
||||
<string name="action_set_caption">Pennu pennawd</string>
|
||||
<string name="action_remove_media">Dileu</string>
|
||||
<string name="lock_account_label">Cloi cyfrif</string>
|
||||
|
|
|
@ -249,7 +249,6 @@
|
|||
<string name="title_lists">Listen</string>
|
||||
<string name="title_list_timeline">Liste</string>
|
||||
<string name="action_remove_media">entfernen</string>
|
||||
<string name="hint_describe_for_visually_impaired">Beschreibung für Menschen mit Sehbehinderung</string>
|
||||
<string name="action_set_caption">Beschreibung eingeben</string>
|
||||
<string name="error_failed_set_caption">Fehler beim Speichern der Beschreibung</string>
|
||||
<string name="add_account_name">Konto hinzufügen</string>
|
||||
|
|
|
@ -300,7 +300,6 @@
|
|||
<string name="compose_active_account_description">Publicando con la cuenta %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Error al añadir leyenda</string>
|
||||
<string name="hint_describe_for_visually_impaired">Descripción para discapacitados visuales</string>
|
||||
<string name="action_set_caption">Añadir leyenda</string>
|
||||
<string name="action_remove_media">Eliminar</string>
|
||||
<string name="lock_account_label">Proteger cuenta</string>
|
||||
|
|
|
@ -305,7 +305,6 @@
|
|||
<string name="compose_active_account_description" >پست با حساب %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption" >ناتوان در تنظیم عنوان</string>
|
||||
<string name="hint_describe_for_visually_impaired" >توصیف برای ضعف دیداری</string>
|
||||
<string name="action_set_caption" >تنظیم عنوان</string>
|
||||
<string name="action_remove_media" >حذف</string>
|
||||
<string name="lock_account_label" >قفل حساب</string>
|
||||
|
|
|
@ -268,7 +268,6 @@
|
|||
<string name="compose_active_account_description">Poster avec le compte %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Impossible de mettre la légende</string>
|
||||
<string name="hint_describe_for_visually_impaired">Décrire pour les mal voyants</string>
|
||||
<string name="action_set_caption">Mettre une légende</string>
|
||||
<string name="action_remove_media">Supprimer le média</string>
|
||||
<string name="lock_account_label">Verrouiller le compte</string>
|
||||
|
|
|
@ -305,7 +305,6 @@
|
|||
<string name="compose_active_account_description">Pubblicando con l\'account %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Impostazione del sottotitolo non riuscita</string>
|
||||
<string name="hint_describe_for_visually_impaired">Descrivi per persone ipovedenti</string>
|
||||
<string name="action_set_caption">Inserisci sottotitolo</string>
|
||||
<string name="action_remove_media">Rimuovi</string>
|
||||
<string name="lock_account_label">Blocca account</string>
|
||||
|
|
|
@ -291,7 +291,6 @@
|
|||
<string name="title_list_timeline">リストタイムライン</string>
|
||||
|
||||
<string name="error_failed_set_caption">説明の設定に失敗しました</string>
|
||||
<string name="hint_describe_for_visually_impaired">視覚障害者のための説明</string>
|
||||
<string name="action_set_caption">説明を設定</string>
|
||||
<string name="action_remove_media">消去</string>
|
||||
<string name="lock_account_label">アカウントをロック</string>
|
||||
|
|
|
@ -264,7 +264,6 @@
|
|||
<string name="compose_active_account_description">다음 계정으로 작성 중: %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">캡션 설정 실패</string>
|
||||
<string name="hint_describe_for_visually_impaired">시각 장애인을 위한 설명</string>
|
||||
<string name="action_set_caption">설명 쓰기</string>
|
||||
<string name="action_remove_media">삭제</string>
|
||||
<string name="lock_account_label">계정 잠금</string>
|
||||
|
|
|
@ -292,7 +292,6 @@
|
|||
<string name="compose_active_account_description">Aan het publiceren met account %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Toevoegen van beschrijving mislukt</string>
|
||||
<string name="hint_describe_for_visually_impaired">Omschrijf dit voor mensen met een visuele beperking</string>
|
||||
<string name="action_set_caption">Beschrijving toevoegen</string>
|
||||
<string name="action_remove_media">Verwijderen</string>
|
||||
<string name="lock_account_label">Account besloten maken</string>
|
||||
|
|
|
@ -299,7 +299,6 @@
|
|||
<string name="compose_active_account_description">Publicar amb lo compte %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Fracàs en apondre una legenda</string>
|
||||
<string name="hint_describe_for_visually_impaired">Descripcion pels mal vesents</string>
|
||||
<string name="action_set_caption">Apondre una legenda</string>
|
||||
<string name="action_remove_media">Levar</string>
|
||||
<string name="lock_account_label">Clavar lo compte</string>
|
||||
|
|
|
@ -300,7 +300,6 @@
|
|||
<string name="compose_active_account_description">Publikowanie z konta %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Nie udało się ustawić podpisu</string>
|
||||
<string name="hint_describe_for_visually_impaired">Opis dla osób korzystających z ułatwień dostępności</string>
|
||||
<string name="action_set_caption">Ustaw podpis</string>
|
||||
<string name="action_remove_media">Usuń</string>
|
||||
<string name="lock_account_label">Zablokuj konto</string>
|
||||
|
|
|
@ -296,7 +296,6 @@
|
|||
<string name="compose_active_account_description">Postando com a conta %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Falha ao atribuir descrição</string>
|
||||
<string name="hint_describe_for_visually_impaired">Descreva a imagem para deficientes visuais</string>
|
||||
<string name="action_set_caption">Escrever descrição</string>
|
||||
<string name="action_remove_media">Remover</string>
|
||||
<string name="lock_account_label">Trancar conta</string>
|
||||
|
|
|
@ -285,7 +285,6 @@
|
|||
<string name="compose_active_account_description">Отправка от имени %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Не удалось добавить подпись</string>
|
||||
<string name="hint_describe_for_visually_impaired">Описание для слабовидящих</string>
|
||||
<string name="action_set_caption">Добавить подпись</string>
|
||||
<string name="action_remove_media">Удалить</string>
|
||||
<string name="lock_account_label">Закрыть аккаунт</string>
|
||||
|
|
|
@ -304,7 +304,6 @@
|
|||
<string name="compose_active_account_description">Inlägg med kontot %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Misslyckades med att ange bildtext</string>
|
||||
<string name="hint_describe_for_visually_impaired">Beskriv för synskadade</string>
|
||||
<string name="action_set_caption">Ange bildtext</string>
|
||||
<string name="action_remove_media">Ta bort</string>
|
||||
<string name="lock_account_label">Lås konto</string>
|
||||
|
|
|
@ -288,7 +288,6 @@
|
|||
<string name="compose_active_account_description">%1$s கணக்குடன் பதிவிட</string>
|
||||
|
||||
<string name="error_failed_set_caption">தலைப்பை அமைக்க முடியவில்லை</string>
|
||||
<string name="hint_describe_for_visually_impaired">பார்வையற்றவர்களுக்கான விளக்கம்</string>
|
||||
<string name="action_set_caption">தலைப்பை அமை</string>
|
||||
<string name="action_remove_media">நீக்கு</string>
|
||||
<string name="lock_account_label">கணக்கை முடக்கு</string>
|
||||
|
|
|
@ -275,7 +275,6 @@
|
|||
<string name="compose_active_account_description">使用帐号 %1$s 发布嘟文</string>
|
||||
|
||||
<string name="error_failed_set_caption">设置图片标题失败。</string>
|
||||
<string name="hint_describe_for_visually_impaired">为视觉障碍者提供的描述</string>
|
||||
<string name="action_set_caption">设置图片标题</string>
|
||||
<string name="action_remove_media">移除</string>
|
||||
<string name="lock_account_label">保护你的帐户(锁嘟)</string>
|
||||
|
|
|
@ -275,7 +275,6 @@
|
|||
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
||||
|
||||
<string name="error_failed_set_caption">設置圖片標題失敗。</string>
|
||||
<string name="hint_describe_for_visually_impaired">為視覺障礙者提供的描述</string>
|
||||
<string name="action_set_caption">設置圖片標題</string>
|
||||
<string name="action_remove_media">移除</string>
|
||||
<string name="lock_account_label">保護你的帳户(鎖嘟)</string>
|
||||
|
|
|
@ -275,7 +275,6 @@
|
|||
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
||||
|
||||
<string name="error_failed_set_caption">設置圖片標題失敗。</string>
|
||||
<string name="hint_describe_for_visually_impaired">為視覺障礙者提供的描述</string>
|
||||
<string name="action_set_caption">設置圖片標題</string>
|
||||
<string name="action_remove_media">移除</string>
|
||||
<string name="lock_account_label">保護你的帳户(鎖嘟)</string>
|
||||
|
|
|
@ -275,7 +275,6 @@
|
|||
<string name="compose_active_account_description">使用帐号 %1$s 发布嘟文</string>
|
||||
|
||||
<string name="error_failed_set_caption">设置图片标题失败。</string>
|
||||
<string name="hint_describe_for_visually_impaired">为视觉障碍者提供的描述</string>
|
||||
<string name="action_set_caption">设置图片标题</string>
|
||||
<string name="action_remove_media">移除</string>
|
||||
<string name="lock_account_label">保护你的帐户(锁嘟)</string>
|
||||
|
|
|
@ -275,7 +275,6 @@
|
|||
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
||||
|
||||
<string name="error_failed_set_caption">設置圖片標題失敗。</string>
|
||||
<string name="hint_describe_for_visually_impaired">為視覺障礙者提供的描述</string>
|
||||
<string name="action_set_caption">設置圖片標題</string>
|
||||
<string name="action_remove_media">移除</string>
|
||||
<string name="lock_account_label">保護你的帳戶(鎖嘟)</string>
|
||||
|
|
|
@ -305,7 +305,7 @@
|
|||
<string name="compose_active_account_description">Posting with account %1$s</string>
|
||||
|
||||
<string name="error_failed_set_caption">Failed to set caption</string>
|
||||
<string name="hint_describe_for_visually_impaired">Describe for visually impaired</string>
|
||||
<string name="hint_describe_for_visually_impaired">Describe for visually impaired\n(%d character limit)</string>
|
||||
<string name="action_set_caption">Set caption</string>
|
||||
<string name="action_remove_media">Remove</string>
|
||||
<string name="lock_account_label">Lock account</string>
|
||||
|
|
Loading…
Reference in a new issue