Merge remote-tracking branch 'origin/develop' into feature/support-info

# Conflicts:
#	app/src/main/res/values-de/strings.xml
#	app/src/main/res/values/strings.xml
This commit is contained in:
Christian Basler 2016-10-07 23:13:06 +02:00
commit 30bb407bbf
47 changed files with 1689 additions and 291 deletions

View File

@ -11,14 +11,14 @@ if (project.hasProperty("project.configs")
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
buildToolsVersion "24.0.3"
defaultConfig {
applicationId "ch.dissem.apps." + appName.toLowerCase()
minSdkVersion 19
targetSdkVersion 24
versionCode 7
versionName "1.0-beta7"
versionCode 8
versionName "1.0-beta8"
}
buildTypes {
release {
@ -29,7 +29,7 @@ android {
}
}
ext.jabitVersion = 'development-SNAPSHOT'
ext.jabitVersion = '2.0.0'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.1'
@ -54,16 +54,18 @@ dependencies {
compile 'com.mikepenz:iconics:1.6.2@aar'
compile 'com.mikepenz:community-material-typeface:1.5.54.2@aar'
compile 'com.journeyapps:zxing-android-embedded:3.1.0@aar'
compile 'com.google.zxing:core:3.2.0'
compile 'io.github.yavski:fab-speed-dial:1.0.2'
compile 'com.journeyapps:zxing-android-embedded:3.3.0@aar'
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.github.angads25:filepicker:1.0.6'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha9'
}
idea.module {

View File

@ -18,7 +18,8 @@
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
@ -103,6 +104,26 @@
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
<activity
android:name=".ImportIdentityActivity"
android:label="@string/title_import_identity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<data
android:host="*"
android:mimeType="*/*"
android:pathPattern=".*\\.dat"
android:scheme="file"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
<service android:name=".service.BitmessageService"/>
<service android:name=".service.ProofOfWorkService"/>

View File

@ -106,8 +106,8 @@ public class AddressDetailFragment extends Fragment {
Drawables.addIcon(getActivity(), menu, R.id.share, GoogleMaterial.Icon.gmd_share);
Drawables.addIcon(getActivity(), menu, R.id.delete, GoogleMaterial.Icon.gmd_delete);
Drawables.addIcon(getActivity(), menu, R.id.export,
CommunityMaterial.Icon.cmd_export)
.setVisible(item != null && item.getPrivateKey() != null);
CommunityMaterial.Icon.cmd_export)
.setVisible(item != null && item.getPrivateKey() != null);
super.onCreateOptionsMenu(menu, inflater);
}
@ -130,41 +130,45 @@ public class AddressDetailFragment extends Fragment {
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();
.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();
}
})
.setNegativeButton(android.R.string.no, null)
.show();
return true;
}
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));
}
})
.setNegativeButton(android.R.string.no, null)
.show();
.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));
}
})
.setNegativeButton(android.R.string.no, null)
.show();
return true;
}
case R.id.share: {
@ -208,7 +212,7 @@ public class AddressDetailFragment extends Fragment {
address.setText(item.getAddress());
address.setSelected(true);
((TextView) rootView.findViewById(R.id.stream_number)).setText(getActivity()
.getString(R.string.stream_number, item.getStream()));
.getString(R.string.stream_number, item.getStream()));
if (item.getPrivateKey() == null) {
Switch active = (Switch) rootView.findViewById(R.id.active);
active.setChecked(item.isSubscribed());
@ -220,12 +224,12 @@ public class AddressDetailFragment extends Fragment {
});
ImageView pubkeyAvailableImg = (ImageView) rootView.findViewById(R.id
.pubkey_available);
.pubkey_available);
if (item.getPubkey() == null) {
pubkeyAvailableImg.setAlpha(0.3f);
TextView pubkeyAvailableDesc = (TextView) rootView.findViewById(R.id
.pubkey_available_desc);
.pubkey_available_desc);
pubkeyAvailableDesc.setText(R.string.pubkey_not_available);
}
} else {
@ -251,7 +255,7 @@ public class AddressDetailFragment extends Fragment {
BitMatrix result;
try {
result = new MultiFormatWriter().encode(link.toString(),
BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE, null);
BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE, null);
} catch (WriterException e) {
LOG.error(e.getMessage(), e);
return null;
@ -274,6 +278,10 @@ public class AddressDetailFragment extends Fragment {
public void onPause() {
if (item != null) {
Singleton.getAddressRepository(getContext()).save(item);
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null && item.getPrivateKey() != null) {
mainActivity.updateIdentityEntry(item);
}
}
super.onPause();
}

View File

@ -0,0 +1,87 @@
/*
* 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.
*/
package ch.dissem.apps.abit;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator;
import java.io.IOException;
import ch.dissem.apps.abit.adapter.AddressSelectorAdapter;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.wif.WifImporter;
/**
* @author Christian Basler
*/
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;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
String wifData = getArguments().getString(WIF_DATA);
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,
false);
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new SimpleListDividerDecorator(
ContextCompat.getDrawable(getActivity(), R.drawable.list_divider_h), true));
} 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);
}
}
getActivity().finish();
}
});
return view;
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.
*/
package ch.dissem.apps.abit;
import android.os.Bundle;
import static ch.dissem.apps.abit.ImportIdentitiesFragment.WIF_DATA;
/**
* @author Christian Basler
*/
public class ImportIdentityActivity extends DetailActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String wifData;
if (savedInstanceState == null) {
wifData = null;
} else {
wifData = savedInstanceState.getString(WIF_DATA);
}
if (wifData == null) {
getFragmentManager().beginTransaction()
.replace(R.id.content, new InputWifFragment())
.commit();
} else {
Bundle bundle = new Bundle();
bundle.putString(WIF_DATA, wifData);
ImportIdentitiesFragment fragment = new ImportIdentitiesFragment();
fragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.replace(R.id.content, fragment)
.commit();
}
}
}

View File

@ -0,0 +1,122 @@
/*
* 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.
*/
package ch.dissem.apps.abit;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
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.TextView;
import android.widget.Toast;
import com.github.angads25.filepicker.controller.DialogSelectionListener;
import com.github.angads25.filepicker.model.DialogConfigs;
import com.github.angads25.filepicker.model.DialogProperties;
import com.github.angads25.filepicker.view.FilePickerDialog;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import static ch.dissem.apps.abit.ImportIdentitiesFragment.WIF_DATA;
/**
* @author Christian Basler
*/
public class InputWifFragment extends Fragment {
private TextView wifData;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_import_input, container, false);
wifData = (TextView) view.findViewById(R.id.wif_input);
view.findViewById(R.id.next).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putString(WIF_DATA, wifData.getText().toString());
ImportIdentitiesFragment fragment = new ImportIdentitiesFragment();
fragment.setArguments(bundle);
getFragmentManager().beginTransaction()
.replace(R.id.content, fragment)
.commit();
}
});
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.import_input_data, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
DialogProperties properties = new DialogProperties();
properties.selection_mode = DialogConfigs.SINGLE_MODE;
properties.selection_type = DialogConfigs.FILE_SELECT;
properties.root = new File(DialogConfigs.DEFAULT_DIR);
properties.error_dir = new File(DialogConfigs.DEFAULT_DIR);
properties.extensions = null;
FilePickerDialog dialog = new FilePickerDialog(getActivity(), properties);
dialog.setTitle(getString(R.string.select_file_title));
dialog.setDialogSelectionListener(new DialogSelectionListener() {
@Override
public void onSelectedFilePaths(String[] files) {
if (files.length > 0) {
try (InputStream in = new FileInputStream(files[0])) {
ByteArrayOutputStream data = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
//noinspection ConstantConditions
while ((length = in.read(buffer)) != -1) {
data.write(buffer, 0, length);
}
wifData.setText(data.toString("UTF-8"));
} catch (IOException e) {
Toast.makeText(
getActivity(),
R.string.error_loading_data,
Toast.LENGTH_SHORT
).show();
}
}
}
});
dialog.show();
return true;
}
}

View File

@ -16,7 +16,6 @@
package ch.dissem.apps.abit;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
@ -24,7 +23,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Point;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.Fragment;
@ -34,8 +32,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.github.amlcurran.showcaseview.ShowcaseView;
import com.github.amlcurran.showcaseview.targets.Target;
@ -65,6 +61,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import ch.dissem.apps.abit.dialog.AddIdentityDialogFragment;
import ch.dissem.apps.abit.listener.ActionBarListener;
import ch.dissem.apps.abit.listener.ListSelectionListener;
import ch.dissem.apps.abit.service.BitmessageService;
@ -75,7 +72,6 @@ import ch.dissem.apps.abit.util.Preferences;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.payload.Pubkey;
import ch.dissem.bitmessage.entity.valueobject.Label;
import static ch.dissem.apps.abit.service.BitmessageService.isRunning;
@ -143,6 +139,7 @@ public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance = new WeakReference<>(this);
bmc = Singleton.getBitmessageContext(this);
List<Label> labels = bmc.messages().getLabels();
if (selectedLabel == null) {
@ -261,15 +258,6 @@ public class MainActivity extends AppCompatActivity
.colorRes(R.color.icons))
.withIdentifier(ADD_IDENTITY)
);
profiles.add(new ProfileSettingDrawerItem()
.withName(getString(R.string.add_chan))
.withDescription(getString(R.string.add_chan_summary))
.withIcon(new IconicsDrawable(this, GoogleMaterial.Icon.gmd_add)
.actionBar()
.paddingDp(5)
.colorRes(R.color.icons))
.withIdentifier(ADD_CHAN)
);
profiles.add(new ProfileSettingDrawerItem()
.withName(getString(R.string.manage_identity))
.withIcon(GoogleMaterial.Icon.gmd_settings)
@ -288,9 +276,6 @@ public class MainActivity extends AppCompatActivity
case ADD_IDENTITY:
addIdentityDialog();
break;
case ADD_CHAN:
addChanDialog();
break;
case MANAGE_IDENTITY:
Intent show = new Intent(MainActivity.this,
AddressDetailActivity.class);
@ -423,102 +408,58 @@ public class MainActivity extends AppCompatActivity
}
private void addIdentityDialog() {
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) {
Toast.makeText(MainActivity.this,
R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
new AsyncTask<Void, Void, BitmessageAddress>() {
@Override
protected BitmessageAddress doInBackground(Void... args) {
return bmc.createIdentity(false, Pubkey.Feature.DOES_ACK);
}
@Override
protected void onPostExecute(BitmessageAddress chan) {
Toast.makeText(MainActivity.this,
R.string.toast_identity_created,
Toast.LENGTH_SHORT).show();
addIdentityEntry(chan);
}
}.execute();
}
})
.setNegativeButton(android.R.string.no, null)
.show();
}
private void addChanDialog() {
@SuppressLint("InflateParams")
final View dialogView = getLayoutInflater().inflate(R.layout.dialog_input_passphrase, null);
new AlertDialog.Builder(MainActivity.this)
.setMessage(R.string.add_chan)
.setView(dialogView)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
TextView passphrase = (TextView) dialogView.findViewById(R.id.passphrase);
Toast.makeText(MainActivity.this, R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
new AsyncTask<String, Void, BitmessageAddress>() {
@Override
protected BitmessageAddress doInBackground(String... args) {
String pass = args[0];
BitmessageAddress chan = bmc.createChan(pass);
chan.setAlias(pass);
bmc.addresses().save(chan);
return chan;
}
@Override
protected void onPostExecute(BitmessageAddress chan) {
Toast.makeText(MainActivity.this,
R.string.toast_chan_created,
Toast.LENGTH_SHORT).show();
addIdentityEntry(chan);
}
}.execute(passphrase.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null)
.show();
AddIdentityDialogFragment dialog = new AddIdentityDialogFragment();
dialog.show(getSupportFragmentManager(), "dialog");
}
@Override
protected void onResume() {
instance = new WeakReference<>(this);
updateUnread();
super.onResume();
}
private void addIdentityEntry(BitmessageAddress identity) {
IProfile newProfile = new
ProfileDrawerItem()
public void addIdentityEntry(BitmessageAddress identity) {
IProfile newProfile = new ProfileDrawerItem()
.withIcon(new Identicon(identity))
.withName(identity.toString())
.withNameShown(true)
.withEmail(identity.getAddress())
.withTag(identity);
if (accountHeader.getProfiles() != null) {
// we know that there are 3 setting
// we know that there are 2 setting
// elements.
// Set the new profile above them ;)
accountHeader.addProfile(
newProfile, accountHeader
.getProfiles().size()
- 3);
- 2);
} else {
accountHeader.addProfiles(newProfile);
}
}
@Override
protected void onPause() {
super.onPause();
instance = null;
public void updateIdentityEntry(BitmessageAddress identity) {
for (IProfile profile : accountHeader.getProfiles()) {
if (profile instanceof ProfileDrawerItem) {
if (identity.equals(((ProfileDrawerItem) profile).getTag())) {
((ProfileDrawerItem) profile)
.withName(identity.toString())
.withTag(identity);
return;
}
}
}
}
public void removeIdentityEntry(BitmessageAddress identity) {
for (IProfile profile : accountHeader.getProfiles()) {
if (profile instanceof ProfileDrawerItem) {
if (identity.equals(((ProfileDrawerItem) profile).getTag())) {
accountHeader.removeProfile(profile);
return;
}
}
}
}
private void checkAndStartNode(final CompoundButton buttonView) {

View File

@ -70,7 +70,7 @@ public class MessageListFragment extends Fragment implements ListHolder {
private Label currentLabel;
private MenuItem emptyTrashMenuItem;
private MessageRepository messageRepo;
private List<Plaintext> messages;
private boolean activateOnItemClick;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
@ -105,7 +105,7 @@ public class MessageListFragment extends Fragment implements ListHolder {
}
private void doUpdateList(Label label) {
messages = Singleton.getMessageRepository(getContext()).findMessages(label);
List<Plaintext> messages = Singleton.getMessageRepository(getContext()).findMessages(label);
if (getActivity() instanceof ActionBarListener) {
if (label != null) {
((ActionBarListener) getActivity()).updateTitle(label.toString());
@ -153,6 +153,7 @@ public class MessageListFragment extends Fragment implements ListHolder {
//adapter
adapter = new SwipeableMessageAdapter();
adapter.setActivateOnItemClick(activateOnItemClick);
adapter.setEventListener(new SwipeableMessageAdapter.EventListener() {
@Override
public void onItemDeleted(Plaintext item) {
@ -174,6 +175,7 @@ public class MessageListFragment extends Fragment implements ListHolder {
@Override
public void onItemViewClicked(View v, boolean pinned) {
int position = recyclerView.getChildAdapterPosition(v);
adapter.setSelectedPosition(position);
if (position != RecyclerView.NO_POSITION) {
Plaintext item = adapter.getItem(position);
((MainActivity) getActivity()).onItemSelected(item);
@ -263,6 +265,9 @@ public class MessageListFragment extends Fragment implements ListHolder {
@Override
public void setActivateOnItemClick(boolean activateOnItemClick) {
// TODO
if (adapter != null) {
adapter.setActivateOnItemClick(activateOnItemClick);
}
this.activateOnItemClick = activateOnItemClick;
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.
*/
package ch.dissem.apps.abit.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import ch.dissem.apps.abit.R;
import ch.dissem.bitmessage.entity.BitmessageAddress;
/**
* @author Christian Basler
*/
public class AddressSelectorAdapter
extends RecyclerView.Adapter<AddressSelectorAdapter.ViewHolder> {
private final List<Selectable<BitmessageAddress>> data;
public AddressSelectorAdapter(List<BitmessageAddress> identities) {
data = new ArrayList<>(identities.size());
for (BitmessageAddress identity : identities) {
data.add(new Selectable<>(identity));
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final View v = inflater.inflate(R.layout.select_identity_row, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Selectable<BitmessageAddress> selectable = data.get(position);
holder.data = selectable;
holder.checkbox.setChecked(selectable.selected);
holder.checkbox.setText(selectable.data.toString());
holder.address.setText(selectable.data.getAddress());
}
@Override
public int getItemCount() {
return data.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
public Selectable<BitmessageAddress> data;
public CheckBox checkbox;
public TextView address;
private ViewHolder(View v) {
super(v);
checkbox = (CheckBox) v.findViewById(R.id.checkbox);
address = (TextView) v.findViewById(R.id.address);
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (data != null) {
data.selected = isChecked;
}
}
});
}
}
public List<BitmessageAddress> getSelected() {
List<BitmessageAddress> result = new LinkedList<>();
for (Selectable<BitmessageAddress> selectable : data) {
if (selectable.selected) {
result.add(selectable.data);
}
}
return result;
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.
*/
package ch.dissem.apps.abit.adapter;
/**
* @author Christian Basler
*/
class Selectable<T> {
final T data;
boolean selected = false;
Selectable(T data) {
this.data = data;
}
}

View File

@ -17,6 +17,7 @@
package ch.dissem.apps.abit.adapter;
import android.annotation.SuppressLint;
import android.graphics.Typeface;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@ -50,7 +51,7 @@ import static ch.dissem.apps.abit.util.Strings.normalizeWhitespaces;
*
* @author Christian Basler
* @see <a href="https://github.com/h6ah4i/android-advancedrecyclerview">
* https://github.com/h6ah4i/android-advancedrecyclerview</a>
* https://github.com/h6ah4i/android-advancedrecyclerview</a>
*/
public class SwipeableMessageAdapter
extends RecyclerView.Adapter<SwipeableMessageAdapter.ViewHolder>
@ -62,6 +63,12 @@ public class SwipeableMessageAdapter
private View.OnClickListener swipeableViewContainerOnClickListener;
private Label label;
private int selectedPosition;
private boolean activateOnItemClick;
public void setActivateOnItemClick(boolean activateOnItemClick) {
this.activateOnItemClick = activateOnItemClick;
}
public interface EventListener {
void onItemDeleted(Plaintext item);
@ -71,14 +78,15 @@ public class SwipeableMessageAdapter
void onItemViewClicked(View v, boolean pinned);
}
public static class ViewHolder extends AbstractSwipeableItemViewHolder {
@SuppressWarnings("WeakerAccess")
static class ViewHolder extends AbstractSwipeableItemViewHolder {
public FrameLayout container;
public final ImageView avatar;
public final TextView sender;
public final TextView subject;
public final TextView extract;
public ViewHolder(View v) {
ViewHolder(View v) {
super(v);
container = (FrameLayout) v.findViewById(R.id.container);
avatar = (ImageView) v.findViewById(R.id.avatar);
@ -150,6 +158,14 @@ public class SwipeableMessageAdapter
public void onBindViewHolder(ViewHolder holder, int position) {
final Plaintext item = data.get(position);
if (activateOnItemClick) {
holder.container.setBackgroundResource(
position == selectedPosition
? R.drawable.bg_item_selected_state
: R.drawable.bg_item_normal_state
);
}
// set listeners
// (if the item is *pinned*, click event comes to the itemView)
holder.itemView.setOnClickListener(itemViewOnClickListener);
@ -184,6 +200,7 @@ public class SwipeableMessageAdapter
}
@Override
@SuppressLint("SwitchIntDef")
public void onSetSwipeBackground(ViewHolder holder, int position, int type) {
int bgRes = 0;
switch (type) {
@ -205,6 +222,7 @@ public class SwipeableMessageAdapter
}
@Override
@SuppressLint("SwitchIntDef")
public SwipeResultAction onSwipeItem(ViewHolder holder, final int position, int result) {
switch (result) {
// swipe right
@ -223,6 +241,13 @@ public class SwipeableMessageAdapter
this.eventListener = eventListener;
}
public void setSelectedPosition(int selectedPosition) {
int oldPosition = this.selectedPosition;
this.selectedPosition = selectedPosition;
notifyItemChanged(oldPosition);
notifyItemChanged(selectedPosition);
}
private static class SwipeLeftResultAction extends SwipeResultActionMoveToSwipedDirection {
private SwipeableMessageAdapter adapter;
private final int position;
@ -274,7 +299,6 @@ public class SwipeableMessageAdapter
protected void onPerformAction() {
super.onPerformAction();
adapter.data.remove(position);
adapter.data.remove(position);
adapter.notifyItemRemoved(position);
}

View File

@ -0,0 +1,163 @@
/*
* 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.
*/
package ch.dissem.apps.abit.dialog;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
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;
import android.view.ViewGroup;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import ch.dissem.apps.abit.ImportIdentityActivity;
import ch.dissem.apps.abit.MainActivity;
import ch.dissem.apps.abit.R;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.payload.Pubkey;
/**
* @author Christian Basler
*/
public class AddIdentityDialogFragment extends AppCompatDialogFragment {
private BitmessageContext bmc;
@Override
public void onAttach(Context context) {
super.onAttach(context);
bmc = Singleton.getBitmessageContext(context);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
getDialog().setTitle(R.string.add_identity);
View view = inflater.inflate(R.layout.dialog_add_identity, container, false);
final RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.radioGroup);
view.findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Context ctx = getActivity().getBaseContext();
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.create_identity:
Toast.makeText(ctx,
R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
new AsyncTask<Void, Void, BitmessageAddress>() {
@Override
protected BitmessageAddress doInBackground(Void... args) {
return bmc.createIdentity(false, Pubkey.Feature.DOES_ACK);
}
@Override
protected void onPostExecute(BitmessageAddress chan) {
Toast.makeText(ctx,
R.string.toast_identity_created,
Toast.LENGTH_SHORT).show();
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
mainActivity.addIdentityEntry(chan);
}
}
}.execute();
break;
case R.id.import_identity:
startActivity(new Intent(ctx, ImportIdentityActivity.class));
break;
case R.id.add_chan:
addChanDialog();
break;
case R.id.add_deterministic_address:
new DeterministicIdentityDialogFragment().show(getFragmentManager(),
"dialog");
break;
default:
return;
}
dismiss();
}
});
view.findViewById(R.id.dismiss)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
return view;
}
private void addChanDialog() {
FragmentActivity activity = getActivity();
final Context ctx = activity.getBaseContext();
@SuppressLint("InflateParams")
final View dialogView = activity.getLayoutInflater()
.inflate(R.layout.dialog_input_passphrase, null);
new AlertDialog.Builder(activity)
.setTitle(R.string.add_chan)
.setView(dialogView)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
TextView passphrase = (TextView) dialogView.findViewById(R.id.passphrase);
Toast.makeText(ctx, R.string.toast_long_running_operation,
Toast.LENGTH_SHORT).show();
new AsyncTask<String, Void, BitmessageAddress>() {
@Override
protected BitmessageAddress doInBackground(String... args) {
String pass = args[0];
BitmessageAddress chan = bmc.createChan(pass);
chan.setAlias(pass);
bmc.addresses().save(chan);
return chan;
}
@Override
protected void onPostExecute(BitmessageAddress chan) {
Toast.makeText(ctx,
R.string.toast_chan_created,
Toast.LENGTH_SHORT).show();
MainActivity mainActivity = MainActivity.getInstance();
if (mainActivity != null) {
mainActivity.addIdentityEntry(chan);
}
}
}.execute(passphrase.getText().toString());
}
})
.setNegativeButton(R.string.cancel, null)
.show();
}
@Override
public int getTheme() {
return R.style.FixedDialog;
}
}

View File

@ -0,0 +1,138 @@
/*
* 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.
*/
package ch.dissem.apps.abit.dialog;
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;
import android.view.ViewGroup;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import ch.dissem.apps.abit.MainActivity;
import ch.dissem.apps.abit.R;
import ch.dissem.apps.abit.service.Singleton;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.payload.Pubkey;
/**
* @author Christian Basler
*/
public class DeterministicIdentityDialogFragment extends AppCompatDialogFragment {
private BitmessageContext bmc;
@Override
public void onAttach(Context context) {
super.onAttach(context);
bmc = Singleton.getBitmessageContext(context);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
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);
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;
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()
);
}
});
view.findViewById(R.id.dismiss)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
return view;
}
@Override
public int getTheme() {
return R.style.FixedDialog;
}
}

View File

@ -0,0 +1,21 @@
<?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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="@color/bg_item_selected_state" />
<item android:state_activated="false" android:drawable="@color/contentBackground" />
</selector>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
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.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<color android:color="@color/bg_item_selected_state"/>
</item>
</layer-list>

View File

@ -0,0 +1,25 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z"/>
</vector>

View File

@ -1,52 +1,58 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:gravity="center">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
android:elevation="4dp"
tools:ignore="UnusedAttribute"/>
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_below="@id/toolbar"
android:baselineAligned="false"
android:divider="?android:attr/dividerHorizontal"
android:orientation="horizontal"
android:showDividers="middle"
tools:context=".MessageListActivity">
tools:context=".MainActivity">
<!--
This layout is a two-pane layout for the Messages
master/detail flow.
-->
<FrameLayout
android:id="@+id/item_list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:context=".MessageListActivity"
tools:layout="@android:layout/list_content"/>
android:id="@+id/item_list"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:context=".MessageListActivity"
tools:layout="@layout/fragment_message_list"/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="@color/bg_item_selected_state">
<FrameLayout
android:id="@+id/message_detail_container"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3"/>
android:layout_margin="16dp"
android:background="@color/contentBackground"
android:elevation="2dp"
tools:layout="@layout/fragment_message_detail"/>
</FrameLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -21,42 +21,42 @@
android:layout_height="wrap_content">
<ImageView
android:id="@+id/avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:src="@color/colorAccent"
android:layout_margin="16dp"
tools:ignore="ContentDescription"/>
android:id="@+id/avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_margin="16dp"
android:src="@color/colorAccent"
tools:ignore="ContentDescription"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Name"
android:lines="1"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_alignTop="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:paddingTop="0dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingBottom="0dp"
android:textStyle="bold"/>
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:ellipsize="end"
android:lines="1"
android:paddingBottom="0dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="0dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
tools:text="Name"/>
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="BM-2cW0000000000000000000000000000000"
android:lines="1"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_alignBottom="@+id/avatar"
android:layout_toEndOf="@+id/avatar"/>
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:ellipsize="marquee"
android:lines="1"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="BM-2cW0000000000000000000000000000000"/>
</RelativeLayout>
</RelativeLayout>

View File

@ -0,0 +1,118 @@
<?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.
-->
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="18dp"
android:paddingEnd="24dp"
android:paddingStart="24dp"
android:paddingTop="18dp">
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/deterministic_address_warning"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/label_wrapper"
android:layout_marginTop="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/description">
<EditText
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/label"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/passphrase_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/label_wrapper">
<EditText
android:id="@+id/passphrase"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/passphrase"
android:inputType="textMultiLine"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/number_of_identities_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/passphrase_wrapper">
<EditText
android:id="@+id/number_of_identities"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/number_of_identities"
android:inputType="number"
android:text="1"/>
</android.support.design.widget.TextInputLayout>
<Switch
android:id="@+id/shorter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/shorter"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/number_of_identities_wrapper"/>
<Button
android:id="@+id/ok"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/ok"
android:textColor="@color/colorAccent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/shorter"/>
<Button
android:id="@+id/dismiss"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:textColor="@color/colorAccent"
app:layout_constraintBottom_toBottomOf="@id/ok"
app:layout_constraintRight_toLeftOf="@id/ok"/>
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,102 @@
<?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.
-->
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="18dp"
android:paddingEnd="24dp"
android:paddingStart="24dp"
android:paddingTop="18dp">
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/add_identity_warning"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1"/>
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="24dp"
android:paddingTop="24dp"
app:layout_constraintLeft_toLeftOf="@+id/description"
app:layout_constraintTop_toBottomOf="@+id/description">
<RadioButton
android:id="@+id/add_chan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/add_chan_description"/>
<RadioButton
android:id="@+id/add_deterministic_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/add_deterministic_address_description"/>
<RadioButton
android:id="@+id/import_identity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/import_identity_description"/>
<RadioButton
android:id="@+id/create_identity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/create_identity_description"/>
</RadioGroup>
<Button
android:id="@+id/ok"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok"
android:textColor="@color/colorAccent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintRight_toRightOf="@+id/radioGroup"
app:layout_constraintTop_toBottomOf="@+id/radioGroup"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintRight_creator="1"
tools:layout_constraintTop_creator="1"/>
<Button
android:id="@+id/dismiss"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel"
android:textColor="@color/colorAccent"
app:layout_constraintRight_toLeftOf="@+id/ok"
app:layout_constraintTop_toBottomOf="@+id/radioGroup"/>
</android.support.constraint.ConstraintLayout>

View File

@ -2,7 +2,11 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:paddingBottom="18dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:paddingTop="18dp">
<EditText
android:id="@+id/passphrase"
@ -11,4 +15,4 @@
android:layout_gravity="center_horizontal"
android:hint="@string/passphrase"
android:inputType="textMultiLine"/>
</LinearLayout>
</LinearLayout>

View File

@ -116,4 +116,4 @@
android:elevation="2dp"
tools:ignore="UnusedAttribute"
tools:src="@drawable/public_key"/>
</RelativeLayout>
</RelativeLayout>

View File

@ -8,6 +8,7 @@
android:id="@id/android:list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
@ -29,4 +30,4 @@
app:elevation="8dp"
app:fabGravity="bottom_end"
app:fabMenu="@menu/fab_address"/>
</RelativeLayout>
</RelativeLayout>

View File

@ -0,0 +1,60 @@
<?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.
-->
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="64dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp">
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/import_input_description"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<EditText
android:id="@+id/wif_input"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="24dp"
android:gravity="start|top"
android:hint="@string/wif_string"
android:inputType="textMultiLine|text"
app:layout_constraintBottom_toTopOf="@+id/next"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/description"/>
<Button
android:id="@+id/next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="@string/next"
android:textColor="@color/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,58 @@
<?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.
-->
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="64dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp">
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/select_identities_to_import"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="24dp"
android:inputType="textMultiLine|text"
app:layout_constraintBottom_toTopOf="@+id/finish"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/description"/>
<Button
android:id="@+id/finish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="@string/do_import"
android:textColor="@color/colorAccent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
@ -15,7 +16,8 @@
android:paddingBottom="88dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"/>
android:scrollbars="vertical"
tools:listitem="@layout/message_row"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_compose_message"

View File

@ -27,7 +27,6 @@
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"/>

View File

@ -0,0 +1,52 @@
<?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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="64dp">
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:ellipsize="end"
android:paddingBottom="8dp"
android:paddingEnd="8dp"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:text="CheckBox"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="Name"/>
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:ellipsize="marquee"
android:lines="1"
android:paddingBottom="8dp"
android:paddingEnd="8dp"
android:paddingStart="48dp"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="BM-2cW0000000000000000000000000000000"/>
</RelativeLayout>

View File

@ -19,56 +19,57 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator">
<ImageView
android:id="@+id/avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:src="@color/colorAccent"
android:layout_margin="16dp"
tools:ignore="ContentDescription"/>
android:id="@+id/avatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_margin="16dp"
android:src="@color/colorAccent"
tools:ignore="ContentDescription"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Name"
android:lines="1"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_alignTop="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:paddingTop="0dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingBottom="0dp"
android:textStyle="bold"
/>
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:ellipsize="end"
android:lines="1"
android:paddingBottom="0dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="0dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
tools:text="Name"
/>
<TextView
android:id="@+id/stream_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Stream #"
android:lines="1"
android:ellipsize="end"
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_alignBottom="@+id/avatar"
android:layout_toEndOf="@+id/avatar"/>
android:id="@+id/stream_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/avatar"
android:layout_toEndOf="@+id/avatar"
android:ellipsize="end"
android:lines="1"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Stream #"/>
<com.mikepenz.iconics.view.IconicsImageView
android:id="@+id/subscribed"
android:layout_width="16dp"
android:layout_height="16dp"
app:iiv_color="@android:color/black"
app:iiv_icon="cmd-rss"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"/>
android:id="@+id/subscribed"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="16dp"
app:iiv_color="@android:color/black"
app:iiv_icon="cmd-rss"/>
</RelativeLayout>
</RelativeLayout>

View File

@ -0,0 +1,25 @@
<?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/open_file"
android:title="@string/open_file"
android:icon="@drawable/ic_action_open_file"
app:showAsAction="ifRoom"/>
</menu>

View File

@ -0,0 +1,20 @@
<?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.
-->
<resources>
<string name="library_fab_speed_dial_libraryDescription">Eine einfache Bibliothek die FAB + Menü-Ressourcen + Speed Dial Metapher von Material Design vereinigt.</string>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="library_filepicker_libraryDescription">Android-Bibliothek um Dateien und Verzeichnisse im Gerätespeicher auszuwählen.</string>
</resources>

View File

@ -1,7 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about">Über Abit</string>
<string name="about_app">Ein Bitmessage-Client für Android</string>
<string name="about_summary">Open Source Abhängigkeiten.</string>
<string name="library_jabit_libraryDescription">Jabit hat das Ziel eine einfach zu benutzende Bitmessage-Bibliothek für Java-Entwickler zu sein, um schnell eigene Bitmessage-Anwendungen zu implementieren.</string>
</resources>
</resources>

View File

@ -0,0 +1,20 @@
<?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.
-->
<resources>
<string name="library_zxing_libraryDescription">ZXing (“Zebrastreifen”) ist eine Open Source Bildverarbeitungs-Bibliothek für verschiedene 1D/2D Barcode-Formate.</string>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="library_zxingandroidembedded_libraryDescription">Barcode-Scanning-Bibliothek für Android, verwendet ZXing als Decoder.</string>
</resources>

View File

@ -1,73 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Abit</string>
<string name="about_app">Ein Bitmessage-Client für Android</string>
<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="bitmessage_full_node">Bitmessage Netzknoten</string>
<string name="subject">Betreff</string>
<string name="to">An</string>
<string name="title_message_detail">Nachricht</string>
<string name="subscriptions">Abonnements</string>
<string name="wifi_mode">Art der WLAN-Verbindung</string>
<string name="action_settings">Einstellungen</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>
<string name="add_chan">Chan hinzufügen</string>
<string name="add_chan_summary">Einen Chan hinzufügen oder erstellen</string>
<string name="broadcast">Broadcast</string>
<string name="cancel">Abbrechen</string>
<string name="do_import">Importieren</string>
<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="manage_identity">Identität verwalten</string>
<string name="subscribe">Abonnieren</string>
<string name="title_activity_open_bitmessage_link">Kontakt importieren</string>
<string name="delete">Löschen</string>
<string name="reply">Antworten</string>
<string name="do_import">Importieren</string>
<string name="cancel">Abbrechen</string>
<string name="broadcast">Broadcast</string>
<string name="n_new_messages">%d neue Nachrichten</string>
<string name="reply">Antworten</string>
<string name="delete">Löschen</string>
<string name="mark_unread">Als ungelesen markieren</string>
<string name="archive">Archiv</string>
<string name="empty_trash">Papierkorb leeren</string>
<string name="mark_unread">Als ungelesen markieren</string>
<string name="stream_number">Stream %d</string>
<string name="enabled">Aktiv</string>
<string name="title_subscription_detail">Abonnement</string>
<string name="sync_timeout">Zeitbeschränkung der Synchronisierung</string>
<string name="sync_timeout_summary">Timeout in Sekunden</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>
<string name="sync_timeout_summary">Timeout in Sekunden</string>
<string name="write_message">Schreiben</string>
<string name="full_node">Aktiver Knoten</string>
<string name="send">Senden</string>
<string name="write_message">Schreiben</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="connection_info_disconnected">Getrennt</string>
<string name="connection_info_pending">Verbindung wird aufgebaut…</string>
<string name="proof_of_work_title">Proof of Work</string>
<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="proof_of_work_title">Proof of Work</string>
<string name="error_invalid_sync_host">Synchronisation fehlgeschlagen: der vertrauenswürdige Knoten konnte nicht erreicht werden.</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>
<string name="server_pow">Server POW</string>
<string name="server_pow_summary">Der vertrauenswürdige Knoten macht den Proof of Work</string>
<string name="full_node_warning">Ein aktiver Bitmessage-Knoten muss viel hoch- und herunterladen, was auf einem mobilen Netzwerk teuer sein kann. Soll tatsächlich ein aktiver Knoten gestartet werden?</string>
<string name="status">Debugging</string>
<string name="alias_default_identity">Ich</string>
<string name="about">Über Abit</string>
<string name="about_summary">Opensource Abhängigkeiten.</string>
<string name="title_activity_status">Debugging</string>
<string name="status">Debugging</string>
<string name="status_summary">Technische Infos</string>
<string name="alias_default_identity">Ich</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. Bist Du sicher?</string>
<string name="add_identity_warning">Mehrere Identitäten zu haben bedeutet einen höheren Resourcenverbrauch. Falls Du sicher bist dass du eine Identität hinzufügen willst, wähle bitte die Vorgehensweise:</string>
<string name="share">Teilen</string>
<string name="delete_contact_warning">Bist Du sicher dass dieser Kontakt gelöscht werden soll?</string>
<string name="delete_identity_warning">Bist Du sicher dass diese Identität gelöscht werden soll? Nachrichten, welche an diese Adresse gesendet werden, können nicht mehr empfangen werden und es est nicht möglich diese Aktion rückgängig zu machen.</string>
<string name="create_contact">Kontakt erfassen</string>
<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.
Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfiguriert werden, aber im Moment muss dieser selbst bereitgestellt werden.</string>
@ -81,7 +91,20 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
<string name="help_out">Entwicklung unterstützen</string>
<string name="help_out_summary">Erfahre wie du die Entwicklung von Abit unterstützen kannst</string>
<string name="help_out_link">https://dissem.github.io/Abit/mithelfen</string>
<string name="toast_chan_created">Chan erstellt</string>
<string name="toast_long_running_operation">Dies kann einige Minuten dauern</string>
<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="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>
<string name="next">Weiter</string>
<string name="title_import_identity">Identität importieren</string>
<string name="open_file">Datei öffnen</string>
<string name="error_loading_data">Fehler beim Laden der Daten</string>
<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

@ -8,6 +8,7 @@
<color name="colorAccent">#607D8B</color>
<color name="colorPrimaryText">#212121</color>
<color name="colorSecondaryText">#727272</color>
<color name="contentBackground">#FFFFFF</color>
<color name="icons">#212121</color>
<color name="divider">#B6B6B6</color>
@ -49,6 +50,7 @@
<color name="bg_item_normal_state">#ffffffff</color>
<color name="bg_item_swiping_state">@color/colorPrimaryLight</color>
<color name="bg_item_swiping_active_state">@color/colorPrimary</color>
<color name="bg_item_selected_state">@color/colorPrimaryLight</color>
<color name="bg_swipe_item_neutral">@android:color/transparent</color>
<color name="bg_swipe_item_trash">#fff45f30</color>
<color name="bg_swipe_item_archive">#fff9930d</color>

View File

@ -0,0 +1,36 @@
<?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.
-->
<resources>
<string name="define_fab_speed_dial" translatable="false"/>
<!-- Author section -->
<string name="library_fab_speed_dial_author" translatable="false">Yavor Ivanov</string>
<string name="library_fab_speed_dial_authorWebsite" translatable="false">https://github.com/yavski/</string>
<!-- Library section -->
<string name="library_fab_speed_dial_libraryName" translatable="false">fab-speed-dial</string>
<string name="library_fab_speed_dial_libraryDescription">A simple library marrying together FAB + menu resources + Speed dial metaphor from Material Design.</string>
<string name="library_fab_speed_dial_libraryWebsite" translatable="false">https://github.com/yavski/fab-speed-dial</string>
<string name="library_fab_speed_dial_libraryVersion" translatable="false">1.0.4</string>
<!-- OpenSource section -->
<string name="library_fab_speed_dial_isOpenSource" translatable="false">true</string>
<string name="library_fab_speed_dial_repositoryLink" translatable="false">https://github.com/yavski/fab-speed-dial</string>
<!-- ClassPath for autoDetect section -->
<string name="library_fab_speed_dial_classPath" translatable="false">io.github.yavski.fabspeeddial.FabSpeedDial</string>
<!-- License section -->
<string name="library_fab_speed_dial_licenseId" translatable="false">apache_2_0</string>
<!-- Language specific section -->
</resources>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<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 -->
</resources>

View File

@ -16,5 +16,5 @@
<string name="library_jabit_classPath" translatable="false">ch.dissem.bitmessage.BitmessageContext</string>
<!-- License section -->
<string name="library_jabit_licenseId" translatable="false">apache_2_0</string>
<!-- Custom variables section -->
</resources>
<!-- Language specific section -->
</resources>

View File

@ -0,0 +1,36 @@
<?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.
-->
<resources>
<string name="define_zxing" translatable="false"/>
<!-- Author section -->
<string name="library_zxing_author" translatable="false">Google, Inc.</string>
<string name="library_zxing_authorWebsite" translatable="false">github.com/zxing/zxing</string>
<!-- Library section -->
<string name="library_zxing_libraryName" translatable="false">ZXing</string>
<string name="library_zxing_libraryDescription">ZXing (“zebra crossing”) is an open-source, multi-format 1D/2D barcode image processing library.</string>
<string name="library_zxing_libraryWebsite" translatable="false">https://zxing.github.io/zxing/</string>
<string name="library_zxing_libraryVersion" translatable="false">3.3.0</string>
<!-- OpenSource section -->
<string name="library_zxing_isOpenSource" translatable="false">true</string>
<string name="library_zxing_repositoryLink" translatable="false">https://github.com/zxing/zxing</string>
<!-- ClassPath for autoDetect section -->
<string name="library_zxing_classPath" translatable="false">com.google.zxing.BarcodeFormat</string>
<!-- License section -->
<string name="library_zxing_licenseId" translatable="false">apache_2_0</string>
<!-- Language specific section -->
</resources>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="define_int_zxingandroidembedded" translatable="false"/>
<!-- Author section -->
<string name="library_zxingandroidembedded_author" translatable="false">JourneyApps</string>
<string name="library_zxingandroidembedded_authorWebsite" translatable="false">github.com/journeyapps</string>
<!-- Library section -->
<string name="library_zxingandroidembedded_libraryName" translatable="false">ZXing Android Embedded</string>
<string name="library_zxingandroidembedded_libraryDescription">Barcode scanning library for Android, using ZXing for decoding.</string>
<string name="library_zxingandroidembedded_libraryWebsite" translatable="false">https://github.com/journeyapps/zxing-android-embedded</string>
<string name="library_zxingandroidembedded_libraryVersion" translatable="false">3.3.0</string>
<!-- OpenSource section -->
<string name="library_zxingandroidembedded_isOpenSource" translatable="false">true</string>
<string name="library_zxingandroidembedded_repositoryLink" translatable="false">https://github.com/journeyapps/zxing-android-embedded</string>
<!-- ClassPath for autoDetect section -->
<string name="library_zxingandroidembedded_classPath" translatable="false">com.journeyapps.barcodescanner.BarcodeView</string>
<!-- License section -->
<string name="library_zxingandroidembedded_licenseId" translatable="false">apache_2_0</string>
<!-- Custom variables section -->
</resources>

View File

@ -14,8 +14,14 @@
<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>
<string name="add_chan">Add Chan</string>
<string name="add_chan_summary">Add or create a chan</string>
<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>
@ -65,7 +71,7 @@
<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="add_identity_warning">Having more identities will reequire more resources. If you are sure you want to add an identity, please select what exactly you want to do:</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>
@ -80,11 +86,24 @@ As an alternative you could configure a trusted node in the settings, but as of
<string name="export">Export</string>
<string name="confirm_export">Do you really want to export your identity? The export will contain the unencrypted private keys.</string>
<string name="compose_message">Compose</string>
<string name="passphrase">passphrase</string>
<string name="passphrase">Passphrase</string>
<string name="help_out">Support Development</string>
<string name="help_out_summary">Want to help out? Have a look here</string>
<string name="help_out_link">https://dissem.github.io/Abit/helping-out</string>
<string name="toast_long_running_operation">This may take a few minutes</string>
<string name="toast_identity_created">Identity created</string>
<string name="toast_identities_created">Identities created</string>
<string name="toast_chan_created">Chan created</string>
<string name="deterministic_address_warning">Be sure to remember those settings correctly when recreating a deterministic address.</string>
<string name="number_of_identities">Number of identities to create</string>
<string name="shorter">Search for shorter addresses</string>
<string name="wif_string">WIF / contents of keys.dat</string>
<string name="next">Continue</string>
<string name="title_import_identity">Import Identity</string>
<string name="open_file">Open File</string>
<string name="error_loading_data">Error loading data</string>
<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

@ -2,7 +2,7 @@
<!-- Base application theme. -->
<style name="AppTheme" parent="MaterialDrawerTheme.Light.DarkToolbar.TranslucentStatus">
<item name="android:activatedBackgroundIndicator">@color/colorPrimaryLight</item>
<item name="android:activatedBackgroundIndicator">@drawable/bg_item_activated</item>
<item name="android:textColor">@color/colorPrimaryText</item>
<item name="android:textColorSecondary">@color/colorSecondaryText</item>
</style>
@ -19,4 +19,7 @@
<item name="android:textColor">@color/colorAccent</item>
</style>
<style name="FixedDialog" parent="Theme.AppCompat.Light.Dialog">
<item name="windowNoTitle">false</item>
</style>
</resources>

View File

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