Merge pull request #6 from vikulin/master

Several improvements in UI
This commit is contained in:
ChronosX88 2020-06-16 22:21:20 +04:00 committed by GitHub
commit 79c3d81c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 195 additions and 201 deletions

View File

@ -6,7 +6,7 @@ android {
compileSdkVersion 29 compileSdkVersion 29
defaultConfig { defaultConfig {
applicationId "io.github.chronosx88.yggdrasil" applicationId "io.github.chronosx88.yggdrasil"
minSdkVersion 21 minSdkVersion 22
targetSdkVersion 29 targetSdkVersion 29
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"

View File

@ -24,10 +24,8 @@
<activity android:name=".MainActivity"> <activity android:name=".MainActivity">
<intent-filter> <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> </intent-filter>
</activity> </activity>
</application> </application>
</manifest> </manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -1,51 +1,78 @@
package io.github.chronosx88.yggdrasil package io.github.chronosx88.yggdrasil
import android.R.attr
import android.app.Activity import android.app.Activity
import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.net.VpnService import android.net.VpnService
import android.os.Bundle import android.os.Bundle
import android.widget.Button import android.util.Log
import android.widget.RadioGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private var isYggStarted = false companion object {
const val PARAM_PINTENT = "pendingIntent"
const val STATUS_START = 1
const val STATUS_FINISH = 0
const val IPv6: String = "IPv6"
private const val TAG="Yggdrasil"
private const val VPN_REQUEST_CODE = 0x0F
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
val connectRadioGroup = findViewById<RadioGroup>(R.id.connectRadioGroup)
connectRadioGroup.setOnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.disconnectButton -> stopVpn()
R.id.connectButton -> startVpn()
else -> { // Note the block
val connectButton = findViewById<Button>(R.id.connect_button) }
connectButton.setOnClickListener {
if(!isYggStarted) {
// Prepare to establish a VPN connection.
// This method returns null if the VPN application is already prepared
// or if the user has previously consented to the VPN application.
// Otherwise, it returns an Intent to a system activity.
val vpnIntent = VpnService.prepare(this)
if (vpnIntent != null) startActivityForResult(
vpnIntent,
0x0F
)
else onActivityResult(0x0F, Activity.RESULT_OK, null)
} else {
// FIXME fix this shit, this code doesn't stop service for some reasons
val intent = Intent(this, YggdrasilTunService::class.java)
stopService(intent)
connectButton.text = "Connect"
isYggStarted = false
} }
} }
} }
fun stopVpn(){
Log.d(TAG,"Stop")
val intent = Intent(this, YggdrasilTunService::class.java)
intent.putExtra("COMMAND", "STOP")
startService(intent)
}
fun startVpn(){
Log.d(TAG,"Start")
val intent= VpnService.prepare(this)
if (intent!=null){
startActivityForResult(intent, VPN_REQUEST_CODE);
}else{
onActivityResult(VPN_REQUEST_CODE, Activity.RESULT_OK, null);
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 0x0F && resultCode == Activity.RESULT_OK) { if (requestCode == VPN_REQUEST_CODE && resultCode== Activity.RESULT_OK){
val intent = Intent(this, YggdrasilTunService::class.java) val intent = Intent(this, YggdrasilTunService::class.java)
val TASK_CODE = 100
var pi = createPendingResult(TASK_CODE, intent, 0);
intent.putExtra("COMMAND", "START")
intent.putExtra(PARAM_PINTENT, pi)
startService(intent) startService(intent)
val connectButton = findViewById<Button>(R.id.connect_button) }
connectButton.text = "Disconnect" when (resultCode) {
isYggStarted = true STATUS_START -> print("service started")
STATUS_FINISH -> {
val result: String = data!!.getStringExtra(IPv6)
findViewById<TextView>(R.id.ip).setText(result)
}
else -> { // Note the block
}
} }
} }
} }

View File

@ -1,9 +1,10 @@
package io.github.chronosx88.yggdrasil package io.github.chronosx88.yggdrasil
import android.app.Service import android.app.PendingIntent
import android.content.Intent import android.content.Intent
import android.net.VpnService import android.net.VpnService
import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor
import android.system.OsConstants
import com.google.gson.Gson import com.google.gson.Gson
import dummy.ConduitEndpoint import dummy.ConduitEndpoint
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -11,13 +12,9 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mobile.Mobile import mobile.Mobile
import mobile.Yggdrasil import mobile.Yggdrasil
import java.io.FileInputStream import java.io.*
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.experimental.or
class YggdrasilTunService : VpnService() { class YggdrasilTunService : VpnService() {
@ -26,7 +23,7 @@ class YggdrasilTunService : VpnService() {
private val MAX_PACKET_SIZE = Short.MAX_VALUE.toInt() private val MAX_PACKET_SIZE = Short.MAX_VALUE.toInt()
companion object { companion object {
private var isRunning: Boolean = false private const val TAG = "Yggdrasil-service"
} }
private var tunInterface: ParcelFileDescriptor? = null private var tunInterface: ParcelFileDescriptor? = null
private lateinit var yggConduitEndpoint: ConduitEndpoint private lateinit var yggConduitEndpoint: ConduitEndpoint
@ -36,17 +33,19 @@ class YggdrasilTunService : VpnService() {
private lateinit var writeCoroutine: CoroutineContext private lateinit var writeCoroutine: CoroutineContext
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
super.onStartCommand(intent, flags, startId) if (intent?.getStringExtra("COMMAND") == "STOP") {
return Service.START_STICKY stopVpn()
}
if (intent?.getStringExtra("COMMAND") == "START") {
val pi: PendingIntent = intent.getParcelableExtra(MainActivity.PARAM_PINTENT)
setupTunInterface(pi)
}
return super.onStartCommand(intent, flags, startId);
} }
override fun onCreate() { private fun setupTunInterface(pi: PendingIntent) {
super.onCreate() pi.send(MainActivity.STATUS_START);
isRunning = true
setupTunInterface()
}
private fun setupTunInterface() {
val builder = Builder() val builder = Builder()
val ygg = Yggdrasil() val ygg = Yggdrasil()
var configJson = Mobile.generateConfigJSON() var configJson = Mobile.generateConfigJSON()
@ -61,19 +60,20 @@ class YggdrasilTunService : VpnService() {
tunInterface = builder tunInterface = builder
.addAddress(address, 7) .addAddress(address, 7)
.addRoute("10.0.0.0", 8) .allowFamily(OsConstants.AF_INET)
.addRoute("172.16.0.0", 12)
.addRoute("192.168.0.0", 16)
.addRoute("0200::", 7)
.setMtu(MAX_PACKET_SIZE) .setMtu(MAX_PACKET_SIZE)
.establish() .establish()
tunInputStream = FileInputStream(tunInterface!!.fileDescriptor) tunInputStream = FileInputStream(tunInterface!!.fileDescriptor)
tunOutputStream = FileOutputStream(tunInterface!!.fileDescriptor) tunOutputStream = FileOutputStream(tunInterface!!.fileDescriptor)
readCoroutine = GlobalScope.launch { readCoroutine = GlobalScope.launch {
// FIXME it will throw exception (bad file descriptor) when coroutine will be canceled var buffer = ByteArray(2048)
while (true) { while (true) {
readPacketsFromTun() try{
readPacketsFromTun(buffer)
} catch (e: IOException){
e.printStackTrace()
}
} }
} }
writeCoroutine = GlobalScope.launch { writeCoroutine = GlobalScope.launch {
@ -81,6 +81,8 @@ class YggdrasilTunService : VpnService() {
writePacketsToTun() writePacketsToTun()
} }
} }
val intent: Intent = Intent().putExtra(MainActivity.IPv6, address)
pi.send(this, MainActivity.STATUS_FINISH, intent)
} }
private fun fixConfig(config: MutableMap<Any?, Any?>): MutableMap<Any?, Any?> { private fun fixConfig(config: MutableMap<Any?, Any?>): MutableMap<Any?, Any?> {
@ -117,34 +119,20 @@ class YggdrasilTunService : VpnService() {
return config return config
} }
private fun readPacketsFromTun() { private fun readPacketsFromTun(buffer: ByteArray) {
if(tunInputStream != null) { if(tunInputStream != null) {
var packet: ByteArray = ByteArray(MAX_PACKET_SIZE)
// Read the outgoing packet from the input stream. // Read the outgoing packet from the input stream.
var length = tunInputStream!!.read(packet) var length = tunInputStream!!.read(buffer)
//System.out.println("packet size:"+packet.size+" "+byteArrayToHex(packet))
//System.out.println("buffer size:"+buffer.array().size+" "+byteArrayToHex(buffer.array()))
if (length > 0) { if (length > 0) {
// Ignore control messages, which start with zero. var byteBuffer = ByteBuffer.allocate(length);
if (packet.get(0).compareTo(0)!=0) { byteBuffer.put(buffer, 0, length)
var buffer = ByteBuffer.allocate(length); yggConduitEndpoint.send(byteBuffer.array())
buffer.put(packet, 0, length) } else {
buffer.limit(length) Thread.sleep(10)
yggConduitEndpoint.send(buffer.array())
}
} }
} }
} }
private fun isBufferEmpty(buffer: ByteArray): Boolean {
var sum: Byte = 0
for (i in buffer) {
sum.or(i)
}
return sum == 0.toByte()
}
private fun writePacketsToTun() { private fun writePacketsToTun() {
if(tunOutputStream != null) { if(tunOutputStream != null) {
val buffer = yggConduitEndpoint.recv() val buffer = yggConduitEndpoint.recv()
@ -152,12 +140,16 @@ class YggdrasilTunService : VpnService() {
} }
} }
override fun onRevoke() { fun stopVpn() {
super.onRevoke()
isRunning = false
readCoroutine.cancel() readCoroutine.cancel()
writeCoroutine.cancel() writeCoroutine.cancel()
tunInterface!!.close() tunInterface!!.close()
tunInterface = null tunInterface = null
stopSelf()
}
override fun onDestroy() {
super.onDestroy()
stopSelf()
} }
} }

View File

@ -1,34 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0"/>
<item
android:color="#00000000"
android:offset="1.0"/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1"/>
</vector>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@ -0,0 +1,8 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="2dp" />
<solid android:color="#80000000" />
<stroke
android:width="1dp"
android:color="@color/green" />
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/dark_20" android:state_checked="true" />
<item android:drawable="@color/dark_10" android:state_pressed="true" />
<item android:drawable="@color/dark_5" />
</selector>

View File

@ -1,18 +1,83 @@
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity" android:orientation="vertical" android:background="@color/grey"
android:gravity="center"> tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toTopOf="@+id/connectRadioGroup"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
android:gravity="left">
<TextView
android:id="@+id/ipLabel"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/dark_10"
android:elevation="8dp"
android:gravity="center_vertical"
android:text="Your IP address:"
android:textColor="@color/white"
android:paddingLeft="20dp"/>
<Button <TextView
android:id="@+id/connect_button" android:id="@+id/ip"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="30dp"
android:text="@string/connect_button" android:background="@color/dark_10"
android:layout_gravity="center"/> android:elevation="8dp"
android:gravity="center_vertical"
android:text=""
android:textColor="@color/white"
android:paddingLeft="20dp"
app:layout_constraintBottom_toTopOf="@+id/connectRadioGroup"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
</LinearLayout>
<RadioGroup
android:id="@+id/connectRadioGroup"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/out_line"
android:checkedButton="@+id/offer"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="50dp">
<RadioButton
android:id="@+id/disconnectButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="1dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:layout_weight="1"
android:background="@drawable/toggle_widget_background"
android:button="@null"
android:gravity="center"
android:text="@string/disconnect_button"
android:textColor="@color/white"
android:checked="true"/>
<RadioButton
android:id="@+id/connectButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginTop="1dp"
android:layout_marginRight="1dp"
android:layout_marginBottom="1dp"
android:layout_weight="1"
android:background="@drawable/toggle_widget_background"
android:button="@null"
android:gravity="center"
android:text="@string/connect_button"
android:textColor="@color/white" />
</RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/> <background android:drawable="@android:color/transparent"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="colorPrimary">#008577</color> <color name="colorPrimary">#555555</color>
<color name="colorPrimaryDark">#00574B</color> <color name="colorPrimaryDark">#343334</color>
<color name="colorAccent">#D81B60</color> <color name="colorAccent">#D81B60</color>
<color name="white">#ffffff</color>
<color name="green">#83cf03</color>
<color name="grey">#343334</color>
<color name="dark_5">#555555</color>
<color name="dark_10">#666666</color>
<color name="dark_20">#777777</color>
</resources> </resources>

View File

@ -1,4 +1,5 @@
<resources> <resources>
<string name="app_name">Yggdrasil</string> <string name="app_name">Yggdrasil</string>
<string name="connect_button">Connect</string> <string name="connect_button">Connect</string>
<string name="disconnect_button">Disconnect</string>
</resources> </resources>

View File

@ -1,7 +1,7 @@
<resources> <resources>
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light"> <style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>