support 'Save to downloads' action for attachments
This commit is contained in:
parent
f9027fa085
commit
9467fc1789
|
@ -664,6 +664,56 @@ public class FileBackend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyAttachmentToDownloadsFolder(Message m) throws FileCopyException {
|
||||||
|
File input = mXmppConnectionService.getFileBackend().getFile(m);
|
||||||
|
|
||||||
|
File parentDirectory =
|
||||||
|
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||||
|
File output = new File(parentDirectory, input.getName());
|
||||||
|
int counter = 1;
|
||||||
|
while (output.exists()) {
|
||||||
|
output = new File(parentDirectory, "(" + counter + ") " + input.getName());
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
output.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new FileCopyException(R.string.error_unable_to_create_temporary_file);
|
||||||
|
}
|
||||||
|
try (final OutputStream os = new FileOutputStream(output);
|
||||||
|
final InputStream is =
|
||||||
|
mXmppConnectionService.getContentResolver().openInputStream(Uri.fromFile(input))) {
|
||||||
|
if (is == null) {
|
||||||
|
throw new FileCopyException(R.string.error_file_not_found);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
ByteStreams.copy(is, os);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new FileWriterException(output);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
os.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new FileWriterException(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMediaScanner(output);
|
||||||
|
} catch (final FileNotFoundException e) {
|
||||||
|
cleanup(output);
|
||||||
|
throw new FileCopyException(R.string.error_file_not_found);
|
||||||
|
} catch (final FileWriterException e) {
|
||||||
|
cleanup(output);
|
||||||
|
throw new FileCopyException(R.string.error_unable_to_create_temporary_file);
|
||||||
|
} catch (final SecurityException | IllegalStateException e) {
|
||||||
|
cleanup(output);
|
||||||
|
throw new FileCopyException(R.string.error_security_exception);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
cleanup(output);
|
||||||
|
throw new FileCopyException(R.string.error_io_exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void copyFileToPrivateStorage(File file, Uri uri) throws FileCopyException {
|
private void copyFileToPrivateStorage(File file, Uri uri) throws FileCopyException {
|
||||||
Log.d(
|
Log.d(
|
||||||
Config.LOGTAG,
|
Config.LOGTAG,
|
||||||
|
|
|
@ -212,7 +212,7 @@ public class XmppConnectionService extends Service {
|
||||||
public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1);
|
public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1);
|
||||||
private final static Executor FILE_OBSERVER_EXECUTOR = Executors.newSingleThreadExecutor();
|
private final static Executor FILE_OBSERVER_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||||
private final static Executor FILE_ATTACHMENT_EXECUTOR = Executors.newSingleThreadExecutor();
|
private final static Executor FILE_ATTACHMENT_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||||
|
private final static Executor COPY_TO_DOWNLOAD_EXECUTOR = Executors.newSingleThreadExecutor();
|
||||||
private final ScheduledExecutorService internalPingExecutor = Executors.newSingleThreadScheduledExecutor();
|
private final ScheduledExecutorService internalPingExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
private final static SerialSingleThreadExecutor VIDEO_COMPRESSION_EXECUTOR = new SerialSingleThreadExecutor("VideoCompression");
|
private final static SerialSingleThreadExecutor VIDEO_COMPRESSION_EXECUTOR = new SerialSingleThreadExecutor("VideoCompression");
|
||||||
private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter");
|
private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter");
|
||||||
|
@ -540,6 +540,17 @@ public class XmppConnectionService extends Service {
|
||||||
return this.restoredFromDatabaseLatch.getCount() == 0;
|
return this.restoredFromDatabaseLatch.getCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void copyAttachmentToDownloadsFolder(Message m, final UiCallback<Integer> callback) {
|
||||||
|
COPY_TO_DOWNLOAD_EXECUTOR.execute(() -> {
|
||||||
|
try {
|
||||||
|
fileBackend.copyAttachmentToDownloadsFolder(m);
|
||||||
|
callback.success(-1);
|
||||||
|
} catch (FileBackend.FileCopyException e) {
|
||||||
|
callback.error(-1, e.getResId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public PgpEngine getPgpEngine() {
|
public PgpEngine getPgpEngine() {
|
||||||
if (!Config.supportOpenPgp()) {
|
if (!Config.supportOpenPgp()) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -18,6 +18,8 @@ import android.app.FragmentManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -28,6 +30,7 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.VibrationEffect;
|
import android.os.VibrationEffect;
|
||||||
|
@ -40,7 +43,6 @@ import android.text.TextUtils;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.util.Range;
|
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.ContextMenu;
|
import android.view.ContextMenu;
|
||||||
import android.view.ContextMenu.ContextMenuInfo;
|
import android.view.ContextMenu.ContextMenuInfo;
|
||||||
|
@ -53,8 +55,6 @@ import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.CycleInterpolator;
|
|
||||||
import android.view.ViewParent;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.AbsListView;
|
import android.widget.AbsListView;
|
||||||
|
@ -64,7 +64,6 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.TextView.OnEditorActionListener;
|
import android.widget.TextView.OnEditorActionListener;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -77,8 +76,6 @@ import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.core.view.inputmethod.InputConnectionCompat;
|
import androidx.core.view.inputmethod.InputConnectionCompat;
|
||||||
import androidx.core.view.inputmethod.InputContentInfoCompat;
|
import androidx.core.view.inputmethod.InputContentInfoCompat;
|
||||||
import androidx.databinding.DataBindingUtil;
|
import androidx.databinding.DataBindingUtil;
|
||||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.viewpager.widget.PagerAdapter;
|
import androidx.viewpager.widget.PagerAdapter;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -86,19 +83,18 @@ import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
import java.util.AbstractMap;
|
import java.util.AbstractMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
@ -150,7 +146,6 @@ import eu.siacs.conversations.ui.widget.HighlighterView;
|
||||||
import eu.siacs.conversations.ui.widget.TabLayout;
|
import eu.siacs.conversations.ui.widget.TabLayout;
|
||||||
import eu.siacs.conversations.utils.AccountUtils;
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
import eu.siacs.conversations.utils.Compatibility;
|
import eu.siacs.conversations.utils.Compatibility;
|
||||||
import eu.siacs.conversations.utils.Emoticons;
|
|
||||||
import eu.siacs.conversations.utils.GeoHelper;
|
import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.MessageUtils;
|
import eu.siacs.conversations.utils.MessageUtils;
|
||||||
import eu.siacs.conversations.utils.NickValidityChecker;
|
import eu.siacs.conversations.utils.NickValidityChecker;
|
||||||
|
@ -172,19 +167,6 @@ import eu.siacs.conversations.xmpp.jingle.OngoingRtpSession;
|
||||||
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
import eu.siacs.conversations.xmpp.jingle.RtpCapability;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
public class ConversationFragment extends XmppFragment
|
public class ConversationFragment extends XmppFragment
|
||||||
implements EditMessage.KeyboardListener,
|
implements EditMessage.KeyboardListener,
|
||||||
MessageAdapter.OnContactPictureLongClicked,
|
MessageAdapter.OnContactPictureLongClicked,
|
||||||
|
@ -1729,6 +1711,7 @@ public class ConversationFragment extends XmppFragment
|
||||||
MenuItem shareWith = menu.findItem(R.id.share_with);
|
MenuItem shareWith = menu.findItem(R.id.share_with);
|
||||||
MenuItem sendAgain = menu.findItem(R.id.send_again);
|
MenuItem sendAgain = menu.findItem(R.id.send_again);
|
||||||
MenuItem copyUrl = menu.findItem(R.id.copy_url);
|
MenuItem copyUrl = menu.findItem(R.id.copy_url);
|
||||||
|
MenuItem saveToDownloads = menu.findItem(R.id.save_to_downloads);
|
||||||
MenuItem downloadFile = menu.findItem(R.id.download_file);
|
MenuItem downloadFile = menu.findItem(R.id.download_file);
|
||||||
MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
|
MenuItem cancelTransmission = menu.findItem(R.id.cancel_transmission);
|
||||||
MenuItem deleteFile = menu.findItem(R.id.delete_file);
|
MenuItem deleteFile = menu.findItem(R.id.delete_file);
|
||||||
|
@ -1792,6 +1775,7 @@ public class ConversationFragment extends XmppFragment
|
||||||
|| t instanceof HttpDownloadConnection) {
|
|| t instanceof HttpDownloadConnection) {
|
||||||
copyUrl.setVisible(true);
|
copyUrl.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.isFileOrImage() && deleted && m.hasFileOnRemoteHost()) {
|
if (m.isFileOrImage() && deleted && m.hasFileOnRemoteHost()) {
|
||||||
downloadFile.setVisible(true);
|
downloadFile.setVisible(true);
|
||||||
downloadFile.setTitle(
|
downloadFile.setTitle(
|
||||||
|
@ -1814,10 +1798,14 @@ public class ConversationFragment extends XmppFragment
|
||||||
|| !path.startsWith("/")
|
|| !path.startsWith("/")
|
||||||
|| FileBackend.inConversationsDirectory(requireActivity(), path)) {
|
|| FileBackend.inConversationsDirectory(requireActivity(), path)) {
|
||||||
deleteFile.setVisible(true);
|
deleteFile.setVisible(true);
|
||||||
|
|
||||||
|
String fileDescriptorString = UIHelper.getFileDescriptionString(activity, m);
|
||||||
deleteFile.setTitle(
|
deleteFile.setTitle(
|
||||||
activity.getString(
|
activity.getString(
|
||||||
R.string.delete_x_file,
|
R.string.delete_x_file,
|
||||||
UIHelper.getFileDescriptionString(activity, m)));
|
fileDescriptorString));
|
||||||
|
|
||||||
|
saveToDownloads.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (showError) {
|
if (showError) {
|
||||||
|
@ -1869,6 +1857,9 @@ public class ConversationFragment extends XmppFragment
|
||||||
case R.id.delete_file:
|
case R.id.delete_file:
|
||||||
deleteFile(selectedMessage);
|
deleteFile(selectedMessage);
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.save_to_downloads:
|
||||||
|
saveToDownloads(selectedMessage);
|
||||||
|
return true;
|
||||||
case R.id.show_error_message:
|
case R.id.show_error_message:
|
||||||
showErrorMessage(selectedMessage);
|
showErrorMessage(selectedMessage);
|
||||||
return true;
|
return true;
|
||||||
|
@ -2635,6 +2626,24 @@ public class ConversationFragment extends XmppFragment
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveToDownloads(final Message message) {
|
||||||
|
activity.xmppConnectionService.copyAttachmentToDownloadsFolder(message, new UiCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void success(Integer object) {
|
||||||
|
runOnUiThread(() -> Toast.makeText(activity, R.string.save_to_downloads_success, Toast.LENGTH_LONG).show());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(int errorCode, Integer object) {
|
||||||
|
runOnUiThread(() -> Toast.makeText(activity, object, Toast.LENGTH_LONG).show());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void userInputRequired(PendingIntent pi, Integer object) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void resendMessage(final Message message) {
|
private void resendMessage(final Message message) {
|
||||||
if (message.isFileOrImage()) {
|
if (message.isFileOrImage()) {
|
||||||
if (!(message.getConversation() instanceof Conversation)) {
|
if (!(message.getConversation() instanceof Conversation)) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
@ -41,6 +42,7 @@ import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.databinding.DataBindingUtil;
|
import androidx.databinding.DataBindingUtil;
|
||||||
|
|
||||||
|
@ -56,6 +58,7 @@ import eu.siacs.conversations.entities.Contact;
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.entities.Conversational;
|
import eu.siacs.conversations.entities.Conversational;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.services.MessageSearchTask;
|
import eu.siacs.conversations.services.MessageSearchTask;
|
||||||
import eu.siacs.conversations.ui.adapter.MessageAdapter;
|
import eu.siacs.conversations.ui.adapter.MessageAdapter;
|
||||||
import eu.siacs.conversations.ui.interfaces.OnSearchResultsAvailable;
|
import eu.siacs.conversations.ui.interfaces.OnSearchResultsAvailable;
|
||||||
|
@ -67,6 +70,7 @@ import eu.siacs.conversations.ui.util.ShareUtil;
|
||||||
import eu.siacs.conversations.ui.util.StyledAttributes;
|
import eu.siacs.conversations.ui.util.StyledAttributes;
|
||||||
import eu.siacs.conversations.utils.FtsUtils;
|
import eu.siacs.conversations.utils.FtsUtils;
|
||||||
import eu.siacs.conversations.utils.MessageUtils;
|
import eu.siacs.conversations.utils.MessageUtils;
|
||||||
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
|
|
||||||
import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.hideSoftKeyboard;
|
import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.hideSoftKeyboard;
|
||||||
import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.showKeyboard;
|
import static eu.siacs.conversations.ui.util.SoftKeyboardUtils.showKeyboard;
|
||||||
|
@ -140,6 +144,26 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
|
||||||
MenuItem copy = menu.findItem(R.id.copy_message);
|
MenuItem copy = menu.findItem(R.id.copy_message);
|
||||||
MenuItem quote = menu.findItem(R.id.quote_message);
|
MenuItem quote = menu.findItem(R.id.quote_message);
|
||||||
MenuItem copyUrl = menu.findItem(R.id.copy_url);
|
MenuItem copyUrl = menu.findItem(R.id.copy_url);
|
||||||
|
MenuItem saveToDownloads = menu.findItem(R.id.save_to_downloads);
|
||||||
|
|
||||||
|
|
||||||
|
final boolean deleted = message.isDeleted();
|
||||||
|
final boolean waitingOfferedSending =
|
||||||
|
message.getStatus() == Message.STATUS_WAITING
|
||||||
|
|| message.getStatus() == Message.STATUS_UNSEND
|
||||||
|
|| message.getStatus() == Message.STATUS_OFFERED;
|
||||||
|
final boolean cancelable =
|
||||||
|
(message.getTransferable() != null && !deleted) || waitingOfferedSending && message.needsUploading();
|
||||||
|
|
||||||
|
if (message.isFileOrImage() && !deleted && !cancelable) {
|
||||||
|
final String path = message.getRelativeFilePath();
|
||||||
|
if (path == null
|
||||||
|
|| !path.startsWith("/")
|
||||||
|
|| FileBackend.inConversationsDirectory(this, path)) {
|
||||||
|
saveToDownloads.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (message.isGeoUri()) {
|
if (message.isGeoUri()) {
|
||||||
copy.setVisible(false);
|
copy.setVisible(false);
|
||||||
quote.setVisible(false);
|
quote.setVisible(false);
|
||||||
|
@ -171,6 +195,23 @@ public class SearchActivity extends XmppActivity implements TextWatcher, OnSearc
|
||||||
case R.id.copy_message:
|
case R.id.copy_message:
|
||||||
ShareUtil.copyToClipboard(this, message);
|
ShareUtil.copyToClipboard(this, message);
|
||||||
break;
|
break;
|
||||||
|
case R.id.save_to_downloads:
|
||||||
|
xmppConnectionService.copyAttachmentToDownloadsFolder(message, new UiCallback<>() {
|
||||||
|
@Override
|
||||||
|
public void success(Integer object) {
|
||||||
|
runOnUiThread(() -> Toast.makeText(SearchActivity.this, R.string.save_to_downloads_success, Toast.LENGTH_LONG).show());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void error(int errorCode, Integer object) {
|
||||||
|
runOnUiThread(() -> Toast.makeText(SearchActivity.this, object, Toast.LENGTH_LONG).show());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void userInputRequired(PendingIntent pi, Integer object) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
case R.id.copy_url:
|
case R.id.copy_url:
|
||||||
ShareUtil.copyUrlToClipboard(this, message);
|
ShareUtil.copyUrlToClipboard(this, message);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -42,6 +42,12 @@
|
||||||
android:id="@+id/copy_url"
|
android:id="@+id/copy_url"
|
||||||
android:title="@string/copy_original_url"
|
android:title="@string/copy_original_url"
|
||||||
android:visible="false" />
|
android:visible="false" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/save_to_downloads"
|
||||||
|
android:title="@string/save_to_downloads"
|
||||||
|
android:visible="false" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/show_error_message"
|
android:id="@+id/show_error_message"
|
||||||
android:title="@string/show_error_message"
|
android:title="@string/show_error_message"
|
||||||
|
|
|
@ -46,4 +46,9 @@
|
||||||
<item
|
<item
|
||||||
android:id="@+id/copy_url"
|
android:id="@+id/copy_url"
|
||||||
android:title="@string/copy_original_url"/>
|
android:title="@string/copy_original_url"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/save_to_downloads"
|
||||||
|
android:title="@string/save_to_downloads"
|
||||||
|
android:visible="false" />
|
||||||
</menu>
|
</menu>
|
|
@ -315,6 +315,8 @@
|
||||||
<string name="quote">Quote</string>
|
<string name="quote">Quote</string>
|
||||||
<string name="paste_as_quote">Paste as quote</string>
|
<string name="paste_as_quote">Paste as quote</string>
|
||||||
<string name="copy_original_url">Copy original URL</string>
|
<string name="copy_original_url">Copy original URL</string>
|
||||||
|
<string name="save_to_downloads">Save to Downloads</string>
|
||||||
|
<string name="save_to_downloads_success">File successfully saved to Downloads folder</string>
|
||||||
<string name="send_again">Send again</string>
|
<string name="send_again">Send again</string>
|
||||||
<string name="file_url">File URL</string>
|
<string name="file_url">File URL</string>
|
||||||
<string name="url_copied_to_clipboard">Copied URL to clipboard</string>
|
<string name="url_copied_to_clipboard">Copied URL to clipboard</string>
|
||||||
|
|
Loading…
Reference in a new issue