Address related improvements
- QR code is now shown in contact details and 'manage identity' view - Contacts and identities can now be deleted
This commit is contained in:
parent
adfb3a920a
commit
9275f5ca9c
@ -40,6 +40,7 @@ dependencies {
|
||||
compile "ch.dissem.jabit:jabit-networking:$jabitVersion"
|
||||
compile "ch.dissem.jabit:jabit-cryptography-spongy:$jabitVersion"
|
||||
compile "ch.dissem.jabit:jabit-extensions:$jabitVersion"
|
||||
compile "ch.dissem.jabit:jabit-wif:$jabitVersion"
|
||||
|
||||
compile 'org.slf4j:slf4j-android:1.7.12'
|
||||
|
||||
@ -51,6 +52,9 @@ dependencies {
|
||||
}
|
||||
compile 'com.mikepenz:iconics:1.6.2@aar'
|
||||
compile 'com.mikepenz:community-material-typeface:1.1.71@aar'
|
||||
|
||||
compile 'com.journeyapps:zxing-android-embedded:3.1.0@aar'
|
||||
compile 'com.google.zxing:core:3.2.0'
|
||||
}
|
||||
|
||||
idea.module {
|
||||
|
@ -38,7 +38,7 @@
|
||||
android:value=".MainActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".SubscriptionDetailActivity"
|
||||
android:name=".AddressDetailActivity"
|
||||
android:label="@string/title_subscription_detail"
|
||||
android:parentActivityName=".MainActivity"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
@ -31,9 +31,9 @@ import android.view.MenuItem;
|
||||
* in a {@link MainActivity}.
|
||||
* <p/>
|
||||
* This activity is mostly just a 'shell' activity containing nothing
|
||||
* more than a {@link SubscriptionDetailFragment}.
|
||||
* more than a {@link AddressDetailFragment}.
|
||||
*/
|
||||
public class SubscriptionDetailActivity extends AppCompatActivity {
|
||||
public class AddressDetailActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -59,9 +59,9 @@ public class SubscriptionDetailActivity extends AppCompatActivity {
|
||||
// Create the detail fragment and add it to the activity
|
||||
// using a fragment transaction.
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putSerializable(SubscriptionDetailFragment.ARG_ITEM,
|
||||
getIntent().getSerializableExtra(SubscriptionDetailFragment.ARG_ITEM));
|
||||
SubscriptionDetailFragment fragment = new SubscriptionDetailFragment();
|
||||
arguments.putSerializable(AddressDetailFragment.ARG_ITEM,
|
||||
getIntent().getSerializableExtra(AddressDetailFragment.ARG_ITEM));
|
||||
AddressDetailFragment fragment = new AddressDetailFragment();
|
||||
fragment.setArguments(arguments);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.content, fragment)
|
259
app/src/main/java/ch/dissem/apps/abit/AddressDetailFragment.java
Normal file
259
app/src/main/java/ch/dissem/apps/abit/AddressDetailFragment.java
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.widget.ShareActionProvider;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.apps.abit.util.Drawables;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
import static android.graphics.Color.BLACK;
|
||||
import static android.graphics.Color.WHITE;
|
||||
|
||||
|
||||
/**
|
||||
* A fragment representing a single Message detail screen.
|
||||
* This fragment is either contained in a {@link MainActivity}
|
||||
* in two-pane mode (on tablets) or a {@link MessageDetailActivity}
|
||||
* on handsets.
|
||||
*/
|
||||
public class AddressDetailFragment extends Fragment {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AddressDetailFragment.class);
|
||||
/**
|
||||
* The fragment argument representing the item ID that this fragment
|
||||
* represents.
|
||||
*/
|
||||
public static final String ARG_ITEM = "item";
|
||||
|
||||
private static final int QR_CODE_SIZE = 350;
|
||||
|
||||
private ShareActionProvider shareActionProvider;
|
||||
/**
|
||||
* The content this fragment is presenting.
|
||||
*/
|
||||
private BitmessageAddress item;
|
||||
|
||||
|
||||
/**
|
||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||
* fragment (e.g. upon screen orientation changes).
|
||||
*/
|
||||
public AddressDetailFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getArguments().containsKey(ARG_ITEM)) {
|
||||
// Load the dummy content specified by the fragment
|
||||
// arguments. In a real-world scenario, use a Loader
|
||||
// to load content from a content provider.
|
||||
item = (BitmessageAddress) getArguments().getSerializable(ARG_ITEM);
|
||||
}
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.address, menu);
|
||||
|
||||
Drawables.addIcon(getActivity(), menu, R.id.write_message, GoogleMaterial.Icon.gmd_mail);
|
||||
Drawables.addIcon(getActivity(), menu, R.id.delete, GoogleMaterial.Icon.gmd_delete);
|
||||
Drawables.addIcon(getActivity(), menu, R.id.share, GoogleMaterial.Icon.gmd_share);
|
||||
|
||||
shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(
|
||||
menu.findItem(R.id.share));
|
||||
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||
final Activity ctx = getActivity();
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.write_message:
|
||||
Intent intent = new Intent(ctx, ComposeMessageActivity.class);
|
||||
intent.putExtra(ComposeMessageActivity.EXTRA_IDENTITY, Singleton.getIdentity(ctx));
|
||||
intent.putExtra(ComposeMessageActivity.EXTRA_RECIPIENT, item);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
case R.id.delete:
|
||||
int warning;
|
||||
if (item.getPrivateKey() != null)
|
||||
warning = R.string.delete_identity_warning;
|
||||
else
|
||||
warning = R.string.delete_contact_warning;
|
||||
new AlertDialog.Builder(ctx)
|
||||
.setMessage(warning)
|
||||
.setPositiveButton(android.R.string.yes, new
|
||||
DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Singleton.getAddressRepository(ctx).remove(item);
|
||||
item = null;
|
||||
ctx.onBackPressed();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
return true;
|
||||
case R.id.share:
|
||||
new AlertDialog.Builder(ctx)
|
||||
.setMessage("I have no fucking clue.")
|
||||
.show();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setShareIntent(Intent shareIntent) {
|
||||
if (shareActionProvider != null) {
|
||||
shareActionProvider.setShareIntent(shareIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_address_detail, container, false);
|
||||
|
||||
// Show the dummy content as text in a TextView.
|
||||
if (item != null) {
|
||||
((ImageView) rootView.findViewById(R.id.avatar)).setImageDrawable(new Identicon(item));
|
||||
TextView name = (TextView) rootView.findViewById(R.id.name);
|
||||
name.setText(item.toString());
|
||||
name.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
item.setAlias(s.toString());
|
||||
}
|
||||
});
|
||||
TextView address = (TextView) rootView.findViewById(R.id.address);
|
||||
address.setText(item.getAddress());
|
||||
address.setSelected(true);
|
||||
((TextView) rootView.findViewById(R.id.stream_number)).setText(getActivity()
|
||||
.getString(R.string.stream_number, item.getStream()));
|
||||
if (item.getPrivateKey() == null) {
|
||||
Switch active = (Switch) rootView.findViewById(R.id.active);
|
||||
active.setChecked(item.isSubscribed());
|
||||
active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
item.setSubscribed(isChecked);
|
||||
}
|
||||
});
|
||||
|
||||
ImageView pubkeyAvailableImg = (ImageView) rootView.findViewById(R.id
|
||||
.pubkey_available);
|
||||
|
||||
if (item.getPubkey() == null) {
|
||||
pubkeyAvailableImg.setAlpha(0.3f);
|
||||
TextView pubkeyAvailableDesc = (TextView) rootView.findViewById(R.id
|
||||
.pubkey_available_desc);
|
||||
pubkeyAvailableDesc.setText(R.string.pubkey_not_available);
|
||||
}
|
||||
} else {
|
||||
rootView.findViewById(R.id.active).setVisibility(View.GONE);
|
||||
rootView.findViewById(R.id.pubkey_available).setVisibility(View.GONE);
|
||||
rootView.findViewById(R.id.pubkey_available_desc).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// QR code
|
||||
ImageView qrCode = (ImageView) rootView.findViewById(R.id.qr_code);
|
||||
qrCode.setImageBitmap(encodeAsBitmap(item));
|
||||
}
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
Bitmap encodeAsBitmap(BitmessageAddress address) {
|
||||
StringBuilder link = new StringBuilder("bitmessage:");
|
||||
link.append(address.getAddress());
|
||||
if (address.getAlias() != null) {
|
||||
link.append("?label=").append(address.getAlias());
|
||||
}
|
||||
BitMatrix result;
|
||||
try {
|
||||
result = new MultiFormatWriter().encode(link.toString(),
|
||||
BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE, null);
|
||||
} catch (WriterException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
int w = result.getWidth();
|
||||
int h = result.getHeight();
|
||||
int[] pixels = new int[w * h];
|
||||
for (int y = 0; y < h; y++) {
|
||||
int offset = y * w;
|
||||
for (int x = 0; x < w; x++) {
|
||||
pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
|
||||
}
|
||||
}
|
||||
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
bitmap.setPixels(pixels, 0, QR_CODE_SIZE, 0, 0, w, h);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (item != null) {
|
||||
Singleton.getAddressRepository(getContext()).save(item);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
}
|
@ -38,7 +38,7 @@ import java.util.List;
|
||||
/**
|
||||
* Fragment that shows a list of all contacts, the ones we subscribed to first.
|
||||
*/
|
||||
public class SubscriptionListFragment extends AbstractItemListFragment<BitmessageAddress> {
|
||||
public class AddressListFragment extends AbstractItemListFragment<BitmessageAddress> {
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@ -113,7 +113,7 @@ public class SubscriptionListFragment extends AbstractItemListFragment<Bitmessag
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_contact_list, container, false);
|
||||
return inflater.inflate(R.layout.fragment_address_list, container, false);
|
||||
}
|
||||
|
||||
@Override
|
@ -26,6 +26,7 @@ import android.support.v7.widget.Toolbar;
|
||||
public class ComposeMessageActivity extends AppCompatActivity {
|
||||
public static final String EXTRA_IDENTITY = "ch.dissem.abit.Message.SENDER";
|
||||
public static final String EXTRA_RECIPIENT = "ch.dissem.abit.Message.RECIPIENT";
|
||||
public static final String EXTRA_SUBJECT = "ch.dissem.abit.Message.SUBJECT";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -36,6 +36,7 @@ import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_IDENTITY;
|
||||
import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_RECIPIENT;
|
||||
import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_SUBJECT;
|
||||
|
||||
/**
|
||||
* Compose a new message.
|
||||
@ -43,6 +44,7 @@ import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_RECIPIENT;
|
||||
public class ComposeMessageFragment extends Fragment {
|
||||
private BitmessageAddress identity;
|
||||
private BitmessageAddress recipient;
|
||||
private String subject;
|
||||
private AutoCompleteTextView recipientInput;
|
||||
private EditText subjectInput;
|
||||
private EditText bodyInput;
|
||||
@ -66,6 +68,9 @@ public class ComposeMessageFragment extends Fragment {
|
||||
if (getArguments().containsKey(EXTRA_RECIPIENT)) {
|
||||
recipient = (BitmessageAddress) getArguments().getSerializable(EXTRA_RECIPIENT);
|
||||
}
|
||||
if (getArguments().containsKey(EXTRA_SUBJECT)) {
|
||||
subject = getArguments().getString(EXTRA_SUBJECT);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("No identity set for ComposeMessageFragment");
|
||||
}
|
||||
@ -99,9 +104,9 @@ public class ComposeMessageFragment extends Fragment {
|
||||
recipientInput.setText(recipient.toString());
|
||||
}
|
||||
subjectInput = (EditText) rootView.findViewById(R.id.subject);
|
||||
subjectInput.setText(subject);
|
||||
bodyInput = (EditText) rootView.findViewById(R.id.body);
|
||||
// bodyInput.setInputType(EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||
// bodyInput.setImeOptions(EditorInfo.IME_ACTION_SEND | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@ -120,7 +125,8 @@ public class ComposeMessageFragment extends Fragment {
|
||||
try {
|
||||
recipient = new BitmessageAddress(inputString);
|
||||
} catch (Exception e) {
|
||||
List<BitmessageAddress> contacts = Singleton.getAddressRepository(getContext()).getContacts();
|
||||
List<BitmessageAddress> contacts = Singleton.getAddressRepository
|
||||
(getContext()).getContacts();
|
||||
for (BitmessageAddress contact : contacts) {
|
||||
if (inputString.equalsIgnoreCase(contact.getAlias())) {
|
||||
recipient = contact;
|
||||
|
@ -94,6 +94,7 @@ public class MainActivity extends AppCompatActivity
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MainActivity.class);
|
||||
private static final int ADD_IDENTITY = 1;
|
||||
private static final int MANAGE_IDENTITY = 2;
|
||||
|
||||
/**
|
||||
* Whether or not the activity is in two-pane mode, i.e. running on a tablet
|
||||
@ -120,7 +121,6 @@ public class MainActivity extends AppCompatActivity
|
||||
private Label selectedLabel;
|
||||
|
||||
private BitmessageContext bmc;
|
||||
private BitmessageAddress selectedIdentity;
|
||||
private AccountHeader accountHeader;
|
||||
|
||||
@Override
|
||||
@ -190,6 +190,7 @@ public class MainActivity extends AppCompatActivity
|
||||
profiles.add(new ProfileDrawerItem()
|
||||
.withIcon(new Identicon(identity))
|
||||
.withName(identity.toString())
|
||||
.withNameShown(true)
|
||||
.withEmail(identity.getAddress())
|
||||
.withTag(identity)
|
||||
);
|
||||
@ -216,6 +217,7 @@ public class MainActivity extends AppCompatActivity
|
||||
profiles.add(new ProfileSettingDrawerItem()
|
||||
.withName(getString(R.string.manage_identity))
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
.withIdentifier(MANAGE_IDENTITY)
|
||||
);
|
||||
// Create the AccountHeader
|
||||
accountHeader = new AccountHeaderBuilder()
|
||||
@ -226,7 +228,14 @@ public class MainActivity extends AppCompatActivity
|
||||
@Override
|
||||
public boolean onProfileChanged(View view, IProfile profile, boolean
|
||||
currentProfile) {
|
||||
if (profile.getIdentifier() == ADD_IDENTITY) {
|
||||
switch (profile.getIdentifier()) {
|
||||
case ADD_IDENTITY:
|
||||
new AlertDialog.Builder(MainActivity.this)
|
||||
.setMessage(R.string.add_identity_warning)
|
||||
.setPositiveButton(android.R.string.yes, new
|
||||
DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
BitmessageAddress identity = bmc.createIdentity(false);
|
||||
IProfile newProfile = new ProfileDrawerItem()
|
||||
.withName(identity.toString())
|
||||
@ -240,10 +249,24 @@ public class MainActivity extends AppCompatActivity
|
||||
} else {
|
||||
accountHeader.addProfiles(newProfile);
|
||||
}
|
||||
} else if (profile instanceof ProfileDrawerItem) {
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
break;
|
||||
case MANAGE_IDENTITY:
|
||||
Intent show = new Intent(MainActivity.this,
|
||||
AddressDetailActivity.class);
|
||||
show.putExtra(AddressDetailFragment.ARG_ITEM,
|
||||
Singleton.getIdentity(getApplicationContext()));
|
||||
startActivity(show);
|
||||
break;
|
||||
default:
|
||||
if (profile instanceof ProfileDrawerItem) {
|
||||
Object tag = ((ProfileDrawerItem) profile).getTag();
|
||||
if (tag instanceof BitmessageAddress) {
|
||||
selectedIdentity = (BitmessageAddress) tag;
|
||||
Singleton.setIdentity((BitmessageAddress) tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
// false if it should close the drawer
|
||||
@ -336,10 +359,10 @@ public class MainActivity extends AppCompatActivity
|
||||
switch (ni.getNameRes()) {
|
||||
case R.string.contacts_and_subscriptions:
|
||||
if (!(getSupportFragmentManager().findFragmentById(R.id
|
||||
.item_list) instanceof SubscriptionListFragment)) {
|
||||
changeList(new SubscriptionListFragment());
|
||||
.item_list) instanceof AddressListFragment)) {
|
||||
changeList(new AddressListFragment());
|
||||
} else {
|
||||
((SubscriptionListFragment) getSupportFragmentManager()
|
||||
((AddressListFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.item_list)).updateList();
|
||||
}
|
||||
|
||||
@ -415,7 +438,7 @@ public class MainActivity extends AppCompatActivity
|
||||
if (item instanceof Plaintext)
|
||||
fragment = new MessageDetailFragment();
|
||||
else if (item instanceof BitmessageAddress)
|
||||
fragment = new SubscriptionDetailFragment();
|
||||
fragment = new AddressDetailFragment();
|
||||
else
|
||||
throw new IllegalArgumentException("Plaintext or BitmessageAddress expected, but " +
|
||||
"was "
|
||||
@ -431,7 +454,7 @@ public class MainActivity extends AppCompatActivity
|
||||
if (item instanceof Plaintext)
|
||||
detailIntent = new Intent(this, MessageDetailActivity.class);
|
||||
else if (item instanceof BitmessageAddress)
|
||||
detailIntent = new Intent(this, SubscriptionDetailActivity.class);
|
||||
detailIntent = new Intent(this, AddressDetailActivity.class);
|
||||
else
|
||||
throw new IllegalArgumentException("Plaintext or BitmessageAddress expected, but " +
|
||||
"was "
|
||||
@ -468,8 +491,4 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
public BitmessageAddress getSelectedIdentity() {
|
||||
return selectedIdentity;
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||
|
||||
import static android.text.util.Linkify.WEB_URLS;
|
||||
import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_IDENTITY;
|
||||
import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_RECIPIENT;
|
||||
import static ch.dissem.apps.abit.ComposeMessageActivity.EXTRA_SUBJECT;
|
||||
import static ch.dissem.apps.abit.util.Constants.BITMESSAGE_ADDRESS_PATTERN;
|
||||
import static ch.dissem.apps.abit.util.Constants.BITMESSAGE_URL_SCHEMA;
|
||||
|
||||
@ -152,8 +155,12 @@ public class MessageDetailFragment extends Fragment {
|
||||
case R.id.reply:
|
||||
Intent replyIntent = new Intent(getActivity().getApplicationContext(),
|
||||
ComposeMessageActivity.class);
|
||||
replyIntent.putExtra(ComposeMessageActivity.EXTRA_RECIPIENT, item.getFrom());
|
||||
replyIntent.putExtra(ComposeMessageActivity.EXTRA_IDENTITY, item.getTo());
|
||||
replyIntent.putExtra(EXTRA_RECIPIENT, item.getFrom());
|
||||
replyIntent.putExtra(EXTRA_IDENTITY, item.getTo());
|
||||
replyIntent.putExtra(EXTRA_SUBJECT,
|
||||
(item.getSubject().substring(0, 3).equalsIgnoreCase("RE:") ? "" : "RE: ")
|
||||
+ item.getSubject()
|
||||
);
|
||||
startActivity(replyIntent);
|
||||
return true;
|
||||
case R.id.delete:
|
||||
|
@ -132,7 +132,7 @@ public class MessageListFragment extends AbstractItemListFragment<Plaintext> {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Intent intent = new Intent(getActivity().getApplicationContext(), ComposeMessageActivity.class);
|
||||
intent.putExtra(ComposeMessageActivity.EXTRA_IDENTITY, ((MainActivity) getActivity()).getSelectedIdentity());
|
||||
intent.putExtra(ComposeMessageActivity.EXTRA_IDENTITY, Singleton.getIdentity(getActivity()));
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
|
||||
/**
|
||||
* A fragment representing a single Message detail screen.
|
||||
* This fragment is either contained in a {@link MainActivity}
|
||||
* in two-pane mode (on tablets) or a {@link MessageDetailActivity}
|
||||
* on handsets.
|
||||
*/
|
||||
public class SubscriptionDetailFragment extends Fragment {
|
||||
/**
|
||||
* The fragment argument representing the item ID that this fragment
|
||||
* represents.
|
||||
*/
|
||||
public static final String ARG_ITEM = "item";
|
||||
|
||||
/**
|
||||
* The content this fragment is presenting.
|
||||
*/
|
||||
private BitmessageAddress item;
|
||||
|
||||
|
||||
/**
|
||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||
* fragment (e.g. upon screen orientation changes).
|
||||
*/
|
||||
public SubscriptionDetailFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getArguments().containsKey(ARG_ITEM)) {
|
||||
// Load the dummy content specified by the fragment
|
||||
// arguments. In a real-world scenario, use a Loader
|
||||
// to load content from a content provider.
|
||||
item = (BitmessageAddress) getArguments().getSerializable(ARG_ITEM);
|
||||
}
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_contact_detail, container, false);
|
||||
|
||||
// Show the dummy content as text in a TextView.
|
||||
if (item != null) {
|
||||
((ImageView) rootView.findViewById(R.id.avatar)).setImageDrawable(new Identicon(item));
|
||||
TextView name = (TextView) rootView.findViewById(R.id.name);
|
||||
name.setText(item.toString());
|
||||
name.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
item.setAlias(s.toString());
|
||||
}
|
||||
});
|
||||
TextView address = (TextView) rootView.findViewById(R.id.address);
|
||||
address.setText(item.getAddress());
|
||||
address.setSelected(true);
|
||||
((TextView) rootView.findViewById(R.id.stream_number)).setText(getActivity()
|
||||
.getString(R.string.stream_number, item.getStream()));
|
||||
Switch active = (Switch) rootView.findViewById(R.id.active);
|
||||
active.setChecked(item.isSubscribed());
|
||||
active.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
item.setSubscribed(isChecked);
|
||||
}
|
||||
});
|
||||
|
||||
ImageView pubkeyAvailableImg = (ImageView) rootView.findViewById(R.id.pubkey_available);
|
||||
if (item.getPubkey() == null) {
|
||||
pubkeyAvailableImg.setAlpha(0.3f);
|
||||
TextView pubkeyAvailableDesc = (TextView) rootView.findViewById(R.id
|
||||
.pubkey_available_desc);
|
||||
pubkeyAvailableDesc.setText(R.string.pubkey_not_available);
|
||||
}
|
||||
}
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
Singleton.getAddressRepository(getContext()).save(item);
|
||||
super.onPause();
|
||||
}
|
||||
}
|
@ -239,7 +239,7 @@ public class AndroidAddressRepository implements AddressRepository {
|
||||
@Override
|
||||
public void remove(BitmessageAddress address) {
|
||||
SQLiteDatabase db = sql.getWritableDatabase();
|
||||
db.delete(TABLE_NAME, "address = " + address.getAddress(), null);
|
||||
db.delete(TABLE_NAME, "address = ?", new String[]{address.getAddress()});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,4 +124,10 @@ public class Singleton {
|
||||
}
|
||||
return identity;
|
||||
}
|
||||
|
||||
public static void setIdentity(BitmessageAddress identity) {
|
||||
if (identity.getPrivateKey() == null)
|
||||
throw new IllegalArgumentException("Identity expected, but no private key available");
|
||||
Singleton.identity = identity;
|
||||
}
|
||||
}
|
||||
|
@ -100,4 +100,18 @@
|
||||
android:text="@string/pubkey_available"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qr_code"
|
||||
tools:src="@drawable/public_key"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_below="@+id/pubkey_available"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="64dp"
|
||||
android:contentDescription="@string/alt_qr_code"/>
|
||||
</RelativeLayout>
|
33
app/src/main/res/menu/address.xml
Normal file
33
app/src/main/res/menu/address.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright 2016 Christian Basler
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/write_message"
|
||||
android:title="@string/write_message"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/delete"
|
||||
android:title="@string/delete"
|
||||
app:showAsAction="ifRoom"/>
|
||||
<item
|
||||
android:id="@+id/share"
|
||||
android:title="@string/share"
|
||||
app:actionProviderClass="android.support.v7.widget.ShareActionProvider"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
@ -58,4 +58,9 @@
|
||||
<string name="status_summary">Technische Infos</string>
|
||||
<string name="pubkey_available">Öffentlicher Schlüssel verfügbar</string>
|
||||
<string name="pubkey_not_available">Öffentlicher Schlüssel noch nicht verfügbar</string>
|
||||
<string name="alt_qr_code">QR-Code</string>
|
||||
<string name="add_identity_warning">Mehrere Identitäten zu haben bedeutet einen höheren Resourcenverbrauch. Sind Sie sicher?</string>
|
||||
<string name="share">Teilen</string>
|
||||
<string name="delete_contact_warning">Sind Sie sicher dass dieser Kontakt gelöscht werden soll?</string>
|
||||
<string name="delete_identity_warning">Sind Sie sicher dass diese Identität gelöscht werden soll? Sie werden keine Nachrichten mehr empfangen können welche an diese Adresse gesendet werden, und es est nicht möglich diese Aktion rückgängig zu machen.</string>
|
||||
</resources>
|
@ -61,4 +61,9 @@
|
||||
<string name="alias_default_identity">Me</string>
|
||||
<string name="pubkey_available">Public key available</string>
|
||||
<string name="pubkey_not_available">Public key not yet available</string>
|
||||
<string name="alt_qr_code">QR code</string>
|
||||
<string name="add_identity_warning">Having more identities will reequire more resources. Are you sure you want to add an identity?</string>
|
||||
<string name="share">Share</string>
|
||||
<string name="delete_identity_warning">Are you sure you want to delete this identity? You won\'t be able to receive any messages sent to this address and can\'t undo this operation.</string>
|
||||
<string name="delete_contact_warning">Are you sure you want to delete this contact?</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user