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.RecyclerView;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
import android.text.InputFilter;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
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_UID_EXTRA = "saved_toot_uid";
|
||||||
private static final String SAVED_TOOT_TEXT_EXTRA = "saved_toot_text";
|
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_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 SAVED_TOOT_VISIBILITY_EXTRA = "saved_toot_visibility";
|
||||||
private static final String IN_REPLY_TO_ID_EXTRA = "in_reply_to_id";
|
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_visibilty";
|
||||||
|
@ -181,6 +183,8 @@ public final class ComposeActivity
|
||||||
private static final String REPLYING_STATUS_CONTENT_EXTRA = "replying_status_content";
|
private static final String REPLYING_STATUS_CONTENT_EXTRA = "replying_status_content";
|
||||||
// Mastodon only counts URLs as this long in terms of status character limits
|
// Mastodon only counts URLs as this long in terms of status character limits
|
||||||
static final int MAXIMUM_URL_LENGTH = 23;
|
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
|
@Inject
|
||||||
public MastodonApi mastodonApi;
|
public MastodonApi mastodonApi;
|
||||||
|
@ -226,6 +230,7 @@ public final class ComposeActivity
|
||||||
private @Px int thumbnailViewSize;
|
private @Px int thumbnailViewSize;
|
||||||
|
|
||||||
private SaveTootHelper saveTootHelper;
|
private SaveTootHelper saveTootHelper;
|
||||||
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -396,6 +401,7 @@ public final class ComposeActivity
|
||||||
|
|
||||||
String[] mentionedUsernames = null;
|
String[] mentionedUsernames = null;
|
||||||
ArrayList<String> loadedDraftMediaUris = null;
|
ArrayList<String> loadedDraftMediaUris = null;
|
||||||
|
ArrayList<String> loadedDraftMediaDescriptions = null;
|
||||||
inReplyToId = null;
|
inReplyToId = null;
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
|
|
||||||
|
@ -428,10 +434,16 @@ public final class ComposeActivity
|
||||||
textEditor.setText(savedTootText);
|
textEditor.setText(savedTootText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to redo a list of media
|
||||||
String savedJsonUrls = intent.getStringExtra(SAVED_JSON_URLS_EXTRA);
|
String savedJsonUrls = intent.getStringExtra(SAVED_JSON_URLS_EXTRA);
|
||||||
|
String savedJsonDescriptions = intent.getStringExtra(SAVED_JSON_DESCRIPTIONS_EXTRA);
|
||||||
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
||||||
// try to redo a list of media
|
loadedDraftMediaUris = gson.fromJson(savedJsonUrls,
|
||||||
loadedDraftMediaUris = new Gson().fromJson(savedJsonUrls,
|
new TypeToken<ArrayList<String>>() {
|
||||||
|
}.getType());
|
||||||
|
}
|
||||||
|
if (!TextUtils.isEmpty(savedJsonDescriptions)) {
|
||||||
|
loadedDraftMediaDescriptions = gson.fromJson(savedJsonDescriptions,
|
||||||
new TypeToken<ArrayList<String>>() {
|
new TypeToken<ArrayList<String>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
}
|
}
|
||||||
|
@ -550,10 +562,14 @@ public final class ComposeActivity
|
||||||
|
|
||||||
// These can only be added after everything affected by the media queue is initialized.
|
// These can only be added after everything affected by the media queue is initialized.
|
||||||
if (!ListUtils.isEmpty(loadedDraftMediaUris)) {
|
if (!ListUtils.isEmpty(loadedDraftMediaUris)) {
|
||||||
for (String uriString : loadedDraftMediaUris) {
|
for (int mediaIndex = 0; mediaIndex < loadedDraftMediaUris.size(); ++mediaIndex) {
|
||||||
Uri uri = Uri.parse(uriString);
|
Uri uri = Uri.parse(loadedDraftMediaUris.get(mediaIndex));
|
||||||
long mediaSize = getMediaSize(getContentResolver(), uri);
|
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) {
|
} else if (savedMediaQueued != null) {
|
||||||
for (SavedQueuedMedia item : savedMediaQueued) {
|
for (SavedQueuedMedia item : savedMediaQueued) {
|
||||||
|
@ -593,7 +609,7 @@ public final class ComposeActivity
|
||||||
}
|
}
|
||||||
for (Uri uri : uriList) {
|
for (Uri uri : uriList) {
|
||||||
long mediaSize = getMediaSize(getContentResolver(), uri);
|
long mediaSize = getMediaSize(getContentResolver(), uri);
|
||||||
pickMedia(uri, mediaSize);
|
pickMedia(uri, mediaSize, null);
|
||||||
}
|
}
|
||||||
} else if (type.equals("text/plain")) {
|
} else if (type.equals("text/plain")) {
|
||||||
String action = intent.getAction();
|
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();
|
textEditor.requestFocus();
|
||||||
}
|
}
|
||||||
|
@ -880,7 +899,7 @@ public final class ComposeActivity
|
||||||
} else {
|
} else {
|
||||||
mediaSize = MEDIA_SIZE_UNKNOWN;
|
mediaSize = MEDIA_SIZE_UNKNOWN;
|
||||||
}
|
}
|
||||||
pickMedia(uri, mediaSize);
|
pickMedia(uri, mediaSize, null);
|
||||||
|
|
||||||
currentInputContentInfo = inputContentInfo;
|
currentInputContentInfo = inputContentInfo;
|
||||||
currentFlags = flags;
|
currentFlags = flags;
|
||||||
|
@ -892,13 +911,15 @@ public final class ComposeActivity
|
||||||
String spoilerText) {
|
String spoilerText) {
|
||||||
ArrayList<String> mediaIds = new ArrayList<>();
|
ArrayList<String> mediaIds = new ArrayList<>();
|
||||||
ArrayList<Uri> mediaUris = new ArrayList<>();
|
ArrayList<Uri> mediaUris = new ArrayList<>();
|
||||||
|
ArrayList<String> mediaDescriptions = new ArrayList<>();
|
||||||
for (QueuedMedia item : mediaQueued) {
|
for (QueuedMedia item : mediaQueued) {
|
||||||
mediaIds.add(item.id);
|
mediaIds.add(item.id);
|
||||||
mediaUris.add(item.uri);
|
mediaUris.add(item.uri);
|
||||||
|
mediaDescriptions.add(item.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent sendIntent = SendTootService.sendTootIntent(this, content, spoilerText,
|
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_CONTENT_EXTRA),
|
||||||
getIntent().getStringExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA),
|
getIntent().getStringExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA),
|
||||||
getIntent().getStringExtra(SAVED_JSON_URLS_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);
|
colorActive ? android.R.attr.textColorTertiary : R.attr.compose_media_button_disabled_tint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize) {
|
private void addMediaToQueue(QueuedMedia.Type type, Bitmap preview, Uri uri, long mediaSize, @Nullable String description) {
|
||||||
addMediaToQueue(null, type, preview, uri, mediaSize, null, null);
|
addMediaToQueue(null, type, preview, uri, mediaSize, null, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMediaToQueue(@Nullable String id, QueuedMedia.Type type, Bitmap preview, Uri uri,
|
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);
|
((LinearLayout.LayoutParams) imageView.getLayoutParams()).setMargins(0, margin, 0, 0);
|
||||||
|
|
||||||
EditText input = new EditText(this);
|
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);
|
dialogLayout.addView(input);
|
||||||
((LinearLayout.LayoutParams) input.getLayoutParams()).setMargins(margin, margin, margin, margin);
|
((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.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
|
||||||
input.setText(item.description);
|
input.setText(item.description);
|
||||||
|
input.setFilters(new InputFilter[] { new InputFilter.LengthFilter(MEDIA_DESCRIPTION_CHARACTER_LIMIT) });
|
||||||
|
|
||||||
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
DialogInterface.OnClickListener okListener = (dialog, which) -> {
|
||||||
mastodonApi.updateMedia(item.id, input.getText().toString())
|
Runnable updateDescription = () -> {
|
||||||
.enqueue(new Callback<Attachment>() {
|
mastodonApi.updateMedia(item.id, input.getText().toString()).enqueue(new Callback<Attachment>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(@NonNull Call<Attachment> call, @NonNull Response<Attachment> response) {
|
public void onResponse(@NonNull Call<Attachment> call, @NonNull Response<Attachment> response) {
|
||||||
Attachment attachment = response.body();
|
Attachment attachment = response.body();
|
||||||
|
@ -1181,13 +1203,23 @@ public final class ComposeActivity
|
||||||
} else {
|
} else {
|
||||||
showFailedCaptionMessage();
|
showFailedCaptionMessage();
|
||||||
}
|
}
|
||||||
|
item.updateDescription = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
|
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
|
||||||
showFailedCaptionMessage();
|
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)
|
AlertDialog dialog = new AlertDialog.Builder(this)
|
||||||
|
@ -1301,6 +1333,9 @@ public final class ComposeActivity
|
||||||
public void onResponse(@NonNull Call<Attachment> call, @NonNull retrofit2.Response<Attachment> response) {
|
public void onResponse(@NonNull Call<Attachment> call, @NonNull retrofit2.Response<Attachment> response) {
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
onUploadSuccess(item, response.body());
|
onUploadSuccess(item, response.body());
|
||||||
|
if (item.updateDescription != null) {
|
||||||
|
item.updateDescription.run();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Upload request failed. " + response.message());
|
Log.d(TAG, "Upload request failed. " + response.message());
|
||||||
onUploadFailure(item, call.isCanceled());
|
onUploadFailure(item, call.isCanceled());
|
||||||
|
@ -1311,6 +1346,7 @@ public final class ComposeActivity
|
||||||
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
|
public void onFailure(@NonNull Call<Attachment> call, @NonNull Throwable t) {
|
||||||
Log.d(TAG, "Upload request failed. " + t.getMessage());
|
Log.d(TAG, "Upload request failed. " + t.getMessage());
|
||||||
onUploadFailure(item, call.isCanceled());
|
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) {
|
if (resultCode == RESULT_OK && requestCode == MEDIA_PICK_RESULT && intent != null) {
|
||||||
Uri uri = intent.getData();
|
Uri uri = intent.getData();
|
||||||
long mediaSize = getMediaSize(getContentResolver(), uri);
|
long mediaSize = getMediaSize(getContentResolver(), uri);
|
||||||
pickMedia(uri, mediaSize);
|
pickMedia(uri, mediaSize, null);
|
||||||
} else if (resultCode == RESULT_OK && requestCode == MEDIA_TAKE_PHOTO_RESULT) {
|
} else if (resultCode == RESULT_OK && requestCode == MEDIA_TAKE_PHOTO_RESULT) {
|
||||||
long mediaSize = getMediaSize(getContentResolver(), photoUploadUri);
|
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) {
|
if (mediaSize == MEDIA_SIZE_UNKNOWN) {
|
||||||
displayTransientError(R.string.error_media_upload_opening);
|
displayTransientError(R.string.error_media_upload_opening);
|
||||||
return;
|
return;
|
||||||
|
@ -1385,7 +1421,7 @@ public final class ComposeActivity
|
||||||
}
|
}
|
||||||
Bitmap bitmap = getVideoThumbnail(this, uri, thumbnailViewSize);
|
Bitmap bitmap = getVideoThumbnail(this, uri, thumbnailViewSize);
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
addMediaToQueue(QueuedMedia.Type.VIDEO, bitmap, uri, mediaSize);
|
addMediaToQueue(QueuedMedia.Type.VIDEO, bitmap, uri, mediaSize, description);
|
||||||
} else {
|
} else {
|
||||||
displayTransientError(R.string.error_media_upload_opening);
|
displayTransientError(R.string.error_media_upload_opening);
|
||||||
}
|
}
|
||||||
|
@ -1394,7 +1430,7 @@ public final class ComposeActivity
|
||||||
case "image": {
|
case "image": {
|
||||||
Bitmap bitmap = getImageThumbnail(contentResolver, uri, thumbnailViewSize);
|
Bitmap bitmap = getImageThumbnail(contentResolver, uri, thumbnailViewSize);
|
||||||
if (bitmap != null) {
|
if (bitmap != null) {
|
||||||
addMediaToQueue(QueuedMedia.Type.IMAGE, bitmap, uri, mediaSize);
|
addMediaToQueue(QueuedMedia.Type.IMAGE, bitmap, uri, mediaSize, description);
|
||||||
} else {
|
} else {
|
||||||
displayTransientError(R.string.error_media_upload_opening);
|
displayTransientError(R.string.error_media_upload_opening);
|
||||||
}
|
}
|
||||||
|
@ -1466,14 +1502,17 @@ public final class ComposeActivity
|
||||||
|
|
||||||
private void saveDraftAndFinish() {
|
private void saveDraftAndFinish() {
|
||||||
ArrayList<String> mediaUris = new ArrayList<>();
|
ArrayList<String> mediaUris = new ArrayList<>();
|
||||||
|
ArrayList<String> mediaDescriptions = new ArrayList<>();
|
||||||
for (QueuedMedia item : mediaQueued) {
|
for (QueuedMedia item : mediaQueued) {
|
||||||
mediaUris.add(item.uri.toString());
|
mediaUris.add(item.uri.toString());
|
||||||
|
mediaDescriptions.add(item.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveTootHelper.saveToot(textEditor.getText().toString(),
|
saveTootHelper.saveToot(textEditor.getText().toString(),
|
||||||
contentWarningEditor.getText().toString(),
|
contentWarningEditor.getText().toString(),
|
||||||
getIntent().getStringExtra("saved_json_urls"),
|
getIntent().getStringExtra("saved_json_urls"),
|
||||||
mediaUris,
|
mediaUris,
|
||||||
|
mediaDescriptions,
|
||||||
savedTootUid,
|
savedTootUid,
|
||||||
inReplyToId,
|
inReplyToId,
|
||||||
getIntent().getStringExtra(REPLYING_STATUS_CONTENT_EXTRA),
|
getIntent().getStringExtra(REPLYING_STATUS_CONTENT_EXTRA),
|
||||||
|
@ -1543,6 +1582,7 @@ public final class ComposeActivity
|
||||||
ReadyStage readyStage;
|
ReadyStage readyStage;
|
||||||
long mediaSize;
|
long mediaSize;
|
||||||
String description;
|
String description;
|
||||||
|
Runnable updateDescription;
|
||||||
|
|
||||||
QueuedMedia(Type type, Uri uri, ProgressImageView preview, long mediaSize,
|
QueuedMedia(Type type, Uri uri, ProgressImageView preview, long mediaSize,
|
||||||
String description) {
|
String description) {
|
||||||
|
@ -1628,6 +1668,8 @@ public final class ComposeActivity
|
||||||
@Nullable
|
@Nullable
|
||||||
private String savedJsonUrls;
|
private String savedJsonUrls;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
private String savedJsonDescriptions;
|
||||||
|
@Nullable
|
||||||
private Collection<String> mentionedUsernames;
|
private Collection<String> mentionedUsernames;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String inReplyToId;
|
private String inReplyToId;
|
||||||
|
@ -1657,6 +1699,11 @@ public final class ComposeActivity
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IntentBuilder savedJsonDescriptions(String jsonDescriptions) {
|
||||||
|
this.savedJsonDescriptions = jsonDescriptions;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public IntentBuilder savedVisibility(Status.Visibility savedVisibility) {
|
public IntentBuilder savedVisibility(Status.Visibility savedVisibility) {
|
||||||
this.savedVisibility = savedVisibility;
|
this.savedVisibility = savedVisibility;
|
||||||
return this;
|
return this;
|
||||||
|
@ -1704,6 +1751,9 @@ public final class ComposeActivity
|
||||||
if (savedJsonUrls != null) {
|
if (savedJsonUrls != null) {
|
||||||
intent.putExtra(SAVED_JSON_URLS_EXTRA, savedJsonUrls);
|
intent.putExtra(SAVED_JSON_URLS_EXTRA, savedJsonUrls);
|
||||||
}
|
}
|
||||||
|
if (savedJsonDescriptions != null) {
|
||||||
|
intent.putExtra(SAVED_JSON_DESCRIPTIONS_EXTRA, savedJsonDescriptions);
|
||||||
|
}
|
||||||
if (mentionedUsernames != null) {
|
if (mentionedUsernames != null) {
|
||||||
String[] usernames = mentionedUsernames.toArray(new String[0]);
|
String[] usernames = mentionedUsernames.toArray(new String[0]);
|
||||||
intent.putExtra(MENTIONED_USERNAMES_EXTRA, usernames);
|
intent.putExtra(MENTIONED_USERNAMES_EXTRA, usernames);
|
||||||
|
|
|
@ -163,6 +163,7 @@ public final class SavedTootActivity extends BaseActivity implements SavedTootAd
|
||||||
.savedTootText(item.getText())
|
.savedTootText(item.getText())
|
||||||
.contentWarning(item.getContentWarning())
|
.contentWarning(item.getContentWarning())
|
||||||
.savedJsonUrls(item.getUrls())
|
.savedJsonUrls(item.getUrls())
|
||||||
|
.savedJsonDescriptions(item.getDescriptions())
|
||||||
.inReplyToId(item.getInReplyToId())
|
.inReplyToId(item.getInReplyToId())
|
||||||
.repyingStatusAuthor(item.getInReplyToUsername())
|
.repyingStatusAuthor(item.getInReplyToUsername())
|
||||||
.replyingStatusContent(item.getInReplyToText())
|
.replyingStatusContent(item.getInReplyToText())
|
||||||
|
|
|
@ -70,7 +70,7 @@ public class TuskyApplication extends Application implements HasActivityInjector
|
||||||
appDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "tuskyDB")
|
appDatabase = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "tuskyDB")
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.addMigrations(AppDatabase.MIGRATION_2_3, AppDatabase.MIGRATION_3_4, AppDatabase.MIGRATION_4_5,
|
.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();
|
.build();
|
||||||
accountManager = new AccountManager(appDatabase);
|
accountManager = new AccountManager(appDatabase);
|
||||||
serviceLocator = new ServiceLocator() {
|
serviceLocator = new ServiceLocator() {
|
||||||
|
|
|
@ -25,7 +25,7 @@ import android.support.annotation.NonNull;
|
||||||
* DB version & declare DAO
|
* 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 class AppDatabase extends RoomDatabase {
|
||||||
|
|
||||||
public abstract TootDao tootDao();
|
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 '[]'");
|
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")
|
@ColumnInfo(name = "urls")
|
||||||
private final String urls;
|
private final String urls;
|
||||||
|
|
||||||
|
@ColumnInfo(name = "descriptions")
|
||||||
|
private final String descriptions;
|
||||||
|
|
||||||
@ColumnInfo(name = "contentWarning")
|
@ColumnInfo(name = "contentWarning")
|
||||||
private final String contentWarning;
|
private final String contentWarning;
|
||||||
|
|
||||||
|
@ -57,12 +60,13 @@ public class TootEntity {
|
||||||
@ColumnInfo(name = "visibility")
|
@ColumnInfo(name = "visibility")
|
||||||
private final Status.Visibility 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,
|
@Nullable String inReplyToText, @Nullable String inReplyToUsername,
|
||||||
Status.Visibility visibility) {
|
Status.Visibility visibility) {
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.urls = urls;
|
this.urls = urls;
|
||||||
|
this.descriptions = descriptions;
|
||||||
this.contentWarning = contentWarning;
|
this.contentWarning = contentWarning;
|
||||||
this.inReplyToId = inReplyToId;
|
this.inReplyToId = inReplyToId;
|
||||||
this.inReplyToText = inReplyToText;
|
this.inReplyToText = inReplyToText;
|
||||||
|
@ -86,6 +90,10 @@ public class TootEntity {
|
||||||
return urls;
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDescriptions() {
|
||||||
|
return descriptions;
|
||||||
|
}
|
||||||
|
|
||||||
public String getInReplyToId() {
|
public String getInReplyToId() {
|
||||||
return inReplyToId;
|
return inReplyToId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
||||||
false,
|
false,
|
||||||
emptyList(),
|
emptyList(),
|
||||||
emptyList(),
|
emptyList(),
|
||||||
|
emptyList(),
|
||||||
citedStatusId,
|
citedStatusId,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -238,6 +238,7 @@ class SendTootService : Service(), Injectable {
|
||||||
toot.warningText,
|
toot.warningText,
|
||||||
toot.savedJsonUrls,
|
toot.savedJsonUrls,
|
||||||
toot.mediaUris,
|
toot.mediaUris,
|
||||||
|
toot.mediaDescriptions,
|
||||||
toot.savedTootUid,
|
toot.savedTootUid,
|
||||||
toot.inReplyToId,
|
toot.inReplyToId,
|
||||||
toot.replyingStatusContent,
|
toot.replyingStatusContent,
|
||||||
|
@ -274,6 +275,7 @@ class SendTootService : Service(), Injectable {
|
||||||
sensitive: Boolean,
|
sensitive: Boolean,
|
||||||
mediaIds: List<String>,
|
mediaIds: List<String>,
|
||||||
mediaUris: List<Uri>,
|
mediaUris: List<Uri>,
|
||||||
|
mediaDescriptions: List<String>,
|
||||||
inReplyToId: String?,
|
inReplyToId: String?,
|
||||||
replyingStatusContent: String?,
|
replyingStatusContent: String?,
|
||||||
replyingStatusAuthorUsername: String?,
|
replyingStatusAuthorUsername: String?,
|
||||||
|
@ -291,6 +293,7 @@ class SendTootService : Service(), Injectable {
|
||||||
sensitive,
|
sensitive,
|
||||||
mediaIds,
|
mediaIds,
|
||||||
mediaUris.map { it.toString() },
|
mediaUris.map { it.toString() },
|
||||||
|
mediaDescriptions,
|
||||||
inReplyToId,
|
inReplyToId,
|
||||||
replyingStatusContent,
|
replyingStatusContent,
|
||||||
replyingStatusAuthorUsername,
|
replyingStatusAuthorUsername,
|
||||||
|
@ -332,6 +335,7 @@ data class TootToSend(val text: String,
|
||||||
val sensitive: Boolean,
|
val sensitive: Boolean,
|
||||||
val mediaIds: List<String>,
|
val mediaIds: List<String>,
|
||||||
val mediaUris: List<String>,
|
val mediaUris: List<String>,
|
||||||
|
val mediaDescriptions: List<String>,
|
||||||
val inReplyToId: String?,
|
val inReplyToId: String?,
|
||||||
val replyingStatusContent: String?,
|
val replyingStatusContent: String?,
|
||||||
val replyingStatusAuthorUsername: String?,
|
val replyingStatusAuthorUsername: String?,
|
||||||
|
|
|
@ -32,6 +32,7 @@ public final class SaveTootHelper {
|
||||||
|
|
||||||
private TootDao tootDao;
|
private TootDao tootDao;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
public SaveTootHelper(@NonNull TootDao tootDao, @NonNull Context context) {
|
public SaveTootHelper(@NonNull TootDao tootDao, @NonNull Context context) {
|
||||||
this.tootDao = tootDao;
|
this.tootDao = tootDao;
|
||||||
|
@ -43,6 +44,7 @@ public final class SaveTootHelper {
|
||||||
@NonNull String contentWarning,
|
@NonNull String contentWarning,
|
||||||
@Nullable String savedJsonUrls,
|
@Nullable String savedJsonUrls,
|
||||||
@NonNull List<String> mediaUris,
|
@NonNull List<String> mediaUris,
|
||||||
|
@NonNull List<String> mediaDescriptions,
|
||||||
int savedTootUid,
|
int savedTootUid,
|
||||||
@Nullable String inReplyToId,
|
@Nullable String inReplyToId,
|
||||||
@Nullable String replyingStatusContent,
|
@Nullable String replyingStatusContent,
|
||||||
|
@ -56,28 +58,31 @@ public final class SaveTootHelper {
|
||||||
// Get any existing file's URIs.
|
// Get any existing file's URIs.
|
||||||
ArrayList<String> existingUris = null;
|
ArrayList<String> existingUris = null;
|
||||||
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
if (!TextUtils.isEmpty(savedJsonUrls)) {
|
||||||
existingUris = new Gson().fromJson(savedJsonUrls,
|
existingUris = gson.fromJson(savedJsonUrls,
|
||||||
new TypeToken<ArrayList<String>>() {
|
new TypeToken<ArrayList<String>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
String mediaUrlsSerialized = null;
|
String mediaUrlsSerialized = null;
|
||||||
|
String mediaDescriptionsSerialized = null;
|
||||||
|
|
||||||
if (!ListUtils.isEmpty(mediaUris)) {
|
if (!ListUtils.isEmpty(mediaUris)) {
|
||||||
List<String> savedList = saveMedia(mediaUris, existingUris);
|
List<String> savedList = saveMedia(mediaUris, existingUris);
|
||||||
if (!ListUtils.isEmpty(savedList)) {
|
if (!ListUtils.isEmpty(savedList)) {
|
||||||
mediaUrlsSerialized = new Gson().toJson(savedList);
|
mediaUrlsSerialized = gson.toJson(savedList);
|
||||||
if (!ListUtils.isEmpty(existingUris)) {
|
if (!ListUtils.isEmpty(existingUris)) {
|
||||||
deleteMedia(setDifference(existingUris, savedList));
|
deleteMedia(setDifference(existingUris, savedList));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
mediaDescriptionsSerialized = gson.toJson(mediaDescriptions);
|
||||||
} else if (!ListUtils.isEmpty(existingUris)) {
|
} else if (!ListUtils.isEmpty(existingUris)) {
|
||||||
/* If there were URIs in the previous draft, but they've now been removed, those files
|
/* If there were URIs in the previous draft, but they've now been removed, those files
|
||||||
* can be deleted. */
|
* can be deleted. */
|
||||||
deleteMedia(existingUris);
|
deleteMedia(existingUris);
|
||||||
}
|
}
|
||||||
final TootEntity toot = new TootEntity(savedTootUid, content, mediaUrlsSerialized, contentWarning,
|
final TootEntity toot = new TootEntity(savedTootUid, content, mediaUrlsSerialized, mediaDescriptionsSerialized, contentWarning,
|
||||||
inReplyToId,
|
inReplyToId,
|
||||||
replyingStatusContent,
|
replyingStatusContent,
|
||||||
replyingStatusAuthorUsername,
|
replyingStatusAuthorUsername,
|
||||||
|
@ -102,7 +107,7 @@ public final class SaveTootHelper {
|
||||||
|
|
||||||
public void deleteDraft(@NonNull TootEntity item){
|
public void deleteDraft(@NonNull TootEntity item){
|
||||||
// Delete any media files associated with the status.
|
// 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());
|
new TypeToken<ArrayList<String>>() {}.getType());
|
||||||
if (uris != null) {
|
if (uris != null) {
|
||||||
for (String uriString : uris) {
|
for (String uriString : uris) {
|
||||||
|
|
|
@ -265,7 +265,6 @@
|
||||||
<string name="compose_active_account_description">النشر بواسطة حساب %1$s</string>
|
<string name="compose_active_account_description">النشر بواسطة حساب %1$s</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">تعذرت عملية إضافة الشرح</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_set_caption">إضافة شرح</string>
|
||||||
<string name="action_remove_media">حذف</string>
|
<string name="action_remove_media">حذف</string>
|
||||||
<string name="lock_account_label">تجميد الحساب</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="compose_active_account_description">Yn postio â chyfrif %1$s</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">Methu gosod pennawd</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_set_caption">Pennu pennawd</string>
|
||||||
<string name="action_remove_media">Dileu</string>
|
<string name="action_remove_media">Dileu</string>
|
||||||
<string name="lock_account_label">Cloi cyfrif</string>
|
<string name="lock_account_label">Cloi cyfrif</string>
|
||||||
|
|
|
@ -249,7 +249,6 @@
|
||||||
<string name="title_lists">Listen</string>
|
<string name="title_lists">Listen</string>
|
||||||
<string name="title_list_timeline">Liste</string>
|
<string name="title_list_timeline">Liste</string>
|
||||||
<string name="action_remove_media">entfernen</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="action_set_caption">Beschreibung eingeben</string>
|
||||||
<string name="error_failed_set_caption">Fehler beim Speichern der Beschreibung</string>
|
<string name="error_failed_set_caption">Fehler beim Speichern der Beschreibung</string>
|
||||||
<string name="add_account_name">Konto hinzufügen</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="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="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_set_caption">Añadir leyenda</string>
|
||||||
<string name="action_remove_media">Eliminar</string>
|
<string name="action_remove_media">Eliminar</string>
|
||||||
<string name="lock_account_label">Proteger cuenta</string>
|
<string name="lock_account_label">Proteger cuenta</string>
|
||||||
|
|
|
@ -305,7 +305,6 @@
|
||||||
<string name="compose_active_account_description" >پست با حساب %1$s</string>
|
<string name="compose_active_account_description" >پست با حساب %1$s</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption" >ناتوان در تنظیم عنوان</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_set_caption" >تنظیم عنوان</string>
|
||||||
<string name="action_remove_media" >حذف</string>
|
<string name="action_remove_media" >حذف</string>
|
||||||
<string name="lock_account_label" >قفل حساب</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="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="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_set_caption">Mettre une légende</string>
|
||||||
<string name="action_remove_media">Supprimer le média</string>
|
<string name="action_remove_media">Supprimer le média</string>
|
||||||
<string name="lock_account_label">Verrouiller le compte</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="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="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_set_caption">Inserisci sottotitolo</string>
|
||||||
<string name="action_remove_media">Rimuovi</string>
|
<string name="action_remove_media">Rimuovi</string>
|
||||||
<string name="lock_account_label">Blocca account</string>
|
<string name="lock_account_label">Blocca account</string>
|
||||||
|
|
|
@ -291,7 +291,6 @@
|
||||||
<string name="title_list_timeline">リストタイムライン</string>
|
<string name="title_list_timeline">リストタイムライン</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">説明の設定に失敗しました</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_set_caption">説明を設定</string>
|
||||||
<string name="action_remove_media">消去</string>
|
<string name="action_remove_media">消去</string>
|
||||||
<string name="lock_account_label">アカウントをロック</string>
|
<string name="lock_account_label">アカウントをロック</string>
|
||||||
|
|
|
@ -264,7 +264,6 @@
|
||||||
<string name="compose_active_account_description">다음 계정으로 작성 중: %1$s</string>
|
<string name="compose_active_account_description">다음 계정으로 작성 중: %1$s</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">캡션 설정 실패</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_set_caption">설명 쓰기</string>
|
||||||
<string name="action_remove_media">삭제</string>
|
<string name="action_remove_media">삭제</string>
|
||||||
<string name="lock_account_label">계정 잠금</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="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="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_set_caption">Beschrijving toevoegen</string>
|
||||||
<string name="action_remove_media">Verwijderen</string>
|
<string name="action_remove_media">Verwijderen</string>
|
||||||
<string name="lock_account_label">Account besloten maken</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="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="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_set_caption">Apondre una legenda</string>
|
||||||
<string name="action_remove_media">Levar</string>
|
<string name="action_remove_media">Levar</string>
|
||||||
<string name="lock_account_label">Clavar lo compte</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="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="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_set_caption">Ustaw podpis</string>
|
||||||
<string name="action_remove_media">Usuń</string>
|
<string name="action_remove_media">Usuń</string>
|
||||||
<string name="lock_account_label">Zablokuj konto</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="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="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_set_caption">Escrever descrição</string>
|
||||||
<string name="action_remove_media">Remover</string>
|
<string name="action_remove_media">Remover</string>
|
||||||
<string name="lock_account_label">Trancar conta</string>
|
<string name="lock_account_label">Trancar conta</string>
|
||||||
|
|
|
@ -285,7 +285,6 @@
|
||||||
<string name="compose_active_account_description">Отправка от имени %1$s</string>
|
<string name="compose_active_account_description">Отправка от имени %1$s</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">Не удалось добавить подпись</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_set_caption">Добавить подпись</string>
|
||||||
<string name="action_remove_media">Удалить</string>
|
<string name="action_remove_media">Удалить</string>
|
||||||
<string name="lock_account_label">Закрыть аккаунт</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="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="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_set_caption">Ange bildtext</string>
|
||||||
<string name="action_remove_media">Ta bort</string>
|
<string name="action_remove_media">Ta bort</string>
|
||||||
<string name="lock_account_label">Lås konto</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="compose_active_account_description">%1$s கணக்குடன் பதிவிட</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">தலைப்பை அமைக்க முடியவில்லை</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_set_caption">தலைப்பை அமை</string>
|
||||||
<string name="action_remove_media">நீக்கு</string>
|
<string name="action_remove_media">நீக்கு</string>
|
||||||
<string name="lock_account_label">கணக்கை முடக்கு</string>
|
<string name="lock_account_label">கணக்கை முடக்கு</string>
|
||||||
|
|
|
@ -275,7 +275,6 @@
|
||||||
<string name="compose_active_account_description">使用帐号 %1$s 发布嘟文</string>
|
<string name="compose_active_account_description">使用帐号 %1$s 发布嘟文</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">设置图片标题失败。</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_set_caption">设置图片标题</string>
|
||||||
<string name="action_remove_media">移除</string>
|
<string name="action_remove_media">移除</string>
|
||||||
<string name="lock_account_label">保护你的帐户(锁嘟)</string>
|
<string name="lock_account_label">保护你的帐户(锁嘟)</string>
|
||||||
|
|
|
@ -275,7 +275,6 @@
|
||||||
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">設置圖片標題失敗。</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_set_caption">設置圖片標題</string>
|
||||||
<string name="action_remove_media">移除</string>
|
<string name="action_remove_media">移除</string>
|
||||||
<string name="lock_account_label">保護你的帳户(鎖嘟)</string>
|
<string name="lock_account_label">保護你的帳户(鎖嘟)</string>
|
||||||
|
|
|
@ -275,7 +275,6 @@
|
||||||
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">設置圖片標題失敗。</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_set_caption">設置圖片標題</string>
|
||||||
<string name="action_remove_media">移除</string>
|
<string name="action_remove_media">移除</string>
|
||||||
<string name="lock_account_label">保護你的帳户(鎖嘟)</string>
|
<string name="lock_account_label">保護你的帳户(鎖嘟)</string>
|
||||||
|
|
|
@ -275,7 +275,6 @@
|
||||||
<string name="compose_active_account_description">使用帐号 %1$s 发布嘟文</string>
|
<string name="compose_active_account_description">使用帐号 %1$s 发布嘟文</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">设置图片标题失败。</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_set_caption">设置图片标题</string>
|
||||||
<string name="action_remove_media">移除</string>
|
<string name="action_remove_media">移除</string>
|
||||||
<string name="lock_account_label">保护你的帐户(锁嘟)</string>
|
<string name="lock_account_label">保护你的帐户(锁嘟)</string>
|
||||||
|
|
|
@ -275,7 +275,6 @@
|
||||||
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
<string name="compose_active_account_description">使用帳號 %1$s 發佈嘟文</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">設置圖片標題失敗。</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_set_caption">設置圖片標題</string>
|
||||||
<string name="action_remove_media">移除</string>
|
<string name="action_remove_media">移除</string>
|
||||||
<string name="lock_account_label">保護你的帳戶(鎖嘟)</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="compose_active_account_description">Posting with account %1$s</string>
|
||||||
|
|
||||||
<string name="error_failed_set_caption">Failed to set caption</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_set_caption">Set caption</string>
|
||||||
<string name="action_remove_media">Remove</string>
|
<string name="action_remove_media">Remove</string>
|
||||||
<string name="lock_account_label">Lock account</string>
|
<string name="lock_account_label">Lock account</string>
|
||||||
|
|
Loading…
Reference in a new issue