Merge branch 'release/1.0-rc1'
This commit is contained in:
commit
2bddd0f256
@ -20,8 +20,8 @@ android {
|
||||
applicationId "ch.dissem.apps.${appName.toLowerCase()}"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 27
|
||||
versionCode 20
|
||||
versionName "1.0-beta20"
|
||||
versionCode 22
|
||||
versionName "1.0-rc1"
|
||||
multiDexEnabled true
|
||||
}
|
||||
compileOptions {
|
||||
@ -62,7 +62,8 @@ dependencies {
|
||||
implementation "com.android.support:appcompat-v7:$supportVersion"
|
||||
implementation "com.android.support:preference-v7:$supportVersion"
|
||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||
implementation "com.android.support:support-v4:$supportVersion"
|
||||
implementation "com.android.support:support-v13:$supportVersion"
|
||||
implementation "com.android.support:preference-v14:$supportVersion"
|
||||
implementation "com.android.support:design:$supportVersion"
|
||||
implementation "com.android.support:multidex:1.0.2"
|
||||
|
||||
|
@ -1,32 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
package="ch.dissem.apps.abit"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="ch.dissem.apps.abit">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
|
||||
<application
|
||||
android:name="android.support.multidex.MultiDexApplication"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme"
|
||||
android:name="android.support.multidex.MultiDexApplication">
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
@ -36,7 +36,7 @@
|
||||
tools:ignore="UnusedAttribute">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity"/>
|
||||
android:value=".MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".AddressDetailActivity"
|
||||
@ -45,42 +45,42 @@
|
||||
tools:ignore="UnusedAttribute">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity"/>
|
||||
android:value=".MainActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".dialog.FullNodeDialogActivity"
|
||||
android:label="@string/full_node"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog"/>
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog" />
|
||||
<activity
|
||||
android:name=".ComposeMessageActivity"
|
||||
android:label="@string/compose_message"
|
||||
android:parentActivityName=".MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity"/>
|
||||
android:value=".MainActivity" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SENDTO"/>
|
||||
<action android:name="android.intent.action.SENDTO" />
|
||||
|
||||
<data android:scheme="bitmessage"/>
|
||||
<data android:scheme="bitmsg"/>
|
||||
<data android:scheme="bm"/>
|
||||
<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.DEFAULT" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND"/>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
|
||||
<data android:mimeType="text/plain"/>
|
||||
<data android:mimeType="text/plain" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE"/>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
|
||||
<data android:mimeType="text/plain"/>
|
||||
<data android:mimeType="text/plain" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
@ -88,14 +88,14 @@
|
||||
android:label="@string/title_activity_open_bitmessage_link"
|
||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<data android:scheme="bitmessage"/>
|
||||
<data android:scheme="bitmsg"/>
|
||||
<data android:scheme="bm"/>
|
||||
<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"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
@ -104,34 +104,34 @@
|
||||
android:parentActivityName=".MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity"/>
|
||||
android:value=".MainActivity" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<data
|
||||
android:host="*"
|
||||
android:mimeType="*/*"
|
||||
android:pathPattern=".*\\.dat"
|
||||
android:scheme="file"/>
|
||||
android:scheme="file" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".service.BitmessageService"
|
||||
android:exported="false"/>
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".service.ProofOfWorkService"
|
||||
android:exported="false"/>
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Synchronization -->
|
||||
<provider
|
||||
android:name=".synchronization.StubProvider"
|
||||
android:authorities="ch.dissem.apps.abit.provider"
|
||||
android:exported="false"
|
||||
android:syncable="true"/>
|
||||
android:syncable="true" />
|
||||
|
||||
<!-- Exports -->
|
||||
<provider
|
||||
@ -149,44 +149,54 @@
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
||||
<action android:name="android.accounts.AccountAuthenticator" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/authenticator"/>
|
||||
android:resource="@xml/authenticator" />
|
||||
</service>
|
||||
<service
|
||||
android:name=".synchronization.SyncService"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter"/>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.content.SyncAdapter"
|
||||
android:resource="@xml/syncadapter"/>
|
||||
android:resource="@xml/syncadapter" />
|
||||
</service>
|
||||
<service
|
||||
android:name=".service.BitmessageIntentService"
|
||||
android:exported="false"/>
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Receive Wi-Fi connection state changes -->
|
||||
<receiver android:name=".listener.WifiReceiver" android:enabled="@bool/is_pre_api_21">
|
||||
<receiver
|
||||
android:name=".listener.WifiReceiver"
|
||||
android:enabled="@bool/is_pre_api_21">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
<!-- This is bad for battery life, but needed on older devices to check
|
||||
if WiFi is available. Let's be honest, the whole app is bad for
|
||||
battery life. -->
|
||||
<action
|
||||
android:name="android.net.conn.CONNECTIVITY_CHANGE"
|
||||
tools:ignore="BatteryLife" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name=".service.StartServiceReceiver" android:enabled="@bool/is_post_api_21">
|
||||
<receiver
|
||||
android:name=".service.StartServiceReceiver"
|
||||
android:enabled="@bool/is_post_api_21">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service
|
||||
android:name=".service.StartupNodeOnWifiService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:exported="true"/>
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<activity
|
||||
android:name=".StatusActivity"
|
||||
@ -194,7 +204,7 @@
|
||||
android:parentActivityName=".MainActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".MainActivity"/>
|
||||
android:value=".MainActivity" />
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
|
@ -204,7 +204,7 @@ class AddressDetailFragment : Fragment() {
|
||||
* The fragment argument representing the item ID that this fragment
|
||||
* represents.
|
||||
*/
|
||||
val ARG_ITEM = "item"
|
||||
val EXPORT_POSTFIX = ".keys.dat"
|
||||
const val ARG_ITEM = "item"
|
||||
const val EXPORT_POSTFIX = ".keys.dat"
|
||||
}
|
||||
}
|
||||
|
@ -43,16 +43,19 @@ class ComposeMessageActivity : AppCompatActivity() {
|
||||
setHomeButtonEnabled(false)
|
||||
}
|
||||
|
||||
// Display the fragment as the main content.
|
||||
val fragment = ComposeMessageFragment()
|
||||
fragment.arguments = intent.extras
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.content, fragment)
|
||||
.commit()
|
||||
if (supportFragmentManager.findFragmentById(R.id.content) == null) {
|
||||
// Display the fragment as the main content.
|
||||
val fragment = ComposeMessageFragment()
|
||||
fragment.arguments = intent.extras
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.content, fragment)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_DRAFT = "ch.dissem.abit.Message.DRAFT"
|
||||
const val EXTRA_IDENTITY = "ch.dissem.abit.Message.SENDER"
|
||||
const val EXTRA_RECIPIENT = "ch.dissem.abit.Message.RECIPIENT"
|
||||
const val EXTRA_SUBJECT = "ch.dissem.abit.Message.SUBJECT"
|
||||
@ -62,10 +65,13 @@ class ComposeMessageActivity : AppCompatActivity() {
|
||||
const val EXTRA_PARENT = "ch.dissem.abit.Message.PARENT"
|
||||
|
||||
fun launchReplyTo(fragment: Fragment, item: Plaintext) =
|
||||
fragment.startActivity(getReplyIntent(
|
||||
ctx = fragment.activity ?: throw IllegalStateException("Fragment not attached to an activity"),
|
||||
item = item
|
||||
))
|
||||
fragment.startActivity(
|
||||
getReplyIntent(
|
||||
ctx = fragment.activity
|
||||
?: throw IllegalStateException("Fragment not attached to an activity"),
|
||||
item = item
|
||||
)
|
||||
)
|
||||
|
||||
fun launchReplyTo(activity: Activity, item: Plaintext) =
|
||||
activity.startActivity(getReplyIntent(activity, item))
|
||||
@ -89,15 +95,20 @@ class ComposeMessageActivity : AppCompatActivity() {
|
||||
}
|
||||
replyIntent.putExtra(EXTRA_PARENT, item)
|
||||
item.subject?.let { subject ->
|
||||
val prefix: String = if (subject.length >= 3 && subject.substring(0, 3).equals("RE:", ignoreCase = true)) {
|
||||
val prefix: String = if (subject.length >= 3 && subject.substring(0, 3).equals(
|
||||
"RE:",
|
||||
ignoreCase = true
|
||||
)) {
|
||||
""
|
||||
} else {
|
||||
"RE: "
|
||||
}
|
||||
replyIntent.putExtra(EXTRA_SUBJECT, prefix + subject)
|
||||
}
|
||||
replyIntent.putExtra(EXTRA_CONTENT,
|
||||
"\n\n------------------------------------------------------\n" + item.text!!)
|
||||
replyIntent.putExtra(
|
||||
EXTRA_CONTENT,
|
||||
"\n\n------------------------------------------------------\n" + item.text!!
|
||||
)
|
||||
return replyIntent
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
@ -25,6 +26,7 @@ import android.widget.AdapterView
|
||||
import android.widget.Toast
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_CONTENT
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_DRAFT
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_ENCODING
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_PARENT
|
||||
@ -38,6 +40,9 @@ import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
import ch.dissem.bitmessage.entity.Plaintext.Type.BROADCAST
|
||||
import ch.dissem.bitmessage.entity.Plaintext.Type.MSG
|
||||
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import ch.dissem.bitmessage.entity.valueobject.extended.Message
|
||||
import kotlinx.android.synthetic.main.fragment_compose_message.*
|
||||
|
||||
@ -52,72 +57,108 @@ class ComposeMessageFragment : Fragment() {
|
||||
|
||||
private var broadcast: Boolean = false
|
||||
private var encoding: Plaintext.Encoding = Plaintext.Encoding.SIMPLE
|
||||
private var parent: Plaintext? = null
|
||||
private val parents = mutableListOf<InventoryVector>()
|
||||
|
||||
private var draft: Plaintext? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let { arguments ->
|
||||
var id = arguments.getSerializable(EXTRA_IDENTITY) as? BitmessageAddress
|
||||
if (context != null && (id == null || id.privateKey == null)) {
|
||||
id = Singleton.getIdentity(context!!)
|
||||
}
|
||||
if (id?.privateKey != null) {
|
||||
identity = id
|
||||
retainInstance = true
|
||||
arguments?.apply {
|
||||
val draft = getSerializable(EXTRA_DRAFT) as Plaintext?
|
||||
if (draft != null) {
|
||||
this@ComposeMessageFragment.draft = draft
|
||||
identity = draft.from
|
||||
recipient = draft.to
|
||||
subject = draft.subject ?: ""
|
||||
content = draft.text ?: ""
|
||||
encoding = draft.encoding ?: Plaintext.Encoding.SIMPLE
|
||||
parents.addAll(draft.parents)
|
||||
} else {
|
||||
throw IllegalStateException("No identity set for ComposeMessageFragment")
|
||||
}
|
||||
broadcast = arguments.getBoolean(EXTRA_BROADCAST, false)
|
||||
if (arguments.containsKey(EXTRA_RECIPIENT)) {
|
||||
recipient = arguments.getSerializable(EXTRA_RECIPIENT) as BitmessageAddress
|
||||
}
|
||||
if (arguments.containsKey(EXTRA_SUBJECT)) {
|
||||
subject = arguments.getString(EXTRA_SUBJECT)
|
||||
}
|
||||
if (arguments.containsKey(EXTRA_CONTENT)) {
|
||||
content = arguments.getString(EXTRA_CONTENT)
|
||||
}
|
||||
encoding = arguments.getSerializable(EXTRA_ENCODING) as? Plaintext.Encoding ?: Plaintext.Encoding.SIMPLE
|
||||
var id = getSerializable(EXTRA_IDENTITY) as? BitmessageAddress
|
||||
if (context != null && (id == null || id.privateKey == null)) {
|
||||
id = Singleton.getIdentity(context!!)
|
||||
}
|
||||
if (id?.privateKey != null) {
|
||||
identity = id
|
||||
} else {
|
||||
throw IllegalStateException("No identity set for ComposeMessageFragment")
|
||||
}
|
||||
broadcast = getBoolean(EXTRA_BROADCAST, false)
|
||||
if (containsKey(EXTRA_RECIPIENT)) {
|
||||
recipient = getSerializable(EXTRA_RECIPIENT) as BitmessageAddress
|
||||
}
|
||||
if (containsKey(EXTRA_SUBJECT)) {
|
||||
subject = getString(EXTRA_SUBJECT)
|
||||
}
|
||||
if (containsKey(EXTRA_CONTENT)) {
|
||||
content = getString(EXTRA_CONTENT)
|
||||
}
|
||||
encoding = getSerializable(EXTRA_ENCODING) as? Plaintext.Encoding ?:
|
||||
Plaintext.Encoding.SIMPLE
|
||||
|
||||
if (arguments.containsKey(EXTRA_PARENT)) {
|
||||
parent = arguments.getSerializable(EXTRA_PARENT) as Plaintext
|
||||
if (containsKey(EXTRA_PARENT)) {
|
||||
val parent = getSerializable(EXTRA_PARENT) as Plaintext
|
||||
parent.inventoryVector?.let { parents.add(it) }
|
||||
}
|
||||
}
|
||||
} ?: {
|
||||
throw IllegalStateException("No identity set for ComposeMessageFragment")
|
||||
}.invoke()
|
||||
} ?: throw IllegalStateException("No identity set for ComposeMessageFragment")
|
||||
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_compose_message, container, false)
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View = inflater.inflate(R.layout.fragment_compose_message, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (broadcast) {
|
||||
recipient_input.visibility = View.GONE
|
||||
} else {
|
||||
val adapter = ContactAdapter(context!!)
|
||||
recipient_input.setAdapter(adapter)
|
||||
recipient_input.onItemClickListener = AdapterView.OnItemClickListener { _, _, pos, _ -> adapter.getItem(pos) }
|
||||
recipient_input.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
|
||||
recipient = adapter.getItem(position)
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) = Unit // leave current selection
|
||||
context?.let { ctx ->
|
||||
val identities = Singleton.getAddressRepository(ctx).getIdentities()
|
||||
sender_input.adapter = ContactAdapter(ctx, identities, true)
|
||||
val index = identities.indexOf(Singleton.getIdentity(ctx))
|
||||
if (index >= 0) {
|
||||
sender_input.setSelection(index)
|
||||
}
|
||||
recipient?.let { recipient_input.setText(it.toString()) }
|
||||
}
|
||||
subject_input.setText(subject)
|
||||
body_input.setText(content)
|
||||
|
||||
when {
|
||||
recipient == null -> recipient_input.requestFocus()
|
||||
subject.isEmpty() -> subject_input.requestFocus()
|
||||
else -> {
|
||||
body_input.requestFocus()
|
||||
body_input.setSelection(0)
|
||||
if (broadcast) {
|
||||
recipient_input.visibility = View.GONE
|
||||
} else {
|
||||
val adapter = ContactAdapter(
|
||||
ctx,
|
||||
Singleton.getAddressRepository(ctx).getContacts()
|
||||
)
|
||||
recipient_input.setAdapter(adapter)
|
||||
recipient_input.onItemClickListener =
|
||||
AdapterView.OnItemClickListener { _, _, pos, _ -> adapter.getItem(pos) }
|
||||
recipient_input.onItemSelectedListener =
|
||||
object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(
|
||||
parent: AdapterView<*>,
|
||||
view: View,
|
||||
position: Int,
|
||||
id: Long
|
||||
) {
|
||||
recipient = adapter.getItem(position)
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>) =
|
||||
Unit // leave current selection
|
||||
}
|
||||
recipient?.let { recipient_input.setText(it.toString()) }
|
||||
}
|
||||
subject_input.setText(subject)
|
||||
body_input.setText(content)
|
||||
|
||||
when {
|
||||
recipient == null -> recipient_input.requestFocus()
|
||||
subject.isEmpty() -> subject_input.requestFocus()
|
||||
else -> {
|
||||
body_input.requestFocus()
|
||||
body_input.setSelection(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -146,18 +187,17 @@ class ComposeMessageFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) = if (requestCode == 0 && data != null && resultCode == RESULT_OK) {
|
||||
encoding = data.getSerializableExtra(EXTRA_ENCODING) as Plaintext.Encoding
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) =
|
||||
if (requestCode == 0 && data != null && resultCode == RESULT_OK) {
|
||||
encoding = data.getSerializableExtra(EXTRA_ENCODING) as Plaintext.Encoding
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
private fun send() {
|
||||
private fun build(ctx: Context): Plaintext {
|
||||
val builder: Plaintext.Builder
|
||||
val ctx = activity ?: throw IllegalStateException("Fragment is not attached to an activity")
|
||||
val bmc = Singleton.getBitmessageContext(ctx)
|
||||
if (broadcast) {
|
||||
builder = Plaintext.Builder(BROADCAST).from(identity)
|
||||
builder = Plaintext.Builder(BROADCAST)
|
||||
} else {
|
||||
val inputString = recipient_input.text.toString()
|
||||
if (recipient == null || recipient?.toString() != inputString) {
|
||||
@ -175,42 +215,77 @@ class ComposeMessageFragment : Fragment() {
|
||||
}
|
||||
|
||||
}
|
||||
if (recipient == null) {
|
||||
Toast.makeText(context, R.string.error_msg_recipient_missing, Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
builder = Plaintext.Builder(MSG)
|
||||
.from(identity)
|
||||
.to(recipient)
|
||||
.to(recipient)
|
||||
}
|
||||
val sender = sender_input.selectedItem as? ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
sender?.let { builder.from(it) }
|
||||
if (!Preferences.requestAcknowledgements(ctx)) {
|
||||
builder.preventAck()
|
||||
}
|
||||
when (encoding) {
|
||||
Plaintext.Encoding.SIMPLE -> builder.message(
|
||||
subject_input.text.toString(),
|
||||
body_input.text.toString()
|
||||
subject_input.text.toString(),
|
||||
body_input.text.toString()
|
||||
)
|
||||
Plaintext.Encoding.EXTENDED -> builder.message(
|
||||
Message.Builder()
|
||||
.subject(subject_input.text.toString())
|
||||
.body(body_input.text.toString())
|
||||
.addParent(parent)
|
||||
.build()
|
||||
ExtendedEncoding(
|
||||
Message(
|
||||
subject = subject_input.text.toString(),
|
||||
body = body_input.text.toString(),
|
||||
parents = parents,
|
||||
files = emptyList()
|
||||
)
|
||||
)
|
||||
)
|
||||
else -> {
|
||||
Toast.makeText(
|
||||
ctx,
|
||||
ctx.getString(R.string.error_unsupported_encoding, encoding),
|
||||
Toast.LENGTH_LONG
|
||||
ctx,
|
||||
ctx.getString(R.string.error_unsupported_encoding, encoding),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
builder.message(
|
||||
subject_input.text.toString(),
|
||||
body_input.text.toString()
|
||||
subject_input.text.toString(),
|
||||
body_input.text.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
bmc.send(builder.build())
|
||||
draft?.id?.let { builder.id(it) }
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
if (draft?.labels?.any { it.type == Label.Type.DRAFT } != false) {
|
||||
context?.let { ctx ->
|
||||
draft = build(ctx).also { msg ->
|
||||
Singleton.labeler.markAsDraft(msg)
|
||||
Singleton.getMessageRepository(ctx).save(msg)
|
||||
}
|
||||
Toast.makeText(ctx, "Message saved as draft", Toast.LENGTH_LONG).show()
|
||||
} ?: throw IllegalStateException("Context is not available")
|
||||
}
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
identity = sender_input.selectedItem as BitmessageAddress
|
||||
// recipient is set when one is selected
|
||||
subject = subject_input.text?.toString() ?: ""
|
||||
content = body_input.text?.toString() ?: ""
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
private fun send() {
|
||||
val ctx = activity ?: throw IllegalStateException("Fragment is not attached to an activity")
|
||||
if (recipient == null) {
|
||||
Toast.makeText(ctx, R.string.error_msg_recipient_missing, Toast.LENGTH_LONG)
|
||||
.show()
|
||||
return
|
||||
}
|
||||
build(ctx).let { message ->
|
||||
draft = message
|
||||
Singleton.getBitmessageContext(ctx).send(message)
|
||||
}
|
||||
ctx.finish()
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class Identicon(input: BitmessageAddress) : Drawable() {
|
||||
override fun getOpacity() = PixelFormat.TRANSPARENT
|
||||
|
||||
companion object {
|
||||
private val SIZE = 9
|
||||
private val CENTER_COLUMN = 5
|
||||
private const val SIZE = 9
|
||||
private const val CENTER_COLUMN = 5
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
|
||||
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator
|
||||
|
||||
import ch.dissem.apps.abit.adapter.AddressSelectorAdapter
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.bitmessage.wif.WifImporter
|
||||
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator
|
||||
import org.ini4j.InvalidFileFormatException
|
||||
import org.jetbrains.anko.longToast
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
@ -39,8 +39,12 @@ class ImportIdentitiesFragment : Fragment() {
|
||||
private lateinit var adapter: AddressSelectorAdapter
|
||||
private lateinit var importer: WifImporter
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
inflater.inflate(R.layout.fragment_import_select_identities, container, false)
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View =
|
||||
inflater.inflate(R.layout.fragment_import_select_identities, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@ -48,17 +52,29 @@ class ImportIdentitiesFragment : Fragment() {
|
||||
val wifData = arguments.getString(WIF_DATA)
|
||||
val bmc = Singleton.getBitmessageContext(activity)
|
||||
|
||||
importer = WifImporter(bmc, wifData)
|
||||
try {
|
||||
importer = WifImporter(bmc, wifData)
|
||||
} catch (e: InvalidFileFormatException) {
|
||||
longToast(R.string.invalid_wif_file)
|
||||
activity.finish()
|
||||
return
|
||||
}
|
||||
|
||||
adapter = AddressSelectorAdapter(importer.getIdentities())
|
||||
val layoutManager = LinearLayoutManager(activity,
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false)
|
||||
val layoutManager = LinearLayoutManager(
|
||||
activity,
|
||||
LinearLayoutManager.VERTICAL,
|
||||
false
|
||||
)
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
recyclerView.layoutManager = layoutManager
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
recyclerView.addItemDecoration(SimpleListDividerDecorator(
|
||||
ContextCompat.getDrawable(activity, R.drawable.list_divider_h), true))
|
||||
recyclerView.addItemDecoration(
|
||||
SimpleListDividerDecorator(
|
||||
ContextCompat.getDrawable(activity, R.drawable.list_divider_h), true
|
||||
)
|
||||
)
|
||||
|
||||
view.findViewById<Button>(R.id.finish).setOnClickListener {
|
||||
importer.importAll(adapter.selected)
|
||||
@ -72,6 +88,6 @@ class ImportIdentitiesFragment : Fragment() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val WIF_DATA = "wif_data"
|
||||
const val WIF_DATA = "wif_data"
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ package ch.dissem.apps.abit
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
interface ListHolder<L> {
|
||||
interface ListHolder<in L> {
|
||||
fun updateList(label: L)
|
||||
|
||||
fun setActivateOnItemClick(activateOnItemClick: Boolean)
|
||||
|
@ -146,12 +146,15 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
SyncAdapter.stopSync(this)
|
||||
}
|
||||
if (drawer.isDrawerOpen) {
|
||||
val lps = RelativeLayout.LayoutParams(ViewGroup
|
||||
.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
lps.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
|
||||
lps.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
|
||||
val margin = ((resources.displayMetrics.density * 12) as Number).toInt()
|
||||
lps.setMargins(margin, margin, margin, margin)
|
||||
val lps = RelativeLayout.LayoutParams(
|
||||
ViewGroup
|
||||
.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
).apply {
|
||||
addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
|
||||
addRule(RelativeLayout.ALIGN_PARENT_LEFT)
|
||||
val margin = ((resources.displayMetrics.density * 12) as Number).toInt()
|
||||
setMargins(margin, margin, margin, margin)
|
||||
}
|
||||
|
||||
ShowcaseView.Builder(this)
|
||||
.withMaterialShowcase()
|
||||
@ -192,19 +195,23 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
|
||||
private fun createDrawer(toolbar: Toolbar) {
|
||||
val profiles = ArrayList<IProfile<*>>()
|
||||
profiles.add(ProfileSettingDrawerItem()
|
||||
.withName(getString(R.string.add_identity))
|
||||
.withDescription(getString(R.string.add_identity_summary))
|
||||
.withIcon(IconicsDrawable(this, GoogleMaterial.Icon.gmd_add)
|
||||
.actionBar()
|
||||
.paddingDp(5)
|
||||
.colorRes(R.color.icons))
|
||||
.withIdentifier(ADD_IDENTITY.toLong())
|
||||
profiles.add(
|
||||
ProfileSettingDrawerItem()
|
||||
.withName(getString(R.string.add_identity))
|
||||
.withDescription(getString(R.string.add_identity_summary))
|
||||
.withIcon(
|
||||
IconicsDrawable(this, GoogleMaterial.Icon.gmd_add)
|
||||
.actionBar()
|
||||
.paddingDp(5)
|
||||
.colorRes(R.color.icons)
|
||||
)
|
||||
.withIdentifier(ADD_IDENTITY.toLong())
|
||||
)
|
||||
profiles.add(ProfileSettingDrawerItem()
|
||||
.withName(getString(R.string.manage_identity))
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
.withIdentifier(MANAGE_IDENTITY.toLong())
|
||||
profiles.add(
|
||||
ProfileSettingDrawerItem()
|
||||
.withName(getString(R.string.manage_identity))
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
.withIdentifier(MANAGE_IDENTITY.toLong())
|
||||
)
|
||||
// Create the AccountHeader
|
||||
accountHeader = AccountHeaderBuilder()
|
||||
@ -212,26 +219,36 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
.withHeaderBackground(R.drawable.header)
|
||||
.withProfiles(profiles)
|
||||
.withOnAccountHeaderProfileImageListener(ProfileImageListener(this))
|
||||
.withOnAccountHeaderListener(ProfileSelectionListener(this@MainActivity, supportFragmentManager))
|
||||
.withOnAccountHeaderListener(
|
||||
ProfileSelectionListener(
|
||||
this@MainActivity,
|
||||
supportFragmentManager
|
||||
)
|
||||
)
|
||||
.build()
|
||||
if (profiles.size > 2) { // There's always the add and manage identity items
|
||||
accountHeader.setActiveProfile(profiles[0], true)
|
||||
}
|
||||
|
||||
val drawerItems = ArrayList<IDrawerItem<*, *>>()
|
||||
drawerItems.add(PrimaryDrawerItem()
|
||||
.withIdentifier(LABEL_ARCHIVE.id as Long)
|
||||
.withName(R.string.archive)
|
||||
.withTag(LABEL_ARCHIVE)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_archive)
|
||||
drawerItems.add(
|
||||
PrimaryDrawerItem()
|
||||
.withIdentifier(LABEL_ARCHIVE.id as Long)
|
||||
.withName(R.string.archive)
|
||||
.withTag(LABEL_ARCHIVE)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_archive)
|
||||
)
|
||||
drawerItems.add(DividerDrawerItem())
|
||||
drawerItems.add(PrimaryDrawerItem()
|
||||
.withName(R.string.contacts_and_subscriptions)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_contacts))
|
||||
drawerItems.add(PrimaryDrawerItem()
|
||||
.withName(R.string.settings)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings))
|
||||
drawerItems.add(
|
||||
PrimaryDrawerItem()
|
||||
.withName(R.string.contacts_and_subscriptions)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_contacts)
|
||||
)
|
||||
drawerItems.add(
|
||||
PrimaryDrawerItem()
|
||||
.withName(R.string.settings)
|
||||
.withIcon(GoogleMaterial.Icon.gmd_settings)
|
||||
)
|
||||
|
||||
nodeSwitch = SwitchDrawerItem()
|
||||
.withIdentifier(ID_NODE_SWITCH)
|
||||
@ -369,7 +386,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
// we know that there are 2 setting elements.
|
||||
// Set the new profile above them ;)
|
||||
accountHeader.addProfile(
|
||||
newProfile, accountHeader.profiles.size - 2)
|
||||
newProfile, accountHeader.profiles.size - 2
|
||||
)
|
||||
} else {
|
||||
accountHeader.addProfiles(newProfile)
|
||||
}
|
||||
@ -435,14 +453,31 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
// In two-pane mode, show the detail view in this activity by
|
||||
// adding or replacing the detail fragment using a
|
||||
// fragment transaction.
|
||||
val arguments = Bundle()
|
||||
arguments.putSerializable(MessageDetailFragment.ARG_ITEM, item)
|
||||
val fragment = when (item) {
|
||||
is Plaintext -> MessageDetailFragment()
|
||||
is BitmessageAddress -> AddressDetailFragment()
|
||||
is Plaintext -> {
|
||||
if (item.labels.any { it.type == Label.Type.DRAFT }) {
|
||||
ComposeMessageFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(ComposeMessageActivity.EXTRA_DRAFT, item)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MessageDetailFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(MessageDetailFragment.ARG_ITEM, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is BitmessageAddress -> {
|
||||
AddressDetailFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putSerializable(AddressDetailFragment.ARG_ITEM, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> throw IllegalArgumentException("Plaintext or BitmessageAddress expected, but was ${item::class.simpleName}")
|
||||
}
|
||||
fragment.arguments = arguments
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.message_detail_container, fragment)
|
||||
.commit()
|
||||
@ -451,19 +486,29 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
// for the selected item ID.
|
||||
val detailIntent = when (item) {
|
||||
is Plaintext -> {
|
||||
Intent(this, MessageDetailActivity::class.java)
|
||||
if (item.labels.any { it.type == Label.Type.DRAFT }) {
|
||||
Intent(this, ComposeMessageActivity::class.java).apply {
|
||||
putExtra(ComposeMessageActivity.EXTRA_DRAFT, item)
|
||||
}
|
||||
} else {
|
||||
Intent(this, MessageDetailActivity::class.java).apply {
|
||||
putExtra(MessageDetailFragment.ARG_ITEM, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
is BitmessageAddress -> Intent(this, AddressDetailActivity::class.java).apply {
|
||||
putExtra(AddressDetailFragment.ARG_ITEM, item)
|
||||
}
|
||||
is BitmessageAddress -> Intent(this, AddressDetailActivity::class.java)
|
||||
else -> throw IllegalArgumentException("Plaintext or BitmessageAddress expected, but was ${item::class.simpleName}")
|
||||
}
|
||||
detailIntent.putExtra(MessageDetailFragment.ARG_ITEM, item)
|
||||
startActivity(detailIntent)
|
||||
}
|
||||
}
|
||||
|
||||
fun setDetailView(fragment: Fragment) {
|
||||
if (hasDetailPane) {
|
||||
supportFragmentManager.beginTransaction()
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.message_detail_container, fragment)
|
||||
.commit()
|
||||
}
|
||||
@ -474,15 +519,15 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val EXTRA_SHOW_MESSAGE = "ch.dissem.abit.ShowMessage"
|
||||
val EXTRA_SHOW_LABEL = "ch.dissem.abit.ShowLabel"
|
||||
val EXTRA_REPLY_TO_MESSAGE = "ch.dissem.abit.ReplyToMessage"
|
||||
val ACTION_SHOW_INBOX = "ch.dissem.abit.ShowInbox"
|
||||
const val EXTRA_SHOW_MESSAGE = "ch.dissem.abit.ShowMessage"
|
||||
const val EXTRA_SHOW_LABEL = "ch.dissem.abit.ShowLabel"
|
||||
const val EXTRA_REPLY_TO_MESSAGE = "ch.dissem.abit.ReplyToMessage"
|
||||
const val ACTION_SHOW_INBOX = "ch.dissem.abit.ShowInbox"
|
||||
|
||||
val ADD_IDENTITY = 1
|
||||
val MANAGE_IDENTITY = 2
|
||||
const val ADD_IDENTITY = 1
|
||||
const val MANAGE_IDENTITY = 2
|
||||
|
||||
private val ID_NODE_SWITCH: Long = 1
|
||||
private const val ID_NODE_SWITCH: Long = 1
|
||||
|
||||
private var instance: WeakReference<MainActivity>? = null
|
||||
|
||||
|
@ -70,7 +70,11 @@ class MessageDetailFragment : Fragment() {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View =
|
||||
inflater.inflate(R.layout.fragment_message_detail, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@ -84,6 +88,13 @@ class MessageDetailFragment : Fragment() {
|
||||
status.setImageResource(Assets.getStatusDrawable(item.status))
|
||||
status.contentDescription = getString(Assets.getStatusString(item.status))
|
||||
avatar.setImageDrawable(Identicon(item.from))
|
||||
val senderClickListener: (View) -> Unit = {
|
||||
MainActivity.apply {
|
||||
onItemSelected(item.from)
|
||||
}
|
||||
}
|
||||
avatar.setOnClickListener(senderClickListener)
|
||||
sender.setOnClickListener(senderClickListener)
|
||||
sender.text = item.from.toString()
|
||||
item.to?.let { to ->
|
||||
recipient.text = to.toString()
|
||||
@ -124,7 +135,11 @@ class MessageDetailFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showRelatedMessages(ctx: Context, rootView: View, @IdRes id: Int, messages: List<Plaintext>) {
|
||||
private fun showRelatedMessages(
|
||||
ctx: Context,
|
||||
rootView: View, @IdRes id: Int,
|
||||
messages: List<Plaintext>
|
||||
) {
|
||||
val recyclerView = rootView.findViewById<RecyclerView>(id)
|
||||
val adapter = RelatedMessageAdapter(ctx, messages)
|
||||
recyclerView.adapter = adapter
|
||||
@ -136,8 +151,10 @@ class MessageDetailFragment : Fragment() {
|
||||
activity?.let { activity ->
|
||||
Drawables.addIcon(activity, menu, R.id.reply, GoogleMaterial.Icon.gmd_reply)
|
||||
Drawables.addIcon(activity, menu, R.id.delete, GoogleMaterial.Icon.gmd_delete)
|
||||
Drawables.addIcon(activity, menu, R.id.mark_unread, GoogleMaterial.Icon
|
||||
.gmd_markunread)
|
||||
Drawables.addIcon(
|
||||
activity, menu, R.id.mark_unread, GoogleMaterial.Icon
|
||||
.gmd_markunread
|
||||
)
|
||||
Drawables.addIcon(activity, menu, R.id.archive, GoogleMaterial.Icon.gmd_archive)
|
||||
}
|
||||
|
||||
@ -187,9 +204,15 @@ class MessageDetailFragment : Fragment() {
|
||||
return false
|
||||
}
|
||||
|
||||
private class RelatedMessageAdapter internal constructor(private val ctx: Context, private val messages: List<Plaintext>) : RecyclerView.Adapter<RelatedMessageAdapter.ViewHolder>() {
|
||||
private class RelatedMessageAdapter internal constructor(
|
||||
private val ctx: Context,
|
||||
private val messages: List<Plaintext>
|
||||
) : RecyclerView.Adapter<RelatedMessageAdapter.ViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RelatedMessageAdapter.ViewHolder {
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): RelatedMessageAdapter.ViewHolder {
|
||||
val context = parent.context
|
||||
val inflater = LayoutInflater.from(context)
|
||||
|
||||
@ -236,7 +259,8 @@ class MessageDetailFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private class LabelAdapter internal constructor(private val ctx: Context, labels: Set<Label>) : RecyclerView.Adapter<LabelAdapter.ViewHolder>() {
|
||||
private class LabelAdapter internal constructor(private val ctx: Context, labels: Set<Label>) :
|
||||
RecyclerView.Adapter<LabelAdapter.ViewHolder>() {
|
||||
|
||||
private val labels = labels.toMutableList()
|
||||
|
||||
@ -274,7 +298,7 @@ class MessageDetailFragment : Fragment() {
|
||||
* The fragment argument representing the item ID that this fragment
|
||||
* represents.
|
||||
*/
|
||||
val ARG_ITEM = "item"
|
||||
const val ARG_ITEM = "item"
|
||||
|
||||
fun isInTrash(item: Plaintext?) = item?.labels?.any { it.type == Label.Type.TRASH } == true
|
||||
}
|
||||
|
@ -20,25 +20,22 @@ import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.Filter
|
||||
import android.widget.Filterable
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import android.widget.*
|
||||
import ch.dissem.apps.abit.Identicon
|
||||
import ch.dissem.apps.abit.R
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* An adapter for contacts. Can be filtered by alias or address.
|
||||
*/
|
||||
class ContactAdapter(ctx: Context) : BaseAdapter(), Filterable {
|
||||
class ContactAdapter(
|
||||
ctx: Context,
|
||||
private val originalData: List<BitmessageAddress>,
|
||||
private val slim: Boolean = false
|
||||
) :
|
||||
BaseAdapter(), Filterable {
|
||||
private val inflater = LayoutInflater.from(ctx)
|
||||
private val originalData = Singleton.getAddressRepository(ctx).getContacts()
|
||||
private var data: List<BitmessageAddress> = originalData
|
||||
|
||||
override fun getCount() = data.size
|
||||
@ -49,23 +46,33 @@ class ContactAdapter(ctx: Context) : BaseAdapter(), Filterable {
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val viewHolder = if (convertView == null) {
|
||||
ViewHolder(inflater.inflate(R.layout.contact_row, parent, false))
|
||||
ViewHolder(
|
||||
inflater.inflate(
|
||||
if (slim) {
|
||||
R.layout.contact_row_slim
|
||||
} else {
|
||||
R.layout.contact_row
|
||||
},
|
||||
parent, false
|
||||
)
|
||||
)
|
||||
} else {
|
||||
convertView.tag as ViewHolder
|
||||
}
|
||||
val item = getItem(position)
|
||||
viewHolder.avatar.setImageDrawable(Identicon(item))
|
||||
viewHolder.name.text = item.toString()
|
||||
viewHolder.address.text = item.address
|
||||
viewHolder.address?.text = item.address
|
||||
|
||||
return viewHolder.view
|
||||
}
|
||||
|
||||
override fun getFilter(): Filter = ContactFilter()
|
||||
|
||||
private inner class ViewHolder(val view: View) {
|
||||
val avatar = view.findViewById<ImageView>(R.id.avatar)!!
|
||||
val name = view.findViewById<TextView>(R.id.name)!!
|
||||
val address = view.findViewById<TextView>(R.id.address)!!
|
||||
val avatar: ImageView = view.findViewById(R.id.avatar)
|
||||
val name: TextView = view.findViewById(R.id.name)
|
||||
val address: TextView? = view.findViewById(R.id.address)
|
||||
|
||||
init {
|
||||
view.tag = this
|
||||
@ -83,27 +90,36 @@ class ContactAdapter(ctx: Context) : BaseAdapter(), Filterable {
|
||||
val newValues = ArrayList<BitmessageAddress>()
|
||||
|
||||
originalData
|
||||
.forEach { value ->
|
||||
value.alias?.toLowerCase()?.let { alias ->
|
||||
if (alias.startsWith(prefixString)) {
|
||||
newValues.add(value)
|
||||
} else {
|
||||
val words = alias.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
.forEach { value ->
|
||||
value.alias?.toLowerCase()?.let { alias ->
|
||||
if (alias.startsWith(prefixString)) {
|
||||
newValues.add(value)
|
||||
} else {
|
||||
val words =
|
||||
alias.split(" ".toRegex()).dropLastWhile { it.isEmpty() }
|
||||
.toTypedArray()
|
||||
|
||||
for (word in words) {
|
||||
if (word.startsWith(prefixString)) {
|
||||
newValues.add(value)
|
||||
break
|
||||
}
|
||||
for (word in words) {
|
||||
if (word.startsWith(prefixString)) {
|
||||
newValues.add(value)
|
||||
break
|
||||
}
|
||||
}
|
||||
} ?: {
|
||||
val address = value.address.toLowerCase()
|
||||
if (address.contains(prefixString)) {
|
||||
newValues.add(value)
|
||||
}
|
||||
}.invoke()
|
||||
}
|
||||
}
|
||||
} ?: {
|
||||
val address = value.address.toLowerCase()
|
||||
if (address.contains(prefixString)) {
|
||||
newValues.add(value)
|
||||
}
|
||||
}.invoke()
|
||||
}
|
||||
|
||||
if (newValues.isEmpty()) {
|
||||
try {
|
||||
newValues.add(BitmessageAddress(prefix.toString()))
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
results.values = newValues
|
||||
results.count = newValues.size
|
||||
@ -125,4 +141,6 @@ class ContactAdapter(ctx: Context) : BaseAdapter(), Filterable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun indexOf(element: BitmessageAddress) = originalData.indexOf(element)
|
||||
}
|
||||
|
@ -55,6 +55,6 @@ class ErrorNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
override val notificationId = ERROR_NOTIFICATION_ID
|
||||
|
||||
companion object {
|
||||
val ERROR_NOTIFICATION_ID = 4
|
||||
const val ERROR_NOTIFICATION_ID = 4
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
override val notificationId = NEW_MESSAGE_NOTIFICATION_ID
|
||||
|
||||
companion object {
|
||||
private val NEW_MESSAGE_NOTIFICATION_ID = 1
|
||||
private const val NEW_MESSAGE_NOTIFICATION_ID = 1
|
||||
private val SPAN_EMPHASIS = StyleSpan(Typeface.BOLD)
|
||||
}
|
||||
}
|
||||
|
@ -68,15 +68,15 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
|
||||
* Returns the contacts in the following order:
|
||||
*
|
||||
* * Subscribed addresses come first
|
||||
* * Addresses with Aliases (alphabetically)
|
||||
* * Addresses (alphabetically)
|
||||
* * Addresses with aliases (alphabetically)
|
||||
* * Addresses without aliases are omitted
|
||||
*
|
||||
*
|
||||
* @return the ordered list of ids (address strings)
|
||||
*/
|
||||
fun getContactIds(): List<String> = findIds(
|
||||
"private_key IS NULL OR chan = '1'",
|
||||
"$COLUMN_SUBSCRIBED DESC, $COLUMN_ALIAS IS NULL, $COLUMN_ALIAS, $COLUMN_ADDRESS"
|
||||
"($COLUMN_PRIVATE_KEY IS NULL OR $COLUMN_CHAN = '1') AND $COLUMN_ALIAS IS NOT NULL",
|
||||
"$COLUMN_SUBSCRIBED DESC, $COLUMN_ALIAS, $COLUMN_ADDRESS"
|
||||
)
|
||||
|
||||
private fun findIds(where: String, orderBy: String): List<String> {
|
||||
|
@ -54,7 +54,7 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory {
|
||||
private fun getCache(stream: Long): MutableMap<InventoryVector, Long> {
|
||||
fun addToCache(stream: Long): MutableMap<InventoryVector, Long> {
|
||||
val result: MutableMap<InventoryVector, Long> = ConcurrentHashMap()
|
||||
cache.put(stream, result)
|
||||
cache[stream] = result
|
||||
|
||||
val projection = arrayOf(COLUMN_HASH, COLUMN_EXPIRES)
|
||||
|
||||
@ -149,7 +149,7 @@ class AndroidInventory(private val sql: SqlHelper) : Inventory {
|
||||
|
||||
sql.writableDatabase.insertOrThrow(TABLE_NAME, null, values)
|
||||
|
||||
getCache(objectMessage.stream).put(iv, objectMessage.expiresTime)
|
||||
getCache(objectMessage.stream)[iv] = objectMessage.expiresTime
|
||||
} catch (e: SQLiteConstraintException) {
|
||||
LOG.trace(e.message, e)
|
||||
}
|
||||
|
@ -125,13 +125,13 @@ class AndroidProofOfWorkRepository(private val sql: SqlHelper) : ProofOfWorkRepo
|
||||
companion object {
|
||||
private val LOG = LoggerFactory.getLogger(AndroidProofOfWorkRepository::class.java)
|
||||
|
||||
private val TABLE_NAME = "POW"
|
||||
private val COLUMN_INITIAL_HASH = "initial_hash"
|
||||
private val COLUMN_DATA = "data"
|
||||
private val COLUMN_VERSION = "version"
|
||||
private val COLUMN_NONCE_TRIALS_PER_BYTE = "nonce_trials_per_byte"
|
||||
private val COLUMN_EXTRA_BYTES = "extra_bytes"
|
||||
private val COLUMN_EXPIRATION_TIME = "expiration_time"
|
||||
private val COLUMN_MESSAGE_ID = "message_id"
|
||||
private const val TABLE_NAME = "POW"
|
||||
private const val COLUMN_INITIAL_HASH = "initial_hash"
|
||||
private const val COLUMN_DATA = "data"
|
||||
private const val COLUMN_VERSION = "version"
|
||||
private const val COLUMN_NONCE_TRIALS_PER_BYTE = "nonce_trials_per_byte"
|
||||
private const val COLUMN_EXTRA_BYTES = "extra_bytes"
|
||||
private const val COLUMN_EXPIRATION_TIME = "expiration_time"
|
||||
private const val COLUMN_MESSAGE_ID = "message_id"
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ class SqlHelper(private val ctx: Context) : SQLiteOpenHelper(ctx, DATABASE_NAME,
|
||||
|
||||
companion object {
|
||||
// If you change the database schema, you must increment the database version.
|
||||
private val DATABASE_VERSION = 7
|
||||
val DATABASE_NAME = "jabit.db"
|
||||
private const val DATABASE_VERSION = 7
|
||||
const val DATABASE_NAME = "jabit.db"
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,9 @@ import android.net.ConnectivityManager
|
||||
import android.os.Handler
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification.Companion.NETWORK_NOTIFICATION_ID
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.utils.Property
|
||||
import org.jetbrains.anko.connectivityManager
|
||||
|
||||
/**
|
||||
* Define a Service that returns an IBinder for the
|
||||
|
@ -19,7 +19,6 @@ package ch.dissem.apps.abit.service
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.IBinder
|
||||
import android.support.v4.content.ContextCompat
|
||||
import ch.dissem.apps.abit.notification.ProofOfWorkNotification
|
||||
import ch.dissem.apps.abit.notification.ProofOfWorkNotification.Companion.ONGOING_NOTIFICATION_ID
|
||||
|
@ -2,7 +2,6 @@ package ch.dissem.apps.abit.service
|
||||
|
||||
import android.app.job.JobParameters
|
||||
import android.app.job.JobService
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.support.annotation.RequiresApi
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
|
@ -18,7 +18,6 @@ package ch.dissem.apps.abit.synchronization
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
|
||||
/**
|
||||
* Define a Service that returns an IBinder for the
|
||||
|
@ -44,7 +44,7 @@ import java.io.ByteArrayOutputStream
|
||||
object Drawables {
|
||||
private val LOG = LoggerFactory.getLogger(Drawables::class.java)
|
||||
|
||||
private val QR_CODE_SIZE = 350
|
||||
private const val QR_CODE_SIZE = 350
|
||||
|
||||
fun addIcon(ctx: Context, menu: Menu, menuItem: Int, icon: IIcon): MenuItem {
|
||||
val item = menu.findItem(menuItem)
|
||||
|
@ -25,7 +25,7 @@ class Observable<T>(value: T) {
|
||||
* To prevent memory leaks, the observer must be removed if it isn't used anymore.
|
||||
*/
|
||||
fun addObserver(key: Any, observer: (T) -> Unit) {
|
||||
observers.put(key, observer)
|
||||
observers[key] = observer
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ public final class PRNGFixes {
|
||||
private static final int VERSION_CODE_JELLY_BEAN = 16;
|
||||
private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
|
||||
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
|
||||
getBuildFingerprintAndDeviceSerial();
|
||||
getBuildFingerprintAndDeviceSerial();
|
||||
|
||||
/**
|
||||
* Hidden constructor to prevent instantiation.
|
||||
@ -70,7 +70,7 @@ public final class PRNGFixes {
|
||||
*/
|
||||
private static void applyOpenSSLFix() throws SecurityException {
|
||||
if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN)
|
||||
|| (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) {
|
||||
|| (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) {
|
||||
// No need to apply the fix
|
||||
return;
|
||||
}
|
||||
@ -78,18 +78,18 @@ public final class PRNGFixes {
|
||||
try {
|
||||
// Mix in the device- and invocation-specific seed.
|
||||
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||
.getMethod("RAND_seed", byte[].class)
|
||||
.invoke(null, (Object) generateSeed());
|
||||
.getMethod("RAND_seed", byte[].class)
|
||||
.invoke(null, (Object) generateSeed());
|
||||
|
||||
// Mix output of Linux PRNG into OpenSSL's PRNG
|
||||
int bytesRead = (Integer) Class.forName(
|
||||
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||
.getMethod("RAND_load_file", String.class, long.class)
|
||||
.invoke(null, "/dev/urandom", 1024);
|
||||
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||
.getMethod("RAND_load_file", String.class, long.class)
|
||||
.invoke(null, "/dev/urandom", 1024);
|
||||
if (bytesRead != 1024) {
|
||||
throw new IOException(
|
||||
"Unexpected number of bytes read from Linux PRNG: "
|
||||
+ bytesRead);
|
||||
"Unexpected number of bytes read from Linux PRNG: "
|
||||
+ bytesRead);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SecurityException("Failed to seed OpenSSL PRNG", e);
|
||||
@ -104,7 +104,7 @@ public final class PRNGFixes {
|
||||
* @throws SecurityException if the fix is needed but could not be applied.
|
||||
*/
|
||||
private static void installLinuxPRNGSecureRandom()
|
||||
throws SecurityException {
|
||||
throws SecurityException {
|
||||
if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) {
|
||||
// No need to apply the fix
|
||||
return;
|
||||
@ -113,11 +113,11 @@ public final class PRNGFixes {
|
||||
// Install a Linux PRNG-based SecureRandom implementation as the
|
||||
// default, if not yet installed.
|
||||
Provider[] secureRandomProviders =
|
||||
Security.getProviders("SecureRandom.SHA1PRNG");
|
||||
Security.getProviders("SecureRandom.SHA1PRNG");
|
||||
if ((secureRandomProviders == null)
|
||||
|| (secureRandomProviders.length < 1)
|
||||
|| (!LinuxPRNGSecureRandomProvider.class.equals(
|
||||
secureRandomProviders[0].getClass()))) {
|
||||
|| (secureRandomProviders.length < 1)
|
||||
|| (!LinuxPRNGSecureRandomProvider.class.equals(
|
||||
secureRandomProviders[0].getClass()))) {
|
||||
Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);
|
||||
}
|
||||
|
||||
@ -126,10 +126,10 @@ public final class PRNGFixes {
|
||||
// by the Linux PRNG-based SecureRandom implementation.
|
||||
SecureRandom rng1 = new SecureRandom();
|
||||
if (!LinuxPRNGSecureRandomProvider.class.equals(
|
||||
rng1.getProvider().getClass())) {
|
||||
rng1.getProvider().getClass())) {
|
||||
throw new SecurityException(
|
||||
"new SecureRandom() backed by wrong Provider: "
|
||||
+ rng1.getProvider().getClass());
|
||||
"new SecureRandom() backed by wrong Provider: "
|
||||
+ rng1.getProvider().getClass());
|
||||
}
|
||||
|
||||
SecureRandom rng2;
|
||||
@ -139,10 +139,10 @@ public final class PRNGFixes {
|
||||
throw new SecurityException("SHA1PRNG not available", e);
|
||||
}
|
||||
if (!LinuxPRNGSecureRandomProvider.class.equals(
|
||||
rng2.getProvider().getClass())) {
|
||||
rng2.getProvider().getClass())) {
|
||||
throw new SecurityException(
|
||||
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
|
||||
+ " Provider: " + rng2.getProvider().getClass());
|
||||
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
|
||||
+ " Provider: " + rng2.getProvider().getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,11 +152,11 @@ public final class PRNGFixes {
|
||||
*/
|
||||
private static class LinuxPRNGSecureRandomProvider extends Provider {
|
||||
|
||||
public LinuxPRNGSecureRandomProvider() {
|
||||
LinuxPRNGSecureRandomProvider() {
|
||||
super("LinuxPRNG",
|
||||
1.0,
|
||||
"A Linux-specific random number provider that uses"
|
||||
+ " /dev/urandom");
|
||||
1.0,
|
||||
"A Linux-specific random number provider that uses"
|
||||
+ " /dev/urandom");
|
||||
// Although /dev/urandom is not a SHA-1 PRNG, some apps
|
||||
// explicitly request a SHA1PRNG SecureRandom and we thus need to
|
||||
// prevent them from getting the default implementation whose output
|
||||
@ -225,7 +225,7 @@ public final class PRNGFixes {
|
||||
// On a small fraction of devices /dev/urandom is not writable.
|
||||
// Log and ignore.
|
||||
Log.w(PRNGFixes.class.getSimpleName(),
|
||||
"Failed to mix seed into " + URANDOM_FILE);
|
||||
"Failed to mix seed into " + URANDOM_FILE);
|
||||
} finally {
|
||||
mSeeded = true;
|
||||
}
|
||||
@ -249,7 +249,7 @@ public final class PRNGFixes {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new SecurityException(
|
||||
"Failed to read from " + URANDOM_FILE, e);
|
||||
"Failed to read from " + URANDOM_FILE, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,10 +269,10 @@ public final class PRNGFixes {
|
||||
// output being pulled into this process prematurely.
|
||||
try {
|
||||
sUrandomIn = new DataInputStream(
|
||||
new FileInputStream(URANDOM_FILE));
|
||||
new FileInputStream(URANDOM_FILE));
|
||||
} catch (IOException e) {
|
||||
throw new SecurityException("Failed to open "
|
||||
+ URANDOM_FILE + " for reading", e);
|
||||
+ URANDOM_FILE + " for reading", e);
|
||||
}
|
||||
}
|
||||
return sUrandomIn;
|
||||
@ -297,7 +297,7 @@ public final class PRNGFixes {
|
||||
try {
|
||||
ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();
|
||||
DataOutputStream seedBufferOut =
|
||||
new DataOutputStream(seedBuffer);
|
||||
new DataOutputStream(seedBuffer);
|
||||
seedBufferOut.writeLong(System.currentTimeMillis());
|
||||
seedBufferOut.writeLong(System.nanoTime());
|
||||
seedBufferOut.writeInt(Process.myPid());
|
||||
|
@ -37,11 +37,11 @@
|
||||
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:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textStyle="bold"
|
||||
tools:text="Name" />
|
||||
@ -53,9 +53,9 @@
|
||||
android:layout_alignBottom="@+id/avatar"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:ellipsize="marquee"
|
||||
android:lines="1"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="BM-2cW0000000000000000000000000000000" />
|
||||
|
||||
|
47
app/src/main/res/layout/contact_row_slim.xml
Normal file
47
app/src/main/res/layout/contact_row_slim.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="4dp"
|
||||
android:src="@color/colorAccent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:paddingBottom="0dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingTop="0dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="Name" />
|
||||
|
||||
</RelativeLayout>
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2016 Christian Basler
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -15,8 +14,7 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<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"
|
||||
@ -34,13 +32,13 @@
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:layout_constraintLeft_creator="1"
|
||||
tools:layout_constraintTop_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"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/description">
|
||||
|
||||
@ -48,7 +46,7 @@
|
||||
android:id="@+id/label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/label"/>
|
||||
android:hint="@string/label" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
@ -64,7 +62,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/passphrase"
|
||||
android:inputType="textMultiLine"/>
|
||||
android:inputType="textMultiLine" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
@ -82,7 +80,8 @@
|
||||
android:ems="10"
|
||||
android:hint="@string/number_of_identities"
|
||||
android:inputType="number"
|
||||
android:text="1"/>
|
||||
android:text="1"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
@ -92,7 +91,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/shorter"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/number_of_identities_wrapper"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/number_of_identities_wrapper" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/ok"
|
||||
@ -103,7 +102,7 @@
|
||||
android:text="@string/ok"
|
||||
android:textColor="@color/colorAccent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/shorter"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/shorter" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/dismiss"
|
||||
@ -113,6 +112,6 @@
|
||||
android:text="@string/cancel"
|
||||
android:textColor="@color/colorAccent"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ok"
|
||||
app:layout_constraintRight_toLeftOf="@id/ok"/>
|
||||
app:layout_constraintRight_toLeftOf="@id/ok" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
@ -1,46 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/recipient_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/to"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLines="1"/>
|
||||
|
||||
</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_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/subject"
|
||||
android:inputType="textEmailSubject"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/body_input"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start|top"
|
||||
android:hint="@string/compose_body_hint"
|
||||
android:inputType="textMultiLine|textCapSentences"
|
||||
android:scrollbars="vertical"/>
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:labelFor="@id/sender_input"
|
||||
android:padding="4dp"
|
||||
android:text="@string/from"
|
||||
android:textColor="#9b9b9b"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/sender_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4dp">
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/recipient_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/to"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLines="1" />
|
||||
|
||||
</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_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/subject"
|
||||
android:inputType="textEmailSubject"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/body_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="start|top"
|
||||
android:hint="@string/compose_body_hint"
|
||||
android:inputType="textMultiLine|textCapSentences"
|
||||
android:scrollbars="none"
|
||||
tools:ignore="InefficientWeight" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
@ -26,6 +26,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/bg_item_normal_state"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2016 Christian Basler
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -16,9 +15,9 @@
|
||||
-->
|
||||
|
||||
<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">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkbox"
|
||||
@ -31,21 +30,22 @@
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="8dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
tools:text="Name"/>
|
||||
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:layout_alignParentStart="true"
|
||||
android:ellipsize="marquee"
|
||||
android:lines="1"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingStart="48dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="BM-2cW0000000000000000000000000000000"/>
|
||||
tools:text="BM-2cW0000000000000000000000000000000" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
135
app/src/main/res/values-ar/strings.xml
Normal file
135
app/src/main/res/values-ar/strings.xml
Normal file
@ -0,0 +1,135 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools"><string name="app_name">Abit</string>
|
||||
<string name="about_app">عميل Bitmessage أندرويد</string>
|
||||
<string name="title_message_detail">رسالة</string>
|
||||
<string name="title_subscription_detail">اشتراك</string>
|
||||
<string name="title_chan_detail">قناة</string>
|
||||
<string name="title_identity_detail">هوية</string>
|
||||
<string name="title_contact_detail">جهة إتصال</string>
|
||||
<string name="bitmessage_full_node">عقدة Bitmessage</string>
|
||||
<string name="settings">إعدادات</string>
|
||||
<string name="wifi_only">Wi-Fi فقط</string>
|
||||
<string name="wifi_only_summary">منع الإتصال من خلال بيانات الهاتف</string>
|
||||
<string name="to">إلى</string>
|
||||
<string name="subject">الموضوع</string>
|
||||
<string name="manage_identity">إدارة الهويات</string>
|
||||
<string name="add_identity">إضافة هوية</string>
|
||||
<string name="add_identity_summary">إنشاء هوية جديدة</string>
|
||||
<string name="create_identity_description">إنشاء هوية عشوائية جديدة</string>
|
||||
<string name="import_identity_description">استيراد هوية موجودة من PyBitmessage او من تصدير</string>
|
||||
<string name="add_deterministic_address">هوية حتمية</string>
|
||||
<string name="add_deterministic_address_description">إنشاء أو إعادة إنشاء هوية حتمية</string>
|
||||
<string name="add_chan">إضافة قناة</string>
|
||||
<string name="add_chan_description">إنشاء أو الإنضمام إلى قناة</string>
|
||||
<string name="title_activity_open_bitmessage_link">إستيراد جهة اتصال</string>
|
||||
|
||||
<string name="subscribe">إشتراك</string>
|
||||
<string name="do_import">استيراد</string>
|
||||
<string name="cancel">إلغاء</string>
|
||||
<string name="n_new_messages" tools:ignore="PluralsCandidate">رسائل جديدة</string>
|
||||
<string name="reply">رد</string>
|
||||
<string name="delete">حذف</string>
|
||||
<string name="empty_trash">أفرغ المهملات</string>
|
||||
<string name="trusted_node">عقدة موثوقة</string>
|
||||
<string name="trusted_node_summary">استخدام العقدة في التزامن</string>
|
||||
<string name="write_message">كتابة رسالة</string>
|
||||
<string name="full_node">عقدة كاملة</string>
|
||||
<string name="send">إرسال</string>
|
||||
<string name="connection_info_disconnected">غير متصل</string>
|
||||
<string name="connection_info_pending">يتصل…</string>
|
||||
<string name="proof_of_work_title">إثبات العمل</string>
|
||||
<string name="proof_of_work_text_0">جاري إثبات العمل لإرسال الرسالة</string>
|
||||
<string name="inbox">صندوق الوارد</string>
|
||||
<string name="draft">مسودات</string>
|
||||
<string name="sent">المرسل</string>
|
||||
<string name="unread">غير مقروء</string>
|
||||
<string name="trash">مُهملات</string>
|
||||
<string name="label">تسمية</string>
|
||||
<string name="connection_info_1">بث #%1$d : توصيل واحد</string>
|
||||
<string name="connection_info_n" tools:ignore="PluralsCandidate">"بث #%1$d: %2$d توصيلات"</string>
|
||||
<string name="broadcast">إذاعة</string>
|
||||
<string name="mark_unread">حدد كمقروء</string>
|
||||
<string name="archive">أرشيف</string>
|
||||
<string name="stream_number">بث #%d</string>
|
||||
<string name="sync_timeout">انتهاء مهلة التزامن</string>
|
||||
<string name="sync_timeout_summary">مهلة الإتصال بالثواني</string>
|
||||
<string name="proof_of_work_text_n" tools:ignore="PluralsCandidate">جاري إثبات العمل لإرسال الرسالة (%1$d في قائمة الانتظار)</string>
|
||||
<string name="error_invalid_sync_port">إعدادات منفذ التزامن غير صالحة</string>
|
||||
<string name="compose_body_hint">كتابة رسالة</string>
|
||||
<string name="contacts_and_subscriptions">جهات اتصال</string>
|
||||
<string name="subscribed">تم الاشتراك</string>
|
||||
<string name="server_pow">خادم إثبات العمل</string>
|
||||
<string name="server_pow_summary">عقدة موثوقة تقوم بإثبات العمل</string>
|
||||
<string name="full_node_warning">تشغيل عقدة Bitmessage كاملة يستهلك الكثير من البيانات، مما قد يكون مكلفًا لبيانات الهاتف، هل أنت متأكد أنك تريد تشغيل عقدة كاملة؟</string>
|
||||
<string name="about">عن Abit</string>
|
||||
<string name="about_summary">التبعيات مفتوحة المصدر.</string>
|
||||
<string name="title_activity_status">تصحيح الأخطاء</string>
|
||||
<string name="status">تصحيح الأخطاء</string>
|
||||
<string name="status_summary">معلومات تقنية</string>
|
||||
<string name="alias_default_identity">أنا</string>
|
||||
<string name="pubkey_available">مفتاح التشفير المعلن متاح</string>
|
||||
<string name="pubkey_not_available">مفتاح التشفير المعلن غير متاح بعد</string>
|
||||
<string name="alt_qr_code">شفرة QR</string>
|
||||
<string name="add_identity_warning">حيازة عدة هويات يحتاج إلى المزيد من الموارد، إذا كنت متأكدًأ أنك تريد إضافة هويات، أختر تمامًا ما تريد عمله:</string>
|
||||
<string name="share">نشر</string>
|
||||
<string name="delete_identity_warning">هل أنت متأكد من أنك تريد حذف هذه الهوية؟ لن تستطيع استقبال أي رسائل مرسلة لهذا العنوان ولا يمكنك التراجع عن هذه العملية.</string>
|
||||
<string name="delete_contact_warning">هل أنت متأكد أنك تريد حذف جهة الاتصال هذه؟</string>
|
||||
<string name="scan_qr_code">مسح شفرة QR</string>
|
||||
<string name="create_contact">إنشاء جهة إتصال</string>
|
||||
<string name="full_node_description">لا يمكنك إرسال أو استقبال رسائل إلا إذا قمت بتشغيل عقدة كاملة. رجاء العلم أن ذلك يستخدم الكثير من الموارد وبيانات الإنترنت. يمكنك تعيين عقدة موثوقة في الإعدادات، ويمكنك إطلاق عقدتك الخاصة.</string>
|
||||
<string name="address">عنوان Bitmessage</string>
|
||||
<string name="error_illegal_address">قد يكون هناك خطأ بالكتابة</string>
|
||||
<string name="export">تصدير</string>
|
||||
<string name="confirm_export">هل أنت متأكد أنك تريد تصدير هويتك؟ سيحتوي التصدير على مفاتيح خاصة غير مشفرة.</string>
|
||||
<string name="compose_message">إنشاء</string>
|
||||
<string name="passphrase">جملة المرور</string>
|
||||
<string name="help_out">ادعم التطوير</string>
|
||||
<string name="help_out_summary">هل تريد المساعدة؟ ألق نظرة هنا</string>
|
||||
<string name="help_out_link">https://dissem.github.io/Abit/helping-out</string>
|
||||
<string name="toast_long_running_operation">قد يستغرق بضع دقائق</string>
|
||||
<string name="toast_identity_created">تم إنشاء الهوية</string>
|
||||
<string name="toast_identities_created">تم إنشاء الهويات</string>
|
||||
<string name="toast_chan_created">تم إنشاء القناة</string>
|
||||
<string name="deterministic_address_warning">تأكد من تذكر هذه الإعدادات جيدًا عندما تعيد إنشاء الهوية الختمية.</string>
|
||||
<string name="number_of_identities">عدد الهويات المنشئة</string>
|
||||
<string name="shorter">ابحث عن عنوان أقصر</string>
|
||||
<string name="wif_string">محتويات keys.dat</string>
|
||||
<string name="next">استمرار</string>
|
||||
<string name="title_import_identity">استيراد هوية</string>
|
||||
<string name="open_file">فتح ملف</string>
|
||||
<string name="error_loading_data">خطأ في تحميل البيانات</string>
|
||||
<string name="select_file_title">اختيار ملف</string>
|
||||
<string name="select_identities_to_import">اختر الهويات التي تريد استيرادها:</string>
|
||||
<string name="import_input_description">يمكنك لصق محتويات تصدير او ملف keys.dat</string>
|
||||
<string name="full_node_stop">إيقاف العقدة</string>
|
||||
<string name="full_node_restart">اعادة تشغيل العقدة</string>
|
||||
<string name="use_mobile_network">استخدم شبكة بيانات الهاتف</string>
|
||||
<string name="personal_message">رسالة</string>
|
||||
<string name="no_identity_warning">أعد المحاولة عند وجود هوية متاحة.</string>
|
||||
<string name="status_public_key">تم طلب المفتاح المعلن</string>
|
||||
<string name="status_sent_acknowledged">تم تسليم الرسالة</string>
|
||||
<string name="status_draft">مسودة</string>
|
||||
<string name="status_sent">تم الارسال</string>
|
||||
<string name="status_received">تم الاستقبال</string>
|
||||
<string name="error_unsupported_encoding">ترميز غير مدعوم، استخدم الترميز البسيط.</string>
|
||||
<string name="select_encoding_warning">الترميز الموسع هو نظام رسالة جديد غير منتشر الدعم بعد، لكن يحتوي مميزات مختلفة. للبقاء على النظام الأكثر انتشارًا، اختر الترميز البسيط.</string>
|
||||
<string name="select_encoding_title">اختر ترميز الرسالة</string>
|
||||
<string name="cleanup">تطهير</string>
|
||||
<string name="cleanup_summary">حذف المدخلات المنتهية</string>
|
||||
<string name="cleanup_notification_start">تم بدأ التنظيف</string>
|
||||
<string name="cleanup_notification_end">تم الانتهاء من التنظيف</string>
|
||||
<string name="wait_for_wifi">انتظر Wi-Fi</string>
|
||||
<string name="error_msg_recipient_missing">حدد المرسل إليه</string>
|
||||
<string name="export_data">تصدير</string>
|
||||
<string name="export_data_summary">تصدير جميع الرسائل وجهات الاتصال (الهويات غير مضمنة)</string>
|
||||
<string name="import_data">استيراد</string>
|
||||
<string name="import_data_summary">استيراد الرسائل وجهات الاتصال (الهويات غير مضمنة)</string>
|
||||
<string name="request_acknowledgements">اطلب التبليغ بوصول الرسائل</string>
|
||||
<string name="request_acknowledgements_summary">التبليغ يسمح بالتأكد من وصول الرسالة، لكن يحتاج المزيد من الوقت</string>
|
||||
<string name="got_it">فهمت</string>
|
||||
<string name="select_encoding">اختيار الترميز</string>
|
||||
<string name="from">من</string>
|
||||
<string name="invalid_wif_file">لم يتم معالجة الملف</string>
|
||||
<string name="outbox">صندوق المرسل</string>
|
||||
<string name="broadcasts">الإذاعات</string>
|
||||
</resources>
|
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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>
|
||||
<string name="inbox">Posteingang</string>
|
||||
<string name="draft">Entwürfe</string>
|
||||
<string name="sent">Gesendet</string>
|
||||
<string name="unread">Ungelesen</string>
|
||||
<string name="trash">Papierkorb</string>
|
||||
<string name="broadcasts">Broadcasts</string>
|
||||
</resources>
|
@ -104,7 +104,6 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
|
||||
<string name="title_chan_detail">Chan</string>
|
||||
<string name="title_contact_detail">Kontakt</string>
|
||||
<string name="title_identity_detail">Identität</string>
|
||||
<string name="outbox">Postausgang</string>
|
||||
<string name="status_draft">Entwurf</string>
|
||||
<string name="status_public_key">öffentlicher Schlüssel angefordert</string>
|
||||
<string name="status_received">empfangen</string>
|
||||
@ -127,4 +126,13 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
|
||||
<string name="import_data">Import</string>
|
||||
<string name="import_data_summary">Nachrichten und Kontakte importieren (aber keine Identitäten)</string>
|
||||
<string name="select_encoding">Kodierung auswählen</string>
|
||||
<string name="from">Von</string>
|
||||
<string name="invalid_wif_file">Die Datei kann nicht verarbeitet werden</string>
|
||||
<string name="inbox">Posteingang</string>
|
||||
<string name="outbox">Postausgang</string>
|
||||
<string name="draft">Entwürfe</string>
|
||||
<string name="sent">Gesendet</string>
|
||||
<string name="unread">Ungelesen</string>
|
||||
<string name="trash">Papierkorb</string>
|
||||
<string name="broadcasts">Broadcasts</string>
|
||||
</resources>
|
||||
|
135
app/src/main/res/values-fr/strings.xml
Normal file
135
app/src/main/res/values-fr/strings.xml
Normal file
@ -0,0 +1,135 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools"><string name="app_name">Abit</string>
|
||||
<string name="about_app">Un client Bitmessage pour Android</string>
|
||||
<string name="title_message_detail">Message</string>
|
||||
<string name="title_subscription_detail">Abonnement</string>
|
||||
<string name="title_chan_detail">Canal</string>
|
||||
<string name="title_identity_detail">Identité</string>
|
||||
<string name="title_contact_detail">Contact</string>
|
||||
<string name="bitmessage_full_node">Nœud de bitmessage</string>
|
||||
<string name="settings">Paramètres</string>
|
||||
<string name="wifi_only">Seulement Wi-Fi</string>
|
||||
<string name="wifi_only_summary">Ne vous connectez pas au réseau mobile</string>
|
||||
<string name="to">A</string>
|
||||
<string name="subject">Objet</string>
|
||||
<string name="manage_identity">Gérer l\'identité</string>
|
||||
<string name="add_identity">Ajouter une identité</string>
|
||||
<string name="add_identity_summary">Créer une nouvelle identité</string>
|
||||
<string name="create_identity_description">Créer une nouvelle identité aléatoire</string>
|
||||
<string name="import_identity_description">Importation d\'une identité existante de PyBitmessage ou d\'une exportation</string>
|
||||
<string name="add_deterministic_address">Identité déterministe</string>
|
||||
<string name="add_deterministic_address_description">Créer ou recréer une identité déterministe</string>
|
||||
<string name="add_chan">Ajouter un canal</string>
|
||||
<string name="add_chan_description">Créer ou rejoindre un canal</string>
|
||||
<string name="title_activity_open_bitmessage_link">Importation de contact</string>
|
||||
|
||||
<string name="connection_info_1">"Flux nº%1$d: une connexion"</string>
|
||||
<string name="connection_info_n" tools:ignore="PluralsCandidate">"Flux nº%1$d: %2$d connexions"</string>
|
||||
<string name="label">Étiquette</string>
|
||||
<string name="subscribe">Inscrivez-vous</string>
|
||||
<string name="do_import">Importation</string>
|
||||
<string name="cancel">Annuler</string>
|
||||
<string name="broadcast">Diffusion</string>
|
||||
<string name="n_new_messages" tools:ignore="PluralsCandidate">%d messages nouveaux</string>
|
||||
<string name="reply">Répondre</string>
|
||||
<string name="delete">Supprimer</string>
|
||||
<string name="mark_unread">Marquer non lu</string>
|
||||
<string name="archive">Archive</string>
|
||||
<string name="stream_number">"Flux nº%d"</string>
|
||||
<string name="trusted_node">Nœud de confiance</string>
|
||||
<string name="trusted_node_summary">Cette adresse est utilisée pour la synchronisation</string>
|
||||
<string name="sync_timeout">Limitation du temps de synchronisation</string>
|
||||
<string name="write_message">Écrire un message</string>
|
||||
<string name="full_node">Nœud actif</string>
|
||||
<string name="send">Transmission</string>
|
||||
<string name="connection_info_disconnected">Déconnecté</string>
|
||||
<string name="connection_info_pending">La connexion est établie…</string>
|
||||
<string name="proof_of_work_title">Preuve de travail</string>
|
||||
<string name="proof_of_work_text_0">Faire du travail pour envoyer la message</string>
|
||||
<string name="proof_of_work_text_n" tools:ignore="PluralsCandidate">Faire du travail pour envoyer la message (%1$d en file d\'attente)</string>
|
||||
<string name="error_invalid_sync_port">Port non valide dans les paramètres de synchronisation : %s</string>
|
||||
<string name="compose_body_hint">Écrire un message</string>
|
||||
<string name="contacts_and_subscriptions">Contacts</string>
|
||||
<string name="subscribed">Souscrit</string>
|
||||
<string name="full_node_warning">L\'exécution d\'un nœud Bitmessage actif consomme beaucoup de trafic, ce qui peut coûter cher sur un réseau mobile. Êtes-vous sûr de vouloir démarrer un nœud actif ?</string>
|
||||
<string name="about">À propos d\'Abit</string>
|
||||
<string name="about_summary">Les dépendances Open Source.</string>
|
||||
<string name="title_activity_status">Déboguage</string>
|
||||
<string name="status">Déboguage</string>
|
||||
<string name="status_summary">Informations techniques</string>
|
||||
<string name="alias_default_identity">Moi</string>
|
||||
<string name="pubkey_available">Clé publique disponible</string>
|
||||
<string name="pubkey_not_available">Clé publique pas encore disponible</string>
|
||||
<string name="alt_qr_code">Code QR</string>
|
||||
<string name="add_identity_warning">Avoir plus d\'identités exigera plus de ressources. Si vous êtes sûr de vouloir ajouter une identité, veuillez choisir la procédure :</string>
|
||||
<string name="delete_identity_warning">Êtes-vous sûr de vouloir effacer cette identité ? Les messages envoyés à cette adresse ne peuvent plus être reçus et il n\'est pas possible d\'annuler cette action.</string>
|
||||
<string name="delete_contact_warning">Êtes-vous sûr de vouloir supprimer ce contact?</string>
|
||||
<string name="scan_qr_code">Scanner code QR</string>
|
||||
<string name="create_contact">Créer un contact</string>
|
||||
<string name="full_node_description">Vous ne pouvez pas recevoir ou envoyer de messages sans lancer un nœud actif. Mais sachez que cela utilise beaucoup de ressources et de trafic internet. Comme alternative, vous pouvez configurer un nœud de confiance dans les paramètres, mais à partir de maintenant vous devrez déployer votre propre nœud.</string>
|
||||
<string name="address">Adresse Bitmessage</string>
|
||||
<string name="error_illegal_address">C\'est peut-être une faute de frappe</string>
|
||||
<string name="export">Exportation</string>
|
||||
<string name="confirm_export">Voulez-vous vraiment exporter votre identité ? L\'exportation contiendra les clés privées non chiffrées.</string>
|
||||
<string name="passphrase">Phrase de passe</string>
|
||||
<string name="help_out">Soutenir le développement</string>
|
||||
<string name="help_out_summary">Apprenez comment soutenir le développement d\'Abit</string>
|
||||
<string name="toast_long_running_operation">Cela peut prendre quelques minutes</string>
|
||||
<string name="toast_identity_created">Identité créée</string>
|
||||
<string name="toast_identities_created">Les identités ont été créées</string>
|
||||
<string name="toast_chan_created">Canal créé</string>
|
||||
<string name="deterministic_address_warning">N\'oubliez pas ces paramètres et assurez-vous qu\'ils sont corrects lorsque vous recréez une adresse déterministe.</string>
|
||||
<string name="number_of_identities">Nombre d\'identités à créer</string>
|
||||
<string name="shorter">Recherche d\'adresses plus courtes</string>
|
||||
<string name="wif_string">WIF / contenu de ‘keys.dat’</string>
|
||||
<string name="next">Continuer</string>
|
||||
<string name="title_import_identity">Importation d\'identité</string>
|
||||
<string name="open_file">Ouvrir un fichier</string>
|
||||
<string name="error_loading_data">Erreur lors du chargement des données</string>
|
||||
<string name="select_file_title">Sélectionnez un fichier</string>
|
||||
<string name="select_identities_to_import">Veuillez sélectionner les identités à importer :</string>
|
||||
<string name="import_input_description">Vous pouvez simplement insérer le contenu d\'une exportation ou d\'un fichier \'keys.dat\'</string>
|
||||
<string name="full_node_stop">arrêter le nœud</string>
|
||||
<string name="full_node_restart">redémarrer le nœud</string>
|
||||
<string name="use_mobile_network">Utiliser le réseau mobile</string>
|
||||
<string name="personal_message">Message</string>
|
||||
<string name="empty_trash">Vider les ordures</string>
|
||||
<string name="sync_timeout_summary">Délai d\'expiration en secondes</string>
|
||||
<string name="server_pow">POW sur le serveur</string>
|
||||
<string name="server_pow_summary">Le nœud de confiance fait la preuve de travail</string>
|
||||
<string name="share">Partager</string>
|
||||
<string name="compose_message">Composer</string>
|
||||
<string name="no_identity_warning">Veuillez réessayer dès qu\'une identité est disponible.</string>
|
||||
<string name="status_public_key">clé publique demandée</string>
|
||||
<string name="status_sent_acknowledged">Réception confirmée</string>
|
||||
<string name="status_draft">brouillon</string>
|
||||
<string name="status_sent">envoyé</string>
|
||||
<string name="status_received">reçu</string>
|
||||
<string name="error_unsupported_encoding">Encodage non supporté \'%s\', \'SIMPLE\' est utilisé.</string>
|
||||
<string name="select_encoding_warning">\'EXTENDED\' est un nouveau format de message qui ne fonctionne pas encore partout, mais qui a des avantages intéressants. Sélectionnez \'SIMPLE\' pour être sûr.</string>
|
||||
<string name="select_encoding_title">Sélectionner le codage des messages</string>
|
||||
<string name="cleanup">Nettoyage</string>
|
||||
<string name="cleanup_summary">Supprimer les entrées d\'inventaire obsolètes</string>
|
||||
<string name="cleanup_notification_start">Démarrage du nettoyage</string>
|
||||
<string name="cleanup_notification_end">Nettoyage terminé</string>
|
||||
<string name="wait_for_wifi">Attendez la connexion Wi-Fi</string>
|
||||
<string name="error_msg_recipient_missing">Veuillez indiquer un destinataire</string>
|
||||
<string name="export_data">Exportation</string>
|
||||
<string name="export_data_summary">Exporter tous les messages et contacts (mais pas les identités)</string>
|
||||
<string name="import_data">Importation</string>
|
||||
<string name="import_data_summary">Importer des messages et des contacts (mais pas des identités)</string>
|
||||
<string name="request_acknowledgements">Demande d\'accusés de réception</string>
|
||||
<string name="request_acknowledgements_summary">Les accusés de réception permettent de s\'assurer qu\'un message a bien été reçu, mais il faut plus de temps pour l\'envoyer</string>
|
||||
<string name="got_it">J\'ai compris</string>
|
||||
<string name="select_encoding">Choix du codage</string>
|
||||
<string name="help_out_link">https://dissem.github.io/Abit/aider</string>
|
||||
<string name="from">De</string>
|
||||
<string name="invalid_wif_file">Le fichier ne peut pas être traité</string>
|
||||
<string name="inbox">Boîte de réception</string>
|
||||
<string name="outbox">Boîte d\'envoi</string>
|
||||
<string name="draft">Brouillons</string>
|
||||
<string name="sent">Envoyé</string>
|
||||
<string name="unread">Non lues</string>
|
||||
<string name="trash">Corbeille</string>
|
||||
<string name="broadcasts">Diffusions</string>
|
||||
</resources>
|
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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>
|
||||
<string name="inbox">Inbox</string>
|
||||
<string name="draft">Drafts</string>
|
||||
<string name="sent">Sent</string>
|
||||
<string name="unread">Unread</string>
|
||||
<string name="trash">Trash</string>
|
||||
<string name="broadcasts">Broadcasts</string>
|
||||
</resources>
|
@ -108,7 +108,6 @@ As an alternative you could configure a trusted node in the settings, but as of
|
||||
<string name="status_draft">draft</string>
|
||||
<string name="status_sent">sent</string>
|
||||
<string name="status_received">received</string>
|
||||
<string name="outbox">Outbox</string>
|
||||
<string name="error_unsupported_encoding">Unsupported encoding ‘%s’, using ‘SIMPLE’ instead.</string>
|
||||
<string name="select_encoding_warning">‘EXTENDED’ is a new message format that\'s not widely supported yet but has some interesting features. To stay on the save side, select ‘SIMPLE’.</string>
|
||||
<string name="select_encoding_title">Select Message Encoding</string>
|
||||
@ -126,4 +125,13 @@ As an alternative you could configure a trusted node in the settings, but as of
|
||||
<string name="request_acknowledgements_summary">Acknowledges allow making sure a message was received, but require additional time to send</string>
|
||||
<string name="got_it">Got it</string>
|
||||
<string name="select_encoding">Select encoding</string>
|
||||
<string name="from">From</string>
|
||||
<string name="invalid_wif_file">The file could not be processed</string>
|
||||
<string name="inbox">Inbox</string>
|
||||
<string name="outbox">Outbox</string>
|
||||
<string name="draft">Drafts</string>
|
||||
<string name="sent">Sent</string>
|
||||
<string name="unread">Unread</string>
|
||||
<string name="trash">Trash</string>
|
||||
<string name="broadcasts">Broadcasts</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<item name="android:activatedBackgroundIndicator">@drawable/bg_item_activated</item>
|
||||
<item name="android:textColor">@color/colorPrimaryText</item>
|
||||
<item name="android:textColorSecondary">@color/colorSecondaryText</item>
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||
</style>
|
||||
|
||||
<style name="CustomShowcaseTheme" parent="ShowcaseView">
|
||||
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<paths>
|
||||
<files-path name="exports" path="exports/"/>
|
||||
</paths>
|
||||
|
@ -1,64 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreferenceCompat
|
||||
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="wifi_only"
|
||||
android:summary="@string/wifi_only_summary"
|
||||
android:title="@string/wifi_only"/>
|
||||
<SwitchPreferenceCompat
|
||||
android:title="@string/wifi_only" />
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="request_acknowledgements"
|
||||
android:summary="@string/request_acknowledgements_summary"
|
||||
android:title="@string/request_acknowledgements"/>
|
||||
<EditTextPreference
|
||||
android:title="@string/request_acknowledgements" />
|
||||
<android.support.v7.preference.EditTextPreference
|
||||
android:inputType="textUri"
|
||||
android:key="trusted_node"
|
||||
android:summary="@string/trusted_node_summary"
|
||||
android:title="@string/trusted_node"/>
|
||||
<EditTextPreference
|
||||
android:title="@string/trusted_node" />
|
||||
<android.support.v7.preference.EditTextPreference
|
||||
android:defaultValue="120"
|
||||
android:inputType="number"
|
||||
android:key="sync_timeout"
|
||||
android:summary="@string/sync_timeout_summary"
|
||||
android:title="@string/sync_timeout"/>
|
||||
<SwitchPreferenceCompat
|
||||
android:title="@string/sync_timeout" />
|
||||
<android.support.v7.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:dependency="trusted_node"
|
||||
android:key="server_pow"
|
||||
android:summary="@string/server_pow_summary"
|
||||
android:title="@string/server_pow"
|
||||
/>
|
||||
<Preference
|
||||
android:title="@string/server_pow" />
|
||||
<android.support.v7.preference.Preference
|
||||
android:key="about"
|
||||
android:summary="@string/about_summary"
|
||||
android:title="@string/about"
|
||||
/>
|
||||
<Preference
|
||||
android:title="@string/about" />
|
||||
<android.support.v7.preference.Preference
|
||||
android:key="help_out"
|
||||
android:summary="@string/help_out_summary"
|
||||
android:title="@string/help_out">
|
||||
<intent
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="@string/help_out_link"/>
|
||||
</Preference>
|
||||
<Preference
|
||||
android:data="@string/help_out_link" />
|
||||
</android.support.v7.preference.Preference>
|
||||
<android.support.v7.preference.Preference
|
||||
android:key="cleanup"
|
||||
android:title="@string/cleanup"
|
||||
android:summary="@string/cleanup_summary"
|
||||
/>
|
||||
<Preference
|
||||
android:title="@string/cleanup" />
|
||||
<android.support.v7.preference.Preference
|
||||
android:key="export"
|
||||
android:title="@string/export_data"
|
||||
android:summary="@string/export_data_summary"
|
||||
/>
|
||||
<Preference
|
||||
android:title="@string/export_data" />
|
||||
<android.support.v7.preference.Preference
|
||||
android:key="import"
|
||||
android:title="@string/import_data"
|
||||
android:summary="@string/import_data_summary"
|
||||
/>
|
||||
<Preference
|
||||
android:title="@string/import_data" />
|
||||
<android.support.v7.preference.Preference
|
||||
android:key="status"
|
||||
android:summary="@string/status_summary"
|
||||
android:title="@string/status"
|
||||
/>
|
||||
</PreferenceScreen>
|
||||
android:title="@string/status" />
|
||||
</android.support.v7.preference.PreferenceScreen>
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.bitmessage.repository
|
||||
|
||||
import android.os.Build
|
||||
import ch.dissem.apps.abit.BuildConfig
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import ch.dissem.apps.abit.repository.AndroidAddressRepository
|
||||
import ch.dissem.apps.abit.repository.SqlHelper
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
@ -32,7 +32,7 @@ import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP), packageName = "ch.dissem.apps.abit")
|
||||
@Config(sdk = [LOLLIPOP], packageName = "ch.dissem.apps.abit")
|
||||
class AndroidAddressRepositoryTest : TestBase() {
|
||||
private val contactA = "BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt"
|
||||
private val contactB = "BM-2cTtkBnb4BUYDndTKun6D9PjtueP2h1bQj"
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.bitmessage.repository
|
||||
|
||||
import android.os.Build
|
||||
import ch.dissem.apps.abit.BuildConfig
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import ch.dissem.apps.abit.repository.AndroidInventory
|
||||
import ch.dissem.apps.abit.repository.SqlHelper
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
@ -40,7 +40,7 @@ import org.robolectric.annotation.Config
|
||||
import java.util.*
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP), packageName = "ch.dissem.apps.abit")
|
||||
@Config(sdk = [LOLLIPOP], packageName = "ch.dissem.apps.abit")
|
||||
class AndroidInventoryTest : TestBase() {
|
||||
private lateinit var inventory: Inventory
|
||||
|
||||
@ -135,11 +135,12 @@ class AndroidInventoryTest : TestBase() {
|
||||
}
|
||||
|
||||
private fun getObjectMessage(stream: Long, TTL: Long, payload: ObjectPayload) = ObjectMessage(
|
||||
nonce = ByteArray(8),
|
||||
expiresTime = now + TTL,
|
||||
stream = stream,
|
||||
payload = payload
|
||||
nonce = ByteArray(8),
|
||||
expiresTime = now + TTL,
|
||||
stream = stream,
|
||||
payload = payload
|
||||
)
|
||||
|
||||
private val getPubkey: GetPubkey = GetPubkey(BitmessageAddress("BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt"))
|
||||
private val getPubkey: GetPubkey =
|
||||
GetPubkey(BitmessageAddress("BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt"))
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package ch.dissem.bitmessage.repository
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository
|
||||
import ch.dissem.apps.abit.repository.SqlHelper
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
@ -30,7 +31,7 @@ import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP), packageName = "ch.dissem.apps.abit")
|
||||
@Config(sdk = [LOLLIPOP], packageName = "ch.dissem.apps.abit")
|
||||
class AndroidLabelRepositoryTest : TestBase() {
|
||||
|
||||
private lateinit var repo: LabelRepository
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package ch.dissem.bitmessage.repository
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import ch.dissem.apps.abit.repository.AndroidAddressRepository
|
||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
@ -31,7 +31,6 @@ import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey
|
||||
import ch.dissem.bitmessage.entity.valueobject.extended.Message
|
||||
import ch.dissem.bitmessage.ports.LabelRepository
|
||||
import ch.dissem.bitmessage.ports.MessageRepository
|
||||
import ch.dissem.bitmessage.utils.UnixTime
|
||||
import org.hamcrest.BaseMatcher
|
||||
@ -48,7 +47,7 @@ import org.robolectric.annotation.Config
|
||||
import java.util.*
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP), packageName = "ch.dissem.apps.abit")
|
||||
@Config(sdk = [LOLLIPOP], packageName = "ch.dissem.apps.abit")
|
||||
class AndroidMessageRepositoryTest : TestBase() {
|
||||
private lateinit var contactA: BitmessageAddress
|
||||
private lateinit var contactB: BitmessageAddress
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.bitmessage.repository
|
||||
|
||||
import android.os.Build
|
||||
import ch.dissem.apps.abit.BuildConfig
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import ch.dissem.apps.abit.repository.AndroidNodeRegistry
|
||||
import ch.dissem.apps.abit.repository.SqlHelper
|
||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress
|
||||
@ -39,7 +39,7 @@ import java.util.*
|
||||
* as the initial nodes' IP addresses are determined by DNS lookup.
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP), packageName = "ch.dissem.apps.abit")
|
||||
@Config(sdk = [LOLLIPOP], packageName = "ch.dissem.apps.abit")
|
||||
class AndroidNodeRegistryTest : TestBase() {
|
||||
private lateinit var registry: NodeRegistry
|
||||
|
||||
|
@ -46,7 +46,7 @@ import kotlin.properties.Delegates
|
||||
* @author Christian Basler
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = intArrayOf(LOLLIPOP), packageName = "ch.dissem.apps.abit")
|
||||
@Config(sdk = [LOLLIPOP], packageName = "ch.dissem.apps.abit")
|
||||
class AndroidProofOfWorkRepositoryTest : TestBase() {
|
||||
private lateinit var repo: ProofOfWorkRepository
|
||||
private lateinit var addressRepo: AddressRepository
|
||||
|
@ -1,5 +1,5 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.20'
|
||||
ext.kotlin_version = '1.2.21'
|
||||
ext.anko_version = '0.10.4'
|
||||
repositories {
|
||||
jcenter()
|
||||
|
Loading…
Reference in New Issue
Block a user