Resolved merge conflict
This commit is contained in:
commit
bb4b4a91c8
@ -5,7 +5,7 @@
|
|||||||
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
||||||
</configurations>
|
</configurations>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -6,6 +6,9 @@ apply plugin: 'kotlin-android-extensions'
|
|||||||
|
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
|
|
||||||
|
|
||||||
|
apply plugin: 'io.gitlab.arturbosch.detekt'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 29
|
||||||
buildToolsVersion "29.0.2"
|
buildToolsVersion "29.0.2"
|
||||||
@ -29,7 +32,10 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
// standard
|
// standard
|
||||||
|
implementation project(':wrapper')
|
||||||
|
detektPlugins "io.gitlab.arturbosch.detekt:detekt-formatting:1.2.2"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
implementation 'androidx.core:core-ktx:1.1.0'
|
implementation 'androidx.core:core-ktx:1.1.0'
|
||||||
@ -58,13 +64,15 @@ dependencies {
|
|||||||
//Card view
|
//Card view
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
|
|
||||||
|
|
||||||
// TESTING
|
// TESTING
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation "io.mockk:mockk:1.9.3"
|
testImplementation "io.mockk:mockk:1.9.3"
|
||||||
testImplementation "com.squareup.okhttp3:mockwebserver:4.2.1"
|
testImplementation "com.squareup.okhttp3:mockwebserver:4.2.1"
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0'
|
||||||
|
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||||
|
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||||
|
|
||||||
implementation "com.squareup.retrofit2:retrofit:2.6.2"
|
implementation "com.squareup.retrofit2:retrofit:2.6.2"
|
||||||
implementation "com.squareup.retrofit2:converter-gson:2.6.2"
|
implementation "com.squareup.retrofit2:converter-gson:2.6.2"
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app
|
||||||
|
|
||||||
|
import androidx.lifecycle.*
|
||||||
|
|
||||||
|
class OneTimeObserver<T>(private val handler: (T) -> Unit) : Observer<T>, LifecycleOwner {
|
||||||
|
private val lifecycle = LifecycleRegistry(this)
|
||||||
|
init {
|
||||||
|
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLifecycle(): Lifecycle = lifecycle
|
||||||
|
|
||||||
|
override fun onChanged(t: T) {
|
||||||
|
handler(t)
|
||||||
|
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> LiveData<T>.observeOnce(onChangeHandler: (T) -> Unit) {
|
||||||
|
val observer = OneTimeObserver(handler = onChangeHandler)
|
||||||
|
observe(observer, observer)
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.data.dao
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.database.BoardDatabase
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.observeOnce
|
||||||
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class BoardDaoTest {
|
||||||
|
private lateinit var dao: BoardDao
|
||||||
|
private lateinit var db: BoardDatabase
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val instantTaskExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun createDb() {
|
||||||
|
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||||
|
db = Room.inMemoryDatabaseBuilder(
|
||||||
|
context, BoardDatabase::class.java
|
||||||
|
).build()
|
||||||
|
dao = db.boardDao()
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun closeDb() {
|
||||||
|
db.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun emptyDatabaseOnCreation() {
|
||||||
|
dao.getAllBoard().observeOnce {
|
||||||
|
assertEquals(0, it.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun insert() {
|
||||||
|
val board = Board("id", "title")
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
dao.insert(board)
|
||||||
|
}
|
||||||
|
|
||||||
|
dao.getAllBoard().observeOnce {
|
||||||
|
assertEquals(1, it.size)
|
||||||
|
assertEquals(board, it[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun replaceOnConflict() {
|
||||||
|
val board0 = Board("id", "title0")
|
||||||
|
val board1 = Board("id", "title1")
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
dao.insert(board0)
|
||||||
|
dao.insert(board1)
|
||||||
|
}
|
||||||
|
|
||||||
|
dao.getAllBoard().observeOnce {
|
||||||
|
assertEquals(1, it.size)
|
||||||
|
assertEquals("title1", it[0].title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getInAscendingOrder() {
|
||||||
|
val board0 = Board("id0", "title0")
|
||||||
|
val board1 = Board("id1", "title1")
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
dao.insert(board1)
|
||||||
|
dao.insert(board0)
|
||||||
|
}
|
||||||
|
|
||||||
|
dao.getAllBoard().observeOnce {
|
||||||
|
assertEquals(2, it.size)
|
||||||
|
assertEquals(board0, it[0])
|
||||||
|
assertEquals(board1, it[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun delete() {
|
||||||
|
val board = Board("id", "title")
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
dao.insert(board)
|
||||||
|
dao.delete(board)
|
||||||
|
}
|
||||||
|
|
||||||
|
dao.getAllBoard().observeOnce {
|
||||||
|
assertEquals(0, it.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view
|
||||||
|
|
||||||
|
import androidx.test.espresso.Espresso.onView
|
||||||
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
|
import androidx.test.espresso.action.ViewActions.swipeDown
|
||||||
|
import androidx.test.espresso.action.ViewActions.swipeLeft
|
||||||
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import androidx.test.espresso.contrib.RecyclerViewActions
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.filters.LargeTest
|
||||||
|
import androidx.test.rule.ActivityTestRule
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.view.adapter.BoardsListAdapter
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@LargeTest
|
||||||
|
class BoardsListsActivityTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val activityRule = ActivityTestRule(BoardsListsActivity::class.java)
|
||||||
|
|
||||||
|
fun swipeLeftToDelete() {
|
||||||
|
onView(withId(R.id.boardList))
|
||||||
|
.perform(
|
||||||
|
RecyclerViewActions.actionOnItemAtPosition<BoardsListAdapter.BoardViewHolder>(
|
||||||
|
0, swipeLeft()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pullToRefresh() {
|
||||||
|
onView(withId(R.id.pullToRefresh))
|
||||||
|
.perform(swipeDown())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun openNewBoardActivity() {
|
||||||
|
onView(withId(R.id.fab))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.newBoardName))
|
||||||
|
.check(matches(isDisplayed()))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view
|
||||||
|
|
||||||
|
import androidx.test.espresso.Espresso.closeSoftKeyboard
|
||||||
|
import androidx.test.espresso.Espresso.onView
|
||||||
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
|
import androidx.test.espresso.action.ViewActions.typeText
|
||||||
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import androidx.test.espresso.matcher.RootMatchers.withDecorView
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.filters.LargeTest
|
||||||
|
import androidx.test.rule.ActivityTestRule
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R
|
||||||
|
import org.hamcrest.CoreMatchers.not
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@LargeTest
|
||||||
|
class LoginActivityTest {
|
||||||
|
@get:Rule
|
||||||
|
val activityRule = ActivityTestRule(LoginActivity::class.java)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loginWithEmptyUrl() {
|
||||||
|
onView(withId(R.id.username))
|
||||||
|
.perform(typeText("username"))
|
||||||
|
onView(withId(R.id.password))
|
||||||
|
.perform(typeText("password"))
|
||||||
|
closeSoftKeyboard()
|
||||||
|
onView(withId(R.id.button))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
onView(withText(R.string.login_empty_field))
|
||||||
|
.inRoot(withDecorView(not(activityRule.activity.window.decorView)))
|
||||||
|
.check(matches(isDisplayed()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loginWithEmptyUsername() {
|
||||||
|
onView(withId(R.id.instanceServer))
|
||||||
|
.perform(typeText("https://wekan.com"))
|
||||||
|
onView(withId(R.id.password))
|
||||||
|
.perform(typeText("password"))
|
||||||
|
closeSoftKeyboard()
|
||||||
|
onView(withId(R.id.button))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
onView(withText(R.string.login_empty_field))
|
||||||
|
.inRoot(withDecorView(not(activityRule.activity.window.decorView)))
|
||||||
|
.check(matches(isDisplayed()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loginWithEmptyPassword() {
|
||||||
|
onView(withId(R.id.instanceServer))
|
||||||
|
.perform(typeText("https://wekan.com"))
|
||||||
|
onView(withId(R.id.username))
|
||||||
|
.perform(typeText("username"))
|
||||||
|
closeSoftKeyboard()
|
||||||
|
onView(withId(R.id.button))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
onView(withText(R.string.login_empty_field))
|
||||||
|
.inRoot(withDecorView(not(activityRule.activity.window.decorView)))
|
||||||
|
.check(matches(isDisplayed()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun loginWithUnformedInstance(){
|
||||||
|
onView(withId(R.id.instanceServer))
|
||||||
|
.perform(typeText("not an URL"))
|
||||||
|
onView(withId(R.id.username))
|
||||||
|
.perform(typeText("username"))
|
||||||
|
onView(withId(R.id.password))
|
||||||
|
.perform(typeText("password"))
|
||||||
|
closeSoftKeyboard()
|
||||||
|
onView(withId(R.id.button))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
onView(withText(R.string.login_unformed_instance))
|
||||||
|
.inRoot(withDecorView(not(activityRule.activity.window.decorView)))
|
||||||
|
.check(matches(isDisplayed()))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view
|
||||||
|
|
||||||
|
import androidx.test.espresso.Espresso.onView
|
||||||
|
import androidx.test.espresso.action.ViewActions.click
|
||||||
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import androidx.test.espresso.matcher.RootMatchers.withDecorView
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.filters.LargeTest
|
||||||
|
import androidx.test.rule.ActivityTestRule
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R
|
||||||
|
import org.hamcrest.core.IsNot.not
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@LargeTest
|
||||||
|
class NewBoardActivityTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val activityRule = ActivityTestRule(NewBoardActivity::class.java)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun showToastOnEmptyName() {
|
||||||
|
onView(withId(R.id.newBoardDone))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
onView(withText(R.string.on_add_new_board_empty_name))
|
||||||
|
.inRoot(withDecorView(not(activityRule.activity.window.decorView)))
|
||||||
|
.check(matches(isDisplayed()))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -11,14 +11,26 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="GoogleAppIndexingWarning">
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
<activity android:name=".DriverActivity">
|
|
||||||
|
<activity android:name=".view.LoginActivity" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".view.NewBoardActivity"
|
||||||
|
android:label="@string/title_activity_new_board"
|
||||||
|
android:theme="@style/AppTheme.NoActionBar" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".view.BoardsListsActivity"
|
||||||
|
android:theme="@style/AppTheme.NoActionBar">
|
||||||
<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>
|
||||||
|
|
||||||
<activity android:name=".view.BoardViewActivity"
|
<activity android:name=".view.BoardViewActivity"
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||||
<activity android:name=".view.WListsListActivity"
|
<activity android:name=".view.WListsListActivity"
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
package it.unisannio.ding.ids.wedroid.app;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import it.unisannio.ding.ids.wedroid.app.util.SharedPreferenceHelper;
|
|
||||||
import it.unisannio.ding.ids.wedroid.app.view.BoardViewActivity;
|
|
||||||
|
|
||||||
public class DriverActivity extends AppCompatActivity {
|
|
||||||
|
|
||||||
SharedPreferenceHelper sharedPreferences;
|
|
||||||
EditText idBoard;
|
|
||||||
Button send;
|
|
||||||
|
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_main);
|
|
||||||
sharedPreferences = new SharedPreferenceHelper(this);
|
|
||||||
|
|
||||||
String baseUrl = sharedPreferences.getBaseUrl();
|
|
||||||
String token = sharedPreferences.getToken();
|
|
||||||
String userId = sharedPreferences.getUserId();
|
|
||||||
|
|
||||||
sharedPreferences.setBaseUrl("https://board.norangeb.it/");
|
|
||||||
sharedPreferences.setToken("4waGrVlk0fkLhiQRDgN_rkbIamp4IyB6mThS0IpKbPx");
|
|
||||||
sharedPreferences.setUserId("jPdkf3a9bmfZWx3GR");
|
|
||||||
|
|
||||||
idBoard = findViewById(R.id.idBoard);
|
|
||||||
|
|
||||||
send= findViewById(R.id.send);
|
|
||||||
send.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
Intent i = new Intent(getApplicationContext(), BoardViewActivity.class);
|
|
||||||
i.putExtra("idBoard", idBoard.getText().toString());
|
|
||||||
startActivity(i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package it.unisannio.ding.ids.wedroid.app
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import android.os.Bundle
|
|
||||||
import it.unisannio.ding.ids.wedroid.wrapper.api.BoardService
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
val service : BoardService? = null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,21 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.data.dao
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface BoardDao {
|
||||||
|
@Query("SELECT * from board_table ORDER BY title ASC")
|
||||||
|
fun getAllBoard(): LiveData<List<Board>>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(board: Board)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(board: Board)
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.data.database;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.room.Database;
|
||||||
|
import androidx.room.Room;
|
||||||
|
import androidx.room.RoomDatabase;
|
||||||
|
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.dao.BoardDao;
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board;
|
||||||
|
|
||||||
|
@Database(entities = Board.class, version = 1, exportSchema = false)
|
||||||
|
public abstract class BoardDatabase extends RoomDatabase {
|
||||||
|
private static volatile BoardDatabase INSTANCE;
|
||||||
|
public abstract BoardDao boardDao();
|
||||||
|
|
||||||
|
public static BoardDatabase getDatabase(Context context) {
|
||||||
|
if (INSTANCE != null)
|
||||||
|
return INSTANCE;
|
||||||
|
synchronized (BoardDatabase.class) {
|
||||||
|
INSTANCE = Room.databaseBuilder(
|
||||||
|
context.getApplicationContext(),
|
||||||
|
BoardDatabase.class,
|
||||||
|
"board_database"
|
||||||
|
).build();
|
||||||
|
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.data.entity
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "board_table")
|
||||||
|
data class Board(
|
||||||
|
@PrimaryKey @ColumnInfo(name = "id") val id: String,
|
||||||
|
@ColumnInfo(name = "title") val title: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
fun it.unisannio.ding.ids.wedroid.wrapper.entity.Board.convert(): Board {
|
||||||
|
return Board(this.id, this.title)
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.data.repository
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.dao.BoardDao
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.convert
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.PreferenceReader
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.BoardService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardBackgroundColor
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardPermission
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardPrototype
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
|
class BoardRepository(
|
||||||
|
private val dao: BoardDao,
|
||||||
|
private val service: BoardService,
|
||||||
|
private val reader: PreferenceReader
|
||||||
|
) {
|
||||||
|
val allBoards by lazy {
|
||||||
|
dao.getAllBoard()
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
synchronize()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun synchronize() {
|
||||||
|
service.getBoardsFromUser(reader.userId)
|
||||||
|
.enqueue(object :
|
||||||
|
Callback<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>> {
|
||||||
|
override fun onFailure(
|
||||||
|
call: Call<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>,
|
||||||
|
t: Throwable
|
||||||
|
) = logNetworkError(t.message)
|
||||||
|
|
||||||
|
override fun onResponse(
|
||||||
|
call: Call<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>,
|
||||||
|
response: Response<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>
|
||||||
|
) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
synchronizeCallback(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun synchronizeCallback(
|
||||||
|
response: Response<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>
|
||||||
|
) {
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
logNetworkError("${response.code()} ${response.message()}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// read boards from the body
|
||||||
|
val boards = (response.body() ?: return)
|
||||||
|
.map { it.convert() }
|
||||||
|
|
||||||
|
addNewBoardToDb(boards)
|
||||||
|
|
||||||
|
removeOldBoardsFromDb(boards)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun insertBoard(title: String, isPrivate: Boolean, color: BoardBackgroundColor) {
|
||||||
|
val permission = if (isPrivate) BoardPermission.PRIVATE else BoardPermission.PUBLIC
|
||||||
|
|
||||||
|
service.newBoard(
|
||||||
|
BoardPrototype.Builder()
|
||||||
|
.setOwner(reader.userId)
|
||||||
|
.setTitle(title)
|
||||||
|
.setBackgroundColor(color)
|
||||||
|
.setBoardPermission(permission)
|
||||||
|
.build()
|
||||||
|
).enqueue(object : Callback<it.unisannio.ding.ids.wedroid.wrapper.entity.Board> {
|
||||||
|
override fun onFailure(
|
||||||
|
call: Call<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>,
|
||||||
|
t: Throwable
|
||||||
|
) = logNetworkError(t.message)
|
||||||
|
|
||||||
|
override fun onResponse(
|
||||||
|
call: Call<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>,
|
||||||
|
response: Response<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>
|
||||||
|
) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
insertBoardCallback(response, title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun insertBoardCallback(
|
||||||
|
response: Response<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>,
|
||||||
|
title: String
|
||||||
|
) {
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
logNetworkError("${response.code()} ${response.message()}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val board = response.body()
|
||||||
|
|
||||||
|
if (board == null) {
|
||||||
|
logNetworkError("empty body")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dao.insert(Board(board.id, title))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteBoard(id: String) {
|
||||||
|
service.deleteBoard(id).enqueue(
|
||||||
|
object : Callback<Void> {
|
||||||
|
override fun onFailure(call: Call<Void>, t: Throwable) {
|
||||||
|
logNetworkError(t.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(
|
||||||
|
call: Call<Void>,
|
||||||
|
response: Response<Void>
|
||||||
|
) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
deleteBoardCallback(response, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun deleteBoardCallback(
|
||||||
|
response: Response<Void>,
|
||||||
|
id: String
|
||||||
|
) {
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
logNetworkError("${response.code()} ${response.message()}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dao.delete(Board(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun addNewBoardToDb(boards: Collection<Board>) {
|
||||||
|
boards.forEach {
|
||||||
|
dao.insert(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun removeOldBoardsFromDb(boards: Collection<Board>) {
|
||||||
|
allBoards.value?.minus(boards)
|
||||||
|
?.forEach {
|
||||||
|
dao.delete(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logNetworkError(message: String?) {
|
||||||
|
Log.e("RETROFIT", message)
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,17 @@
|
|||||||
package it.unisannio.ding.ids.wedroid.app.util
|
package it.unisannio.ding.ids.wedroid.app.util
|
||||||
|
|
||||||
import it.unisannio.ding.ids.wedroid.wrapper.api.*
|
import it.unisannio.ding.ids.wedroid.wrapper.api.BoardService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.CardCommentService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.CardService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.ChecklistService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.ListService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.SwimlanesService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.UserService
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
|
||||||
class ServicesFactory(
|
class ServicesFactory(
|
||||||
reader: PreferenceReader
|
reader: PreferenceReader
|
||||||
) {
|
) {
|
||||||
@ -75,4 +82,3 @@ class ServicesFactory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@ package it.unisannio.ding.ids.wedroid.app.util
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
class SharedPreferenceHelper(context : Context) : PreferenceReader, PreferenceWriter {
|
class SharedPreferenceHelper(context: Context) : PreferenceReader, PreferenceWriter {
|
||||||
|
|
||||||
private val sp = context.getSharedPreferences("userinfo", Context.MODE_PRIVATE)
|
private val sp = context.getSharedPreferences("userinfo", Context.MODE_PRIVATE)
|
||||||
|
|
||||||
override fun getBaseUrl(): String? {
|
override fun getBaseUrl(): String? {
|
||||||
@ -20,8 +21,7 @@ class SharedPreferenceHelper(context : Context) : PreferenceReader, PreferenceWr
|
|||||||
override fun setBaseUrl(baseUrl: String?) {
|
override fun setBaseUrl(baseUrl: String?) {
|
||||||
val editor = sp.edit()
|
val editor = sp.edit()
|
||||||
editor.putString("url", baseUrl).apply()
|
editor.putString("url", baseUrl).apply()
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun setUserId(userId: String?) {
|
override fun setUserId(userId: String?) {
|
||||||
val editor = sp.edit()
|
val editor = sp.edit()
|
||||||
@ -41,4 +41,5 @@ class SharedPreferenceHelper(context : Context) : PreferenceReader, PreferenceWr
|
|||||||
val editor = sp.edit()
|
val editor = sp.edit()
|
||||||
editor.putString("boardId", token).apply()
|
editor.putString("boardId", token).apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,133 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.PreferenceReader
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.SharedPreferenceHelper
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.view.adapter.BoardsListAdapter
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.viewModel.BoardsListViewModel
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardBackgroundColor
|
||||||
|
|
||||||
|
import kotlinx.android.synthetic.main.activity_boards_lists.*
|
||||||
|
import kotlinx.android.synthetic.main.content_boards_lists.*
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
class BoardsListsActivity : AppCompatActivity() {
|
||||||
|
private lateinit var viewModel: BoardsListViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_boards_lists)
|
||||||
|
setSupportActionBar(toolbar)
|
||||||
|
val reader: PreferenceReader = SharedPreferenceHelper(this)
|
||||||
|
|
||||||
|
if (reader.token == "")
|
||||||
|
startActivityForResult(
|
||||||
|
Intent(this, LoginActivity::class.java),
|
||||||
|
LOGIN_CODE
|
||||||
|
)
|
||||||
|
else initializeUi()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeUi() {
|
||||||
|
viewModel = ViewModelProvider(this).get(BoardsListViewModel::class.java)
|
||||||
|
|
||||||
|
val adapter = BoardsListAdapter(this)
|
||||||
|
boardList.adapter = adapter
|
||||||
|
boardList.layoutManager = LinearLayoutManager(this)
|
||||||
|
|
||||||
|
viewModel.allBoards.observe(this, Observer {
|
||||||
|
it.let { adapter.setBoards(it) }
|
||||||
|
pullToRefresh.isRefreshing = false
|
||||||
|
})
|
||||||
|
|
||||||
|
swipeLeftToDelete()
|
||||||
|
|
||||||
|
fab.setOnClickListener {
|
||||||
|
startActivityForResult(
|
||||||
|
Intent(this, NewBoardActivity::class.java),
|
||||||
|
NEW_BOARD_CODE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pullToRefresh.setColorSchemeColors(getColor(R.color.colorAccent))
|
||||||
|
pullToRefresh.setOnRefreshListener {
|
||||||
|
viewModel.refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun swipeLeftToDelete() {
|
||||||
|
val swipeToDelete = ItemTouchHelper(
|
||||||
|
object : ItemTouchHelper.SimpleCallback(
|
||||||
|
0, ItemTouchHelper.LEFT
|
||||||
|
) {
|
||||||
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
target: RecyclerView.ViewHolder
|
||||||
|
): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||||
|
val pos = viewHolder.adapterPosition
|
||||||
|
viewModel.deleteBoard(pos)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
swipeToDelete.attachToRecyclerView(boardList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
when (requestCode) {
|
||||||
|
LOGIN_CODE -> onLoginResult(resultCode)
|
||||||
|
NEW_BOARD_CODE -> if (data != null) onAddBoardResult(resultCode, data)
|
||||||
|
else -> finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onLoginResult(resultCode: Int) {
|
||||||
|
when (resultCode) {
|
||||||
|
LoginActivity.LOGIN_OK -> initializeUi()
|
||||||
|
LoginActivity.LOGIN_ERROR -> finish()
|
||||||
|
else -> finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onAddBoardResult(resultCode: Int, data: Intent) {
|
||||||
|
if (resultCode != NewBoardActivity.RESULT_OK) {
|
||||||
|
Toast.makeText(this, R.string.on_add_new_board_error, Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val title = data.getStringExtra(NewBoardActivity.BOARD_NAME)
|
||||||
|
if (title == null) {
|
||||||
|
Toast.makeText(this, R.string.on_null_new_board_name, Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val isPrivate = data.getBooleanExtra(NewBoardActivity.BOARD_PRIVATE, true)
|
||||||
|
|
||||||
|
val colorName = data.getStringExtra(NewBoardActivity.BOARD_BACKGROUND_COLOR) ?: "belize"
|
||||||
|
val backgroundColor = BoardBackgroundColor
|
||||||
|
.valueOf(colorName.toUpperCase(Locale.ROOT))
|
||||||
|
|
||||||
|
viewModel.insertBoard(title, isPrivate, backgroundColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val NEW_BOARD_CODE = 17
|
||||||
|
const val LOGIN_CODE = 19
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.webkit.URLUtil
|
||||||
|
import android.widget.Toast
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.SharedPreferenceHelper
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.LoginService
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.UserPrototype
|
||||||
|
import kotlinx.android.synthetic.main.activity_login.*
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
lateinit var sph: SharedPreferenceHelper
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_login)
|
||||||
|
sph = SharedPreferenceHelper(this)
|
||||||
|
|
||||||
|
setResult(LOGIN_ERROR)
|
||||||
|
|
||||||
|
val id = sph.userId
|
||||||
|
val token = sph.token
|
||||||
|
val url = sph.baseUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loginButton(v: View) {
|
||||||
|
if (username.text.isBlank() || instanceServer.text.isBlank() || password.text.isBlank()) {
|
||||||
|
Toast.makeText(this, R.string.login_empty_field, Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val userNameText = username.text.toString()
|
||||||
|
val passwordText = password.text.toString()
|
||||||
|
val instanceServerText = instanceServer.text.toString()
|
||||||
|
|
||||||
|
if (!URLUtil.isValidUrl(instanceServerText)){
|
||||||
|
Toast.makeText(this, R.string.login_unformed_instance, Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val service = Retrofit.Builder()
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.baseUrl(instanceServerText)
|
||||||
|
.build()
|
||||||
|
.create(LoginService::class.java)
|
||||||
|
|
||||||
|
service.login(userNameText, passwordText).enqueue(object : Callback<UserPrototype> {
|
||||||
|
override fun onFailure(call: Call<UserPrototype>, t: Throwable) {
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
R.string.login_network_error,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call<UserPrototype>, response: Response<UserPrototype>) {
|
||||||
|
|
||||||
|
if (response.code() != 200) {
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
R.string.login_wrong_field,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val users = response.body()
|
||||||
|
sph.baseUrl = instanceServer.text.toString()
|
||||||
|
sph.token = users?.token
|
||||||
|
sph.userId = users?.id
|
||||||
|
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
R.string.login_success,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
|
||||||
|
setResult(LOGIN_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val LOGIN_OK = 0
|
||||||
|
const val LOGIN_ERROR = 1
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.Switch;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R;
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardBackgroundColor;
|
||||||
|
|
||||||
|
public class NewBoardActivity extends AppCompatActivity {
|
||||||
|
private EditText boardName;
|
||||||
|
private Switch isPrivate;
|
||||||
|
private Spinner colorPicker;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_new_board);
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
|
boardName = findViewById(R.id.newBoardName);
|
||||||
|
isPrivate = findViewById(R.id.newBoardPermission);
|
||||||
|
|
||||||
|
colorPicker = findViewById(R.id.newBoardColor);
|
||||||
|
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
|
||||||
|
this,
|
||||||
|
R.array.board_background_colors,
|
||||||
|
android.R.layout.simple_spinner_item
|
||||||
|
);
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
colorPicker.setAdapter(adapter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDone(View v) {
|
||||||
|
if (boardName.getText().toString().equals("")) {
|
||||||
|
Toast.makeText(this, R.string.on_add_new_board_empty_name, Toast.LENGTH_LONG)
|
||||||
|
.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Intent data = new Intent();
|
||||||
|
data.putExtra(BOARD_NAME, boardName.getText().toString());
|
||||||
|
data.putExtra(BOARD_PRIVATE, isPrivate.isChecked());
|
||||||
|
data.putExtra(BOARD_BACKGROUND_COLOR, colorPicker.getSelectedItem().toString());
|
||||||
|
setResult(RESULT_OK, data);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCancel(View v) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int RESULT_OK = 17;
|
||||||
|
public static final String BOARD_NAME = "BOARD_NAME";
|
||||||
|
public static final String BOARD_PRIVATE = "BOARD_PRIVATE";
|
||||||
|
public static final String BOARD_BACKGROUND_COLOR = "BOARD_BACKGROUND_COLOR";
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.view.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.R
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.view.BoardViewActivity
|
||||||
|
|
||||||
|
class BoardsListAdapter internal constructor(
|
||||||
|
context: Context
|
||||||
|
) : RecyclerView.Adapter<BoardsListAdapter.BoardViewHolder>() {
|
||||||
|
|
||||||
|
private val inflater = LayoutInflater.from(context)
|
||||||
|
private var boards = emptyList<Board>()
|
||||||
|
|
||||||
|
inner class BoardViewHolder(
|
||||||
|
view: View
|
||||||
|
) : RecyclerView.ViewHolder(view) {
|
||||||
|
val boardTitle: TextView = view.findViewById(R.id.boardTitle)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BoardViewHolder {
|
||||||
|
val view = inflater.inflate(R.layout.board_recycle_item, parent, false)
|
||||||
|
return BoardViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return boards.size
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: BoardViewHolder, position: Int) {
|
||||||
|
val board = boards[position]
|
||||||
|
holder.boardTitle.text = board.title
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener {
|
||||||
|
val intent = Intent(it.context, BoardViewActivity::class.java)
|
||||||
|
intent.putExtra("idBoard", board.id)
|
||||||
|
it.context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun setBoards(boards: List<Board>) {
|
||||||
|
this.boards = boards
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val BOARD_ID = "BOARD_ID"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.viewModel;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.database.BoardDatabase;
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board;
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.repository.BoardRepository;
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.PreferenceReader;
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.ServicesFactory;
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.SharedPreferenceHelper;
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardBackgroundColor;
|
||||||
|
|
||||||
|
public class BoardsListViewModel extends AndroidViewModel {
|
||||||
|
private BoardRepository repository;
|
||||||
|
private LiveData<List<Board>> allBoards;
|
||||||
|
|
||||||
|
public BoardsListViewModel(@NonNull Application application) {
|
||||||
|
super(application);
|
||||||
|
PreferenceReader reader = new SharedPreferenceHelper(application);
|
||||||
|
repository = new BoardRepository(
|
||||||
|
BoardDatabase.getDatabase(application).boardDao(),
|
||||||
|
ServicesFactory.Companion.getInstance(reader).getBoardService(),
|
||||||
|
reader
|
||||||
|
);
|
||||||
|
|
||||||
|
allBoards = repository.getAllBoards();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<List<Board>> getAllBoards() {
|
||||||
|
return allBoards;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertBoard(String title, boolean isPrivate, BoardBackgroundColor color) {
|
||||||
|
repository.insertBoard(title, isPrivate, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteBoard(int position) {
|
||||||
|
List<Board> boards = allBoards.getValue();
|
||||||
|
|
||||||
|
if (boards != null)
|
||||||
|
repository.deleteBoard(boards.get(position).getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
repository.synchronize();
|
||||||
|
}
|
||||||
|
}
|
9
app/src/main/res/drawable/ic_add_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_add_black_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
</vector>
|
33
app/src/main/res/layout/activity_boards_lists.xml
Normal file
33
app/src/main/res/layout/activity_boards_lists.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".view.BoardsListsActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/AppTheme.AppBarOverlay">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/content_boards_lists" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="@dimen/fab_margin"
|
||||||
|
app:srcCompat="@drawable/ic_add_black_24dp" />
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
56
app/src/main/res/layout/activity_login.xml
Normal file
56
app/src/main/res/layout/activity_login.xml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.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"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".view.LoginActivity">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/username"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="100dp"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="UserName"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/password"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/password"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="50dp"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="Password"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="200dp"
|
||||||
|
android:onClick="loginButton"
|
||||||
|
android:text="LOGIN"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/instanceServer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="50dp"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="Istance Server"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/username"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,40 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.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"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".MainActivity">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias="0.033"
|
|
||||||
tools:ignore="MissingConstraints"
|
|
||||||
tools:layout_editor_absoluteX="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="1dp"
|
|
||||||
android:text="Activity driver that passed id board" />
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/idBoard"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:ems="10"
|
|
||||||
android:inputType="textPersonName"
|
|
||||||
android:text="ID_BOARD" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/send"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Send" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
25
app/src/main/res/layout/activity_new_board.xml
Normal file
25
app/src/main/res/layout/activity_new_board.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".view.NewBoardActivity">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:theme="@style/AppTheme.AppBarOverlay">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<include layout="@layout/content_new_board" />
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
13
app/src/main/res/layout/board_recycle_item.xml
Normal file
13
app/src/main/res/layout/board_recycle_item.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/boardTitle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="@dimen/board_item_padding"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
29
app/src/main/res/layout/content_boards_lists.xml
Normal file
29
app/src/main/res/layout/content_boards_lists.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.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"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
tools:context=".view.BoardsListsActivity"
|
||||||
|
tools:showIn="@layout/activity_boards_lists">
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:id="@+id/pullToRefresh"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:id="@+id/boardList"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
72
app/src/main/res/layout/content_new_board.xml
Normal file
72
app/src/main/res/layout/content_new_board.xml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.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"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
|
tools:context=".view.NewBoardActivity"
|
||||||
|
tools:showIn="@layout/activity_new_board">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/newBoardName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="@string/new_board_name_field"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.20999998" />
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/newBoardPermission"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/new_board_switch"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/newBoardName"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/newBoardName"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/newBoardName"
|
||||||
|
app:layout_constraintVertical_bias="0.1" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/newBoardDone"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:onClick="onDone"
|
||||||
|
android:text="@string/new_board_done_button"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/newBoardPermission"
|
||||||
|
app:layout_constraintHorizontal_bias="1.0"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/newBoardColor"
|
||||||
|
app:layout_constraintVertical_bias="0.40" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/newBoardCancel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:onClick="onCancel"
|
||||||
|
android:text="@string/new_board_cancel_button"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.0"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/newBoardPermission"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/newBoardColor"
|
||||||
|
app:layout_constraintVertical_bias="0.40" />
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/newBoardColor"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/newBoardPermission"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/newBoardPermission"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/newBoardPermission"
|
||||||
|
app:layout_constraintVertical_bias="0.120000005" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,4 +1,8 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
|
|
||||||
<dimen name="padding">10dp</dimen>
|
<dimen name="padding">10dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="board_item_padding">8dp</dimen>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -12,4 +12,34 @@
|
|||||||
<string name="add_card_button">Add Card</string>
|
<string name="add_card_button">Add Card</string>
|
||||||
<string name="enter_text_here">Enter text here...</string>
|
<string name="enter_text_here">Enter text here...</string>
|
||||||
<string name="enter_card_name">Enter card name</string>
|
<string name="enter_card_name">Enter card name</string>
|
||||||
|
<string name="title_activity_boards_lists">BoardsListActivity</string>
|
||||||
|
<string name="title_activity_new_board">NewBoardActivity</string>
|
||||||
|
<string name="new_board_name_field">Board name</string>
|
||||||
|
<string name="new_board_switch">Private</string>
|
||||||
|
<string name="new_board_cancel_button">Cancel</string>
|
||||||
|
<string name="new_board_done_button">Done</string>
|
||||||
|
<string name="on_null_new_board_name">There was a problem with the name of the new board</string>
|
||||||
|
<string name="on_add_new_board_error">It was not possible to add a new board</string>
|
||||||
|
<string name="on_add_new_board_empty_name">Name cannot be empty</string>
|
||||||
|
|
||||||
|
<string-array name="board_background_colors">
|
||||||
|
<item>Belize</item>
|
||||||
|
<item>Nephritis</item>
|
||||||
|
<item>Pomegranate</item>
|
||||||
|
<item>Pumpkin</item>
|
||||||
|
<item>Wisteria</item>
|
||||||
|
<item>Moderatepink</item>
|
||||||
|
<item>Strongcyan</item>
|
||||||
|
<item>Limegreen</item>
|
||||||
|
<item>Midnight</item>
|
||||||
|
<item>Dark</item>
|
||||||
|
<item>Relax</item>
|
||||||
|
<item>Corteza</item>
|
||||||
|
</string-array>
|
||||||
|
<string name="login_empty_field">Riempire tutti i campi</string>
|
||||||
|
<string name="login_unformed_instance">Formato URL non valido</string>
|
||||||
|
<string name="login_network_error">Controlla la tua connessione internet</string>
|
||||||
|
<string name="login_wrong_field">Credenziali non corrette</string>
|
||||||
|
<string name="login_success">Login effettuato con successo</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
import kotlin.reflect.full.declaredFunctions
|
||||||
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
|
fun getPrivateFun(name: String, kClass: KClass<*>): KFunction<*>? {
|
||||||
|
return kClass.declaredFunctions
|
||||||
|
.find { it.name == name }
|
||||||
|
.also { it?.isAccessible = true }
|
||||||
|
}
|
@ -0,0 +1,318 @@
|
|||||||
|
package it.unisannio.ding.ids.wedroid.app.data.repository
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import io.mockk.*
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.dao.BoardDao
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.data.entity.Board
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.getPrivateFun
|
||||||
|
import it.unisannio.ding.ids.wedroid.app.util.PreferenceReader
|
||||||
|
import it.unisannio.ding.ids.wedroid.wrapper.api.BoardService
|
||||||
|
import junit.framework.TestCase.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import okhttp3.mockwebserver.MockWebServer
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import kotlin.reflect.full.callSuspend
|
||||||
|
|
||||||
|
class BoardRepositoryTest {
|
||||||
|
private val reader = mockk<PreferenceReader>()
|
||||||
|
private val webServer = MockWebServer()
|
||||||
|
private lateinit var service: BoardService
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
webServer.start()
|
||||||
|
service = Retrofit.Builder()
|
||||||
|
.baseUrl(webServer.url("/"))
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
.create(BoardService::class.java)
|
||||||
|
|
||||||
|
mockkStatic(Log::class)
|
||||||
|
every { reader.userId } returns "user id"
|
||||||
|
every { Log.e(any(), any()) } returns 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun teardown() {
|
||||||
|
webServer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun addNewBoardsToDb() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
var count = 0
|
||||||
|
|
||||||
|
coEvery {
|
||||||
|
dao.insert(any())
|
||||||
|
} answers {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
val addNewBoardToDb = getPrivateFun(
|
||||||
|
"addNewBoardToDb", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
val board0 = Board("id0", "title0")
|
||||||
|
val board1 = Board("id1", "title1")
|
||||||
|
val board2 = Board("id2", "title2")
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
addNewBoardToDb?.callSuspend(
|
||||||
|
repository,
|
||||||
|
listOf(board0, board1, board2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
coVerifyAll {
|
||||||
|
dao.insert(board0)
|
||||||
|
dao.insert(board1)
|
||||||
|
dao.insert(board2)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(3, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun insertBoardCallbackSuccess() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>()
|
||||||
|
val board = mockk<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns true
|
||||||
|
every { response.body() } returns board
|
||||||
|
every { board.id } returns "id"
|
||||||
|
coEvery { dao.insert(any()) } answers {}
|
||||||
|
|
||||||
|
val insertBoard = getPrivateFun(
|
||||||
|
"insertBoardCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
insertBoard?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response,
|
||||||
|
"title"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
coVerify { dao.insert(Board("id", "title")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun insertBoardCallbackEmptyBody() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns true
|
||||||
|
every { response.body() } returns null
|
||||||
|
|
||||||
|
val insertBoard = getPrivateFun(
|
||||||
|
"insertBoardCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
insertBoard?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response,
|
||||||
|
"title"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify { Log.e("RETROFIT", "empty body") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun insertBoardCallbackError() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns false
|
||||||
|
every { response.code() } returns 400
|
||||||
|
every { response.message() } returns "Error"
|
||||||
|
|
||||||
|
val insertBoard = getPrivateFun(
|
||||||
|
"insertBoardCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
insertBoard?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response,
|
||||||
|
"title"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify { Log.e("RETROFIT", "400 Error") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deleteBoardCallbackSuccess() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<Void>>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns true
|
||||||
|
coEvery { dao.delete(any()) } answers {}
|
||||||
|
|
||||||
|
val deleteBoard = getPrivateFun(
|
||||||
|
"deleteBoardCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
deleteBoard?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response,
|
||||||
|
"id"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
coVerify { dao.delete(Board("id")) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deleteBoardCallbackError() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<Void>>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns false
|
||||||
|
every { response.code() } returns 400
|
||||||
|
every { response.message() } returns "Error"
|
||||||
|
|
||||||
|
val deleteBoard = getPrivateFun(
|
||||||
|
"deleteBoardCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
deleteBoard?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response,
|
||||||
|
"id"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify { Log.e("RETROFIT", "400 Error") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun deleteOldBoardFromDb() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val dbBoards = mockk<LiveData<List<Board>>>()
|
||||||
|
|
||||||
|
val board0 = Board("id0", "title0")
|
||||||
|
val board1 = Board("id1", "title1")
|
||||||
|
val board2 = Board("id2", "title2")
|
||||||
|
val board3 = Board("id2", "title3")
|
||||||
|
|
||||||
|
every { dbBoards.value } returns listOf(
|
||||||
|
board0, board1, board2, board3
|
||||||
|
)
|
||||||
|
coEvery { dao.getAllBoard() } returns dbBoards
|
||||||
|
coEvery { dao.delete(any()) } answers {}
|
||||||
|
|
||||||
|
val removeOldBoards = getPrivateFun(
|
||||||
|
"removeOldBoardsFromDb", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
removeOldBoards?.callSuspend(
|
||||||
|
repository,
|
||||||
|
listOf(
|
||||||
|
board0, board1, board3
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
coVerify { dao.delete(board2) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun synchronizeCallbackError() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns false
|
||||||
|
every { response.code() } returns 400
|
||||||
|
every { response.message() } returns "Error"
|
||||||
|
|
||||||
|
val synchronize = getPrivateFun(
|
||||||
|
"synchronizeCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
synchronize?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify { Log.e("RETROFIT", "400 Error") }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun synchronizeCallbackEmptyBody() {
|
||||||
|
val dao = mockk<BoardDao>()
|
||||||
|
val response =
|
||||||
|
mockk<Response<MutableList<it.unisannio.ding.ids.wedroid.wrapper.entity.Board>>>()
|
||||||
|
|
||||||
|
every { response.isSuccessful } returns true
|
||||||
|
every { response.body() } returns null
|
||||||
|
|
||||||
|
val synchronize = getPrivateFun(
|
||||||
|
"synchronizeCallback", BoardRepository::class
|
||||||
|
)
|
||||||
|
|
||||||
|
val repository = BoardRepository(
|
||||||
|
dao, service, reader
|
||||||
|
)
|
||||||
|
|
||||||
|
runBlocking {
|
||||||
|
synchronize?.callSuspend(
|
||||||
|
repository,
|
||||||
|
response
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,21 +5,24 @@ buildscript {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.2.2"
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
apply plugin: 'checkstyle'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
241
config/checkstyle/checkstyle.xml
Normal file
241
config/checkstyle/checkstyle.xml
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module PUBLIC
|
||||||
|
"-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
|
||||||
|
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Checkstyle configuration that checks the Google coding conventions from Google Java Style
|
||||||
|
that can be found at https://google.github.io/styleguide/javaguide.html
|
||||||
|
|
||||||
|
Checkstyle is very configurable. Be sure to read the documentation at
|
||||||
|
http://checkstyle.sf.net (or in your downloaded distribution).
|
||||||
|
|
||||||
|
To completely disable a check, just comment it out or delete it from the file.
|
||||||
|
|
||||||
|
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<module name = "Checker">
|
||||||
|
<property name="charset" value="UTF-8"/>
|
||||||
|
|
||||||
|
<property name="severity" value="warning"/>
|
||||||
|
|
||||||
|
<property name="fileExtensions" value="java, properties, xml"/>
|
||||||
|
<!-- Excludes all 'module-info.java' files -->
|
||||||
|
<!-- See https://checkstyle.org/config_filefilters.html -->
|
||||||
|
<module name="BeforeExecutionExclusionFileFilter">
|
||||||
|
<property name="fileNamePattern" value="module\-info\.java$"/>
|
||||||
|
</module>
|
||||||
|
<!-- Checks for whitespace -->
|
||||||
|
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
|
||||||
|
<module name="FileTabCharacter">
|
||||||
|
<property name="eachLine" value="true"/>
|
||||||
|
</module>
|
||||||
|
|
||||||
|
<module name="TreeWalker">
|
||||||
|
<module name="OuterTypeFilename"/>
|
||||||
|
<module name="IllegalTokenText">
|
||||||
|
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
||||||
|
<property name="format"
|
||||||
|
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
||||||
|
<property name="message"
|
||||||
|
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
|
||||||
|
</module>
|
||||||
|
<module name="AvoidEscapedUnicodeCharacters">
|
||||||
|
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||||
|
<property name="allowByTailComment" value="true"/>
|
||||||
|
<property name="allowNonPrintableEscapes" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="AvoidStarImport"/>
|
||||||
|
<module name="OneTopLevelClass"/>
|
||||||
|
<module name="NoLineWrap"/>
|
||||||
|
<module name="EmptyBlock">
|
||||||
|
<property name="option" value="TEXT"/>
|
||||||
|
<property name="tokens"
|
||||||
|
value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
||||||
|
</module>
|
||||||
|
<module name="NeedBraces"/>
|
||||||
|
<module name="LeftCurly"/>
|
||||||
|
<module name="RightCurly">
|
||||||
|
<property name="id" value="RightCurlySame"/>
|
||||||
|
<property name="tokens"
|
||||||
|
value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
|
||||||
|
LITERAL_DO"/>
|
||||||
|
</module>
|
||||||
|
<module name="RightCurly">
|
||||||
|
<property name="id" value="RightCurlyAlone"/>
|
||||||
|
<property name="option" value="alone"/>
|
||||||
|
<property name="tokens"
|
||||||
|
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
|
||||||
|
INSTANCE_INIT"/>
|
||||||
|
</module>
|
||||||
|
<module name="WhitespaceAround">
|
||||||
|
<property name="allowEmptyConstructors" value="true"/>
|
||||||
|
<property name="allowEmptyLambdas" value="true"/>
|
||||||
|
<property name="allowEmptyMethods" value="true"/>
|
||||||
|
<property name="allowEmptyTypes" value="true"/>
|
||||||
|
<property name="allowEmptyLoops" value="true"/>
|
||||||
|
<message key="ws.notFollowed"
|
||||||
|
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
|
||||||
|
<message key="ws.notPreceded"
|
||||||
|
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
|
||||||
|
</module>
|
||||||
|
<module name="OneStatementPerLine"/>
|
||||||
|
<module name="MultipleVariableDeclarations"/>
|
||||||
|
<module name="ArrayTypeStyle"/>
|
||||||
|
<module name="MissingSwitchDefault"/>
|
||||||
|
<module name="FallThrough"/>
|
||||||
|
<module name="UpperEll"/>
|
||||||
|
<module name="ModifierOrder"/>
|
||||||
|
<module name="EmptyLineSeparator">
|
||||||
|
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<property name="id" value="SeparatorWrapDot"/>
|
||||||
|
<property name="tokens" value="DOT"/>
|
||||||
|
<property name="option" value="nl"/>
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<property name="id" value="SeparatorWrapComma"/>
|
||||||
|
<property name="tokens" value="COMMA"/>
|
||||||
|
<property name="option" value="EOL"/>
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
|
||||||
|
<property name="id" value="SeparatorWrapEllipsis"/>
|
||||||
|
<property name="tokens" value="ELLIPSIS"/>
|
||||||
|
<property name="option" value="EOL"/>
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
|
||||||
|
<property name="id" value="SeparatorWrapArrayDeclarator"/>
|
||||||
|
<property name="tokens" value="ARRAY_DECLARATOR"/>
|
||||||
|
<property name="option" value="EOL"/>
|
||||||
|
</module>
|
||||||
|
<module name="SeparatorWrap">
|
||||||
|
<property name="id" value="SeparatorWrapMethodRef"/>
|
||||||
|
<property name="tokens" value="METHOD_REF"/>
|
||||||
|
<property name="option" value="nl"/>
|
||||||
|
</module>
|
||||||
|
<module name="PackageName">
|
||||||
|
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="TypeName">
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="MemberName">
|
||||||
|
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="ParameterName">
|
||||||
|
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="LambdaParameterName">
|
||||||
|
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Lambda parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="CatchParameterName">
|
||||||
|
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="LocalVariableName">
|
||||||
|
<property name="tokens" value="VARIABLE_DEF"/>
|
||||||
|
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="ClassTypeParameterName">
|
||||||
|
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="MethodTypeParameterName">
|
||||||
|
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="InterfaceTypeParameterName">
|
||||||
|
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="NoFinalizer"/>
|
||||||
|
<module name="GenericWhitespace">
|
||||||
|
<message key="ws.followed"
|
||||||
|
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
|
||||||
|
<message key="ws.preceded"
|
||||||
|
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
|
||||||
|
<message key="ws.illegalFollow"
|
||||||
|
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
|
||||||
|
<message key="ws.notPreceded"
|
||||||
|
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
|
||||||
|
</module>
|
||||||
|
<module name="Indentation">
|
||||||
|
<property name="basicOffset" value="4"/>
|
||||||
|
<property name="braceAdjustment" value="0"/>
|
||||||
|
<property name="caseIndent" value="4"/>
|
||||||
|
<property name="throwsIndent" value="4"/>
|
||||||
|
<property name="lineWrappingIndentation" value="4"/>
|
||||||
|
<property name="arrayInitIndent" value="4"/>
|
||||||
|
</module>
|
||||||
|
<module name="AbbreviationAsWordInName">
|
||||||
|
<property name="ignoreFinal" value="false"/>
|
||||||
|
<property name="allowedAbbreviationLength" value="1"/>
|
||||||
|
</module>
|
||||||
|
<module name="OverloadMethodsDeclarationOrder"/>
|
||||||
|
<module name="VariableDeclarationUsageDistance"/>
|
||||||
|
<module name="CustomImportOrder">
|
||||||
|
<property name="sortImportsInGroupAlphabetically" value="true"/>
|
||||||
|
<property name="separateLineBetweenGroups" value="true"/>
|
||||||
|
<property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE"/>
|
||||||
|
</module>
|
||||||
|
<module name="MethodParamPad"/>
|
||||||
|
<module name="NoWhitespaceBefore">
|
||||||
|
<property name="tokens"
|
||||||
|
value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
|
||||||
|
<property name="allowLineBreaks" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="ParenPad"/>
|
||||||
|
<module name="OperatorWrap">
|
||||||
|
<property name="option" value="eol"/>
|
||||||
|
<property name="tokens"
|
||||||
|
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
|
||||||
|
LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
|
||||||
|
</module>
|
||||||
|
<module name="AnnotationLocation">
|
||||||
|
<property name="id" value="AnnotationLocationMostCases"/>
|
||||||
|
<property name="tokens"
|
||||||
|
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
||||||
|
</module>
|
||||||
|
<module name="AnnotationLocation">
|
||||||
|
<property name="id" value="AnnotationLocationVariables"/>
|
||||||
|
<property name="tokens" value="VARIABLE_DEF"/>
|
||||||
|
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
||||||
|
</module>
|
||||||
|
<module name="AtclauseOrder">
|
||||||
|
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
||||||
|
<property name="target"
|
||||||
|
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
||||||
|
</module>
|
||||||
|
<module name="MethodName">
|
||||||
|
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
||||||
|
<message key="name.invalidPattern"
|
||||||
|
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
||||||
|
</module>
|
||||||
|
<module name="SingleLineJavadoc">
|
||||||
|
<property name="ignoreInlineTags" value="false"/>
|
||||||
|
</module>
|
||||||
|
<module name="EmptyCatchBlock">
|
||||||
|
<property name="exceptionVariableName" value="expected"/>
|
||||||
|
</module>
|
||||||
|
<module name="CommentsIndentation"/>
|
||||||
|
</module>
|
||||||
|
</module>
|
580
config/detekt/detekt.yml
Normal file
580
config/detekt/detekt.yml
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
build:
|
||||||
|
maxIssues: 10
|
||||||
|
weights:
|
||||||
|
# complexity: 2
|
||||||
|
# LongParameterList: 1
|
||||||
|
# style: 1
|
||||||
|
# comments: 1
|
||||||
|
|
||||||
|
config:
|
||||||
|
validation: true
|
||||||
|
# when writing own rules with new properties, exclude the property path e.g.: "my_rule_set,.*>.*>[my_property]"
|
||||||
|
excludes: ""
|
||||||
|
|
||||||
|
processors:
|
||||||
|
active: true
|
||||||
|
exclude:
|
||||||
|
# - 'DetektProgressListener'
|
||||||
|
# - 'FunctionCountProcessor'
|
||||||
|
# - 'PropertyCountProcessor'
|
||||||
|
# - 'ClassCountProcessor'
|
||||||
|
# - 'PackageCountProcessor'
|
||||||
|
# - 'KtFileCountProcessor'
|
||||||
|
|
||||||
|
console-reports:
|
||||||
|
active: true
|
||||||
|
exclude:
|
||||||
|
# - 'ProjectStatisticsReport'
|
||||||
|
# - 'ComplexityReport'
|
||||||
|
# - 'NotificationReport'
|
||||||
|
# - 'FindingsReport'
|
||||||
|
- 'FileBasedFindingsReport'
|
||||||
|
# - 'BuildFailureReport'
|
||||||
|
|
||||||
|
comments:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
CommentOverPrivateFunction:
|
||||||
|
active: false
|
||||||
|
CommentOverPrivateProperty:
|
||||||
|
active: false
|
||||||
|
EndOfSentenceFormat:
|
||||||
|
active: false
|
||||||
|
endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!:]$)
|
||||||
|
UndocumentedPublicClass:
|
||||||
|
active: false
|
||||||
|
searchInNestedClass: true
|
||||||
|
searchInInnerClass: true
|
||||||
|
searchInInnerObject: true
|
||||||
|
searchInInnerInterface: true
|
||||||
|
UndocumentedPublicFunction:
|
||||||
|
active: false
|
||||||
|
UndocumentedPublicProperty:
|
||||||
|
active: false
|
||||||
|
|
||||||
|
complexity:
|
||||||
|
active: true
|
||||||
|
ComplexCondition:
|
||||||
|
active: true
|
||||||
|
threshold: 4
|
||||||
|
ComplexInterface:
|
||||||
|
active: false
|
||||||
|
threshold: 10
|
||||||
|
includeStaticDeclarations: false
|
||||||
|
ComplexMethod:
|
||||||
|
active: true
|
||||||
|
threshold: 15
|
||||||
|
ignoreSingleWhenExpression: false
|
||||||
|
ignoreSimpleWhenEntries: false
|
||||||
|
ignoreNestingFunctions: false
|
||||||
|
nestingFunctions: run,let,apply,with,also,use,forEach,isNotNull,ifNull
|
||||||
|
LabeledExpression:
|
||||||
|
active: false
|
||||||
|
ignoredLabels: ""
|
||||||
|
LargeClass:
|
||||||
|
active: true
|
||||||
|
threshold: 600
|
||||||
|
LongMethod:
|
||||||
|
active: true
|
||||||
|
threshold: 60
|
||||||
|
LongParameterList:
|
||||||
|
active: true
|
||||||
|
threshold: 6
|
||||||
|
ignoreDefaultParameters: false
|
||||||
|
MethodOverloading:
|
||||||
|
active: false
|
||||||
|
threshold: 6
|
||||||
|
NestedBlockDepth:
|
||||||
|
active: true
|
||||||
|
threshold: 4
|
||||||
|
StringLiteralDuplication:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
threshold: 3
|
||||||
|
ignoreAnnotation: true
|
||||||
|
excludeStringsWithLessThan5Characters: true
|
||||||
|
ignoreStringsRegex: '$^'
|
||||||
|
TooManyFunctions:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
thresholdInFiles: 11
|
||||||
|
thresholdInClasses: 11
|
||||||
|
thresholdInInterfaces: 11
|
||||||
|
thresholdInObjects: 11
|
||||||
|
thresholdInEnums: 11
|
||||||
|
ignoreDeprecated: false
|
||||||
|
ignorePrivate: false
|
||||||
|
ignoreOverridden: false
|
||||||
|
|
||||||
|
empty-blocks:
|
||||||
|
active: true
|
||||||
|
EmptyCatchBlock:
|
||||||
|
active: true
|
||||||
|
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
||||||
|
EmptyClassBlock:
|
||||||
|
active: true
|
||||||
|
EmptyDefaultConstructor:
|
||||||
|
active: true
|
||||||
|
EmptyDoWhileBlock:
|
||||||
|
active: true
|
||||||
|
EmptyElseBlock:
|
||||||
|
active: true
|
||||||
|
EmptyFinallyBlock:
|
||||||
|
active: true
|
||||||
|
EmptyForBlock:
|
||||||
|
active: true
|
||||||
|
EmptyFunctionBlock:
|
||||||
|
active: true
|
||||||
|
ignoreOverriddenFunctions: false
|
||||||
|
EmptyIfBlock:
|
||||||
|
active: true
|
||||||
|
EmptyInitBlock:
|
||||||
|
active: true
|
||||||
|
EmptyKtFile:
|
||||||
|
active: true
|
||||||
|
EmptySecondaryConstructor:
|
||||||
|
active: true
|
||||||
|
EmptyWhenBlock:
|
||||||
|
active: true
|
||||||
|
EmptyWhileBlock:
|
||||||
|
active: true
|
||||||
|
|
||||||
|
exceptions:
|
||||||
|
active: true
|
||||||
|
ExceptionRaisedInUnexpectedLocation:
|
||||||
|
active: false
|
||||||
|
methodNames: 'toString,hashCode,equals,finalize'
|
||||||
|
InstanceOfCheckForException:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
NotImplementedDeclaration:
|
||||||
|
active: false
|
||||||
|
PrintStackTrace:
|
||||||
|
active: false
|
||||||
|
RethrowCaughtException:
|
||||||
|
active: false
|
||||||
|
ReturnFromFinally:
|
||||||
|
active: false
|
||||||
|
ignoreLabeled: false
|
||||||
|
SwallowedException:
|
||||||
|
active: false
|
||||||
|
ignoredExceptionTypes: 'InterruptedException,NumberFormatException,ParseException,MalformedURLException'
|
||||||
|
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
||||||
|
ThrowingExceptionFromFinally:
|
||||||
|
active: false
|
||||||
|
ThrowingExceptionInMain:
|
||||||
|
active: false
|
||||||
|
ThrowingExceptionsWithoutMessageOrCause:
|
||||||
|
active: false
|
||||||
|
exceptions: 'IllegalArgumentException,IllegalStateException,IOException'
|
||||||
|
ThrowingNewInstanceOfSameException:
|
||||||
|
active: false
|
||||||
|
TooGenericExceptionCaught:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
exceptionNames:
|
||||||
|
- ArrayIndexOutOfBoundsException
|
||||||
|
- Error
|
||||||
|
- Exception
|
||||||
|
- IllegalMonitorStateException
|
||||||
|
- NullPointerException
|
||||||
|
- IndexOutOfBoundsException
|
||||||
|
- RuntimeException
|
||||||
|
- Throwable
|
||||||
|
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
||||||
|
TooGenericExceptionThrown:
|
||||||
|
active: true
|
||||||
|
exceptionNames:
|
||||||
|
- Error
|
||||||
|
- Exception
|
||||||
|
- Throwable
|
||||||
|
- RuntimeException
|
||||||
|
|
||||||
|
formatting:
|
||||||
|
active: true
|
||||||
|
android: true
|
||||||
|
autoCorrect: true
|
||||||
|
AnnotationOnSeparateLine:
|
||||||
|
active: false
|
||||||
|
autoCorrect: true
|
||||||
|
ChainWrapping:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
CommentSpacing:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
Filename:
|
||||||
|
active: true
|
||||||
|
FinalNewline:
|
||||||
|
active: false
|
||||||
|
autoCorrect: true
|
||||||
|
ImportOrdering:
|
||||||
|
active: false
|
||||||
|
autoCorrect: true
|
||||||
|
Indentation:
|
||||||
|
active: false
|
||||||
|
autoCorrect: true
|
||||||
|
indentSize: 4
|
||||||
|
continuationIndentSize: 4
|
||||||
|
MaximumLineLength:
|
||||||
|
active: true
|
||||||
|
maxLineLength: 120
|
||||||
|
ModifierOrdering:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
MultiLineIfElse:
|
||||||
|
active: false
|
||||||
|
autoCorrect: true
|
||||||
|
NoBlankLineBeforeRbrace:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoConsecutiveBlankLines:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoEmptyClassBody:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoLineBreakAfterElse:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoLineBreakBeforeAssignment:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoMultipleSpaces:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoSemicolons:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoTrailingSpaces:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoUnitReturn:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoUnusedImports:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
NoWildcardImports:
|
||||||
|
active: true
|
||||||
|
PackageName:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
ParameterListWrapping:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
indentSize: 4
|
||||||
|
SpacingAroundColon:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundComma:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundCurly:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundDot:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundKeyword:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundOperators:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundParens:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
SpacingAroundRangeOperator:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
StringTemplate:
|
||||||
|
active: true
|
||||||
|
autoCorrect: true
|
||||||
|
|
||||||
|
naming:
|
||||||
|
active: true
|
||||||
|
ClassNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
classPattern: '[A-Z$][a-zA-Z0-9$]*'
|
||||||
|
ConstructorParameterNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
parameterPattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
privateParameterPattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverridden: true
|
||||||
|
EnumNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
|
||||||
|
ForbiddenClassName:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
forbiddenName: ''
|
||||||
|
FunctionMaxLength:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
maximumFunctionNameLength: 30
|
||||||
|
FunctionMinLength:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
minimumFunctionNameLength: 3
|
||||||
|
FunctionNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverridden: true
|
||||||
|
FunctionParameterNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
parameterPattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverriddenFunctions: true
|
||||||
|
InvalidPackageDeclaration:
|
||||||
|
active: false
|
||||||
|
rootPackage: ''
|
||||||
|
MatchingDeclarationName:
|
||||||
|
active: true
|
||||||
|
MemberNameEqualsClassName:
|
||||||
|
active: true
|
||||||
|
ignoreOverriddenFunction: true
|
||||||
|
ObjectPropertyNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
PackageNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$'
|
||||||
|
TopLevelPropertyNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
constantPattern: '[A-Z][_A-Z0-9]*'
|
||||||
|
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
|
||||||
|
VariableMaxLength:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
maximumVariableNameLength: 64
|
||||||
|
VariableMinLength:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
minimumVariableNameLength: 1
|
||||||
|
VariableNaming:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
variablePattern: '[a-z][A-Za-z0-9]*'
|
||||||
|
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
|
||||||
|
excludeClassPattern: '$^'
|
||||||
|
ignoreOverridden: true
|
||||||
|
|
||||||
|
performance:
|
||||||
|
active: true
|
||||||
|
ArrayPrimitive:
|
||||||
|
active: true
|
||||||
|
ForEachOnRange:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
SpreadOperator:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
UnnecessaryTemporaryInstantiation:
|
||||||
|
active: true
|
||||||
|
|
||||||
|
potential-bugs:
|
||||||
|
active: true
|
||||||
|
Deprecation:
|
||||||
|
active: false
|
||||||
|
DuplicateCaseInWhenExpression:
|
||||||
|
active: true
|
||||||
|
EqualsAlwaysReturnsTrueOrFalse:
|
||||||
|
active: true
|
||||||
|
EqualsWithHashCodeExist:
|
||||||
|
active: true
|
||||||
|
ExplicitGarbageCollectionCall:
|
||||||
|
active: true
|
||||||
|
HasPlatformType:
|
||||||
|
active: false
|
||||||
|
ImplicitDefaultLocale:
|
||||||
|
active: false
|
||||||
|
InvalidRange:
|
||||||
|
active: true
|
||||||
|
IteratorHasNextCallsNextMethod:
|
||||||
|
active: true
|
||||||
|
IteratorNotThrowingNoSuchElementException:
|
||||||
|
active: true
|
||||||
|
LateinitUsage:
|
||||||
|
active: false
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
excludeAnnotatedProperties: ""
|
||||||
|
ignoreOnClassesPattern: ""
|
||||||
|
MissingWhenCase:
|
||||||
|
active: true
|
||||||
|
RedundantElseInWhen:
|
||||||
|
active: true
|
||||||
|
UnconditionalJumpStatementInLoop:
|
||||||
|
active: false
|
||||||
|
UnreachableCode:
|
||||||
|
active: true
|
||||||
|
UnsafeCallOnNullableType:
|
||||||
|
active: true
|
||||||
|
UnsafeCast:
|
||||||
|
active: false
|
||||||
|
UselessPostfixExpression:
|
||||||
|
active: false
|
||||||
|
WrongEqualsTypeParameter:
|
||||||
|
active: true
|
||||||
|
|
||||||
|
style:
|
||||||
|
active: true
|
||||||
|
CollapsibleIfStatements:
|
||||||
|
active: false
|
||||||
|
DataClassContainsFunctions:
|
||||||
|
active: false
|
||||||
|
conversionFunctionPrefix: 'to'
|
||||||
|
DataClassShouldBeImmutable:
|
||||||
|
active: false
|
||||||
|
EqualsNullCall:
|
||||||
|
active: true
|
||||||
|
EqualsOnSignatureLine:
|
||||||
|
active: false
|
||||||
|
ExplicitItLambdaParameter:
|
||||||
|
active: false
|
||||||
|
ExpressionBodySyntax:
|
||||||
|
active: false
|
||||||
|
includeLineWrapping: false
|
||||||
|
ForbiddenComment:
|
||||||
|
active: true
|
||||||
|
values: 'TODO:,FIXME:,STOPSHIP:'
|
||||||
|
allowedPatterns: ""
|
||||||
|
ForbiddenImport:
|
||||||
|
active: false
|
||||||
|
imports: ''
|
||||||
|
forbiddenPatterns: ""
|
||||||
|
ForbiddenVoid:
|
||||||
|
active: false
|
||||||
|
ignoreOverridden: false
|
||||||
|
ignoreUsageInGenerics: false
|
||||||
|
FunctionOnlyReturningConstant:
|
||||||
|
active: true
|
||||||
|
ignoreOverridableFunction: true
|
||||||
|
excludedFunctions: 'describeContents'
|
||||||
|
excludeAnnotatedFunction: "dagger.Provides"
|
||||||
|
LibraryCodeMustSpecifyReturnType:
|
||||||
|
active: true
|
||||||
|
LoopWithTooManyJumpStatements:
|
||||||
|
active: true
|
||||||
|
maxJumpCount: 1
|
||||||
|
MagicNumber:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
ignoreNumbers: '-1,0,1,2'
|
||||||
|
ignoreHashCodeFunction: true
|
||||||
|
ignorePropertyDeclaration: false
|
||||||
|
ignoreLocalVariableDeclaration: false
|
||||||
|
ignoreConstantDeclaration: true
|
||||||
|
ignoreCompanionObjectPropertyDeclaration: true
|
||||||
|
ignoreAnnotation: false
|
||||||
|
ignoreNamedArgument: true
|
||||||
|
ignoreEnums: false
|
||||||
|
ignoreRanges: false
|
||||||
|
MandatoryBracesIfStatements:
|
||||||
|
active: false
|
||||||
|
MaxLineLength:
|
||||||
|
active: true
|
||||||
|
maxLineLength: 120
|
||||||
|
excludePackageStatements: true
|
||||||
|
excludeImportStatements: true
|
||||||
|
excludeCommentStatements: false
|
||||||
|
MayBeConst:
|
||||||
|
active: true
|
||||||
|
ModifierOrder:
|
||||||
|
active: true
|
||||||
|
NestedClassesVisibility:
|
||||||
|
active: false
|
||||||
|
NewLineAtEndOfFile:
|
||||||
|
active: true
|
||||||
|
NoTabs:
|
||||||
|
active: false
|
||||||
|
OptionalAbstractKeyword:
|
||||||
|
active: true
|
||||||
|
OptionalUnit:
|
||||||
|
active: false
|
||||||
|
OptionalWhenBraces:
|
||||||
|
active: false
|
||||||
|
PreferToOverPairSyntax:
|
||||||
|
active: false
|
||||||
|
ProtectedMemberInFinalClass:
|
||||||
|
active: true
|
||||||
|
RedundantExplicitType:
|
||||||
|
active: false
|
||||||
|
RedundantVisibilityModifierRule:
|
||||||
|
active: false
|
||||||
|
ReturnCount:
|
||||||
|
active: true
|
||||||
|
max: 2
|
||||||
|
excludedFunctions: "equals"
|
||||||
|
excludeLabeled: false
|
||||||
|
excludeReturnFromLambda: true
|
||||||
|
excludeGuardClauses: false
|
||||||
|
SafeCast:
|
||||||
|
active: true
|
||||||
|
SerialVersionUIDInSerializableClass:
|
||||||
|
active: false
|
||||||
|
SpacingBetweenPackageAndImports:
|
||||||
|
active: false
|
||||||
|
ThrowsCount:
|
||||||
|
active: true
|
||||||
|
max: 2
|
||||||
|
TrailingWhitespace:
|
||||||
|
active: false
|
||||||
|
UnderscoresInNumericLiterals:
|
||||||
|
active: false
|
||||||
|
acceptableDecimalLength: 5
|
||||||
|
UnnecessaryAbstractClass:
|
||||||
|
active: true
|
||||||
|
excludeAnnotatedClasses: "dagger.Module"
|
||||||
|
UnnecessaryApply:
|
||||||
|
active: false
|
||||||
|
UnnecessaryInheritance:
|
||||||
|
active: true
|
||||||
|
UnnecessaryLet:
|
||||||
|
active: false
|
||||||
|
UnnecessaryParentheses:
|
||||||
|
active: false
|
||||||
|
UntilInsteadOfRangeTo:
|
||||||
|
active: false
|
||||||
|
UnusedImports:
|
||||||
|
active: false
|
||||||
|
UnusedPrivateClass:
|
||||||
|
active: true
|
||||||
|
UnusedPrivateMember:
|
||||||
|
active: false
|
||||||
|
allowedNames: "(_|ignored|expected|serialVersionUID)"
|
||||||
|
UseArrayLiteralsInAnnotations:
|
||||||
|
active: false
|
||||||
|
UseCheckOrError:
|
||||||
|
active: false
|
||||||
|
UseDataClass:
|
||||||
|
active: false
|
||||||
|
excludeAnnotatedClasses: ""
|
||||||
|
allowVars: false
|
||||||
|
UseIfInsteadOfWhen:
|
||||||
|
active: false
|
||||||
|
UseRequire:
|
||||||
|
active: false
|
||||||
|
UselessCallOnNotNull:
|
||||||
|
active: true
|
||||||
|
UtilityClassWithPublicConstructor:
|
||||||
|
active: true
|
||||||
|
VarCouldBeVal:
|
||||||
|
active: false
|
||||||
|
WildcardImport:
|
||||||
|
active: true
|
||||||
|
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||||
|
excludeImports: 'java.util.*,kotlinx.android.synthetic.*'
|
@ -10,7 +10,7 @@ public enum BoardBackgroundColor {
|
|||||||
@SerializedName("pomegranate")
|
@SerializedName("pomegranate")
|
||||||
POMEGRANATE,
|
POMEGRANATE,
|
||||||
@SerializedName("pumpkin")
|
@SerializedName("pumpkin")
|
||||||
PUMPIK,
|
PUMPKIN,
|
||||||
@SerializedName("wisteria")
|
@SerializedName("wisteria")
|
||||||
WISTERIA,
|
WISTERIA,
|
||||||
@SerializedName("moderatepink")
|
@SerializedName("moderatepink")
|
||||||
|
Loading…
Reference in New Issue
Block a user