Receiving almost works, unfortunately, JDBC doesn't so I have to rewrite the whole damn repository code.
@ -37,6 +37,8 @@ dependencies {
|
||||
compile('com.mikepenz:materialdrawer:3.1.0@aar') {
|
||||
transitive = true
|
||||
}
|
||||
compile 'com.mikepenz:iconics:1.6.2@aar'
|
||||
compile 'com.mikepenz:community-material-typeface:1.1.71@aar'
|
||||
}
|
||||
|
||||
idea.module {
|
||||
|
@ -30,12 +30,45 @@
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MessageListActivity"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ComposeMessageActivity"
|
||||
android:label="Compose"
|
||||
android:parentActivityName=".MessageListActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MessageListActivity"/>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SENDTO"/>
|
||||
|
||||
<data android:scheme="bitmessage"/>
|
||||
<data android:scheme="bitmsg"/>
|
||||
<data android:scheme="bm"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
|
||||
<data android:mimeType="text/plain"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE"/>
|
||||
|
||||
<data android:mimeType="text/plain"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/settings"
|
||||
android:parentActivityName=".MessageListActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
@ -46,6 +79,22 @@
|
||||
android:exported="true"
|
||||
android:permission="">
|
||||
</service>
|
||||
|
||||
<activity
|
||||
android:name=".OpenBitmessageLinkActivity"
|
||||
android:label="@string/title_activity_open_bitmessage_link"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
|
||||
<data android:scheme="bitmessage"/>
|
||||
<data android:scheme="bitmsg"/>
|
||||
<data android:scheme="bm"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@ -0,0 +1,28 @@
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
|
||||
/**
|
||||
* Compose a new message.
|
||||
*/
|
||||
public class ComposeMessageActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.toolbar_layout);
|
||||
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_action_close);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(false);
|
||||
|
||||
// Display the fragment as the main content.
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.content, new ComposeMessageFragment())
|
||||
.commit();
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.*;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
/**
|
||||
* Compose a new message.
|
||||
*/
|
||||
public class ComposeMessageFragment extends Fragment {
|
||||
/**
|
||||
* The fragment argument representing the sender identity.
|
||||
*/
|
||||
public static final String ARG_IDENTITY = "from";
|
||||
/**
|
||||
* The fragment argument representing the recipient.
|
||||
*/
|
||||
public static final String ARG_RECIPIENT = "to";
|
||||
|
||||
private BitmessageContext bmCtx;
|
||||
private BitmessageAddress identity;
|
||||
private BitmessageAddress recipient;
|
||||
|
||||
/**
|
||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||
* fragment (e.g. upon screen orientation changes).
|
||||
*/
|
||||
public ComposeMessageFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
if (getArguments().containsKey(ARG_IDENTITY)) {
|
||||
identity = (BitmessageAddress) getArguments().getSerializable(ARG_IDENTITY);
|
||||
}
|
||||
if (getArguments().containsKey(ARG_RECIPIENT)) {
|
||||
recipient = (BitmessageAddress) getArguments().getSerializable(ARG_RECIPIENT);
|
||||
}
|
||||
}
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_compose_message, container, false);
|
||||
EditText body = (EditText) rootView.findViewById(R.id.body);
|
||||
body.setInputType(EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||
body.setImeOptions(EditorInfo.IME_ACTION_SEND | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.compose, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.send:
|
||||
Toast.makeText(getActivity(), "TODO: Send", Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
102
app/src/main/java/ch/dissem/apps/abit/Identicon.java
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
|
||||
import android.graphics.*;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Identicon extends Drawable {
|
||||
private static final int SIZE = 9;
|
||||
private static final int CENTER_COLUMN = 5;
|
||||
|
||||
private final Paint paint;
|
||||
private float cellWidth;
|
||||
private float cellHeight;
|
||||
private byte[] hash;
|
||||
private int color;
|
||||
private int background;
|
||||
private boolean[][] fields;
|
||||
|
||||
public Identicon(BitmessageAddress input) {
|
||||
paint = new Paint();
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
hash = input.getRipe();
|
||||
|
||||
fields = new boolean[SIZE][SIZE];
|
||||
color = Color.HSVToColor(new float[]{Math.abs(hash[0] * hash[1] + hash[2]) % 360, 0.8f, 1.0f});
|
||||
background = Color.HSVToColor(new float[]{Math.abs(hash[1] * hash[2] + hash[0]) % 360, 0.8f, 1.0f});
|
||||
|
||||
for (int row = 0; row < SIZE; row++) {
|
||||
for (int column = 0; column < SIZE; column++) {
|
||||
fields[row][column] = hash[(row * (column < CENTER_COLUMN ? column : SIZE - column - 1)) % hash.length] >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte getByte(int index) {
|
||||
return hash[index % hash.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
float x, y;
|
||||
paint.setColor(background);
|
||||
canvas.drawPaint(paint);
|
||||
paint.setColor(color);
|
||||
for (int row = 0; row < SIZE; row++) {
|
||||
for (int column = 0; column < SIZE; column++) {
|
||||
if (fields[row][column]) {
|
||||
x = cellWidth * column;
|
||||
y = cellHeight * row;
|
||||
|
||||
canvas.drawCircle(x + cellWidth / 2, y + cellHeight / 2, cellHeight / 2, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
paint.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
paint.setColorFilter(cf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.OPAQUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
|
||||
cellWidth = bounds.width() / (float) SIZE;
|
||||
cellHeight = bounds.height() / (float) SIZE;
|
||||
}
|
||||
|
||||
}
|
@ -5,13 +5,16 @@ import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Toast;
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import com.mikepenz.community_material_typeface_library.CommunityMaterial;
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
|
||||
import com.mikepenz.iconics.IconicsDrawable;
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
@ -59,6 +62,7 @@ public class MessageListActivity extends AppCompatActivity
|
||||
private AccountHeader accountHeader;
|
||||
private BitmessageContext bmc;
|
||||
private Label selectedLabel;
|
||||
private Menu menu;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -68,7 +72,7 @@ public class MessageListActivity extends AppCompatActivity
|
||||
|
||||
setContentView(R.layout.activity_message_list);
|
||||
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if (findViewById(R.id.message_detail_container) != null) {
|
||||
@ -109,7 +113,7 @@ public class MessageListActivity extends AppCompatActivity
|
||||
.withIdentifier(ADD_IDENTITY)
|
||||
);
|
||||
profiles.add(new ProfileSettingDrawerItem()
|
||||
.withName("Manage Account")
|
||||
.withName(getString(R.string.manage_identity))
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
);
|
||||
// Create the AccountHeader
|
||||
@ -150,6 +154,9 @@ public class MessageListActivity extends AppCompatActivity
|
||||
.withAccountHeader(accountHeader)
|
||||
.withDrawerItems(drawerItems)
|
||||
.addStickyDrawerItems(
|
||||
new SecondaryDrawerItem()
|
||||
.withName(getString(R.string.subscriptions))
|
||||
.withIcon(CommunityMaterial.Icon.cmd_rss),
|
||||
new SecondaryDrawerItem()
|
||||
.withName(R.string.settings)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
@ -162,6 +169,9 @@ public class MessageListActivity extends AppCompatActivity
|
||||
} else if (item instanceof Nameable<?>) {
|
||||
Nameable<?> ni = (Nameable<?>) item;
|
||||
switch (ni.getNameRes()) {
|
||||
case R.string.subscriptions:
|
||||
// TODO
|
||||
break;
|
||||
case R.string.settings:
|
||||
startActivity(new Intent(MessageListActivity.this, SettingsActivity.class));
|
||||
break;
|
||||
@ -176,10 +186,37 @@ public class MessageListActivity extends AppCompatActivity
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main, menu);
|
||||
this.menu = menu;
|
||||
updateMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateMenu() {
|
||||
boolean running = bmc.isRunning();
|
||||
menu.findItem(R.id.sync_enabled).setVisible(running);
|
||||
menu.findItem(R.id.sync_disabled).setVisible(!running);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.sync_disabled:
|
||||
bmc.startup(new BitmessageContext.Listener() {
|
||||
@Override
|
||||
public void receive(Plaintext plaintext) {
|
||||
// TODO
|
||||
Toast.makeText(MessageListActivity.this, plaintext.getSubject(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
updateMenu();
|
||||
return true;
|
||||
case R.id.sync_enabled:
|
||||
bmc.shutdown();
|
||||
updateMenu();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.ListFragment;
|
||||
@ -9,8 +10,6 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
@ -97,7 +96,7 @@ public class MessageListFragment extends ListFragment {
|
||||
fab.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Toast.makeText(MessageListFragment.this.getActivity(), "TODO", Toast.LENGTH_SHORT).show();
|
||||
startActivity(new Intent(getActivity().getApplicationContext(), ComposeMessageActivity.class));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2015 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
import ch.dissem.apps.abit.service.Singleton;
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
|
||||
public class OpenBitmessageLinkActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_open_bitmessage_link);
|
||||
|
||||
final TextView addressView = (TextView) findViewById(R.id.address);
|
||||
final EditText label = (EditText) findViewById(R.id.label);
|
||||
final Switch importContact = (Switch) findViewById(R.id.import_contact);
|
||||
final Switch subscribe = (Switch) findViewById(R.id.subscribe);
|
||||
|
||||
Uri uri = getIntent().getData();
|
||||
final String address = getAddress(uri);
|
||||
String[] parameters = getParameters(uri);
|
||||
for (String parameter : parameters) {
|
||||
String name = parameter.substring(0, 6).toLowerCase();
|
||||
if (name.startsWith("label")) {
|
||||
label.setText(parameter.substring(parameter.indexOf('=') + 1).trim());
|
||||
} else if (name.startsWith("action")) {
|
||||
parameter = parameter.toLowerCase();
|
||||
importContact.setChecked(parameter.contains("add"));
|
||||
subscribe.setChecked(parameter.contains("subscribe"));
|
||||
}
|
||||
}
|
||||
|
||||
addressView.setText(address);
|
||||
|
||||
|
||||
final Button cancel = (Button) findViewById(R.id.cancel);
|
||||
cancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setResult(Activity.RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
final Button ok = (Button) findViewById(R.id.do_import);
|
||||
ok.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
BitmessageContext bmc = Singleton.getBitmessageContext(OpenBitmessageLinkActivity.this);
|
||||
BitmessageAddress bmAddress = new BitmessageAddress(address);
|
||||
bmAddress.setAlias(label.getText().toString());
|
||||
if (subscribe.isChecked()) {
|
||||
bmc.addSubscribtion(bmAddress);
|
||||
}
|
||||
if (importContact.isChecked()) {
|
||||
bmc.addContact(bmAddress);
|
||||
}
|
||||
setResult(Activity.RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String getAddress(Uri uri) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
String schemeSpecificPart = uri.getSchemeSpecificPart();
|
||||
if (!schemeSpecificPart.startsWith("BM-")) {
|
||||
result.append("BM-");
|
||||
}
|
||||
if (schemeSpecificPart.contains("?")) {
|
||||
result.append(schemeSpecificPart.substring(0, schemeSpecificPart.indexOf('?')));
|
||||
} else if (schemeSpecificPart.contains("#")) {
|
||||
result.append(schemeSpecificPart.substring(0, schemeSpecificPart.indexOf('#')));
|
||||
} else {
|
||||
result.append(schemeSpecificPart);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private String[] getParameters(Uri uri) {
|
||||
int index = uri.getSchemeSpecificPart().indexOf('?');
|
||||
if (index >= 0) {
|
||||
String parameterPart = uri.getSchemeSpecificPart().substring(index + 1);
|
||||
return parameterPart.split("&");
|
||||
} else {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package ch.dissem.apps.abit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Environment;
|
||||
import ch.dissem.bitmessage.repository.JdbcConfig;
|
||||
import org.flywaydb.core.api.android.ContextHolder;
|
||||
import org.sqldroid.SQLDroidDriver;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Created by chris on 14.07.15.
|
||||
*/
|
||||
public class SQLiteConfig extends JdbcConfig {
|
||||
|
||||
public SQLiteConfig(Context ctx) {
|
||||
super(getDbUrl(ctx), "", "");
|
||||
}
|
||||
|
||||
private static String getDbUrl(Context ctx) {
|
||||
SQLiteDatabase db = ctx.openOrCreateDatabase(Environment.getExternalStorageDirectory()
|
||||
+ "/jabit.db", Context.MODE_PRIVATE, null);
|
||||
ContextHolder.setContext(ctx);
|
||||
return "jdbc:sqlite:" + db.getPath() + "?timeout=5";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
Properties removeLocale = new Properties();
|
||||
removeLocale.put(SQLDroidDriver.ADDITONAL_DATABASE_FLAGS, android.database.sqlite.SQLiteDatabase.NO_LOCALIZED_COLLATORS);
|
||||
return DriverManager.getConnection(dbUrl, removeLocale);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package ch.dissem.apps.abit.repositories;
|
||||
|
||||
/**
|
||||
* Created by chris on 14.08.15.
|
||||
*/
|
||||
public class AndroidInventory {
|
||||
}
|
@ -1,213 +0,0 @@
|
||||
package im.delight.android.identicons;
|
||||
|
||||
/**
|
||||
* Copyright 2014 www.delight.im <info@delight.im>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
abstract public class Identicon extends View {
|
||||
|
||||
private static final String HASH_ALGORITHM = "SHA-256";
|
||||
private final int mRowCount;
|
||||
private final int mColumnCount;
|
||||
private final Paint mPaint;
|
||||
private volatile int mCellWidth;
|
||||
private volatile int mCellHeight;
|
||||
private volatile byte[] mHash;
|
||||
private volatile int[][] mColors;
|
||||
private volatile boolean mReady;
|
||||
|
||||
public Identicon(Context context) {
|
||||
super(context);
|
||||
|
||||
mRowCount = getRowCount();
|
||||
mColumnCount = getColumnCount();
|
||||
mPaint = new Paint();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public Identicon(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
mRowCount = getRowCount();
|
||||
mColumnCount = getColumnCount();
|
||||
mPaint = new Paint();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public Identicon(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mRowCount = getRowCount();
|
||||
mColumnCount = getColumnCount();
|
||||
mPaint = new Paint();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
protected void init() {
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setDither(true);
|
||||
|
||||
setWillNotDraw(false);
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void show(String input) {
|
||||
// if the input was null
|
||||
if (input == null) {
|
||||
// we can't create a hash value and have nothing to show (draw to the view)
|
||||
mHash = null;
|
||||
}
|
||||
// if the input was a proper string (non-null)
|
||||
else {
|
||||
// generate a hash from the string to get unique but deterministic byte values
|
||||
try {
|
||||
final MessageDigest digest = java.security.MessageDigest.getInstance(HASH_ALGORITHM);
|
||||
digest.update(input == null ? new byte[0] : input.getBytes());
|
||||
mHash = digest.digest();
|
||||
}
|
||||
catch (Exception e) {
|
||||
mHash = null;
|
||||
}
|
||||
}
|
||||
|
||||
// set up the cell colors according to the input that was provided via show(...)
|
||||
setupColors();
|
||||
|
||||
// this view may now be drawn (and thus must be re-drawn)
|
||||
mReady = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void show(int input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(long input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(float input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(double input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(byte input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(char input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(boolean input) {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
|
||||
public void show(Object input) {
|
||||
if (input == null) {
|
||||
mHash = null;
|
||||
}
|
||||
else {
|
||||
show(String.valueOf(input));
|
||||
}
|
||||
}
|
||||
|
||||
protected void setupColors() {
|
||||
mColors = new int[mRowCount][mColumnCount];
|
||||
int colorVisible = getIconColor();
|
||||
|
||||
for (int r = 0; r < mRowCount; r++) {
|
||||
for (int c = 0; c < mColumnCount; c++) {
|
||||
if (isCellVisible(r, c)) {
|
||||
mColors[r][c] = colorVisible;
|
||||
}
|
||||
else {
|
||||
mColors[r][c] = Color.TRANSPARENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected byte getByte(int index) {
|
||||
if (mHash == null) {
|
||||
return -128;
|
||||
}
|
||||
else {
|
||||
return mHash[index % mHash.length];
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected int getRowCount();
|
||||
|
||||
abstract protected int getColumnCount();
|
||||
|
||||
abstract protected boolean isCellVisible(int row, int column);
|
||||
|
||||
abstract protected int getIconColor();
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
mCellWidth = w / mColumnCount;
|
||||
mCellHeight = h / mRowCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
|
||||
setMeasuredDimension(size, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (mReady) {
|
||||
int x, y;
|
||||
for (int r = 0; r < mRowCount; r++) {
|
||||
for (int c = 0; c < mColumnCount; c++) {
|
||||
x = mCellWidth * c;
|
||||
y = mCellHeight * r;
|
||||
|
||||
mPaint.setColor(mColors[r][c]);
|
||||
|
||||
canvas.drawRect(x, y + mCellHeight, x + mCellWidth, y, mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
BIN
app/src/main/res/drawable-hdpi/ic_action_close.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_send.png
Normal file
After Width: | Height: | Size: 371 B |
BIN
app/src/main/res/drawable-hdpi/ic_fab_compose_message.png
Normal file
After Width: | Height: | Size: 862 B |
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 302 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_close.png
Normal file
After Width: | Height: | Size: 182 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_send.png
Normal file
After Width: | Height: | Size: 277 B |
BIN
app/src/main/res/drawable-mdpi/ic_fab_compose_message.png
Normal file
After Width: | Height: | Size: 593 B |
Before Width: | Height: | Size: 230 B After Width: | Height: | Size: 232 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_close.png
Normal file
After Width: | Height: | Size: 280 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_send.png
Normal file
After Width: | Height: | Size: 497 B |
BIN
app/src/main/res/drawable-xhdpi/ic_fab_compose_message.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 383 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_close.png
Normal file
After Width: | Height: | Size: 422 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_send.png
Normal file
After Width: | Height: | Size: 814 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_fab_compose_message.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 600 B After Width: | Height: | Size: 759 B |
Before Width: | Height: | Size: 895 B After Width: | Height: | Size: 1.0 KiB |
66
app/src/main/res/layout/activity_open_bitmessage_link.xml
Normal file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BM-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:id="@+id/address"/>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/label_wrapper"
|
||||
android:layout_below="@+id/address">
|
||||
|
||||
<EditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPersonName"
|
||||
android:hint="@string/label"
|
||||
android:id="@+id/label"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/import_contact"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/import_contact"
|
||||
android:layout_below="@+id/label_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
<Switch
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/subscribe"
|
||||
android:id="@+id/subscribe"
|
||||
android:layout_below="@+id/import_contact"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/do_import"
|
||||
android:id="@+id/do_import"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel"
|
||||
android:id="@+id/cancel"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toLeftOf="@id/do_import"/>
|
||||
|
||||
</RelativeLayout>
|
51
app/src/main/res/layout/fragment_compose_message.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/recipient"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:singleLine="true"
|
||||
android:hint="@string/to"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/subject"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textEmailSubject"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:hint="@string/subject"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/body"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"/>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
@ -2,7 +2,8 @@
|
||||
<RelativeLayout 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_height="match_parent"
|
||||
xmlns:fab="http://schemas.android.com/tools">
|
||||
|
||||
<ListView
|
||||
android:layout_width="wrap_content"
|
||||
@ -18,7 +19,7 @@
|
||||
android:id="@+id/fab_compose_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_plus_sign"
|
||||
android:src="@drawable/ic_fab_compose_message"
|
||||
app:elevation="8dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
|
@ -1,26 +1,36 @@
|
||||
<?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"
|
||||
android:gravity="center"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
android:elevation="4dp" />
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
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:fitsSystemWindows="true">
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MessageListActivity"
|
||||
tools:layout="@android:layout/list_content"/>
|
||||
</RelativeLayout>
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MessageListActivity"
|
||||
tools:layout="@android:layout/list_content"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:elevation="4dp"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
app:layout_scrollFlags="scroll|enterAlways"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
|
9
app/src/main/res/menu/compose.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/send"
|
||||
app:showAsAction="always"
|
||||
android:icon="@drawable/ic_action_send"
|
||||
android:title="@string/disable_sync"/>`
|
||||
</menu>
|
@ -4,4 +4,14 @@
|
||||
<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_active">Bitmessage ist aktiv</string>
|
||||
<string name="disable_sync">Synchronisieren ausschalten</string>
|
||||
<string name="emoji_input">Eingabe von Emojis</string>
|
||||
<string name="emoji_input_summary">Emoji-Taste anstelle von Eingabe anzeigen</string>
|
||||
<string name="enable_sync">Synchronisieren einschalten</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>
|
||||
</resources>
|
22
app/src/main/res/values-w820dp/dimens.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<!--
|
||||
~ Copyright 2015 Christian Basler
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
||||
(such as screen margins) for screens with more than 820dp of available width. This
|
||||
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||
</resources>
|
@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Palette generated by Material Palette - materialpalette.com/blue-grey/orange -->
|
||||
<resources>
|
||||
<color name="primary">#607D8B</color>
|
||||
<color name="primary_dark">#455A64</color>
|
||||
<color name="primary_light">#CFD8DC</color>
|
||||
<color name="accent">#FF9800</color>
|
||||
<color name="primary">#FFC107</color>
|
||||
<color name="primary_dark">#FFA000</color>
|
||||
<color name="primary_light">#FFECB3</color>
|
||||
<color name="accent">#607D8B</color>
|
||||
<color name="primary_text">#212121</color>
|
||||
<color name="secondary_text">#727272</color>
|
||||
<color name="icons">#FFFFFF</color>
|
||||
<color name="icons">#212121</color>
|
||||
<color name="divider">#B6B6B6</color>
|
||||
</resources>
|
||||
|
21
app/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<!--
|
||||
~ Copyright 2015 Christian Basler
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
</resources>
|
@ -8,4 +8,22 @@
|
||||
<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="emoji_input">Emoji Input</string>
|
||||
<string name="emoji_input_summary">Show the emoji button instead of enter</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="title_activity_open_bitmessage_link">Import Contact</string>
|
||||
|
||||
<string name="hello_world">Hello world!</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="import_address">Import Address</string>
|
||||
<string name="import_contact">Add to contacts</string>
|
||||
<string name="label">Label</string>
|
||||
<string name="subscribe">Subscribe</string>
|
||||
<string name="do_import">Import</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
</resources>
|
||||
|