Fixed the 'full node' switch, activated the jack tools to support some Java 8 features, and fixed some lint issues

This commit is contained in:
Christian Basler 2016-10-16 23:16:38 +02:00
parent a5b3c33394
commit 2b1fb436a9
30 changed files with 367 additions and 436 deletions

View File

@ -5,10 +5,11 @@ ext {
appName = "Abit"
}
if (project.hasProperty("project.configs")
&& new File(project.property("project.configs") + appName + ".gradle").exists()) {
&& new File(project.property("project.configs") + appName + ".gradle").exists()) {
apply from: project.property("project.configs") + appName + ".gradle";
}
//noinspection GroovyMissingReturnStatement
android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
@ -19,17 +20,23 @@ android {
targetSdkVersion 24
versionCode 9
versionName "1.0-beta9"
jackOptions.enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
}
ext.jabitVersion = '2.0.1'
ext.jabitVersion = '2.0.2'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.1'
@ -58,8 +65,8 @@ dependencies {
compile 'com.google.zxing:core:3.3.0'
compile 'io.github.yavski:fab-speed-dial:1.0.4'
compile 'com.github.amlcurran.showcaseview:library:5.4.3'
compile ('com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.9.3@aar'){
transitive=true
compile('com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:0.9.3@aar') {
transitive = true
}
compile 'com.github.angads25:filepicker:1.0.6'

View File

@ -23,7 +23,6 @@ import android.view.View;
import android.widget.ListView;
import ch.dissem.apps.abit.listener.ListSelectionListener;
import ch.dissem.bitmessage.entity.valueobject.Label;
/**
* @author Christian Basler
@ -38,11 +37,7 @@ public abstract class AbstractItemListFragment<T> extends ListFragment implement
* A dummy implementation of the {@link ListSelectionListener} interface that does
* nothing. Used only when this fragment is not attached to an activity.
*/
private static ListSelectionListener<Object> dummyCallbacks = new
ListSelectionListener<Object>() {
@Override
public void onItemSelected(Object plaintext) {
}
private static ListSelectionListener<Object> dummyCallbacks = plaintext -> {
};
/**
* The fragment's current callback object, which is notified of list item
@ -61,7 +56,7 @@ public abstract class AbstractItemListFragment<T> extends ListFragment implement
// Restore the previously serialized activated item position.
if (savedInstanceState != null
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
&& savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
}
}
@ -73,8 +68,8 @@ public abstract class AbstractItemListFragment<T> extends ListFragment implement
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(activateOnItemClick
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
@Override
@ -129,8 +124,8 @@ public abstract class AbstractItemListFragment<T> extends ListFragment implement
// When setting CHOICE_MODE_SINGLE, ListView will automatically
// give items the 'activated' state when touched.
getListView().setChoiceMode(activateOnItemClick
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
? ListView.CHOICE_MODE_SINGLE
: ListView.CHOICE_MODE_NONE);
}
}

View File

@ -18,7 +18,6 @@ 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;
@ -31,7 +30,6 @@ 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;
@ -131,19 +129,15 @@ public class AddressDetailFragment extends Fragment {
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);
MainActivity mainActivity = MainActivity.getInstance();
if (item.getPrivateKey() != null && mainActivity != null) {
mainActivity.removeIdentityEntry(item);
}
item = null;
ctx.onBackPressed();
}
})
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
Singleton.getAddressRepository(ctx).remove(item);
MainActivity mainActivity = MainActivity.getInstance();
if (item.getPrivateKey() != null && mainActivity != null) {
mainActivity.removeIdentityEntry(item);
}
item = null;
ctx.onBackPressed();
})
.setNegativeButton(android.R.string.no, null)
.show();
return true;
@ -151,22 +145,18 @@ public class AddressDetailFragment extends Fragment {
case R.id.export: {
new AlertDialog.Builder(ctx)
.setMessage(R.string.confirm_export)
.setPositiveButton(android.R.string.yes, new
DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TITLE, item +
EXPORT_POSTFIX);
WifExporter exporter = new WifExporter(Singleton
.getBitmessageContext(ctx));
exporter.addIdentity(item);
shareIntent.putExtra(Intent.EXTRA_TEXT, exporter.toString
());
startActivity(Intent.createChooser(shareIntent, null));
}
})
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TITLE, item +
EXPORT_POSTFIX);
WifExporter exporter = new WifExporter(Singleton
.getBitmessageContext(ctx));
exporter.addIdentity(item);
shareIntent.putExtra(Intent.EXTRA_TEXT, exporter.toString
());
startActivity(Intent.createChooser(shareIntent, null));
})
.setNegativeButton(android.R.string.no, null)
.show();
return true;
@ -216,12 +206,8 @@ public class AddressDetailFragment extends Fragment {
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);
}
});
active.setOnCheckedChangeListener((buttonView, isChecked) ->
item.setSubscribed(isChecked));
ImageView pubkeyAvailableImg = (ImageView) rootView.findViewById(R.id
.pubkey_available);

View File

@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.MenuItem;
@ -32,7 +33,6 @@ import android.widget.TextView;
import com.google.zxing.integration.android.IntentIntegrator;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import ch.dissem.apps.abit.listener.ActionBarListener;
@ -55,59 +55,53 @@ public class AddressListFragment extends AbstractItemListFragment<BitmessageAddr
public void updateList() {
List<BitmessageAddress> addresses = Singleton.getAddressRepository(getContext())
.getContacts();
Collections.sort(addresses, new Comparator<BitmessageAddress>() {
/**
* Yields the following order:
* <ol>
* <li>Subscribed addresses come first</li>
* <li>Addresses with Aliases (alphabetically)</li>
* <li>Addresses (alphabetically)</li>
* </ol>
*/
@Override
public int compare(BitmessageAddress lhs, BitmessageAddress rhs) {
if (lhs.isSubscribed() == rhs.isSubscribed()) {
if (lhs.getAlias() != null) {
if (rhs.getAlias() != null) {
return lhs.getAlias().compareTo(rhs.getAlias());
} else {
return -1;
}
} else if (rhs.getAlias() != null) {
return 1;
.getContacts();
Collections.sort(addresses, (lhs, rhs) -> {
// Yields the following order:
// * Subscribed addresses come first
// * Addresses with Aliases (alphabetically)
// * Addresses (alphabetically)
if (lhs.isSubscribed() == rhs.isSubscribed()) {
if (lhs.getAlias() != null) {
if (rhs.getAlias() != null) {
return lhs.getAlias().compareTo(rhs.getAlias());
} else {
return lhs.getAddress().compareTo(rhs.getAddress());
return -1;
}
}
if (lhs.isSubscribed()) {
return -1;
} else {
} else if (rhs.getAlias() != null) {
return 1;
} else {
return lhs.getAddress().compareTo(rhs.getAddress());
}
}
if (lhs.isSubscribed()) {
return -1;
} else {
return 1;
}
});
setListAdapter(new ArrayAdapter<BitmessageAddress>(
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
addresses) {
getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
addresses) {
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.subscription_row, null, false);
convertView = inflater.inflate(R.layout.subscription_row, parent, false);
}
BitmessageAddress item = getItem(position);
((ImageView) convertView.findViewById(R.id.avatar)).setImageDrawable(new
Identicon(item));
Identicon(item));
TextView name = (TextView) convertView.findViewById(R.id.name);
name.setText(item.toString());
TextView streamNumber = (TextView) convertView.findViewById(R.id.stream_number);
streamNumber.setText(getContext().getString(R.string.stream_number, item
.getStream()));
.getStream()));
convertView.findViewById(R.id.subscribed).setVisibility(item.isSubscribed() ?
View.VISIBLE : View.INVISIBLE);
View.VISIBLE : View.INVISIBLE);
return convertView;
}
});
@ -124,7 +118,7 @@ public class AddressListFragment extends AbstractItemListFragment<BitmessageAddr
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_address_list, container, false);
FabSpeedDial fabSpeedDial = (FabSpeedDial) view.findViewById(R.id.fab_add_contact);
@ -134,8 +128,8 @@ public class AddressListFragment extends AbstractItemListFragment<BitmessageAddr
switch (menuItem.getItemId()) {
case R.id.action_read_qr_code:
IntentIntegrator.forSupportFragment(AddressListFragment.this)
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
.initiateScan();
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
.initiateScan();
return true;
case R.id.action_create_contact:
Intent intent = new Intent(getActivity(), CreateAddressActivity.class);

View File

@ -18,7 +18,6 @@ package ch.dissem.apps.abit;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Selection;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -90,12 +89,9 @@ public class ComposeMessageFragment extends Fragment {
recipientInput = (AutoCompleteTextView) rootView.findViewById(R.id.recipient);
final ContactAdapter adapter = new ContactAdapter(getContext());
recipientInput.setAdapter(adapter);
recipientInput.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
recipient = adapter.getItem(position);
}
});
recipientInput.setOnItemClickListener(
(parent, view, position, id) -> recipient = adapter.getItem(position)
);
recipientInput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

View File

@ -42,9 +42,6 @@ import ch.dissem.bitmessage.wif.WifImporter;
public class ImportIdentitiesFragment extends Fragment {
public static final String WIF_DATA = "wif_data";
private BitmessageContext bmc;
private RecyclerView recyclerView;
private LinearLayoutManager layoutManager;
private AddressSelectorAdapter adapter;
private WifImporter importer;
@ -53,14 +50,15 @@ public class ImportIdentitiesFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
String wifData = getArguments().getString(WIF_DATA);
bmc = Singleton.getBitmessageContext(getActivity());
BitmessageContext bmc = Singleton.getBitmessageContext(getActivity());
View view = inflater.inflate(R.layout.fragment_import_select_identities, container, false);
try {
importer = new WifImporter(bmc, wifData);
adapter = new AddressSelectorAdapter(importer.getIdentities());
layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL,
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(),
LinearLayoutManager.VERTICAL,
false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
@ -69,18 +67,15 @@ public class ImportIdentitiesFragment extends Fragment {
} catch (IOException e) {
return super.onCreateView(inflater, container, savedInstanceState);
}
view.findViewById(R.id.finish).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
importer.importAll(adapter.getSelected());
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
for (BitmessageAddress selected : adapter.getSelected()) {
mainActivity.addIdentityEntry(selected);
}
view.findViewById(R.id.finish).setOnClickListener(v -> {
importer.importAll(adapter.getSelected());
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
for (BitmessageAddress selected : adapter.getSelected()) {
mainActivity.addIdentityEntry(selected);
}
getActivity().finish();
}
getActivity().finish();
});
return view;
}

View File

@ -19,7 +19,6 @@ package ch.dissem.apps.abit;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Point;
@ -34,7 +33,6 @@ import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import com.github.amlcurran.showcaseview.ShowcaseView;
import com.github.amlcurran.showcaseview.targets.Target;
import com.mikepenz.community_material_typeface_library.CommunityMaterial;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.iconics.IconicsDrawable;
@ -42,7 +40,6 @@ import com.mikepenz.materialdrawer.AccountHeader;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.interfaces.OnCheckedChangeListener;
import com.mikepenz.materialdrawer.model.DividerDrawerItem;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
@ -102,7 +99,8 @@ 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;
private static final int ADD_CHAN = 3;
private static final long ID_NODE_SWITCH = 1;
private static WeakReference<MainActivity> instance;
@ -134,7 +132,7 @@ public class MainActivity extends AppCompatActivity
private AccountHeader accountHeader;
private Drawer drawer;
private ShowcaseView showcaseView;
private SwitchDrawerItem nodeSwitch;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -152,7 +150,9 @@ public class MainActivity extends AppCompatActivity
setSupportActionBar(toolbar);
MessageListFragment listFragment = new MessageListFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.item_list, listFragment)
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.item_list, listFragment)
.commit();
if (findViewById(R.id.message_detail_container) != null) {
@ -189,27 +189,23 @@ public class MainActivity extends AppCompatActivity
int margin = ((Number) (getResources().getDisplayMetrics().density * 12)).intValue();
lps.setMargins(margin, margin, margin, margin);
showcaseView = new ShowcaseView.Builder(this)
new ShowcaseView.Builder(this)
.withMaterialShowcase()
.setStyle(R.style.CustomShowcaseTheme)
.setContentTitle(R.string.full_node)
.setContentText(R.string.full_node_description)
.setTarget(new Target() {
@Override
public Point getPoint() {
View view = drawer.getStickyFooter();
int[] location = new int[2];
view.getLocationInWindow(location);
int x = location[0] + 7 * view.getWidth() / 8;
int y = location[1] + view.getHeight() / 2;
return new Point(x, y);
}
}
)
.setTarget(() -> {
View view = drawer.getStickyFooter();
int[] location = new int[2];
view.getLocationInWindow(location);
int x = location[0] + 7 * view.getWidth() / 8;
int y = location[1] + view.getHeight() / 2;
return new Point(x, y);
})
.replaceEndButton(R.layout.showcase_button)
.hideOnTouchOutside()
.build();
showcaseView.setButtonPosition(lps);
.build()
.setButtonPosition(lps);
}
}
@ -268,32 +264,28 @@ public class MainActivity extends AppCompatActivity
.withActivity(this)
.withHeaderBackground(R.drawable.header)
.withProfiles(profiles)
.withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
@Override
public boolean onProfileChanged(View view, IProfile profile, boolean
currentProfile) {
switch ((int) profile.getIdentifier()) {
case ADD_IDENTITY:
addIdentityDialog();
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) {
Singleton.setIdentity((BitmessageAddress) tag);
}
.withOnAccountHeaderListener((view, profile, currentProfile) -> {
switch ((int) profile.getIdentifier()) {
case ADD_IDENTITY:
addIdentityDialog();
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) {
Singleton.setIdentity((BitmessageAddress) tag);
}
}
// false if it should close the drawer
return false;
}
}
// false if it should close the drawer
return false;
})
.build();
if (profiles.size() > 2) { // There's always the add and manage identity items
@ -346,62 +338,55 @@ public class MainActivity extends AppCompatActivity
.withName(R.string.settings)
.withIcon(GoogleMaterial.Icon.gmd_settings));
nodeSwitch = new SwitchDrawerItem()
.withIdentifier(ID_NODE_SWITCH)
.withName(R.string.full_node)
.withIcon(CommunityMaterial.Icon.cmd_cloud_outline)
.withChecked(isRunning())
.withOnCheckedChangeListener((drawerItem, buttonView, isChecked) -> {
if (isChecked) {
checkAndStartNode(buttonView);
} else {
service.shutdownNode();
}
});
drawer = new DrawerBuilder()
.withActivity(this)
.withToolbar(toolbar)
.withAccountHeader(accountHeader)
.withDrawerItems(drawerItems)
.addStickyDrawerItems(
new SwitchDrawerItem()
.withName(R.string.full_node)
.withIcon(CommunityMaterial.Icon.cmd_cloud_outline)
.withChecked(isRunning())
.withOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(IDrawerItem drawerItem,
CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
checkAndStartNode(buttonView);
} else {
service.shutdownNode();
}
}
})
)
.withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
@Override
public boolean onItemClick(View view, int position, IDrawerItem item) {
if (item.getTag() instanceof Label) {
selectedLabel = (Label) item.getTag();
showSelectedLabel();
return false;
} else if (item instanceof Nameable<?>) {
Nameable<?> ni = (Nameable<?>) item;
switch (ni.getName().getTextRes()) {
case R.string.contacts_and_subscriptions:
if (!(getSupportFragmentManager().findFragmentById(R.id
.item_list) instanceof AddressListFragment)) {
changeList(new AddressListFragment());
} else {
((AddressListFragment) getSupportFragmentManager()
.findFragmentById(R.id.item_list)).updateList();
}
break;
case R.string.settings:
startActivity(new Intent(MainActivity.this, SettingsActivity
.class));
break;
case R.string.archive:
selectedLabel = null;
showSelectedLabel();
break;
case R.string.full_node:
return true;
}
}
.addStickyDrawerItems(nodeSwitch)
.withOnDrawerItemClickListener((view, position, item) -> {
if (item.getTag() instanceof Label) {
selectedLabel = (Label) item.getTag();
showSelectedLabel();
return false;
} else if (item instanceof Nameable<?>) {
Nameable<?> ni = (Nameable<?>) item;
switch (ni.getName().getTextRes()) {
case R.string.contacts_and_subscriptions:
if (!(getSupportFragmentManager().findFragmentById(R.id
.item_list) instanceof AddressListFragment)) {
changeList(new AddressListFragment());
} else {
((AddressListFragment) getSupportFragmentManager()
.findFragmentById(R.id.item_list)).updateList();
}
break;
case R.string.settings:
startActivity(new Intent(MainActivity.this, SettingsActivity
.class));
break;
case R.string.archive:
selectedLabel = null;
showSelectedLabel();
break;
case R.string.full_node:
return true;
}
}
return false;
})
.withShowDrawerOnFirstLaunch(true)
.build();
@ -415,6 +400,7 @@ public class MainActivity extends AppCompatActivity
@Override
protected void onResume() {
updateUnread();
updateNodeSwitch();
super.onResume();
}
@ -470,18 +456,14 @@ public class MainActivity extends AppCompatActivity
} else {
new AlertDialog.Builder(MainActivity.this)
.setMessage(R.string.full_node_warning)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
service.startupNode();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
buttonView.setChecked(false);
}
})
.setPositiveButton(
android.R.string.yes,
(dialog, which) -> service.startupNode()
)
.setNegativeButton(
android.R.string.no,
(dialog, which) -> updateNodeSwitch()
)
.show();
}
}
@ -501,6 +483,13 @@ public class MainActivity extends AppCompatActivity
}
}
public void updateNodeSwitch() {
runOnUiThread(() -> {
nodeSwitch.withChecked(bmc.isRunning());
drawer.updateStickyFooterItem(nodeSwitch);
});
}
private void showSelectedLabel() {
if (getSupportFragmentManager().findFragmentById(R.id.item_list) instanceof
MessageListFragment) {

View File

@ -1,8 +1,6 @@
package ch.dissem.apps.abit;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
/**
* @author Christian Basler

View File

@ -20,7 +20,6 @@ import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatDialogFragment;
import android.view.LayoutInflater;
import android.view.View;
@ -41,7 +40,6 @@ import ch.dissem.bitmessage.entity.payload.Pubkey;
/**
* @author Christian Basler
*/
public class DeterministicIdentityDialogFragment extends AppCompatDialogFragment {
private BitmessageContext bmc;
@ -58,76 +56,68 @@ public class DeterministicIdentityDialogFragment extends AppCompatDialogFragment
getDialog().setTitle(R.string.add_deterministic_address);
View view = inflater.inflate(R.layout.dialog_add_deterministic_identity, container, false);
view.findViewById(R.id.ok)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
final Context context = getActivity().getBaseContext();
View dialogView = getView();
TextView label = (TextView) dialogView.findViewById(R.id.label);
TextView passphrase = (TextView) dialogView.findViewById(R.id.passphrase);
TextView numberOfAddresses = (TextView) dialogView.findViewById(R.id
.number_of_identities);
Switch shorter = (Switch) dialogView.findViewById(R.id.shorter);
.setOnClickListener(v -> {
dismiss();
final Context context = getActivity().getBaseContext();
View dialogView = getView();
TextView label = (TextView) dialogView.findViewById(R.id.label);
TextView passphrase = (TextView) dialogView.findViewById(R.id.passphrase);
TextView numberOfAddresses = (TextView) dialogView.findViewById(R.id
.number_of_identities);
Switch shorter = (Switch) dialogView.findViewById(R.id.shorter);
Toast.makeText(context, R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
new AsyncTask<Object, Void, List<BitmessageAddress>>() {
@Override
protected List<BitmessageAddress> doInBackground(Object... args) {
String label = (String) args[0];
String pass = (String) args[1];
int numberOfAddresses = (int) args[2];
boolean shorter = (boolean) args[3];
List<BitmessageAddress> identities = bmc.createDeterministicAddresses
(pass,
numberOfAddresses, Pubkey.LATEST_VERSION, 1L, shorter);
int i = 0;
for (BitmessageAddress identity : identities) {
i++;
if (identities.size() == 1) {
identity.setAlias(label);
} else {
identity.setAlias(label + " (" + i + ")");
}
bmc.addresses().save(identity);
}
return identities;
}
@Override
protected void onPostExecute(List<BitmessageAddress> identities) {
int messageRes;
Toast.makeText(context, R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
new AsyncTask<Object, Void, List<BitmessageAddress>>() {
@Override
protected List<BitmessageAddress> doInBackground(Object... args) {
String label = (String) args[0];
String pass = (String) args[1];
int numberOfAddresses = (int) args[2];
boolean shorter = (boolean) args[3];
List<BitmessageAddress> identities = bmc.createDeterministicAddresses
(pass,
numberOfAddresses, Pubkey.LATEST_VERSION, 1L, shorter);
int i = 0;
for (BitmessageAddress identity : identities) {
i++;
if (identities.size() == 1) {
messageRes = R.string.toast_identity_created;
identity.setAlias(label);
} else {
messageRes = R.string.toast_identities_created;
identity.setAlias(label + " (" + i + ")");
}
Toast.makeText(context,
messageRes,
Toast.LENGTH_SHORT).show();
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
for (BitmessageAddress identity : identities) {
mainActivity.addIdentityEntry(identity);
}
bmc.addresses().save(identity);
}
return identities;
}
@Override
protected void onPostExecute(List<BitmessageAddress> identities) {
int messageRes;
if (identities.size() == 1) {
messageRes = R.string.toast_identity_created;
} else {
messageRes = R.string.toast_identities_created;
}
Toast.makeText(context,
messageRes,
Toast.LENGTH_SHORT).show();
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
for (BitmessageAddress identity : identities) {
mainActivity.addIdentityEntry(identity);
}
}
}.execute(
label.getText().toString(),
passphrase.getText().toString(),
Integer.valueOf(numberOfAddresses.getText().toString()),
shorter.isChecked()
);
}
}
}.execute(
label.getText().toString(),
passphrase.getText().toString(),
Integer.valueOf(numberOfAddresses.getText().toString()),
shorter.isChecked()
);
});
view.findViewById(R.id.dismiss)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
.setOnClickListener(v -> dismiss());
return view;
}

View File

@ -17,7 +17,6 @@
package ch.dissem.apps.abit.notification;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@ -28,7 +27,7 @@ import java.util.TimerTask;
import ch.dissem.apps.abit.MainActivity;
import ch.dissem.apps.abit.R;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.apps.abit.service.BitmessageService;
import ch.dissem.bitmessage.utils.Property;
/**
@ -37,31 +36,32 @@ import ch.dissem.bitmessage.utils.Property;
public class NetworkNotification extends AbstractNotification {
public static final int ONGOING_NOTIFICATION_ID = 2;
private final BitmessageContext bmc;
private NotificationCompat.Builder builder;
public NetworkNotification(Context ctx, BitmessageContext bmc) {
public NetworkNotification(Context ctx) {
super(ctx);
this.bmc = bmc;
Intent showMessageIntent = new Intent(ctx, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 1, showMessageIntent, 0);
builder = new NotificationCompat.Builder(ctx);
builder.setSmallIcon(R.drawable.ic_notification_full_node)
.setContentTitle(ctx.getString(R.string.bitmessage_full_node))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
}
@Override
public Notification getNotification() {
update();
return notification;
.setContentTitle(ctx.getString(R.string.bitmessage_full_node))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setShowWhen(false)
.setContentIntent(pendingIntent);
}
@SuppressLint("StringFormatMatches")
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean update() {
boolean running = bmc.isRunning();
boolean running = BitmessageService.isRunning();
builder.setOngoing(running);
Property connections = bmc.status().getProperty("network").getProperty("connections");
Property connections = BitmessageService.getStatus().getProperty("network", "connections");
if (!running) {
builder.setContentText(ctx.getString(R.string.connection_info_disconnected));
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
mainActivity.updateNodeSwitch();
}
} else if (connections.getProperties().length == 0) {
builder.setContentText(ctx.getString(R.string.connection_info_pending));
} else {
@ -71,29 +71,24 @@ public class NetworkNotification extends AbstractNotification {
Integer nodeCount = (Integer) stream.getProperty("nodes").getValue();
if (nodeCount == 1) {
info.append(ctx.getString(R.string.connection_info_1,
streamNumber));
streamNumber));
} else {
info.append(ctx.getString(R.string.connection_info_n,
streamNumber, nodeCount));
streamNumber, nodeCount));
}
info.append('\n');
}
builder.setContentText(info);
}
Intent showMessageIntent = new Intent(ctx, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 1, showMessageIntent, 0);
builder.setContentIntent(pendingIntent);
notification = builder.build();
return running;
}
@Override
public void show() {
update();
super.show();
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
if (!update()) {
@ -108,4 +103,10 @@ public class NetworkNotification extends AbstractNotification {
protected int getNotificationId() {
return ONGOING_NOTIFICATION_ID;
}
public void connecting() {
builder.setOngoing(true);
builder.setContentText(ctx.getString(R.string.connection_info_pending));
notification = builder.build();
}
}

View File

@ -36,7 +36,7 @@ import ch.dissem.bitmessage.entity.Plaintext;
import static ch.dissem.apps.abit.util.Drawables.toBitmap;
public class NewMessageNotification extends AbstractNotification {
public static final int NEW_MESSAGE_NOTIFICATION_ID = 1;
private static final int NEW_MESSAGE_NOTIFICATION_ID = 1;
private static final StyleSpan SPAN_EMPHASIS = new StyleSpan(Typeface.BOLD);
public NewMessageNotification(Context ctx) {
@ -62,6 +62,7 @@ public class NewMessageNotification extends AbstractNotification {
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
// TODO: add proper intents to reply/delete
builder.addAction(R.drawable.ic_action_reply, ctx.getString(R.string.reply), pendingIntent);
builder.addAction(R.drawable.ic_action_delete, ctx.getString(R.string.delete),
pendingIntent);

View File

@ -196,7 +196,9 @@ public class AndroidAddressRepository implements AddressRepository {
SQLiteDatabase db = sql.getWritableDatabase();
// Create a new map of values, where column names are the keys
ContentValues values = new ContentValues();
values.put(COLUMN_ALIAS, address.getAlias());
if (address.getAlias() != null) {
values.put(COLUMN_ALIAS, address.getAlias());
}
if (address.getPubkey() != null) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
address.getPubkey().writeUnencrypted(out);
@ -207,7 +209,9 @@ public class AndroidAddressRepository implements AddressRepository {
if (address.getPrivateKey() != null) {
values.put(COLUMN_PRIVATE_KEY, Encode.bytes(address.getPrivateKey()));
}
values.put(COLUMN_CHAN, address.isChan());
if (address.isChan()) {
values.put(COLUMN_CHAN, true);
}
values.put(COLUMN_SUBSCRIBED, address.isSubscribed());
int update = db.update(TABLE_NAME, values, "address=?",

View File

@ -33,7 +33,6 @@ import ch.dissem.bitmessage.entity.ObjectMessage;
import ch.dissem.bitmessage.factory.Factory;
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
import ch.dissem.bitmessage.utils.Encode;
import ch.dissem.bitmessage.utils.Strings;
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
import static ch.dissem.bitmessage.utils.Strings.hex;

View File

@ -21,11 +21,9 @@ import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.dissem.apps.abit.notification.NetworkNotification;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.utils.Property;
import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIFICATION_ID;
@ -35,12 +33,7 @@ import static ch.dissem.apps.abit.notification.NetworkNotification.ONGOING_NOTIF
* onPerformSync().
*/
public class BitmessageService extends Service {
public static final Logger LOG = LoggerFactory.getLogger(BitmessageService.class);
// Object to use as a thread-safe lock
private static final Object lock = new Object();
private static NetworkNotification notification = null;
private NetworkNotification notification = null;
private static BitmessageContext bmc = null;
private static volatile boolean running = false;
@ -51,11 +44,11 @@ public class BitmessageService extends Service {
@Override
public void onCreate() {
synchronized (lock) {
synchronized (BitmessageService.class) {
if (bmc == null) {
bmc = Singleton.getBitmessageContext(this);
notification = new NetworkNotification(this, bmc);
}
notification = new NetworkNotification(this);
}
}
@ -70,7 +63,6 @@ public class BitmessageService extends Service {
running = false;
}
/**
* Return an object that allows the system to invoke
* the sync adapter.
@ -84,6 +76,7 @@ public class BitmessageService extends Service {
public void startupNode() {
startService(new Intent(BitmessageService.this, BitmessageService.class));
running = true;
notification.connecting();
startForeground(ONGOING_NOTIFICATION_ID, notification.getNotification());
if (!bmc.isRunning()) {
bmc.startup();
@ -96,8 +89,17 @@ public class BitmessageService extends Service {
bmc.shutdown();
}
running = false;
stopForeground(false);
stopForeground(true);
notification.show();
stopSelf();
}
}
}
public static Property getStatus() {
if (bmc != null) {
return bmc.status();
} else {
return new Property("bitmessage context", null);
}
}
}

View File

@ -40,7 +40,7 @@ public class ProofOfWorkService extends Service {
private static ProofOfWorkEngine engine = new MultiThreadedPOWEngine();
private static boolean calculating;
private static final Queue<PowItem> queue = new LinkedList<>();
private static ProofOfWorkNotification notification;
private ProofOfWorkNotification notification;
@Override
public void onCreate() {
@ -55,16 +55,18 @@ public class ProofOfWorkService extends Service {
public static class PowBinder extends Binder {
private final ProofOfWorkService service;
private final ProofOfWorkNotification notification;
private PowBinder(ProofOfWorkService service) {
this.service = service;
this.notification = service.notification;
}
public void process(PowItem item) {
void process(PowItem item) {
synchronized (queue) {
service.startService(new Intent(service, ProofOfWorkService.class));
service.startForeground(ONGOING_NOTIFICATION_ID,
notification.getNotification());
notification.getNotification());
if (!calculating) {
calculating = true;
service.calculateNonce(item);
@ -90,28 +92,25 @@ public class ProofOfWorkService extends Service {
}
private void calculateNonce(final PowItem item) {
engine.calculateNonce(item.initialHash, item.targetValue, new ProofOfWorkEngine.Callback() {
@Override
public void onNonceCalculated(byte[] initialHash, byte[] nonce) {
try {
item.callback.onNonceCalculated(initialHash, nonce);
} finally {
PowItem item;
synchronized (queue) {
item = queue.poll();
if (item == null) {
calculating = false;
stopForeground(true);
stopSelf();
} else {
notification.update(queue.size()).show();
}
}
if (item != null) {
calculateNonce(item);
engine.calculateNonce(item.initialHash, item.targetValue, (initialHash, nonce) -> {
try {
item.callback.onNonceCalculated(initialHash, nonce);
} finally {
PowItem next;
synchronized (queue) {
next = queue.poll();
if (next == null) {
calculating = false;
stopForeground(true);
stopSelf();
} else {
notification.update(queue.size()).show();
}
}
if (next != null) {
calculateNonce(next);
}
}
});
}
}
}

View File

@ -46,7 +46,6 @@ import static ch.dissem.bitmessage.utils.UnixTime.DAY;
* Provides singleton objects across the application.
*/
public class Singleton {
public static final Object lock = new Object();
private static BitmessageContext bitmessageContext;
private static MessageListener messageListener;
private static BitmessageAddress identity;
@ -54,28 +53,28 @@ public class Singleton {
public static BitmessageContext getBitmessageContext(Context context) {
if (bitmessageContext == null) {
synchronized (lock) {
synchronized (Singleton.class) {
if (bitmessageContext == null) {
final Context ctx = context.getApplicationContext();
SqlHelper sqlHelper = new SqlHelper(ctx);
powRepo = new AndroidProofOfWorkRepository(sqlHelper);
TTL.pubkey(2 * DAY);
bitmessageContext = new BitmessageContext.Builder()
.proofOfWorkEngine(new SwitchingProofOfWorkEngine(
ctx, Constants.PREFERENCE_SERVER_POW,
new ServerPowEngine(ctx),
new ServicePowEngine(ctx)
))
.cryptography(new AndroidCryptography())
.nodeRegistry(new AndroidNodeRegistry(sqlHelper))
.inventory(new AndroidInventory(sqlHelper))
.addressRepo(new AndroidAddressRepository(sqlHelper))
.messageRepo(new AndroidMessageRepository(sqlHelper, ctx))
.powRepo(powRepo)
.networkHandler(new NioNetworkHandler())
.listener(getMessageListener(ctx))
.doNotSendPubkeyOnIdentityCreation()
.build();
.proofOfWorkEngine(new SwitchingProofOfWorkEngine(
ctx, Constants.PREFERENCE_SERVER_POW,
new ServerPowEngine(ctx),
new ServicePowEngine(ctx)
))
.cryptography(new AndroidCryptography())
.nodeRegistry(new AndroidNodeRegistry(sqlHelper))
.inventory(new AndroidInventory(sqlHelper))
.addressRepo(new AndroidAddressRepository(sqlHelper))
.messageRepo(new AndroidMessageRepository(sqlHelper, ctx))
.powRepo(powRepo)
.networkHandler(new NioNetworkHandler())
.listener(getMessageListener(ctx))
.doNotSendPubkeyOnIdentityCreation()
.build();
}
}
}
@ -108,11 +107,12 @@ public class Singleton {
public static BitmessageAddress getIdentity(Context ctx) {
if (identity == null) {
BitmessageContext bmc = getBitmessageContext(ctx);
synchronized (Singleton.class) {
if (identity == null) {
BitmessageContext bmc = getBitmessageContext(ctx);
// FIXME: this may block the UI, there must be a better way!
List<BitmessageAddress> identities = bmc.addresses()
.getIdentities();
.getIdentities();
if (identities.size() > 0) {
identity = identities.get(0);
} else {

View File

@ -25,7 +25,6 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import ch.dissem.apps.abit.R;
import ch.dissem.apps.abit.listener.WifiReceiver;
@ -39,8 +38,6 @@ import static ch.dissem.apps.abit.util.Constants.PREFERENCE_WIFI_ONLY;
* @author Christian Basler
*/
public class Preferences {
private static Logger LOG = LoggerFactory.getLogger(Preferences.class);
public static boolean useTrustedNode(Context ctx) {
String trustedNode = getPreference(ctx, PREFERENCE_TRUSTED_NODE);
return trustedNode != null && !trustedNode.trim().isEmpty();

View File

@ -51,7 +51,8 @@
android:layout_margin="16dp"
android:background="@color/contentBackground"
android:elevation="2dp"
tools:layout="@layout/fragment_message_detail"/>
tools:layout="@layout/fragment_message_detail"
tools:ignore="InconsistentLayout,UnusedAttribute"/>
</FrameLayout>
</LinearLayout>

View File

@ -15,7 +15,7 @@
android:layout_height="wrap_content"
android:hint="@string/to"
android:inputType="textNoSuggestions"
android:singleLine="true"/>
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
@ -43,4 +43,4 @@
android:inputType="textMultiLine|textCapSentences"
android:scrollbars="vertical"/>
</LinearLayout>
</LinearLayout>

View File

@ -1,14 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Got it"
android:textStyle="bold"
android:background="@drawable/material_showcase_button_bg"
android:textSize="13sp"
android:text="Got it"
android:textAllCaps="true"
android:textColor="@android:color/white"
>
</Button>
android:textSize="13sp"
android:textStyle="bold">
</Button>

View File

@ -34,10 +34,11 @@
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:layout_toStartOf="@+id/subscribed"
android:ellipsize="end"
android:lines="1"
android:paddingBottom="0dp"
@ -60,7 +61,8 @@
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Stream #"/>
tools:text="Stream #"
tools:ignore="RelativeOverlap"/>
<com.mikepenz.iconics.view.IconicsImageView
android:id="@+id/subscribed"

View File

@ -5,19 +5,15 @@
<string name="title_message_detail">Nachricht</string>
<string name="title_subscription_detail">Abonnement</string>
<string name="bitmessage_full_node">Bitmessage Netzknoten</string>
<string name="wifi_mode">Art der WLAN-Verbindung</string>
<string name="settings">Einstellungen</string>
<string name="wifi_only">Nur WLAN</string>
<string name="wifi_only_summary">Nicht mit Mobilfunknetz verbinden</string>
<string name="subscriptions">Abonnements</string>
<string name="to">An</string>
<string name="subject">Betreff</string>
<string name="manage_identity">Identität verwalten</string>
<string name="add_identity">Identität hinzufügen</string>
<string name="add_identity_summary">Eine neue Identität erstellen</string>
<string name="create_identity">Erstellen</string>
<string name="create_identity_description">Eine neue, zufällige Identität erstellen</string>
<string name="import_identity">Importieren</string>
<string name="import_identity_description">Eine existierende Identität von PyBitmessage oder einem Export importieren</string>
<string name="add_deterministic_address">Deterministische Identität</string>
<string name="add_deterministic_address_description">Eine deterministische Identität erstellen oder wiederherstellen</string>
@ -25,11 +21,8 @@
<string name="add_chan_description">Einen Chan erstellen oder einem beitreten</string>
<string name="title_activity_open_bitmessage_link">Kontakt importieren</string>
<string name="action_settings">Einstellungen</string>
<string name="connection_info_1">Stream %1$d: eine Verbindung</string>
<string name="connection_info_n">Stream %1$d: %2$d Verbindungen</string>
<string name="import_address">Adresse importieren</string>
<string name="import_contact">Kontakt hinzufügen</string>
<string name="label">Label</string>
<string name="subscribe">Abonnieren</string>
<string name="do_import">Importieren</string>
@ -42,7 +35,6 @@
<string name="archive">Archiv</string>
<string name="empty_trash">Papierkorb leeren</string>
<string name="stream_number">Stream %d</string>
<string name="enabled">Aktiv</string>
<string name="trusted_node">Vertrauenswürdiger Knoten</string>
<string name="trusted_node_summary">Diese Adresse wird für die Synchronisation verwendet</string>
<string name="sync_timeout">Zeitbeschränkung der Synchronisierung</string>
@ -56,7 +48,6 @@
<string name="proof_of_work_text_0">Arbeite am Versenden</string>
<string name="proof_of_work_text_n">Arbeite am Versenden (%1$d in Warteschlange)</string>
<string name="error_invalid_sync_port">Ungültiger Port in den Synchronisationseinstellungen: %s</string>
<string name="error_invalid_sync_host">Synchronisation fehlgeschlagen: der vertrauenswürdige Knoten konnte nicht erreicht werden.</string>
<string name="compose_body_hint">Nachricht schreiben</string>
<string name="contacts_and_subscriptions">Kontakte</string>
<string name="subscribed">Abonniert</string>
@ -78,10 +69,9 @@
<string name="delete_contact_warning">Bist Du sicher dass dieser Kontakt gelöscht werden soll?</string>
<string name="scan_qr_code">QR-Code scannen</string>
<string name="create_contact">Kontakt erfassen</string>
<string name="full_node_description">Solange kein aktiver Knoten gestartet ist, werden keine Meldungen empfangen oder gesendet. Dies braucht jedoch viele Resourcen und Daten.
<string name="full_node_description">Solange kein aktiver Knoten gestartet ist, werden keine Meldungen empfangen oder gesendet. Dies braucht jedoch viele Ressourcen und Daten.
Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfiguriert werden, aber im Moment muss dieser selbst bereitgestellt werden.</string>
<string name="got_it">Alles klar</string>
<string name="address">Bitmessage-Adresse</string>
<string name="error_illegal_address">Vielleicht hat es einen Tippfehler</string>
<string name="export">Exportieren</string>
@ -95,7 +85,7 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
<string name="toast_identity_created">Identität erstellt</string>
<string name="toast_identities_created">Identitäten erstellt</string>
<string name="toast_chan_created">Chan erstellt</string>
<string name="deterministic_address_warning">Merke dir diese Enstellungen und stelle sicher dass sie korrekt sind wenn du eine deterministische Addresse wiederherstellst.</string>
<string name="deterministic_address_warning">Merke dir diese Enstellungen und stelle sicher dass sie korrekt sind wenn du eine deterministische Adresse wiederherstellst.</string>
<string name="number_of_identities">Anzahl zu generierender Identitäten</string>
<string name="shorter">Kürzere Adressen suchen</string>
<string name="wif_string">WIF / Inhalt von keys.dat</string>
@ -106,5 +96,4 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
<string name="select_file_title">Datei auswählen</string>
<string name="select_identities_to_import">Bitte wähle die zu importierenden Identitäten:</string>
<string name="import_input_description">Du kannst einfach den Inhalt eines Exports oder einer keys.dat-Datei einfügen</string>
<string name="name">Name</string>
</resources>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Palette generated by Material Palette - materialpalette.com/blue-grey/orange -->
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<color name="colorPrimary">#FFC107</color>
<color name="colorPrimaryDark">#FFA000</color>
<color name="colorPrimaryDarkText">#DEFFFFFF</color>

View File

@ -15,7 +15,7 @@
~ limitations under the License.
-->
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<string name="define_fab_speed_dial" translatable="false"/>
<!-- Author section -->
<string name="library_fab_speed_dial_author" translatable="false">Yavor Ivanov</string>

View File

@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<string name="define_int_filepicker" translatable="false"/>
<!-- Author section -->
<string name="library_filepicker_author" translatable="false">Angad Singh</string>
<string name="library_filepicker_authorWebsite" translatable="false">https://github.com/Angads25</string>
<!-- Library section -->
<string name="library_filepicker_libraryName" translatable="false">FilePicker</string>
<string name="library_filepicker_libraryDescription">Android Library to select files/directories from Device Storage.</string>
<string name="library_filepicker_libraryWebsite" translatable="false">https://github.com/Angads25/android-filepicker</string>
<string name="library_filepicker_libraryVersion" translatable="false">1.0.6</string>
<!-- OpenSource section -->
<string name="library_filepicker_isOpenSource" translatable="false">true</string>
<string name="library_filepicker_repositoryLink" translatable="false">https://github.com/Angads25/android-filepicker</string>
<!-- ClassPath for autoDetect section -->
<string name="library_filepicker_classPath" translatable="false">com.github.angads25.filepicker.view.FilePickerDialog</string>
<!-- License section -->
<string name="library_filepicker_licenseId" translatable="false">apache_2_0</string>
<!-- Custom variables section -->
<!-- Author section -->
<string name="library_filepicker_author" translatable="false">Angad Singh</string>
<string name="library_filepicker_authorWebsite" translatable="false">https://github.com/Angads25</string>
<!-- Library section -->
<string name="library_filepicker_libraryName" translatable="false">FilePicker</string>
<string name="library_filepicker_libraryDescription">Android Library to select files/directories from Device Storage.</string>
<string name="library_filepicker_libraryWebsite" translatable="false">https://github.com/Angads25/android-filepicker</string>
<string name="library_filepicker_libraryVersion" translatable="false">1.0.6</string>
<!-- OpenSource section -->
<string name="library_filepicker_isOpenSource" translatable="false">true</string>
<string name="library_filepicker_repositoryLink" translatable="false">https://github.com/Angads25/android-filepicker</string>
<!-- ClassPath for autoDetect section -->
<string name="library_filepicker_classPath" translatable="false">com.github.angads25.filepicker.view.FilePickerDialog</string>
<!-- License section -->
<string name="library_filepicker_licenseId" translatable="false">apache_2_0</string>
<!-- Custom variables section -->
</resources>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<string name="define_jabit" translatable="false"/>
<!-- Author section -->
<string name="library_jabit_author" translatable="false">Christian Basler</string>

View File

@ -15,7 +15,7 @@
~ limitations under the License.
-->
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<string name="define_zxing" translatable="false"/>
<!-- Author section -->
<string name="library_zxing_author" translatable="false">Google, Inc.</string>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources">
<string name="define_int_zxingandroidembedded" translatable="false"/>
<!-- Author section -->
<string name="library_zxingandroidembedded_author" translatable="false">JourneyApps</string>

View File

@ -1,22 +1,18 @@
<resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">Abit</string>
<string name="about_app">A Bitmessage client for Android</string>
<string name="title_message_detail">Message Detail</string>
<string name="title_subscription_detail">Subscription Detail</string>
<string name="bitmessage_full_node">Bitmessage Node</string>
<string name="wifi_mode">Wi-Fi Connection Mode</string>
<string name="settings">Settings</string>
<string name="wifi_only">Wi-Fi only</string>
<string name="wifi_only_summary">Don\'t connect to the mobile network</string>
<string name="subscriptions">Subscriptions</string>
<string name="to">To</string>
<string name="subject">Subject</string>
<string name="manage_identity">Manage Identity</string>
<string name="add_identity">Add Identity</string>
<string name="add_identity_summary">Create new identity</string>
<string name="create_identity">Create new</string>
<string name="create_identity_description">Create a new, random identity</string>
<string name="import_identity">Import existing</string>
<string name="import_identity_description">Import an existing identity from PyBitmessage or from an export</string>
<string name="add_deterministic_address">Deterministic identity</string>
<string name="add_deterministic_address_description">Create or recreate a deterministic identity</string>
@ -24,24 +20,20 @@
<string name="add_chan_description">Create or join a chan</string>
<string name="title_activity_open_bitmessage_link">Import Contact</string>
<string name="action_settings">Settings</string>
<string name="connection_info_1">Stream #%1$d: one connection</string>
<string name="connection_info_n">Stream #%1$d: %2$d connections</string>
<string name="import_address">Import Address</string>
<string name="import_contact">Add to contacts</string>
<string name="connection_info_n" tools:ignore="PluralsCandidate">Stream #%1$d: %2$d connections</string>
<string name="label">Label</string>
<string name="subscribe">Subscribe</string>
<string name="do_import">Import</string>
<string name="cancel">Cancel</string>
<string name="broadcast">Broadcast</string>
<string name="n_new_messages">%d new messages</string>
<string name="n_new_messages" tools:ignore="PluralsCandidate">%d new messages</string>
<string name="reply">Reply</string>
<string name="delete">Delete</string>
<string name="mark_unread">Mark unread</string>
<string name="archive">Archive</string>
<string name="empty_trash">Empty Trash</string>
<string name="stream_number">Stream #%d</string>
<string name="enabled">Enabled</string>
<string name="trusted_node">Trusted node</string>
<string name="trusted_node_summary">Use this node for synchronization</string>
<string name="sync_timeout">Synchronization Timeout</string>
@ -53,9 +45,8 @@
<string name="connection_info_pending">Connecting…</string>
<string name="proof_of_work_title">Proof of Work</string>
<string name="proof_of_work_text_0">Doing work to send message</string>
<string name="proof_of_work_text_n">Doing work to send message (%1$d queued)</string>
<string name="proof_of_work_text_n" tools:ignore="PluralsCandidate">Doing work to send message (%1$d queued)</string>
<string name="error_invalid_sync_port">Invalid port in synchronization settings: %s</string>
<string name="error_invalid_sync_host">Synchronization failed: Trusted node could not be reached.</string>
<string name="compose_body_hint">Write message</string>
<string name="contacts_and_subscriptions">Contacts</string>
<string name="subscribed">Subscribed</string>
@ -80,7 +71,6 @@
<string name="full_node_description">You can\'t receive or send messages unless you start a full node. But be aware that this uses a lot of resources and internet traffic.
As an alternative you could configure a trusted node in the settings, but as of now you\'ll need to deploy your own.</string>
<string name="got_it">Got it</string>
<string name="address">Bitmessage Address</string>
<string name="error_illegal_address">There might be a typo</string>
<string name="export">Export</string>
@ -105,5 +95,4 @@ As an alternative you could configure a trusted node in the settings, but as of
<string name="select_file_title">Select a File</string>
<string name="select_identities_to_import">Please select the identities you want to import:</string>
<string name="import_input_description">You can just paste the contents of an export or a keys.dat file</string>
<string name="name">Name</string>
</resources>

View File

@ -9,7 +9,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.android.tools.build:gradle:2.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files