Commit f9f5fdb2 authored by Gilbert Gilb's's avatar Gilbert Gilb's

Add an option to delay sending messages.

parent d2809692
......@@ -32,72 +32,98 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout android:id="@+id/bottom_panel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:clickable="true"
android:background="?android:windowBackground"
android:padding="5dp">
<LinearLayout android:id="@+id/compose_bubble"
android:layout_width="0dp"
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
>
<LinearLayout android:id="@+id/bottom_panel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/sent_bubble">
<org.smssecure.smssecure.components.emoji.EmojiToggle
android:id="@+id/emoji_toggle"
android:layout_width="37dp"
android:layout_height="37dp"
android:layout_gravity="bottom"
android:background="@drawable/touch_highlight_background"
android:contentDescription="@string/conversation_activity__emoji_toggle_description" />
<org.smssecure.smssecure.components.ComposeText
style="@style/ComposeEditText"
android:id="@+id/embedded_text_editor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:minHeight="37dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:nextFocusForward="@+id/send_button"
android:nextFocusRight="@+id/send_button"
tools:hint="Send Silence message">
<requestFocus />
</org.smssecure.smssecure.components.ComposeText>
</LinearLayout>
<org.smssecure.smssecure.components.AnimatingToggle
android:id="@+id/button_toggle"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/circle_tintable"
android:layout_gravity="bottom">
<ImageButton android:id="@+id/attach_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@drawable/circle_touch_highlight_background"
android:src="@drawable/ic_attach_white_24dp"
android:contentDescription="@string/ConversationActivity_add_attachment"
android:nextFocusLeft="@+id/embedded_text_editor" />
<org.smssecure.smssecure.components.SendButton
android:id="@+id/send_button"
android:gravity="center_vertical"
android:orientation="horizontal"
android:clickable="true"
android:background="?android:windowBackground"
android:padding="5dp">
<LinearLayout android:id="@+id/compose_bubble"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/sent_bubble">
<org.smssecure.smssecure.components.emoji.EmojiToggle
android:id="@+id/emoji_toggle"
android:layout_width="37dp"
android:layout_height="37dp"
android:layout_gravity="bottom"
android:background="@drawable/touch_highlight_background"
android:contentDescription="@string/conversation_activity__emoji_toggle_description" />
<org.smssecure.smssecure.components.ComposeText
style="@style/ComposeEditText"
android:id="@+id/embedded_text_editor"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:minHeight="37dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:nextFocusForward="@+id/send_button"
android:nextFocusRight="@+id/send_button"
tools:hint="Send Silence message">
<requestFocus />
</org.smssecure.smssecure.components.ComposeText>
</LinearLayout>
<org.smssecure.smssecure.components.AnimatingToggle
android:id="@+id/button_toggle"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="@drawable/circle_tintable"
android:layout_gravity="bottom">
<ImageButton android:id="@+id/attach_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@drawable/circle_touch_highlight_background"
android:src="@drawable/ic_attach_white_24dp"
android:contentDescription="@string/ConversationActivity_add_attachment"
android:nextFocusLeft="@+id/embedded_text_editor" />
<org.smssecure.smssecure.components.SendButton
android:id="@+id/send_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/conversation_activity__send"
android:nextFocusLeft="@+id/embedded_text_editor"
android:background="@drawable/circle_touch_highlight_background" />
<ImageButton android:id="@+id/cancel_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/conversation_activity__send"
android:nextFocusLeft="@+id/embedded_text_editor"
android:background="@drawable/circle_touch_highlight_background" />
</org.smssecure.smssecure.components.AnimatingToggle>
android:layout_gravity="center"
android:background="@drawable/circle_touch_highlight_background"
android:src="@drawable/ic_clear_white_24dp"
android:contentDescription="@string/ConversationActivity_cancel"
android:nextFocusLeft="@+id/embedded_text_editor" />
</LinearLayout>
</org.smssecure.smssecure.components.AnimatingToggle>
</LinearLayout>
<ProgressBar
android:id="@+id/cancel_message_progress_bar"
android:layout_alignTop="@+id/bottom_panel"
android:background="@color/transparent"
android:progressBackgroundTint="@color/transparent"
android:progressTint="@color/blue"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:progress="0"
android:visibility="invisible"
/>
</RelativeLayout>
<Button android:id="@+id/unblock_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
......
......@@ -93,6 +93,7 @@
<string name="ConversationActivity_delete_thread_question">Delete conversation?</string>
<string name="ConversationActivity_this_will_permanently_delete_all_messages_in_this_conversation">This will permanently delete all messages in this conversation.</string>
<string name="ConversationActivity_add_attachment">Add attachment</string>
<string name="ConversationActivity_cancel">Cancel pending message</string>
<string name="ConversationActivity_select_contact_info">Select contact info</string>
<string name="ConversationActivity_compose_message">Compose message</string>
<string name="ConversationActivity_sorry_there_was_an_error_adding_your_attachment">Sorry, there was an error adding your attachment.</string>
......@@ -729,6 +730,8 @@
<string name="preferences__submit_debug_log">Submit debug log</string>
<string name="preferences__support_wifi_calling">\'Wi-Fi Calling\' compatibility mode</string>
<string name="preferences__enable_if_your_device_supports_sms_mms_delivery_over_wifi">Enable if your device uses SMS/MMS delivery over Wi-Fi (only enable when \'Wi-Fi Calling\' is enabled on your device).</string>
<string name="preferences__sending_delay">Sending delay</string>
<string name="preferences__give_some_time_to_cancel_a_message">Give some time to cancel a message</string>
<string name="preferences__about">About Silence</string>
<string name="preferences__about_version">Version %s</string>
<string name="preferences__privacy_policy">Privacy policy</string>
......
......@@ -41,6 +41,12 @@
android:title="@string/preferences__support_wifi_calling"
android:summary="@string/preferences__enable_if_your_device_supports_sms_mms_delivery_over_wifi"/>
<EditTextPreference android:defaultValue="0"
android:key="pref_sending_delay"
android:title="@string/preferences__sending_delay"
android:summary="@string/preferences__give_some_time_to_cancel_a_message"/>
android:inputType="number" />
<Preference android:key="pref_mms_preferences"
android:title="@string/preferences__advanced_mms_access_point_names"/>
......
......@@ -56,6 +56,7 @@ import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
......@@ -168,6 +169,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private AnimatingToggle buttonToggle;
private SendButton sendButton;
private ImageButton attachButton;
private ImageButton cancelButton;
private ProgressBar cancelProgressBar;
protected ConversationTitleView titleView;
private TextView charactersLeft;
private ConversationFragment fragment;
......@@ -176,11 +179,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private View composePanel;
private View composeBubble;
private AttachmentTypeSelectorAdapter attachmentAdapter;
private AttachmentManager attachmentManager;
private BroadcastReceiver securityUpdateReceiver;
private Stub<EmojiDrawer> emojiDrawerStub;
private EmojiToggle emojiToggle;
private AttachmentTypeSelectorAdapter attachmentAdapter;
private AttachmentManager attachmentManager;
private BroadcastReceiver securityUpdateReceiver;
private Stub<EmojiDrawer> emojiDrawerStub;
private EmojiToggle emojiToggle;
private AsyncTask<Void, Integer, Void> deferredMessageTask = null;
private Recipients recipients;
private long threadId;
......@@ -276,6 +280,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
AudioSlidePlayer.stopAll();
}
@Override
protected void onStop() {
super.onStop();
if (cancelDeferredMessage()) {
sendMessage();
}
}
@Override public void onConfigurationChanged(Configuration newConfig) {
Log.w(TAG, "onConfigurationChanged(" + newConfig.orientation + ")");
super.onConfigurationChanged(newConfig);
......@@ -681,6 +693,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
}
private boolean cancelDeferredMessage() {
return deferredMessageTask != null && deferredMessageTask.cancel(false);
}
private void handleAddAttachment() {
if (this.isMmsEnabled) {
new AlertDialog.Builder(this).setAdapter(attachmentAdapter, new AttachmentTypeListener())
......@@ -807,18 +823,20 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void initializeViews() {
titleView = (ConversationTitleView) getSupportActionBar().getCustomView();
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
sendButton = ViewUtil.findById(this, R.id.send_button);
attachButton = ViewUtil.findById(this, R.id.attach_button);
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
charactersLeft = ViewUtil.findById(this, R.id.space_left);
emojiToggle = ViewUtil.findById(this, R.id.emoji_toggle);
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
unblockButton = ViewUtil.findById(this, R.id.unblock_button);
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
composeBubble = ViewUtil.findById(this, R.id.compose_bubble);
container = ViewUtil.findById(this, R.id.layout_container);
titleView = (ConversationTitleView) getSupportActionBar().getCustomView();
buttonToggle = ViewUtil.findById(this, R.id.button_toggle);
sendButton = ViewUtil.findById(this, R.id.send_button);
attachButton = ViewUtil.findById(this, R.id.attach_button);
cancelButton = ViewUtil.findById(this, R.id.cancel_button);
cancelProgressBar = ViewUtil.findById(this, R.id.cancel_message_progress_bar);
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
charactersLeft = ViewUtil.findById(this, R.id.space_left);
emojiToggle = ViewUtil.findById(this, R.id.emoji_toggle);
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
unblockButton = ViewUtil.findById(this, R.id.unblock_button);
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
composeBubble = ViewUtil.findById(this, R.id.compose_bubble);
container = ViewUtil.findById(this, R.id.layout_container);
if (SilencePreferences.isEmojiDrawerDisabled(this))
emojiToggle.setVisibility(View.GONE);
......@@ -853,6 +871,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText.setOnEditorActionListener(sendButtonListener);
attachButton.setOnClickListener(new AttachButtonListener());
attachButton.setOnLongClickListener(new AttachButtonLongClickListener());
cancelButton.setOnClickListener(new CancelButtonListener());
sendButton.setOnClickListener(sendButtonListener);
sendButton.setEnabled(true);
sendButton.addOnTransportChangedListener(new OnTransportChangedListener() {
......@@ -1273,6 +1292,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void updateToggleButtonState() {
if (composeText.getText().length() == 0 && !attachmentManager.isAttachmentPresent()) {
buttonToggle.display(attachButton);
} else if (deferredMessageTask != null) {
buttonToggle.display(cancelButton);
} else {
buttonToggle.display(sendButton);
}
......@@ -1326,7 +1347,67 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private class SendButtonListener implements OnClickListener, TextView.OnEditorActionListener {
@Override
public void onClick(View v) {
sendMessage();
final int delay = SilencePreferences.getSendingDelay(ConversationActivity.this) * 1000;
if (delay <= 0) {
sendMessage();
return;
}
deferredMessageTask = new AsyncTask<Void, Integer, Void>() {
@Override
protected void onPreExecute() {
cancelProgressBar.setProgress(0);
cancelProgressBar.setVisibility(View.VISIBLE);
composeText.setEnabled(false);
updateToggleButtonState();
}
@Override
protected Void doInBackground(Void... params) {
publishProgress(0);
long begin = System.currentTimeMillis();
long end = begin + delay;
long now = begin;
while (now < end) {
publishProgress((int)(100 * (float)(now - begin) / (end - begin)));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
break;
}
if (isCancelled()) break;
now = System.currentTimeMillis();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
cancelProgressBar.setProgress(progress[0]);
}
private void cleanup() {
deferredMessageTask = null;
cancelProgressBar.setVisibility(View.INVISIBLE);
cancelProgressBar.setProgress(0);
composeText.setEnabled(true);
}
@Override
protected void onCancelled(Void result) {
cleanup();
updateToggleButtonState();
}
@Override
protected void onPostExecute(Void result) {
cleanup();
sendMessage();
updateToggleButtonState();
}
};
deferredMessageTask.execute();
}
@Override
......@@ -1339,6 +1420,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
}
private class CancelButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
cancelDeferredMessage();
}
}
private class AttachButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
......
......@@ -127,6 +127,7 @@ public class ComposeText extends EmojiEditText {
@Override
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
InputConnection inputConnection = super.onCreateInputConnection(editorInfo);
if (inputConnection == null) return null;
if (SilencePreferences.getEnterKeyType(getContext()).equals("send")) {
editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
......
......@@ -82,6 +82,7 @@ public class SilencePreferences {
private static final String FALLBACK_MMS_ENABLED_PREF = "pref_mms_fallback_enabled";
private static final String SIGNED_PREKEY_REGISTERED_PREF = "pref_signed_prekey_registered";
private static final String WIFI_SMS_PREF = "pref_wifi_sms";
private static final String SENDING_DELAY = "pref_sending_delay";
private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
......@@ -127,6 +128,10 @@ public class SilencePreferences {
return getBooleanPreference(context, WIFI_SMS_PREF, false);
}
public static int getSendingDelay(Context context) {
return Integer.parseInt(getStringPreference(context, SENDING_DELAY, "0"));
}
public static int getRepeatAlertsCount(Context context) {
try {
return Integer.parseInt(getStringPreference(context, REPEAT_ALERTS_PREF, "0"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment