mirror of
https://github.com/yggdrasil-network/yggdrasil-android.git
synced 2025-04-27 13:45:09 +03:00
Changes for updating to Yggdrasil 0.5. (#49)
This commit is contained in:
parent
9df80c0612
commit
f4e1a75cfc
16 changed files with 189 additions and 78 deletions
|
@ -4,15 +4,14 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "30.0.3"
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "eu.neilalexander.yggdrasil"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 13
|
||||
versionName "0.1-013"
|
||||
targetSdkVersion 33
|
||||
versionCode 14
|
||||
versionName "0.1-014"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
@ -51,12 +50,12 @@ android {
|
|||
dependencies {
|
||||
implementation fileTree(include: ['*.aar'], dir: 'libs')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.5.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'androidx.preference:preference-ktx:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.6.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
testImplementation 'junit:junit:4.+'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
|
||||
<application
|
||||
|
@ -23,8 +24,8 @@
|
|||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".SettingsActivity" android:parentActivityName=".MainActivity" />
|
||||
<activity android:name=".PeersActivity" android:parentActivityName=".MainActivity" />
|
||||
<activity android:name=".SettingsActivity" android:parentActivityName=".MainActivity" android:exported="false" />
|
||||
<activity android:name=".PeersActivity" android:parentActivityName=".MainActivity" android:exported="false" />
|
||||
<activity android:name=".DnsActivity" android:exported="false" />
|
||||
<activity android:name=".TileServiceActivity" android:theme="@android:style/Theme.NoDisplay"
|
||||
android:allowTaskReparenting="true"
|
||||
|
|
|
@ -32,14 +32,12 @@ object ConfigurationProxy {
|
|||
val newJson = JSONObject(String(Mobile.generateConfigJSON()))
|
||||
updateJSON { json ->
|
||||
json.put("PrivateKey", newJson.getString("PrivateKey"))
|
||||
json.put("PublicKey", newJson.getString("PublicKey"))
|
||||
}
|
||||
}
|
||||
|
||||
fun setKeys(privateKey: String, publicKey: String) {
|
||||
fun setKeys(privateKey: String) {
|
||||
updateJSON { json ->
|
||||
json.put("PrivateKey", privateKey)
|
||||
json.put("PublicKey", publicKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,7 +60,8 @@ object ConfigurationProxy {
|
|||
{
|
||||
"Regex": ".*",
|
||||
"Beacon": true,
|
||||
"Listen": true
|
||||
"Listen": true,
|
||||
"Password": ""
|
||||
}
|
||||
""".trimIndent()))
|
||||
json.put("MulticastInterfaces", ar)
|
||||
|
@ -94,4 +93,12 @@ object ConfigurationProxy {
|
|||
(json.getJSONArray("MulticastInterfaces").get(0) as JSONObject).put("Beacon", value)
|
||||
}
|
||||
}
|
||||
|
||||
var multicastPassword: String
|
||||
get() = (json.getJSONArray("MulticastInterfaces").get(0) as JSONObject).getString("Password")
|
||||
set(value) {
|
||||
updateJSON { json ->
|
||||
(json.getJSONArray("MulticastInterfaces").get(0) as JSONObject).put("Password", value)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,8 +47,10 @@ class GlobalApplication: Application(), YggStateReceiver.StateReceiver {
|
|||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
override fun onStateChange(state: State) {
|
||||
if (state != currentState) {
|
||||
val componentName = ComponentName(this, YggTileService::class.java)
|
||||
TileService.requestListeningState(this, componentName)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val componentName = ComponentName(this, YggTileService::class.java)
|
||||
TileService.requestListeningState(this, componentName)
|
||||
}
|
||||
|
||||
if (state != State.Disabled) {
|
||||
val notification = createServiceNotification(this, state)
|
||||
|
@ -68,7 +70,11 @@ fun createServiceNotification(context: Context, state: State): Notification {
|
|||
val intent = Intent(context, MainActivity::class.java).apply {
|
||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
var flags = PendingIntent.FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
}
|
||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, flags)
|
||||
|
||||
val text = when (state) {
|
||||
State.Disabled -> context.getText(R.string.tile_disabled)
|
||||
|
@ -91,7 +97,11 @@ fun createPermissionMissingNotification(context: Context): Notification {
|
|||
val intent = Intent(context, MainActivity::class.java).apply {
|
||||
this.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
var flags = PendingIntent.FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
}
|
||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, flags)
|
||||
|
||||
return NotificationCompat.Builder(context, MAIN_CHANNEL_ID)
|
||||
.setShowWhen(false)
|
||||
|
|
|
@ -24,7 +24,7 @@ class MainActivity : AppCompatActivity() {
|
|||
private lateinit var enabledLabel: TextView
|
||||
private lateinit var ipAddressLabel: TextView
|
||||
private lateinit var subnetLabel: TextView
|
||||
private lateinit var coordinatesLabel: TextView
|
||||
private lateinit var treeLengthLabel: TextView
|
||||
private lateinit var peersLabel: TextView
|
||||
private lateinit var peersRow: LinearLayoutCompat
|
||||
private lateinit var dnsLabel: TextView
|
||||
|
@ -53,7 +53,7 @@ class MainActivity : AppCompatActivity() {
|
|||
enabledLabel = findViewById(R.id.yggdrasilStatusLabel)
|
||||
ipAddressLabel = findViewById(R.id.ipAddressValue)
|
||||
subnetLabel = findViewById(R.id.subnetValue)
|
||||
coordinatesLabel = findViewById(R.id.coordinatesValue)
|
||||
treeLengthLabel = findViewById(R.id.treeLengthValue)
|
||||
peersLabel = findViewById(R.id.peersValue)
|
||||
peersRow = findViewById(R.id.peersTableRow)
|
||||
dnsLabel = findViewById(R.id.dnsValue)
|
||||
|
@ -155,11 +155,11 @@ class MainActivity : AppCompatActivity() {
|
|||
"state" -> {
|
||||
enabledLabel.text = if (intent.getBooleanExtra("started", false)) {
|
||||
var count = 0
|
||||
if (intent.hasExtra("dht")) {
|
||||
val dht = intent.getStringExtra("dht")
|
||||
if (dht != null && dht != "null") {
|
||||
val dhtState = JSONArray(dht)
|
||||
count = dhtState.length()
|
||||
if (intent.hasExtra("tree")) {
|
||||
val tree = intent.getStringExtra("tree")
|
||||
if (tree != null && tree != "null") {
|
||||
val treeState = JSONArray(tree)
|
||||
count = treeState.length()
|
||||
}
|
||||
}
|
||||
if (count == 0) {
|
||||
|
@ -175,7 +175,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
ipAddressLabel.text = intent.getStringExtra("ip") ?: "N/A"
|
||||
subnetLabel.text = intent.getStringExtra("subnet") ?: "N/A"
|
||||
coordinatesLabel.text = intent.getStringExtra("coords") ?: "[]"
|
||||
treeLengthLabel.text = intent.getStringExtra("coords") ?: "0"
|
||||
if (intent.hasExtra("peers")) {
|
||||
val peerState = JSONArray(intent.getStringExtra("peers") ?: "[]")
|
||||
peersLabel.text = when (val count = peerState.length()) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package eu.neilalexander.yggdrasil
|
||||
|
||||
import android.content.*
|
||||
import android.content.Intent
|
||||
import android.net.VpnService
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Build
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.system.OsConstants
|
||||
|
@ -42,6 +43,7 @@ open class PacketTunnelProvider: VpnService() {
|
|||
private var parcel: ParcelFileDescriptor? = null
|
||||
private var readerStream: FileInputStream? = null
|
||||
private var writerStream: FileOutputStream? = null
|
||||
private var multicastLock: WifiManager.MulticastLock? = null
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
@ -101,6 +103,13 @@ open class PacketTunnelProvider: VpnService() {
|
|||
val notification = createServiceNotification(this, State.Enabled)
|
||||
startForeground(SERVICE_NOTIFICATION_ID, notification)
|
||||
|
||||
// Acquire multicast lock
|
||||
val wifi = applicationContext.getSystemService(WIFI_SERVICE) as WifiManager
|
||||
multicastLock = wifi.createMulticastLock("Yggdrasil").apply {
|
||||
setReferenceCounted(false)
|
||||
acquire()
|
||||
}
|
||||
|
||||
Log.d(TAG, config.getJSON().toString())
|
||||
yggdrasil.startJSON(config.getJSONByteArray())
|
||||
|
||||
|
@ -163,16 +172,7 @@ open class PacketTunnelProvider: VpnService() {
|
|||
updater()
|
||||
}
|
||||
|
||||
var intent = Intent(STATE_INTENT)
|
||||
intent.putExtra("type", "state")
|
||||
intent.putExtra("started", true)
|
||||
intent.putExtra("ip", yggdrasil.addressString)
|
||||
intent.putExtra("subnet", yggdrasil.subnetString)
|
||||
intent.putExtra("coords", yggdrasil.coordsString)
|
||||
intent.putExtra("peers", yggdrasil.peersJSON)
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
|
||||
intent = Intent(YGG_STATE_INTENT)
|
||||
var intent = Intent(YGG_STATE_INTENT)
|
||||
intent.putExtra("state", STATE_ENABLED)
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
}
|
||||
|
@ -221,6 +221,7 @@ open class PacketTunnelProvider: VpnService() {
|
|||
|
||||
stopForeground(true)
|
||||
stopSelf()
|
||||
multicastLock?.release()
|
||||
}
|
||||
|
||||
private fun connect() {
|
||||
|
@ -231,27 +232,37 @@ open class PacketTunnelProvider: VpnService() {
|
|||
}
|
||||
|
||||
private fun updater() {
|
||||
Thread.sleep(500)
|
||||
var lastStateUpdate = System.currentTimeMillis()
|
||||
updates@ while (started.get()) {
|
||||
val treeJSON = yggdrasil.treeJSON
|
||||
var treeLength = 0
|
||||
if (treeJSON != null && treeJSON != "null") {
|
||||
val treeState = JSONArray(treeJSON)
|
||||
treeLength = treeState.length()
|
||||
}
|
||||
if ((application as GlobalApplication).needUiUpdates()) {
|
||||
val intent = Intent(STATE_INTENT)
|
||||
intent.putExtra("type", "state")
|
||||
intent.putExtra("started", true)
|
||||
intent.putExtra("ip", yggdrasil.addressString)
|
||||
intent.putExtra("subnet", yggdrasil.subnetString)
|
||||
intent.putExtra("coords", yggdrasil.coordsString)
|
||||
intent.putExtra("pubkey", yggdrasil.publicKeyString)
|
||||
intent.putExtra("coords", "$treeLength")
|
||||
intent.putExtra("peers", yggdrasil.peersJSON)
|
||||
intent.putExtra("dht", yggdrasil.dhtjson)
|
||||
intent.putExtra("tree", treeJSON)
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
}
|
||||
val curTime = System.currentTimeMillis()
|
||||
if (lastStateUpdate + 10000 < curTime) {
|
||||
val intent = Intent(YGG_STATE_INTENT)
|
||||
var state = STATE_ENABLED
|
||||
val dht = yggdrasil.dhtjson
|
||||
if (dht != null && dht != "null") {
|
||||
val dhtState = JSONArray(dht)
|
||||
val count = dhtState.length()
|
||||
if (yggdrasil.routingEntries > 0) {
|
||||
state = STATE_CONNECTED
|
||||
}
|
||||
if (treeJSON != null && treeJSON != "null") {
|
||||
val treeState = JSONArray(treeJSON)
|
||||
val count = treeState.length()
|
||||
if (count > 1)
|
||||
state = STATE_CONNECTED
|
||||
}
|
||||
|
|
|
@ -7,10 +7,13 @@ import android.content.Intent
|
|||
import android.content.IntentFilter
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.KeyEvent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.*
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import org.json.JSONArray
|
||||
|
@ -27,6 +30,7 @@ class PeersActivity : AppCompatActivity() {
|
|||
private lateinit var configuredTableLabel: TextView
|
||||
private lateinit var multicastListenSwitch: Switch
|
||||
private lateinit var multicastBeaconSwitch: Switch
|
||||
private lateinit var passwordEdit: EditText
|
||||
private lateinit var addPeerButton: ImageButton
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -62,6 +66,30 @@ class PeersActivity : AppCompatActivity() {
|
|||
multicastListenPanel.setOnClickListener {
|
||||
multicastListenSwitch.toggle()
|
||||
}
|
||||
passwordEdit = findViewById(R.id.passwordEdit)
|
||||
passwordEdit.setText(config.multicastPassword)
|
||||
|
||||
passwordEdit.doOnTextChanged { text, _, _, _ ->
|
||||
config.multicastPassword = text.toString()
|
||||
}
|
||||
|
||||
passwordEdit.setOnKeyListener { _, keyCode, _ ->
|
||||
(keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER)
|
||||
}
|
||||
|
||||
findViewById<View>(R.id.passwordTableRow).setOnKeyListener { _, keyCode, event ->
|
||||
Log.i("Key", keyCode.toString())
|
||||
if (event.action == KeyEvent.ACTION_DOWN) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
passwordEdit.requestFocus()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
addPeerButton = findViewById(R.id.addPeerButton)
|
||||
addPeerButton.setOnClickListener {
|
||||
|
@ -156,7 +184,7 @@ class PeersActivity : AppCompatActivity() {
|
|||
val view = inflater.inflate(R.layout.peers_connected, null)
|
||||
val ip = peer.getString("IP")
|
||||
view.findViewById<TextView>(R.id.addressLabel).text = ip
|
||||
view.findViewById<TextView>(R.id.detailsLabel).text = peer.getString("Remote")
|
||||
view.findViewById<TextView>(R.id.detailsLabel).text = peer.getString("URI")
|
||||
connectedTableLayout.addView(view)
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +196,9 @@ class PeersActivity : AppCompatActivity() {
|
|||
when (intent.getStringExtra("type")) {
|
||||
"state" -> {
|
||||
if (intent.hasExtra("peers")) {
|
||||
val peersArray = JSONArray(intent.getStringExtra("peers") ?: "[]")
|
||||
val peers1 = intent.getStringExtra("peers")
|
||||
//Log.i("PeersActivity", "Peers json: $peers1")
|
||||
val peersArray = JSONArray(peers1 ?: "[]")
|
||||
val array = Array(peersArray.length()) { i ->
|
||||
peersArray.getJSONObject(i)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package eu.neilalexander.yggdrasil
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
|
@ -13,6 +17,7 @@ import android.view.View
|
|||
import android.widget.*
|
||||
import androidx.appcompat.widget.LinearLayoutCompat
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import org.json.JSONObject
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
|
@ -87,11 +92,10 @@ class SettingsActivity : AppCompatActivity() {
|
|||
val view = inflater.inflate(R.layout.dialog_set_keys, null)
|
||||
val builder: AlertDialog.Builder = AlertDialog.Builder(ContextThemeWrapper(this, R.style.Theme_MaterialComponents_DayNight_Dialog))
|
||||
val privateKey = view.findViewById<EditText>(R.id.private_key)
|
||||
val publicKey = view.findViewById<EditText>(R.id.public_key)
|
||||
builder.setTitle(getString(R.string.set_keys))
|
||||
builder.setView(view)
|
||||
builder.setPositiveButton(getString(R.string.save)) { dialog, _ ->
|
||||
config.setKeys(privateKey.text.toString(), publicKey.text.toString())
|
||||
config.setKeys(privateKey.text.toString())
|
||||
updateView()
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
@ -113,13 +117,40 @@ class SettingsActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun updateView() {
|
||||
val nodeinfo = config.getJSON().optJSONObject("NodeInfo")
|
||||
val json = config.getJSON()
|
||||
val nodeinfo = json.optJSONObject("NodeInfo")
|
||||
if (nodeinfo != null) {
|
||||
deviceNameEntry.setText(nodeinfo.getString("name"), TextView.BufferType.EDITABLE)
|
||||
} else {
|
||||
deviceNameEntry.setText("", TextView.BufferType.EDITABLE)
|
||||
}
|
||||
|
||||
publicKeyLabel.text = config.getJSON().getString("PublicKey")
|
||||
publicKeyLabel.text = json.optString("PublicKey")
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
receiver, IntentFilter(PacketTunnelProvider.STATE_INTENT)
|
||||
)
|
||||
(application as GlobalApplication).subscribe()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
(application as GlobalApplication).unsubscribe()
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver)
|
||||
}
|
||||
|
||||
// To be able to get public key from running Yggdrasil we use this receiver, as we don't have this field in config
|
||||
private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent) {
|
||||
if (intent.hasExtra("pubkey")) {
|
||||
val tree = intent.getStringExtra("pubkey")
|
||||
if (tree != null && tree != "null") {
|
||||
publicKeyLabel.text = intent.getStringExtra("pubkey")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -210,11 +210,11 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:text="@string/main_coordinates"
|
||||
android:text="@string/main_tree_length"
|
||||
android:textColor="?attr/textDefault" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/coordinatesValue"
|
||||
android:id="@+id/treeLengthValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
@ -224,7 +224,7 @@
|
|||
android:scrollHorizontally="false"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:text="[]"
|
||||
android:text="0"
|
||||
android:textAlignment="viewEnd"
|
||||
android:textIsSelectable="true" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
|
|
|
@ -217,6 +217,37 @@
|
|||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:id="@+id/passwordTableRow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:paddingStart="4pt"
|
||||
android:paddingTop="4pt"
|
||||
android:paddingEnd="4pt"
|
||||
android:paddingBottom="4pt">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/peers_multicast_password_hint"
|
||||
android:textColor="?attr/textDefault" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/passwordEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@null"
|
||||
android:ems="10"
|
||||
android:hint="@string/tap_to_edit"
|
||||
android:inputType="textVisiblePassword"
|
||||
android:padding="0pt"
|
||||
android:textAlignment="textEnd"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -12,15 +12,6 @@
|
|||
android:paddingTop="4pt"
|
||||
android:paddingBottom="4pt">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/public_key_label" />
|
||||
<EditText
|
||||
android:id="@+id/public_key"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
<string name="main_not_available">Н/Д</string>
|
||||
<string name="main_ip">Адрес</string>
|
||||
<string name="main_subnet">Подсеть</string>
|
||||
<string name="main_coordinates">Координаты</string>
|
||||
<string name="main_tree_length">Высота дерева</string>
|
||||
<string name="main_configuration">Конфигурация</string>
|
||||
<string name="main_peers">Пиры</string>
|
||||
<string name="main_dns_servers">Серверы DNS</string>
|
||||
|
@ -58,7 +58,8 @@
|
|||
<string name="discoverable_over_multicast">Находимый через multicast</string>
|
||||
<string name="search_for_multicast_peers">Искать пиров через multicast</string>
|
||||
<string name="configured_peers_hint">Yggdrasil будет пытаться подключаться к этим пирам автоматически. Если вы добавите несколько пиров, ваше устройство может быть использовано для переноса данных между другими узлами сети. Чтобы этого избежать настройте только один пир.</string>
|
||||
<string name="peer_connectivity_hint">Пиры могут быть найдены с помощью Multicast если они находятся в той же Wi-Fi сети, либо через USB. Трафик в мобильной сети может быть платным. Вы можете отключить мобильные данные в настройках устройства.</string>
|
||||
<string name="peer_connectivity_hint">Пиры могут быть найдены с помощью Multicast если они находятся в той же Wi-Fi сети, либо через USB. У них должен быть одинаковый пароль. Трафик в мобильной сети может быть платным. Вы можете отключить мобильные данные в настройках устройства.</string>
|
||||
<string name="peers_multicast_password_hint">Пароль</string>
|
||||
<string name="node_info">Об узле</string>
|
||||
<string name="device_name">Название устройства</string>
|
||||
<string name="tap_to_edit">Нажмите для изменения</string>
|
||||
|
@ -79,8 +80,7 @@
|
|||
<string name="channel_description">Главный канал нотификаций сервиса</string>
|
||||
<string name="permission_notification_text">Нажмите здесь чтобы включить Yggdrasil.</string>
|
||||
<string name="add_peer_help">Введите полный URI пира для добавления. Yggdrasil будет автоматически подключаться к нему при запуске.</string>
|
||||
<string name="public_key_label">Публичный ключ:</string>
|
||||
<string name="private_key_label">Приватный ключ:</string>
|
||||
<string name="set_keys">Установить свои ключи</string>
|
||||
<string name="set_keys">Установить свой ключ</string>
|
||||
<string name="save">Сохранить</string>
|
||||
</resources>
|
|
@ -46,7 +46,7 @@
|
|||
<string name="main_not_available">N/A</string>
|
||||
<string name="main_ip">IP</string>
|
||||
<string name="main_subnet">Subnet</string>
|
||||
<string name="main_coordinates">Coordinates</string>
|
||||
<string name="main_tree_length">Tree length</string>
|
||||
<string name="main_configuration">Configuration</string>
|
||||
<string name="main_peers">Peers</string>
|
||||
<string name="main_dns_servers">DNS servers</string>
|
||||
|
@ -58,7 +58,8 @@
|
|||
<string name="discoverable_over_multicast">Discoverable over multicast</string>
|
||||
<string name="search_for_multicast_peers">Search for multicast peers</string>
|
||||
<string name="configured_peers_hint">Yggdrasil will automatically attempt to connect to configured peers when started. If you configure more than one peer, your device may carry traffic on behalf of other network nodes. Avoid this by configuring only a single peer.</string>
|
||||
<string name="peer_connectivity_hint">Multicast peers will be discovered on the same Wi-Fi network or via USB. Data charges may apply when using mobile data. You can prevent data usage in the device settings.</string>
|
||||
<string name="peer_connectivity_hint">Multicast peers will be discovered on the same Wi-Fi network or via USB. They must have the same password. Data charges may apply when using mobile data. You can prevent data usage in the device settings.</string>
|
||||
<string name="peers_multicast_password_hint">Password</string>
|
||||
<string name="node_info">Node Info</string>
|
||||
<string name="device_name">Device Name</string>
|
||||
<string name="tap_to_edit">Tap to edit</string>
|
||||
|
@ -79,8 +80,7 @@
|
|||
<string name="channel_description">Main channel for foreground notification</string>
|
||||
<string name="permission_notification_text">Tap here to enable Yggdrasil.</string>
|
||||
<string name="add_peer_help">Enter the full URI of the peer to add. Yggdrasil will automatically connect to this peer when started.</string>
|
||||
<string name="public_key_label">Public key:</string>
|
||||
<string name="private_key_label">Private key:</string>
|
||||
<string name="set_keys">Set your own keys</string>
|
||||
<string name="set_keys">Set your own key</string>
|
||||
<string name="save">Save</string>
|
||||
</resources>
|
|
@ -1,12 +1,12 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.7.20'
|
||||
ext.kotlin_version = '1.9.10'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:4.2.2"
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Mon Jun 14 15:11:35 BST 2021
|
||||
#Sat Aug 26 21:38:34 CEST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 14f1cd4696a37b0f7fdcb067fac337c46953f8af
|
||||
Subproject commit 7f9d4f3f6d06262e212a8dd101d51fda134332da
|
Loading…
Add table
Add a link
Reference in a new issue