mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-19 19:48:27 +00:00
ShareActivity, destruction of RecipientsPanel
// FREEBIE
This commit is contained in:
parent
e2f7c1529a
commit
12dac6ccc3
@ -71,7 +71,7 @@
|
||||
<data android:mimeType="image/*" />
|
||||
<data android:mimeType="text/plain" />
|
||||
<data android:mimeType="video/*" />
|
||||
</intent-filter>
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
@ -93,11 +93,18 @@
|
||||
<activity android:name=".MmsPreferencesActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name=".ConversationListActivity"
|
||||
android:label="@string/app_name"
|
||||
<activity android:name=".ShareActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleTask"
|
||||
android:noHistory="true"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name=".ConversationListActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name=".ConversationActivity"
|
||||
android:windowSoftInputMode="stateUnchanged"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
@ -126,7 +133,7 @@
|
||||
<activity android:name=".PassphrasePromptActivity"
|
||||
android:label="@string/AndroidManifest__enter_passphrase"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/NoAnimation.Theme.Sherlock.Light.DarkActionBar"
|
||||
android:theme="@style/NoAnimation.Theme.Sherlock.Light.DarkActionBar"
|
||||
android:windowSoftInputMode="stateUnchanged"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
|
13
res/drawable/share_list_divider_shape.xml
Normal file
13
res/drawable/share_list_divider_shape.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_list_item_background_read_light" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:left="73dp" android:right="10dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_list_divider_light" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
13
res/drawable/share_list_divider_shape_dark.xml
Normal file
13
res/drawable/share_list_divider_shape_dark.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_list_item_background_read_dark" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:left="73dp" android:right="10dp">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/conversation_list_divider_dark" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
@ -6,12 +6,6 @@
|
||||
android:background="?conversation_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<org.thoughtcrime.securesms.components.RecipientsPanel
|
||||
android:id="@+id/recipients"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/layout_container"
|
||||
android:layout_width="fill_parent"
|
||||
|
13
res/layout/share_activity.xml
Normal file
13
res/layout/share_activity.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<fragment android:id="@+id/fragment_content"
|
||||
android:name="org.thoughtcrime.securesms.ShareFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</LinearLayout>
|
17
res/layout/share_fragment.xml
Normal file
17
res/layout/share_fragment.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ListView android:id="@android:id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:drawSelectorOnTop="false"
|
||||
android:scrollbarStyle="insideOverlay"
|
||||
android:fadingEdgeLength="16dip"
|
||||
android:divider="?share_list_item_divider"
|
||||
android:dividerHeight="1px" />
|
||||
|
||||
</LinearLayout>
|
44
res/layout/share_list_item_view.xml
Normal file
44
res/layout/share_list_item_view.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.thoughtcrime.securesms.ShareListItem
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<org.thoughtcrime.securesms.components.ForegroundImageView
|
||||
android:id="@+id/contact_photo_image"
|
||||
android:foreground="@drawable/contact_photo_background"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginBottom="3dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:cropToPadding="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/SingleContactSelectionActivity_contact_photo" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dip"
|
||||
android:layout_marginLeft="4dip"
|
||||
android:layout_marginRight="8dip"
|
||||
android:layout_marginBottom="4dip"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@id/contact_photo_image"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/from"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="?attr/conversation_list_item_contact_color"
|
||||
android:singleLine="true"
|
||||
android:gravity="bottom"
|
||||
android:ellipsize="marquee" />
|
||||
|
||||
</LinearLayout>
|
||||
</org.thoughtcrime.securesms.ShareListItem>
|
8
res/menu/share.xml
Normal file
8
res/menu/share.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:title="@string/text_secure_normal__menu_new_message"
|
||||
android:id="@+id/menu_new_message"
|
||||
android:icon="?attr/menu_new_conversation_icon"
|
||||
android:showAsAction="always" />
|
||||
|
||||
</menu>
|
@ -9,6 +9,8 @@
|
||||
<attr name="conversation_list_item_date_color" format="reference|color"/>
|
||||
<attr name="conversation_list_item_divider" format="reference"/>
|
||||
|
||||
<attr name="share_list_item_divider" format="reference"/>
|
||||
|
||||
<attr name="conversation_sent_card_background" format="reference|color"/>
|
||||
<attr name="conversation_group_member_name" format="reference|color"/>
|
||||
<attr name="conversation_sent_text_primary_color" format="reference|color"/>
|
||||
|
@ -84,13 +84,12 @@
|
||||
<string name="ConversationActivity_sorry_the_selected_audio_exceeds_message_size_restrictions">Sorry, the selected audio exceeds message size restrictions.</string>
|
||||
<string name="ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation">Recipient is not a valid SMS or email address!</string>
|
||||
<string name="ConversationActivity_message_is_empty_exclamation">Message is empty!</string>
|
||||
<string name="ConversationActivity_forward_message_prefix">FWD</string>
|
||||
<string name="ConversationActivity_group_conversation_recipients">Group Conversation Recipients</string>
|
||||
<string name="ConversationActivity_group_conversation">Group Conversation</string>
|
||||
<string name="ConversationActivity_unnamed_group">Unnamed Group</string>
|
||||
<string name="ConversationActivity_d_recipients_in_group">%d members</string>
|
||||
<string name="ConversationActivity_d_recipients_in_group_singular">1 member</string>
|
||||
<string name="ConversationActivity_saving_draft">Saving draft...</string>
|
||||
<string name="ConversationActivity_saved_draft">Saved draft</string>
|
||||
<string name="ConversationActivity_invalid_recipient">Invalid recipient!</string>
|
||||
<string name="ConversationActivity_calls_not_supported">Calls Not Supported</string>
|
||||
<string name="ConversationActivity_this_device_does_not_appear_to_support_dial_actions">This device does not appear to support dial actions.</string>
|
||||
@ -116,6 +115,9 @@
|
||||
<!-- ConversationListItem -->
|
||||
<string name="ConversationListItem_key_exchange_message">Key exchange message...</string>
|
||||
|
||||
<!-- ShareActivity -->
|
||||
<string name="ShareActivity_share_with">Share with</string>
|
||||
|
||||
<!-- ExportFragment -->
|
||||
<string name="ExportFragment_export_to_sd_card">Export To SD Card?</string>
|
||||
<string name="ExportFragment_this_will_export_your_encrypted_keys_settings_and_messages">This
|
||||
|
@ -14,6 +14,8 @@
|
||||
<item name="conversation_list_item_date_color">#ff999999</item>
|
||||
<item name="conversation_list_item_divider">@drawable/conversation_list_divider_shape</item>
|
||||
|
||||
<item name="share_list_item_divider">@drawable/share_list_divider_shape</item>
|
||||
|
||||
<item name="actionbar_icon">@drawable/actionbar_icon_holo_light</item>
|
||||
<item name="lower_right_divet">@drawable/divet_lower_right_dark</item>
|
||||
|
||||
@ -87,6 +89,8 @@
|
||||
<item name="conversation_list_item_date_color">#ffdddddd</item>
|
||||
<item name="conversation_list_item_divider">@drawable/conversation_list_divider_shape_dark</item>
|
||||
|
||||
<item name="share_list_item_divider">@drawable/share_list_divider_shape_dark</item>
|
||||
|
||||
<item name="conversation_group_member_name">#99ffffff</item>
|
||||
<item name="conversation_sent_text_primary_color">#ffeeeeee</item>
|
||||
<item name="conversation_sent_text_secondary_color">#44eeeeee</item>
|
||||
|
@ -58,7 +58,6 @@ import com.google.protobuf.ByteString;
|
||||
|
||||
import org.thoughtcrime.securesms.components.EmojiDrawer;
|
||||
import org.thoughtcrime.securesms.components.EmojiToggle;
|
||||
import org.thoughtcrime.securesms.components.RecipientsPanel;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.crypto.KeyExchangeInitiator;
|
||||
@ -139,21 +138,18 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
public static final String DRAFT_VIDEO_EXTRA = "draft_video";
|
||||
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
|
||||
|
||||
private static final int PICK_CONTACT = 1;
|
||||
private static final int PICK_IMAGE = 2;
|
||||
private static final int PICK_VIDEO = 3;
|
||||
private static final int PICK_AUDIO = 4;
|
||||
private static final int PICK_CONTACT_INFO = 5;
|
||||
private static final int GROUP_EDIT = 6;
|
||||
private static final int PICK_IMAGE = 1;
|
||||
private static final int PICK_VIDEO = 2;
|
||||
private static final int PICK_AUDIO = 3;
|
||||
private static final int PICK_CONTACT_INFO = 4;
|
||||
private static final int GROUP_EDIT = 5;
|
||||
|
||||
private static final int SEND_ATTRIBUTES[] = new int[]{R.attr.conversation_send_button_push,
|
||||
R.attr.conversation_send_button_sms_secure,
|
||||
R.attr.conversation_send_button_sms_insecure};
|
||||
|
||||
private MasterSecret masterSecret;
|
||||
private RecipientsPanel recipientsPanel;
|
||||
private EditText composeText;
|
||||
private ImageButton addContactButton;
|
||||
private ImageButton sendButton;
|
||||
private TextView charactersLeft;
|
||||
|
||||
@ -200,7 +196,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
initializeRecipientsInput();
|
||||
|
||||
super.onResume();
|
||||
dynamicTheme.onResume(this);
|
||||
@ -241,11 +236,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
|
||||
if (data == null || resultCode != RESULT_OK) return;
|
||||
switch (reqCode) {
|
||||
case PICK_CONTACT:
|
||||
Recipients recipients = data.getParcelableExtra("recipients");
|
||||
if (recipients != null)
|
||||
recipientsPanel.addRecipients(recipients);
|
||||
break;
|
||||
case PICK_IMAGE:
|
||||
addAttachmentImage(data.getData());
|
||||
break;
|
||||
@ -723,12 +713,10 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
recipientsPanel = (RecipientsPanel)findViewById(R.id.recipients);
|
||||
recipients = RecipientFactory.getRecipientsForIds(this, getIntent().getStringExtra(RECIPIENTS_EXTRA), true);
|
||||
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
||||
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA,
|
||||
ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
addContactButton = (ImageButton)findViewById(R.id.contacts_button);
|
||||
sendButton = (ImageButton)findViewById(R.id.send_button);
|
||||
composeText = (EditText)findViewById(R.id.embedded_text_editor);
|
||||
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
|
||||
@ -746,10 +734,8 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
SendButtonListener sendButtonListener = new SendButtonListener();
|
||||
ComposeKeyPressedListener composeKeyPressedListener = new ComposeKeyPressedListener();
|
||||
|
||||
recipientsPanel.setPanelChangeListener(new RecipientsPanelChangeListener());
|
||||
sendButton.setOnClickListener(sendButtonListener);
|
||||
sendButton.setEnabled(true);
|
||||
addContactButton.setOnClickListener(new AddRecipientButtonListener());
|
||||
composeText.setOnKeyListener(composeKeyPressedListener);
|
||||
composeText.addTextChangedListener(composeKeyPressedListener);
|
||||
composeText.setOnEditorActionListener(sendButtonListener);
|
||||
@ -769,23 +755,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && TextSecurePreferences.isScreenSecurityEnabled(this)) {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
|
||||
}
|
||||
|
||||
if (getIntent().getStringExtra("forwarded_message") != null) {
|
||||
composeText.setText(getString(R.string.ConversationActivity_forward_message_prefix) + ": " +
|
||||
getIntent().getStringExtra("forwarded_message"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initializeRecipientsInput() {
|
||||
if (recipients == null || recipients.isEmpty()) {
|
||||
recipientsPanel.setVisibility(View.VISIBLE);
|
||||
} else if (recipients != null) {
|
||||
recipientsPanel.addRecipients(this.recipients);
|
||||
} else {
|
||||
InputMethodManager input = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
input.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeReceivers() {
|
||||
@ -945,9 +914,10 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
Toast.makeText(ConversationActivity.this,
|
||||
R.string.ConversationActivity_saving_draft,
|
||||
R.string.ConversationActivity_saved_draft,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@ -1004,13 +974,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
}
|
||||
|
||||
private Recipients getRecipients() {
|
||||
try {
|
||||
if (isExistingConversation()) return this.recipients;
|
||||
else return recipientsPanel.getRecipients();
|
||||
} catch (RecipientFormattingException rfe) {
|
||||
Log.d(TAG, "Empty list of recipients retrieved from RecipientsPanel.");
|
||||
return null;
|
||||
}
|
||||
return this.recipients;
|
||||
}
|
||||
|
||||
private String getMessage() throws InvalidMessageException {
|
||||
@ -1038,7 +1002,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
|
||||
private void sendComplete(Recipients recipients, long threadId, boolean refreshFragment) {
|
||||
attachmentManager.clear();
|
||||
recipientsPanel.disable();
|
||||
composeText.setText("");
|
||||
|
||||
this.recipients = recipients;
|
||||
@ -1049,7 +1012,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
if (refreshFragment) {
|
||||
fragment.reload(recipients, threadId);
|
||||
|
||||
this.recipientsPanel.setVisibility(View.GONE);
|
||||
initializeTitleBar();
|
||||
initializeSecurity();
|
||||
}
|
||||
@ -1114,14 +1076,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
|
||||
// Listeners
|
||||
|
||||
private class AddRecipientButtonListener implements OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(ConversationActivity.this, ContactSelectionActivity.class);
|
||||
startActivityForResult(intent, PICK_CONTACT);
|
||||
}
|
||||
}
|
||||
|
||||
private class AttachmentTypeListener implements DialogInterface.OnClickListener {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
@ -1129,15 +1083,6 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
||||
}
|
||||
}
|
||||
|
||||
private class RecipientsPanelChangeListener implements RecipientsPanel.RecipientsPanelChangedListener {
|
||||
@Override
|
||||
public void onRecipientsPanelUpdate(Recipients recipients) {
|
||||
initializeSecurity();
|
||||
initializeTitleBar();
|
||||
calculateCharactersRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
private class EmojiToggleListener implements OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -184,9 +184,9 @@ public class ConversationFragment extends SherlockListFragment
|
||||
}
|
||||
|
||||
private void handleForwardMessage(MessageRecord message) {
|
||||
Intent composeIntent = new Intent(getActivity(), ConversationActivity.class);
|
||||
composeIntent.putExtra("forwarded_message", message.getDisplayBody().toString());
|
||||
composeIntent.putExtra("master_secret", masterSecret);
|
||||
Intent composeIntent = new Intent(getActivity(), ShareActivity.class);
|
||||
composeIntent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, message.getDisplayBody().toString());
|
||||
composeIntent.putExtra(ShareActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||
startActivity(composeIntent);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
|
||||
|
||||
setContentView(R.layout.conversation_list_activity);
|
||||
|
||||
ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar(), "TextSecure");
|
||||
ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar(), R.string.app_name);
|
||||
|
||||
initializeNavigationDrawer();
|
||||
initializeSenderReceiverService();
|
||||
@ -287,7 +287,7 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
|
||||
|
||||
this.drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
|
||||
this.drawerList = (ListView)findViewById(R.id.left_drawer);
|
||||
this.masterSecret = (MasterSecret)getIntent().getParcelableExtra("master_secret");
|
||||
this.masterSecret = getIntent().getParcelableExtra("master_secret");
|
||||
|
||||
this.fragment = (ConversationListFragment)this.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.fragment_content);
|
||||
|
@ -1,3 +1,20 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.app.Activity;
|
||||
@ -67,7 +84,11 @@ import ws.com.google.android.mms.MmsException;
|
||||
import static org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import static org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent.GroupContext;
|
||||
|
||||
|
||||
/**
|
||||
* Activity to create and update groups
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class GroupCreateActivity extends PassphraseRequiredSherlockFragmentActivity {
|
||||
|
||||
private final static String TAG = GroupCreateActivity.class.getSimpleName();
|
||||
|
@ -19,16 +19,12 @@ package org.thoughtcrime.securesms;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
import org.thoughtcrime.securesms.components.SingleRecipientPanel;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
@ -40,7 +36,6 @@ import org.thoughtcrime.securesms.util.ActionBarUtil;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
import org.thoughtcrime.securesms.util.ProgressDialogAsyncTask;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
|
||||
@ -159,6 +154,10 @@ public class NewConversationActivity extends PassphraseRequiredSherlockFragmentA
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.toIdString());
|
||||
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA));
|
||||
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA));
|
||||
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA));
|
||||
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, getIntent().getParcelableExtra(ConversationActivity.DRAFT_IMAGE_EXTRA));
|
||||
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
@ -126,16 +127,25 @@ public class RoutingActivity extends PassphraseRequiredSherlockActivity {
|
||||
}
|
||||
|
||||
private void handleDisplayConversationOrList() {
|
||||
ConversationParameters parameters = getConversationParameters();
|
||||
final ConversationParameters parameters = getConversationParameters();
|
||||
|
||||
Intent intent;
|
||||
|
||||
if (isShareAction() || parameters.recipients != null) {
|
||||
final Intent intent;
|
||||
if (isShareAction()) {
|
||||
intent = getShareIntent(parameters);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
}
|
||||
} else if (parameters.recipients != null) {
|
||||
intent = getConversationIntent(parameters);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
} else {
|
||||
intent = getConversationListIntent();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
}
|
||||
}
|
||||
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
@ -153,6 +163,20 @@ public class RoutingActivity extends PassphraseRequiredSherlockActivity {
|
||||
return intent;
|
||||
}
|
||||
|
||||
private Intent getShareIntent(ConversationParameters parameters) {
|
||||
Intent intent = new Intent(this, ShareActivity.class);
|
||||
intent.putExtra("master_secret", masterSecret);
|
||||
|
||||
if (parameters != null) {
|
||||
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, parameters.draftText);
|
||||
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, parameters.draftImage);
|
||||
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, parameters.draftAudio);
|
||||
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, parameters.draftVideo);
|
||||
}
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
private Intent getConversationListIntent() {
|
||||
Intent intent = new Intent(this, ConversationListActivity.class);
|
||||
intent.putExtra("master_secret", masterSecret);
|
||||
@ -197,8 +221,8 @@ public class RoutingActivity extends PassphraseRequiredSherlockActivity {
|
||||
}
|
||||
|
||||
private ConversationParameters getConversationParametersForSendAction() {
|
||||
Recipients recipients = null;
|
||||
long threadId = getIntent().getLongExtra("thread_id", -1);
|
||||
Recipients recipients;
|
||||
long threadId = getIntent().getLongExtra("thread_id", -1);
|
||||
|
||||
try {
|
||||
String data = getIntent().getData().getSchemeSpecificPart();
|
||||
@ -220,11 +244,11 @@ public class RoutingActivity extends PassphraseRequiredSherlockActivity {
|
||||
|
||||
if ("text/plain".equals(type)) {
|
||||
draftText = getIntent().getStringExtra(Intent.EXTRA_TEXT);
|
||||
} else if (type.startsWith("image/")) {
|
||||
} else if (type != null && type.startsWith("image/")) {
|
||||
draftImage = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
} else if (type.startsWith("audio/")) {
|
||||
} else if (type != null && type.startsWith("audio/")) {
|
||||
draftAudio = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
} else if (type.startsWith("video/")) {
|
||||
} else if (type != null && type.startsWith("video/")) {
|
||||
draftVideo = getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
}
|
||||
|
||||
|
173
src/org/thoughtcrime/securesms/ShareActivity.java
Normal file
173
src/org/thoughtcrime/securesms/ShareActivity.java
Normal file
@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.DirectoryRefreshListener;
|
||||
import org.thoughtcrime.securesms.util.ActionBarUtil;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.MemoryCleaner;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
|
||||
/**
|
||||
* An activity to quickly share content with contacts
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareActivity extends PassphraseRequiredSherlockFragmentActivity
|
||||
implements ShareFragment.ConversationSelectedListener
|
||||
{
|
||||
public final static String MASTER_SECRET_EXTRA = "master_secret";
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicTheme ();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
private ShareFragment fragment;
|
||||
private MasterSecret masterSecret;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
dynamicTheme.onCreate(this);
|
||||
dynamicLanguage.onCreate(this);
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.share_activity);
|
||||
ActionBarUtil.initializeDefaultActionBar(this, getSupportActionBar(), R.string.ShareActivity_share_with);
|
||||
initializeResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
dynamicTheme.onResume(this);
|
||||
dynamicLanguage.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (!isFinishing()) finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
MemoryCleaner.clean(masterSecret);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = this.getSupportMenuInflater();
|
||||
menu.clear();
|
||||
|
||||
inflater.inflate(R.menu.share, menu);
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_new_message: handleNewConversation(); return true;
|
||||
case android.R.id.home: finish(); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMasterSecretCleared() {
|
||||
startActivity(new Intent(this, RoutingActivity.class));
|
||||
super.onMasterSecretCleared();
|
||||
}
|
||||
|
||||
private void handleNewConversation() {
|
||||
Intent intent = getBaseShareIntent(NewConversationActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
createConversation(threadId, recipients, distributionType);
|
||||
}
|
||||
|
||||
private void createConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
final Intent intent = getBaseShareIntent(ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients.toIdString());
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
||||
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && TextSecurePreferences.isScreenSecurityEnabled(this)) {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE);
|
||||
}
|
||||
|
||||
this.masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
|
||||
|
||||
this.fragment = (ShareFragment)this.getSupportFragmentManager()
|
||||
.findFragmentById(R.id.fragment_content);
|
||||
|
||||
this.fragment.setMasterSecret(masterSecret);
|
||||
}
|
||||
|
||||
private Intent getBaseShareIntent(final Class<?> target) {
|
||||
final Intent intent = new Intent(this, target);
|
||||
final Intent originalIntent = getIntent();
|
||||
final String draftText = originalIntent.getStringExtra(ConversationActivity.DRAFT_TEXT_EXTRA);
|
||||
final Uri draftImage = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_IMAGE_EXTRA);
|
||||
final Uri draftAudio = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_AUDIO_EXTRA);
|
||||
final Uri draftVideo = originalIntent.getParcelableExtra(ConversationActivity.DRAFT_VIDEO_EXTRA);
|
||||
|
||||
intent.putExtra(ConversationActivity.DRAFT_TEXT_EXTRA, draftText);
|
||||
intent.putExtra(ConversationActivity.DRAFT_IMAGE_EXTRA, draftImage);
|
||||
intent.putExtra(ConversationActivity.DRAFT_AUDIO_EXTRA, draftAudio);
|
||||
intent.putExtra(ConversationActivity.DRAFT_VIDEO_EXTRA, draftVideo);
|
||||
intent.putExtra(NewConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||
|
||||
return intent;
|
||||
}
|
||||
}
|
110
src/org/thoughtcrime/securesms/ShareFragment.java
Normal file
110
src/org/thoughtcrime/securesms/ShareFragment.java
Normal file
@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
|
||||
/**
|
||||
* A fragment to select and share to open conversations
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
private ConversationSelectedListener listener;
|
||||
private MasterSecret masterSecret;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||
return inflater.inflate(R.layout.share_fragment, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle bundle) {
|
||||
super.onActivityCreated(bundle);
|
||||
|
||||
initializeListAdapter();
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
this.listener = (ConversationSelectedListener) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
if (v instanceof ShareListItem) {
|
||||
ShareListItem headerView = (ShareListItem) v;
|
||||
|
||||
handleCreateConversation(headerView.getThreadId(), headerView.getRecipients(),
|
||||
headerView.getDistributionType());
|
||||
}
|
||||
}
|
||||
|
||||
public void setMasterSecret(MasterSecret masterSecret) {
|
||||
if (this.masterSecret != masterSecret) {
|
||||
this.masterSecret = masterSecret;
|
||||
initializeListAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeListAdapter() {
|
||||
this.setListAdapter(new ShareListAdapter(getActivity(), null, masterSecret));
|
||||
getListView().setRecyclerListener((ShareListAdapter) getListAdapter());
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
|
||||
private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
listener.onCreateConversation(threadId, recipients, distributionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return new ConversationListLoader(getActivity(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> arg0) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(null);
|
||||
}
|
||||
|
||||
public interface ConversationSelectedListener {
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType);
|
||||
}
|
||||
}
|
75
src/org/thoughtcrime/securesms/ShareListAdapter.java
Normal file
75
src/org/thoughtcrime/securesms/ShareListAdapter.java
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.whispersystems.textsecure.crypto.MasterCipher;
|
||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||
|
||||
/**
|
||||
* A CursorAdapter for building a list of open conversations
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareListAdapter extends CursorAdapter implements AbsListView.RecyclerListener {
|
||||
|
||||
private final ThreadDatabase threadDatabase;
|
||||
private final MasterCipher masterCipher;
|
||||
private final Context context;
|
||||
private final LayoutInflater inflater;
|
||||
|
||||
public ShareListAdapter(Context context, Cursor cursor, MasterSecret masterSecret) {
|
||||
super(context, cursor, 0);
|
||||
|
||||
if (masterSecret != null) this.masterCipher = new MasterCipher(masterSecret);
|
||||
else this.masterCipher = null;
|
||||
|
||||
this.context = context;
|
||||
this.threadDatabase = DatabaseFactory.getThreadDatabase(context);
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
return inflater.inflate(R.layout.share_list_item_view, parent, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
if (masterCipher != null) {
|
||||
ThreadDatabase.Reader reader = threadDatabase.readerFor(cursor, masterCipher);
|
||||
ThreadRecord record = reader.getCurrent();
|
||||
|
||||
((ShareListItem)view).set(record);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovedToScrapHeap(View view) {
|
||||
((ShareListItem)view).unbind();
|
||||
}
|
||||
}
|
155
src/org/thoughtcrime/securesms/ShareListItem.java
Normal file
155
src/org/thoughtcrime/securesms/ShareListItem.java
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Typeface;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.provider.Contacts.Intents;
|
||||
import android.provider.ContactsContract.QuickContact;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.Emoji;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A simple view to show the recipients of an open conversation
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareListItem extends RelativeLayout
|
||||
implements Recipient.RecipientModifiedListener
|
||||
{
|
||||
private final static String TAG = ShareListItem.class.getSimpleName();
|
||||
|
||||
private Context context;
|
||||
private Recipients recipients;
|
||||
private long threadId;
|
||||
private TextView fromView;
|
||||
|
||||
private ImageView contactPhotoImage;
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private int distributionType;
|
||||
|
||||
public ShareListItem(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public ShareListItem(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
this.fromView = (TextView) findViewById(R.id.from);
|
||||
this.contactPhotoImage = (ImageView) findViewById(R.id.contact_photo_image);
|
||||
}
|
||||
|
||||
public void set(ThreadRecord thread) {
|
||||
this.recipients = thread.getRecipients();
|
||||
this.threadId = thread.getThreadId();
|
||||
this.distributionType = thread.getDistributionType();
|
||||
|
||||
this.recipients.addListener(this);
|
||||
this.fromView.setText(formatFrom(recipients));
|
||||
|
||||
setBackground();
|
||||
setContactPhoto(this.recipients.getPrimaryRecipient());
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
if (this.recipients != null) this.recipients.removeListener(this);
|
||||
}
|
||||
|
||||
private void setContactPhoto(final Recipient recipient) {
|
||||
if (recipient == null) return;
|
||||
contactPhotoImage.setImageBitmap(BitmapUtil.getCircleCroppedBitmap(recipient.getContactPhoto()));
|
||||
}
|
||||
|
||||
private void setBackground() {
|
||||
int[] attributes = new int[]{R.attr.conversation_list_item_background_read};
|
||||
TypedArray drawables = context.obtainStyledAttributes(attributes);
|
||||
|
||||
setBackgroundDrawable(drawables.getDrawable(0));
|
||||
|
||||
drawables.recycle();
|
||||
}
|
||||
|
||||
private CharSequence formatFrom(Recipients from) {
|
||||
final String fromString;
|
||||
final boolean isUnnamedGroup = from.isGroupRecipient() && TextUtils.isEmpty(from.getPrimaryRecipient().getName());
|
||||
if (isUnnamedGroup) {
|
||||
fromString = context.getString(R.string.ConversationActivity_unnamed_group);
|
||||
} else {
|
||||
fromString = from.toShortString();
|
||||
}
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(fromString);
|
||||
|
||||
final int typeface;
|
||||
if (isUnnamedGroup) typeface = Typeface.ITALIC;
|
||||
else typeface = Typeface.NORMAL;
|
||||
|
||||
builder.setSpan(new StyleSpan(typeface), 0, builder.length(),
|
||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
|
||||
public int getDistributionType() {
|
||||
return distributionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(Recipient recipient) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fromView.setText(formatFrom(recipients));
|
||||
setContactPhoto(recipients.getPrimaryRecipient());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.RecipientsAdapter;
|
||||
import org.thoughtcrime.securesms.contacts.RecipientsEditor;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Panel component combining both an editable field with a button for
|
||||
* a list-based contact selector.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class RecipientsPanel extends RelativeLayout {
|
||||
|
||||
private RecipientsPanelChangedListener panelChangeListener;
|
||||
private RecipientsEditor recipientsText;
|
||||
private View panel;
|
||||
|
||||
private static final int RECIPIENTS_MAX_LENGTH = 312;
|
||||
|
||||
public RecipientsPanel(Context context) {
|
||||
super(context);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public RecipientsPanel(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public RecipientsPanel(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public void addRecipient(String name, String number) {
|
||||
if (name != null) recipientsText.append(sanitizeRecipientName(name) + "< " + number + ">, ");
|
||||
else recipientsText.append(number + ", ");
|
||||
}
|
||||
|
||||
public void addContacts(List<ContactAccessor.ContactData> contacts) {
|
||||
for (ContactAccessor.ContactData contact : contacts) {
|
||||
for (ContactAccessor.NumberData number : contact.numbers) {
|
||||
addRecipient(contact.name, number.number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addRecipients(Recipients recipients) {
|
||||
Set<Recipient> panelRecipients;
|
||||
|
||||
try {
|
||||
panelRecipients = new HashSet<Recipient>(getRecipients().getRecipientsList());
|
||||
} catch (RecipientFormattingException e) {
|
||||
Log.w("RecipientsPanel", e);
|
||||
panelRecipients = new HashSet<Recipient>();
|
||||
}
|
||||
|
||||
List<Recipient> recipientList = recipients.getRecipientsList();
|
||||
Iterator<Recipient> iterator = recipientList.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Recipient recipient = iterator.next();
|
||||
if (!panelRecipients.contains(recipient)) {
|
||||
addRecipient(recipient.getName(), recipient.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Recipients getRecipients() throws RecipientFormattingException {
|
||||
String rawText = recipientsText.getText().toString();
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(getContext(), rawText, false);
|
||||
|
||||
if (recipients.isEmpty())
|
||||
throw new RecipientFormattingException("Recipient List Is Empty!");
|
||||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
recipientsText.setText("");
|
||||
panel.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void setPanelChangeListener(RecipientsPanelChangedListener panelChangeListener) {
|
||||
this.panelChangeListener = panelChangeListener;
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
inflater.inflate(R.layout.recipients_panel, this, true);
|
||||
|
||||
View imageButton = findViewById(R.id.contacts_button);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
((MarginLayoutParams) imageButton.getLayoutParams()).topMargin = 0;
|
||||
|
||||
panel = findViewById(R.id.recipients_panel);
|
||||
initRecipientsEditor();
|
||||
}
|
||||
|
||||
private void initRecipientsEditor() {
|
||||
Recipients recipients = null;
|
||||
recipientsText = (RecipientsEditor)findViewById(R.id.recipients_text);
|
||||
|
||||
try {
|
||||
recipients = getRecipients();
|
||||
} catch (RecipientFormattingException e) {
|
||||
recipients = new Recipients( new LinkedList<Recipient>() );
|
||||
}
|
||||
|
||||
recipientsText.setAdapter(new RecipientsAdapter(this.getContext()));
|
||||
recipientsText.populate(recipients);
|
||||
recipientsText.setOnFocusChangeListener(new FocusChangedListener());
|
||||
}
|
||||
|
||||
private static String sanitizeRecipientName(String name) {
|
||||
return name.replaceAll("[,<>]", "");
|
||||
}
|
||||
|
||||
private class FocusChangedListener implements View.OnFocusChangeListener {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (!hasFocus && (panelChangeListener != null)) {
|
||||
try {
|
||||
panelChangeListener.onRecipientsPanelUpdate(getRecipients());
|
||||
} catch (RecipientFormattingException rfe) {
|
||||
panelChangeListener.onRecipientsPanelUpdate(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface RecipientsPanelChangedListener {
|
||||
public void onRecipientsPanelUpdate(Recipients recipients);
|
||||
}
|
||||
|
||||
}
|
@ -16,8 +16,6 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.util;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.sms.SmsTransportDetails;
|
||||
|
||||
public class EncryptedCharacterCalculator extends CharacterCalculator {
|
||||
@ -37,7 +35,6 @@ public class EncryptedCharacterCalculator extends CharacterCalculator {
|
||||
spilloverMessagesSpent++;
|
||||
|
||||
int charactersRemaining = (SmsTransportDetails.MULTI_MESSAGE_MAX_BYTES * spilloverMessagesSpent) - spillover;
|
||||
Log.w("EncryptedCharacterCalculator", "charactersRemaining: " + charactersRemaining);
|
||||
|
||||
return new CharacterState(spilloverMessagesSpent+1, charactersRemaining, SmsTransportDetails.MULTI_MESSAGE_MAX_BYTES);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user