diff --git a/build.gradle b/build.gradle index 6bf31345f..93a12897c 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,9 @@ buildscript { ext.ktlint_version = '0.36.0' ext.ktlint_gradle_version = '9.1.1' ext.sqldelight_version = '1.2.2' - ext.nav_version = "2.2.0" + ext.nav_version = "2.2.1" + ext.fragment_version = "1.2.2" + ext.lifecycle_version = "2.2.0" ext.dokka_version = "0.10.1" repositories { google() @@ -13,7 +15,7 @@ buildscript { maven { url "https://plugins.gradle.org/m2/" } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:3.6.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jlleitschuh.gradle:ktlint-gradle:$ktlint_gradle_version" classpath "com.squareup.sqldelight:gradle-plugin:$sqldelight_version" diff --git a/demo-android/build.gradle b/demo-android/build.gradle index 8e175577b..939fc5220 100644 --- a/demo-android/build.gradle +++ b/demo-android/build.gradle @@ -2,6 +2,15 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: "androidx.navigation.safeargs" +apply plugin: 'org.jlleitschuh.gradle.ktlint' + +ktlint { + version = "$ktlint_version" + android = true + outputToConsole = true + ignoreFailures = true +} + android { compileSdkVersion 29 buildToolsVersion "29.0.2" @@ -33,23 +42,30 @@ android { jvmTarget = "1.8" } + viewBinding { + enabled = true + } } dependencies { - def fragment_version = "1.2.0" - implementation project(':ipv8-android') // AndroidX implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.core:core-ktx:1.1.0' + implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation "androidx.recyclerview:recyclerview:1.1.0" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version" implementation "androidx.fragment:fragment-ktx:$fragment_version" implementation "androidx.preference:preference:1.1.0" - implementation 'com.google.android.material:material:1.0.0' + implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" + + // Material + implementation 'com.google.android.material:material:1.1.0' // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" @@ -57,10 +73,12 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3' implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation 'com.mattskala:itemadapter:0.2' + // Logging implementation 'io.github.microutils:kotlin-logging:1.7.7' implementation 'com.github.tony19:logback-android:2.0.0' + implementation 'com.mattskala:itemadapter:0.2' + // Testing testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/DemoApplication.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/DemoApplication.kt index 9708f09ba..2eff5bd28 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/DemoApplication.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/DemoApplication.kt @@ -4,7 +4,6 @@ import android.app.Application import android.util.Log import androidx.preference.PreferenceManager import com.squareup.sqldelight.android.AndroidSqliteDriver -import com.squareup.sqldelight.db.SqlDriver import nl.tudelft.ipv8.* import nl.tudelft.ipv8.android.IPv8Android import nl.tudelft.ipv8.android.demo.service.DemoService diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/BaseFragment.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/BaseFragment.kt index 065f96491..445931bb4 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/BaseFragment.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/BaseFragment.kt @@ -1,5 +1,6 @@ package nl.tudelft.ipv8.android.demo.ui +import androidx.annotation.LayoutRes import androidx.fragment.app.Fragment import nl.tudelft.ipv8.IPv8 import nl.tudelft.ipv8.android.IPv8Android @@ -8,7 +9,7 @@ import nl.tudelft.ipv8.android.demo.DemoCommunity import nl.tudelft.ipv8.android.demo.TrustChainHelper import nl.tudelft.ipv8.attestation.trustchain.TrustChainCommunity -abstract class BaseFragment : Fragment() { +abstract class BaseFragment(@LayoutRes contentLayoutId: Int = 0) : Fragment(contentLayoutId) { protected val trustchain: TrustChainHelper by lazy { TrustChainHelper(getTrustChainCommunity()) } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlockItem.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlockItem.kt index 055dc7082..bf45a3874 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlockItem.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlockItem.kt @@ -8,7 +8,7 @@ data class BlockItem( var isExpanded: Boolean = false, val canSign: Boolean = false, val status: BlockStatus? = null -): Item() { +) : Item() { override fun areItemsTheSame(other: Item): Boolean { return other is BlockItem && other.block.blockId == block.blockId } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlocksFragment.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlocksFragment.kt index 6f4dd8739..f14d6072f 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlocksFragment.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/BlocksFragment.kt @@ -13,19 +13,18 @@ import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mattskala.itemadapter.Item import com.mattskala.itemadapter.ItemAdapter -import kotlinx.android.synthetic.main.fragment_blocks.* -import kotlinx.android.synthetic.main.fragment_peers.recyclerView import kotlinx.coroutines.* import nl.tudelft.ipv8.android.demo.R +import nl.tudelft.ipv8.android.demo.databinding.FragmentBlocksBinding import nl.tudelft.ipv8.android.demo.ui.BaseFragment +import nl.tudelft.ipv8.android.demo.util.viewBinding import nl.tudelft.ipv8.attestation.trustchain.ANY_COUNTERPARTY_PK import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import nl.tudelft.ipv8.attestation.trustchain.UNKNOWN_SEQ import nl.tudelft.ipv8.util.hexToBytes - @UseExperimental(ExperimentalUnsignedTypes::class) -open class BlocksFragment : BaseFragment() { +open class BlocksFragment : BaseFragment(R.layout.fragment_blocks) { private val adapter = ItemAdapter() private lateinit var publicKey: ByteArray @@ -35,6 +34,8 @@ open class BlocksFragment : BaseFragment() { protected open val isNewBlockAllowed = true + protected val binding: FragmentBlocksBinding by viewBinding(FragmentBlocksBinding::bind) + init { lifecycleScope.launchWhenStarted { while (isActive) { @@ -74,23 +75,15 @@ open class BlocksFragment : BaseFragment() { publicKey = getPublicKey() } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_blocks, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - recyclerView.adapter = adapter - recyclerView.layoutManager = LinearLayoutManager(context) + binding.recyclerView.adapter = adapter + binding.recyclerView.layoutManager = LinearLayoutManager(context) val dividerItemDecoration = DividerItemDecoration(context, LinearLayout.VERTICAL) dividerItemDecoration.setDrawable(ResourcesCompat.getDrawable(resources, R.drawable.list_divider, null)!!) - recyclerView.addItemDecoration(dividerItemDecoration) + binding.recyclerView.addItemDecoration(dividerItemDecoration) } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -103,14 +96,14 @@ open class BlocksFragment : BaseFragment() { return when (item.itemId) { R.id.item_new_block -> { showNewBlockDialog() - true + true } else -> super.onOptionsItemSelected(item) } } protected open fun getPublicKey(): ByteArray { - val args = BlocksFragmentArgs.fromBundle(arguments!!) + val args = BlocksFragmentArgs.fromBundle(requireArguments()) return args.publicKey.hexToBytes() } @@ -125,8 +118,8 @@ open class BlocksFragment : BaseFragment() { protected open suspend fun updateView() { val items = createItems(blocks) adapter.updateItems(items) - imgNoBlocks.isVisible = items.isEmpty() - progress.isVisible = false + binding.imgNoBlocks.isVisible = items.isEmpty() + binding.progress.isVisible = false } private suspend fun createItems(blocks: List): List = @@ -170,7 +163,7 @@ open class BlocksFragment : BaseFragment() { lifecycleScope.launch { refreshBlocks() updateView() - recyclerView.smoothScrollToPosition(0) + binding.recyclerView.smoothScrollToPosition(0) } } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/LatestBlocksFragment.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/LatestBlocksFragment.kt index ceb801b8c..11931e6c4 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/LatestBlocksFragment.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/blocks/LatestBlocksFragment.kt @@ -1,7 +1,6 @@ package nl.tudelft.ipv8.android.demo.ui.blocks import androidx.recyclerview.widget.LinearLayoutManager -import kotlinx.android.synthetic.main.fragment_blocks.* import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock import kotlin.math.min @@ -19,13 +18,13 @@ class LatestBlocksFragment : BlocksFragment() { } override suspend fun updateView() { - val layoutManager = recyclerView.layoutManager as LinearLayoutManager + val layoutManager = binding.recyclerView.layoutManager as LinearLayoutManager val firstVisibleItem = layoutManager.findFirstCompletelyVisibleItemPosition() super.updateView() if (firstVisibleItem == 0) { - recyclerView.smoothScrollToPosition(0) + binding.recyclerView.smoothScrollToPosition(0) } } } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/debug/DebugFragment.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/debug/DebugFragment.kt index 7b87861cd..7123dc922 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/debug/DebugFragment.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/debug/DebugFragment.kt @@ -1,25 +1,18 @@ package nl.tudelft.ipv8.android.demo.ui.debug import android.os.Bundle -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup import androidx.lifecycle.lifecycleScope -import kotlinx.android.synthetic.main.fragment_debug.* import kotlinx.coroutines.* import nl.tudelft.ipv8.Community import nl.tudelft.ipv8.android.demo.R +import nl.tudelft.ipv8.android.demo.databinding.FragmentDebugBinding import nl.tudelft.ipv8.android.demo.ui.BaseFragment +import nl.tudelft.ipv8.android.demo.util.viewBinding import nl.tudelft.ipv8.util.toHex -class DebugFragment : BaseFragment() { - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_debug, container, false) - } +class DebugFragment : BaseFragment(R.layout.fragment_debug) { + private val binding by viewBinding(FragmentDebugBinding::bind) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -35,12 +28,12 @@ class DebugFragment : BaseFragment() { private fun updateView() { val ipv8 = getIpv8() val demo = getDemoCommunity() - txtBootstrap.text = Community.DEFAULT_ADDRESSES.joinToString("\n") - txtLanAddress.text = demo.myEstimatedLan.toString() - txtWanAddress.text = demo.myEstimatedWan.toString() - txtPeerId.text = ipv8.myPeer.mid - txtPublicKey.text = ipv8.myPeer.publicKey.keyToBin().toHex() - txtOverlays.text = ipv8.overlays.values.toList().joinToString("\n") { + binding.txtBootstrap.text = Community.DEFAULT_ADDRESSES.joinToString("\n") + binding.txtLanAddress.text = demo.myEstimatedLan.toString() + binding.txtWanAddress.text = demo.myEstimatedWan.toString() + binding.txtPeerId.text = ipv8.myPeer.mid + binding.txtPublicKey.text = ipv8.myPeer.publicKey.keyToBin().toHex() + binding.txtOverlays.text = ipv8.overlays.values.toList().joinToString("\n") { it.javaClass.simpleName + " (" + it.getPeers().size + " peers)" } @@ -48,14 +41,14 @@ class DebugFragment : BaseFragment() { val blockCount = withContext(Dispatchers.IO) { getTrustChainCommunity().database.getAllBlocks().size } - txtBlockCount.text = blockCount.toString() + binding.txtBlockCount.text = blockCount.toString() } lifecycleScope.launch { val chainLength = withContext(Dispatchers.IO) { getTrustChainCommunity().getChainLength() } - txtChainLength.text = chainLength.toString() + binding.txtChainLength.text = chainLength.toString() } } } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/AddressItem.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/AddressItem.kt index d8dd771f7..3dad92da8 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/AddressItem.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/AddressItem.kt @@ -8,7 +8,7 @@ class AddressItem( val address: Address, val discovered: Date?, val contacted: Date? -): Item() { +) : Item() { override fun areItemsTheSame(other: Item): Boolean { return other is AddressItem && other.address == address } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/MainActivity.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/MainActivity.kt index 3d83addac..d2fce9979 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/MainActivity.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/MainActivity.kt @@ -1,10 +1,6 @@ package nl.tudelft.ipv8.android.demo.ui.peers -import android.content.ComponentName -import android.content.Intent -import android.content.ServiceConnection import android.os.Bundle -import android.os.IBinder import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController @@ -12,16 +8,19 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import kotlinx.android.synthetic.main.activity_main.* import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import mu.KotlinLogging import nl.tudelft.ipv8.android.demo.R +import nl.tudelft.ipv8.android.demo.databinding.ActivityMainBinding +import nl.tudelft.ipv8.android.demo.util.viewBinding val logger = KotlinLogging.logger {} class MainActivity : AppCompatActivity() { + private val binding by viewBinding(ActivityMainBinding::inflate) + private val navController by lazy { findNavController(R.id.navHostFragment) } @@ -35,13 +34,13 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) + setContentView(binding.root) // Setup ActionBar setupActionBarWithNavController(navController, appBarConfiguration) // Setup bottom navigation - bottomNavigation.setupWithNavController(navController) + binding.bottomNavigation.setupWithNavController(navController) lifecycleScope.launch { while (isActive) { diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeerItem.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeerItem.kt index 67dc0f7a6..00523387d 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeerItem.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeerItem.kt @@ -3,7 +3,7 @@ package nl.tudelft.ipv8.android.demo.ui.peers import com.mattskala.itemadapter.Item import nl.tudelft.ipv8.Peer -class PeerItem(val peer: Peer): Item() { +class PeerItem(val peer: Peer) : Item() { override fun areItemsTheSame(other: Item): Boolean { return other is PeerItem && other.peer.mid == peer.mid } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeersFragment.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeersFragment.kt index 1095a898d..d2277b4bc 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeersFragment.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/peers/PeersFragment.kt @@ -1,10 +1,7 @@ package nl.tudelft.ipv8.android.demo.ui.peers import android.os.Bundle -import android.util.Log -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup import android.widget.LinearLayout import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope @@ -12,21 +9,18 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mattskala.itemadapter.ItemAdapter -import kotlinx.android.synthetic.main.fragment_peers.* import kotlinx.coroutines.* -import nl.tudelft.ipv8.android.demo.DemoCommunity import nl.tudelft.ipv8.android.demo.R +import nl.tudelft.ipv8.android.demo.databinding.FragmentPeersBinding import nl.tudelft.ipv8.android.demo.ui.BaseFragment -import nl.tudelft.ipv8.attestation.trustchain.BlockListener -import nl.tudelft.ipv8.attestation.trustchain.TrustChainBlock -import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore -import nl.tudelft.ipv8.attestation.trustchain.validation.TransactionValidator -import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationResult +import nl.tudelft.ipv8.android.demo.util.viewBinding import nl.tudelft.ipv8.util.toHex -class PeersFragment : BaseFragment() { +class PeersFragment : BaseFragment(R.layout.fragment_peers) { private val adapter = ItemAdapter() + private val binding by viewBinding(FragmentPeersBinding::bind) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -43,20 +37,12 @@ class PeersFragment : BaseFragment() { }) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_peers, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - recyclerView.adapter = adapter - recyclerView.layoutManager = LinearLayoutManager(context) - recyclerView.addItemDecoration(DividerItemDecoration(context, LinearLayout.VERTICAL)) + binding.recyclerView.adapter = adapter + binding.recyclerView.layoutManager = LinearLayoutManager(context) + binding.recyclerView.addItemDecoration(DividerItemDecoration(context, LinearLayout.VERTICAL)) loadNetworkInfo() } @@ -86,12 +72,12 @@ class PeersFragment : BaseFragment() { val items = peerItems + addressItems adapter.updateItems(items) - txtCommunityName.text = demoCommunity.javaClass.simpleName - txtPeerCount.text = resources.getQuantityString( + binding.txtCommunityName.text = demoCommunity.javaClass.simpleName + binding.txtPeerCount.text = resources.getQuantityString( R.plurals.x_peers, peers.size, peers.size ) - imgEmpty.isVisible = items.isEmpty() + binding.imgEmpty.isVisible = items.isEmpty() delay(1000) } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/users/UsersFragment.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/users/UsersFragment.kt index 3318a56c9..efc898c0c 100644 --- a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/users/UsersFragment.kt +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/ui/users/UsersFragment.kt @@ -11,16 +11,19 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import com.mattskala.itemadapter.ItemAdapter -import kotlinx.android.synthetic.main.fragment_peers.* import kotlinx.coroutines.* import nl.tudelft.ipv8.android.demo.R +import nl.tudelft.ipv8.android.demo.databinding.FragmentUsersBinding import nl.tudelft.ipv8.android.demo.ui.BaseFragment +import nl.tudelft.ipv8.android.demo.util.viewBinding import nl.tudelft.ipv8.android.keyvault.AndroidCryptoProvider import nl.tudelft.ipv8.util.toHex -class UsersFragment : BaseFragment() { +class UsersFragment : BaseFragment(R.layout.fragment_users) { private val adapter = ItemAdapter() + private val binding by viewBinding(FragmentUsersBinding::bind) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -31,25 +34,16 @@ class UsersFragment : BaseFragment() { }) } - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - return inflater.inflate(R.layout.fragment_users, container, false) - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - recyclerView.adapter = adapter - recyclerView.layoutManager = LinearLayoutManager(context) - recyclerView.addItemDecoration(DividerItemDecoration(context, LinearLayout.VERTICAL)) + binding.recyclerView.adapter = adapter + binding.recyclerView.layoutManager = LinearLayoutManager(context) + binding.recyclerView.addItemDecoration(DividerItemDecoration(context, LinearLayout.VERTICAL)) loadNetworkInfo() } - private fun loadNetworkInfo() { lifecycleScope.launchWhenStarted { while (isActive) { @@ -70,7 +64,7 @@ class UsersFragment : BaseFragment() { } adapter.updateItems(items) - imgEmpty.isVisible = items.isEmpty() + binding.imgEmpty.isVisible = items.isEmpty() delay(1000) } diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/util/ActivityViewBindingDelegate.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/util/ActivityViewBindingDelegate.kt new file mode 100644 index 000000000..932600fec --- /dev/null +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/util/ActivityViewBindingDelegate.kt @@ -0,0 +1,14 @@ +package nl.tudelft.ipv8.android.demo.util + +import android.view.LayoutInflater +import androidx.appcompat.app.AppCompatActivity +import androidx.viewbinding.ViewBinding + +/** + * @url https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c + */ +inline fun AppCompatActivity.viewBinding( + crossinline bindingInflater: (LayoutInflater) -> T +) = lazy(LazyThreadSafetyMode.NONE) { + bindingInflater.invoke(layoutInflater) +} diff --git a/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/util/FragmentViewBindingDelegate.kt b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/util/FragmentViewBindingDelegate.kt new file mode 100644 index 000000000..a47b7d7ac --- /dev/null +++ b/demo-android/src/main/java/nl/tudelft/ipv8/android/demo/util/FragmentViewBindingDelegate.kt @@ -0,0 +1,53 @@ +package nl.tudelft.ipv8.android.demo.util + +import android.view.View +import androidx.fragment.app.Fragment +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.observe +import androidx.viewbinding.ViewBinding +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +/** + * @url https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c + */ +class FragmentViewBindingDelegate( + val fragment: Fragment, + val viewBindingFactory: (View) -> T +) : ReadOnlyProperty { + private var _binding: T? = null + + init { + fragment.lifecycle.addObserver(object : DefaultLifecycleObserver { + override fun onCreate(owner: LifecycleOwner) { + fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner -> + viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver { + override fun onDestroy(owner: LifecycleOwner) { + _binding = null + } + }) + } + } + }) + } + + override fun getValue(thisRef: Fragment, property: KProperty<*>): T { + val binding = _binding + if (binding != null) { + return binding + } + + val lifecycle = fragment.viewLifecycleOwner.lifecycle + if (!lifecycle.currentState.isAtLeast(Lifecycle.State.INITIALIZED)) { + throw IllegalStateException("Should not attempt to get bindings when Fragment views are destroyed.") + } + + return viewBindingFactory(thisRef.requireView()).also { _binding = it } + } +} + +fun Fragment.viewBinding( + viewBindingFactory: (View) -> T +) = FragmentViewBindingDelegate(this, viewBindingFactory) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9f3c21fe7..e0d73c986 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Dec 18 15:47:32 CET 2019 +#Mon Feb 24 23:30:31 CET 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt b/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt index b048820df..e3ff74b5b 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt @@ -374,6 +374,7 @@ abstract class Community : Overlay { discoverAddress(peer, payload.lanIntroductionAddress, serviceId) } else if (!payload.wanIntroductionAddress.isEmpty()) { // WAN is same as ours, but we do not know the LAN + // Should not happen with kotlin-ipv8 peers, but we'll keep it for py-ipv8 compatibility // Try to connect via WAN, NAT needs to support hairpinning discoverAddress(peer, payload.wanIntroductionAddress, serviceId) @@ -439,18 +440,18 @@ abstract class Community : Overlay { // Address("131.180.27.156", 6424), // Address("131.180.27.161", 6427), // IPv8 - /* - Address("131.180.27.161", 6521), - Address("131.180.27.161", 6522), - Address("131.180.27.162", 6523), - Address("131.180.27.162", 6524), - Address("130.161.119.215", 6525), - Address("130.161.119.215", 6526), - Address("81.171.27.194", 6527), - //Address("81.171.27.194", 6528) - */ - // IPv8 + LibNaCL - Address("131.180.27.161", 6427) + // Address("131.180.27.161", 6521), + // Address("131.180.27.161", 6522), + // Address("131.180.27.162", 6523), + // Address("131.180.27.162", 6524), + // Address("130.161.119.215", 6525), + // Address("130.161.119.215", 6526), + // Address("81.171.27.194", 6527), + // Address("81.171.27.194", 6528) + // py-ipv8 + LibNaCL + Address("131.180.27.161", 6427), + // kotlin-ipv8 + Address("178.62.16.66", 8090) ) // Timeout before we bootstrap again (bootstrap kills performance) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt index cc90719bc..91a734f9e 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt @@ -456,6 +456,8 @@ open class TrustChainCommunity( } private fun onCrawlResponse(sourceAddress: Address, payload: CrawlResponsePayload) { + logger.debug("<- $payload") + onHalfBlock(sourceAddress, payload.block) val block = payload.block.toBlock() diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt index a13846c2a..25349a524 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt @@ -5,7 +5,7 @@ import nl.tudelft.ipv8.messaging.* /** * Request a crawl of blocks starting with a specific sequence number or the first if 0. */ -class CrawlRequestPayload( +data class CrawlRequestPayload( val publicKey: ByteArray, val startSeqNum: Long, val endSeqNum: Long, diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt index aa22c4a02..c0592b06a 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt @@ -6,7 +6,7 @@ import nl.tudelft.ipv8.messaging.* /** * Payload for the response to a crawl request. */ -open class CrawlResponsePayload( +data class CrawlResponsePayload( val block: HalfBlockPayload, val crawlId: UInt, val curCount: UInt,