diff --git a/.travis.yml b/.travis.yml
index 909f1c69..94978353 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,9 +11,8 @@ cache:
- $HOME/.gradle/native #Cache library downloaded from the gradle dependency
env:
global:
- - ANDROID_API=27
- - EMULATOR_API=26
- - ANDROID_BUILD_TOOLS=27.0.3
+ - ANDROID_API=28
+ - ANDROID_BUILD_TOOLS=28.0.2
- ADB_INSTALL_TIMEOUT=5
- secure: UH6Td9+MFk1nsYYMKN9t6/XcMmSZtB+L4sWMUmYBMaK1Q6YnGCnyHmU5RWkP+9a3AiZQ+n9XK+9TV+azMxJzyOoPMEzvBYtienvI1ZwTg+gqVOsMGG8TKubdgBfYQKm+mtdc3ctgucqjRg0yb4aUDp4CeNwwCuX1zuzIaAYp8IgRElkJzhJMeTcrCUWTBNk2F9ix0eRyOKOCIwgiAa6wNn1zMRvpbPh3esJ7CcnC0xesBtWriFtJDKFhPPWowPrWhGerLe3y5oNySqPpjxfBDIU9HPThNLNwBgp25Ww2c4Ib4Im0p59dPyKBU8mv3eoHvWtrSYW0bZQfKuJD6JsI0wg7Afx2hOxhPWw2evwjmhYWEfspSTUDUZIV/BhLhR2WbeZgAgd1gBh1ulxe79kne1FLsojVr+wZXA5Cn1TF2R4pnTj8EYLctbz/J1/sbcKwut6+I4z7FgbLDOEvaHTJZiscotR0ofML6OoYkKba8LznCES8RqYc3oyCKJvRD5oiVyHhMScAptMeignnPCGmhzm2evpclZfjoZ6vGyI/MgZML4as7WWz1FuiaNV+vJx6PyuNzBjYyNpKJ7O/G4yUT6EITrw3UPVCaSJr6eM3o8eAjy8XTkFsuRJ4iEhMAGiDRlvIlAMrUQyp8PxxvKB9YS6skFfAXXAUp59m/PLbRc0=
- secure: b9RwM5JGKpo0axCpeqDx9WZfZppiJWKF6d1zxTpO6cIiUmsgpL2GQy1fK/jHzKA1mlFIgq87pu11M696PqPJq7RadkeqlhKAq0zw8lBphg5Tn50wZUglusvIbMPC4VnsFLNeBd3elZIepglbh994sQxxpCpc8IF29x8cj//xrR6Z+EvyWYjnLgtbQjjdql6K0JRhGyTn+FXe5qLxmgu2lc4QL/RBcpnF+gpLrFfzBf/M/ruSyLjjpLZLCtzz90dAD/Ewb+sLvlfM0SUbXvFg+P2YoSo7rbDum+l45S6meIs6ygqcpb/3ByL9pSK3XEzrqLFQFggST8Puy8pHkwL8IVLuOtTPiO2HUtyzbTJLbEmupwEr6nXF2xtQE4vqgCNCLd63JxldRf3D2nrLG9OXJMlQRzkAfYtXj15tqyDfiLlCzIocfASsj/MF8XKzeR45+6GC9KLULpR0s1MdxYYhhb+Ss4sV8VElC3C4mlQiCA6G5AOJtPcnUshGNXbw3oWotJgY76IEJG2gSnb2SSI94VuXCI/39DLxXoTF1knixdaFJOO2QvBU2b8eZKrU4w1+rUrSfIMnBdn27hdqs+uKYNuJIwtMMCcrFtZmZnKjXcBwjgQdm51gWuMiJN5S8xM8turo23jL2Cak7rXn8RUmLHbhu3Jpl8iQzQOPFm1zmkg=
@@ -24,31 +23,32 @@ android:
- platform-tools
- build-tools-$ANDROID_BUILD_TOOLS
- android-$ANDROID_API
- - android-$EMULATOR_API_LEVEL
- extra-google-m2repository
- extra-android-m2repository
- addon-google_apis-google-19
- sys-img-armeabi-v7a-addon-google_apis-google-$ANDROID_API_LEVEL
- - sys-img-armeabi-v7a-addon-google_apis-google-$EMULATOR_API_LEVEL
licenses:
- android-sdk-preview-license-.+
- android-sdk-license-.+
- google-gdk-license-.+
+ - android-googletv-license-.+
before_install:
-- yes | sdkmanager "platforms;android-27"
+- yes | sdkmanager "platform-tools" "platforms;android-28"
- openssl aes-256-cbc -K $encrypted_c5c67234e863_key -iv $encrypted_c5c67234e863_iv
-in android/DartsScorecard/scripts/dsc_keystore.enc -out android/DartsScorecard/scripts/dsc_keystore
-d
- openssl aes-256-cbc -K $encrypted_60401f83f63b_key -iv $encrypted_60401f83f63b_iv -in android/DartsScorecard/app/google-services.json.enc -out android/DartsScorecard/app/google-services.json -d
- mkdir "$ANDROID_HOME/licenses" || true
-- echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license"
+- echo -e "\nd56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license"
- echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
+- echo -e "\n601085b94cd77f0b54ff86406957099ebe79c4d6" > "$ANDROID_HOME/licenses/android-googletv-license"
+- echo -e "\n33b6a2b64607f11b759f320ef9dff4ae5c47d97a" > "$ANDROID_HOME/licenses/google-gdk-license"
- cd android/DartsScorecard/
- chmod +x gradlew
- ./gradlew dependencies || true
script:
-- ./gradlew clean build checkDebug -PdisablePreDex --stacktrace
+- ./gradlew clean build -PdisablePreDex --stacktrace
after_success:
- ./gradlew jacocoFullReport coveralls
before_deploy:
@@ -59,6 +59,7 @@ before_deploy:
- ${ANDROID_HOME}/build-tools/${ANDROID_BUILD_TOOLS}/apksigner sign --ks $HOME/dsc_keystore
--ks-key-alias Entreco --ks-pass pass:$storepass --key-pass pass:$keypass --in _${APP_NAME} --out $APP_NAME
- ${ANDROID_HOME}/build-tools/${ANDROID_BUILD_TOOLS}/apksigner verify $APP_NAME
+
deploy:
provider: releases
file:
diff --git a/android/DartsScorecard/app/build.gradle b/android/DartsScorecard/app/build.gradle
index 0bdf919c..c324fcbc 100644
--- a/android/DartsScorecard/app/build.gradle
+++ b/android/DartsScorecard/app/build.gradle
@@ -1,18 +1,21 @@
apply plugin: 'com.android.application'
-apply plugin: 'io.fabric'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
+apply plugin: 'io.fabric'
apply plugin: 'com.getkeepsafe.dexcount'
-apply from: '../scripts/versioning.gradle'
apply from: '../scripts/coverage.gradle'
apply from: '../scripts/android_common.gradle'
+apply from: '../scripts/versioning.gradle'
android {
+
def config = rootProject.extensions.getByName("ext")
defaultConfig {
applicationId "nl.entreco.dartsscorecard"
resValue "string", "version", "${config.versionName}"
+
+ ndk {abiFilters "armeabi", "armeabi-v7a", "x86", "mips"}
}
buildTypes {
debug {
@@ -22,34 +25,48 @@ android {
shrinkResources true
}
}
- dataBinding {
- enabled = true
+
+ sourceSets.main {
+ jniLibs.srcDir 'libs'
+ jni.srcDirs = [] //disable automatic ndk-build call
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
+
+ implementation project(":shared")
implementation project(':domain')
implementation project(':data')
+
// Annotation Processing
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
kapt "android.arch.persistence.room:compiler:$room"
- kapt "com.github.bumptech.glide:compiler:$glide"
// Implementation
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "com.google.dagger:dagger:$daggerVersion"
- implementation "com.android.support:appcompat-v7:$support"
implementation "com.android.support:design:$support"
+ implementation "com.android.support:appcompat-v7:$support"
+ implementation "com.android.support:leanback-v17:$support"
implementation "com.android.support.constraint:constraint-layout:$constraint"
- implementation "com.google.firebase:firebase-ads:$firebase"
- implementation "com.google.firebase:firebase-firestore:$firebase"
- implementation "com.google.firebase:firebase-config:$firebase"
- implementation "android.arch.lifecycle:extensions:$architecture"
+ implementation "com.google.firebase:firebase-ads:$fbAds"
+ implementation "com.google.firebase:firebase-core:$fbCore"
+ implementation "com.google.firebase:firebase-firestore:$fbStore"
+ implementation "com.google.firebase:firebase-config:$fbConfig"
+ implementation "com.google.firebase:firebase-database:$fbDatabase"
implementation "android.arch.persistence.room:runtime:$room"
- implementation "com.github.yalantis:jellytoolbar:$jelly"
+ implementation "android.arch.lifecycle:extensions:$architecture"
+ implementation "com.google.code.gson:gson:$gson"
implementation "com.github.bumptech.glide:glide:$glide"
+ implementation "com.github.yalantis:jellytoolbar:$jelly"
implementation "de.hdodenhof:circleimageview:$circleImageView"
+ implementation "org.webrtc:google-webrtc:$webRtc"
+
implementation("com.crashlytics.sdk.android:crashlytics:$crash") {
transitive = true
}
diff --git a/android/DartsScorecard/app/google-services.json.enc b/android/DartsScorecard/app/google-services.json.enc
index 8ba3ff4d..5136a48f 100644
Binary files a/android/DartsScorecard/app/google-services.json.enc and b/android/DartsScorecard/app/google-services.json.enc differ
diff --git a/android/DartsScorecard/app/proguard-rules.pro b/android/DartsScorecard/app/proguard-rules.pro
index 72027cce..1708def0 100644
--- a/android/DartsScorecard/app/proguard-rules.pro
+++ b/android/DartsScorecard/app/proguard-rules.pro
@@ -20,18 +20,13 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile
--keepattributes Signature
+-keepattributes Signature,InnerClasses
# Crashlytics
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public class * extends java.lang.Exception
-# Google Play Services
--keep public class com.google.android.gms.* { public *; }
--dontwarn com.google.android.gms.**
--dontnote com.google.android.gms.**
-
# Okio
-dontwarn okio.**
-dontnote okio.**
@@ -49,3 +44,7 @@
**[] $VALUES;
public *;
}
+
+# WebRtc
+-keep class org.webrtc.** { *; }
+
diff --git a/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png b/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 35fcb234..00000000
Binary files a/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png
deleted file mode 100644
index 964fb6d0..00000000
Binary files a/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ
diff --git a/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png
deleted file mode 100644
index 00637107..00000000
Binary files a/android/DartsScorecard/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ
diff --git a/android/DartsScorecard/app/src/debug/res/values/keys.xml b/android/DartsScorecard/app/src/debug/res/values/keys.xml
index b12fbc00..c6dd737e 100644
--- a/android/DartsScorecard/app/src/debug/res/values/keys.xml
+++ b/android/DartsScorecard/app/src/debug/res/values/keys.xml
@@ -1,8 +1,8 @@
- ca-app-pub-3793327349392749~1846337901
- ca-app-pub-3940256099942544/6300978111
- ca-app-pub-3940256099942544/6300978111
- ca-app-pub-3940256099942544/1033173712
+ ca-app-pub-3793327349392749~1846337901
+ ca-app-pub-3940256099942544/6300978111
+ ca-app-pub-3940256099942544/6300978111
+ ca-app-pub-3940256099942544/1033173712
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/AndroidManifest.xml b/android/DartsScorecard/app/src/main/AndroidManifest.xml
index cb4fe281..b999295d 100644
--- a/android/DartsScorecard/app/src/main/AndroidManifest.xml
+++ b/android/DartsScorecard/app/src/main/AndroidManifest.xml
@@ -2,11 +2,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:name=".faq.WtfActivity"
+ android:parentActivityName=".launch.LaunchActivity"
+ android:windowSoftInputMode="stateHidden" />
@@ -59,6 +89,7 @@
android:windowSoftInputMode="adjustResize" />
+
+
+
+
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/DscLogger.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/AppLogger.kt
similarity index 86%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/DscLogger.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/AppLogger.kt
index 60509514..c5636ea4 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/DscLogger.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/AppLogger.kt
@@ -1,12 +1,12 @@
package nl.entreco.dartsscorecard
import android.util.Log
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
/**
* Created by Entreco on 27/11/2017.
*/
-internal class DscLogger(private val tag: String) : Logger {
+internal class AppLogger(private val tag: String) : Logger {
companion object {
private var ENABLED = BuildConfig.DEBUG
@@ -89,6 +89,8 @@ internal class DscLogger(private val tag: String) : Logger {
}
private fun withArgs(message: String, args: Array): String {
- return StringBuilder(message).append(SEPARATOR).apply { args.take(args.size - 1).forEach { append(it).append(SEPARATOR) }.apply { append(args.last()) } }.toString()
+ return StringBuilder(message).append(
+ SEPARATOR).apply { args.take(args.size - 1).forEach { append(it).append(
+ SEPARATOR) }.apply { append(args.last()) } }.toString()
}
}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ContextExt.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ContextExt.kt
new file mode 100644
index 00000000..fd9c292e
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ContextExt.kt
@@ -0,0 +1,25 @@
+package nl.entreco.dartsscorecard
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.provider.Settings
+import android.support.annotation.ColorRes
+import android.support.v4.content.ContextCompat
+
+fun Context.getColorCompat(@ColorRes color: Int) = ContextCompat.getColor(this, color)
+
+fun Context.startAppSettings() {
+ Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).run {
+ addCategory(Intent.CATEGORY_DEFAULT)
+ data = Uri.parse("package:$packageName")
+ startActivity(this)
+ }
+}
+
+fun Context.checkIsPermissionGranted(permission: String) =
+ ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
+
+fun Context.areAllPermissionsGranted(
+ vararg permission: String) = permission.all { checkIsPermissionGranted(it) }
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ad/AdViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ad/AdViewModel.kt
index 58767a37..f567efee 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ad/AdViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/ad/AdViewModel.kt
@@ -10,7 +10,7 @@ import nl.entreco.dartsscorecard.base.BaseViewModel
import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
import nl.entreco.domain.ad.FetchPurchasedItemsResponse
import nl.entreco.domain.ad.FetchPurchasedItemsUsecase
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.purchases.connect.ConnectToBillingUsecase
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/archive/ArchiveJobService.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/archive/ArchiveJobService.kt
index f15d0208..5a5ecc36 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/archive/ArchiveJobService.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/archive/ArchiveJobService.kt
@@ -27,7 +27,7 @@ class ArchiveJobService : JobService() {
}
private val app by lazy { application as App }
- private val component by lazy { app.appComponent.plus(ServiceModule()) }
+ private val component by lazy { app.appComponent.plus(ServiceModule(this)) }
private val archiveStatsUsecase by lazy { component.plus(ArchiveModule()).archive() }
private val isWorking = AtomicBoolean(false)
@@ -38,7 +38,7 @@ class ArchiveJobService : JobService() {
private val notif by lazy {
NotificationCompat.Builder(baseContext, CHANNEL_ID)
.setOngoing(true)
- .setContentTitle(getString(R.string.notif_title))
+ .setContentTitle(getString(R.string.archive_notif_title))
.setSmallIcon(R.drawable.ic_stat_name)
.setColor(Color.parseColor(NOTIF_COLOR))
.setBadgeIconType(R.mipmap.ic_launcher_foreground)
@@ -57,8 +57,8 @@ class ArchiveJobService : JobService() {
private fun registerChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- val name = getString(R.string.channel_name)
- val desc = getString(R.string.channel_description)
+ val name = getString(R.string.archive_channel_name)
+ val desc = getString(R.string.archive_channel_description)
val importance = NotificationManager.IMPORTANCE_LOW
val channel = NotificationChannel(CHANNEL_ID, name, importance)
channel.description = desc
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/BaseFragment.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/BaseFragment.kt
new file mode 100644
index 00000000..8b2f1762
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/BaseFragment.kt
@@ -0,0 +1,43 @@
+package nl.entreco.dartsscorecard.base
+
+import android.arch.lifecycle.ViewModel
+import android.arch.lifecycle.ViewModelProvider
+import android.arch.lifecycle.ViewModelProviders
+import android.support.annotation.StringRes
+import android.support.design.widget.BaseTransientBottomBar
+import android.support.design.widget.Snackbar
+import android.support.v4.app.Fragment
+import nl.entreco.dartsscorecard.App
+import nl.entreco.dartsscorecard.di.viewmodel.ViewModelComponent
+import nl.entreco.dartsscorecard.di.viewmodel.ViewModelModule
+
+abstract class BaseFragment : Fragment() {
+
+ inline fun componentProvider(
+ mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
+ crossinline provider: (ViewModelComponent) -> VM) = lazy(mode) {
+
+ val app = activity!!.application as App
+ val component = app.appComponent.plus(ViewModelModule(activity!!))
+ provider(component)
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ inline fun viewModelProvider(
+ mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
+ crossinline provider: () -> VM) = lazy(mode) {
+ ViewModelProviders.of(this, object : ViewModelProvider.Factory {
+ override fun create(aClass: Class) =
+ provider() as T1
+ }).get(VM::class.java)
+ }
+
+ fun showSnackbarMessage(@StringRes resId: Int, @BaseTransientBottomBar.Duration duration: Int) {
+ view?.let {
+ val snackbar = Snackbar.make(it, resId, duration)
+// val layout = snackbar.view as Snackbar.SnackbarLayout
+// layout.setBackgroundColor(context.getColorCompat(R.color.transparent_black))
+ snackbar.show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/DialogHelper.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/DialogHelper.kt
index f8c9e224..a4e4f27e 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/DialogHelper.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/DialogHelper.kt
@@ -1,14 +1,28 @@
package nl.entreco.dartsscorecard.base
+import android.content.ActivityNotFoundException
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.support.design.widget.TextInputEditText
import android.support.v7.app.AlertDialog
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.RatingBar
import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.di.play.Play01Scope
+import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
+import nl.entreco.domain.Analytics
import nl.entreco.domain.model.players.Team
+import nl.entreco.domain.repository.RatingPrefRepository
import javax.inject.Inject
+
/**
* Created by entreco on 20/02/2018.
*/
-class DialogHelper @Inject constructor(private val builder: AlertDialog.Builder) {
+class DialogHelper @Inject constructor(private val builder: AlertDialog.Builder, @ActivityScope private val ratingPrefRepository: RatingPrefRepository) {
fun revanche(previousIndex: Int, teams: Array, select: (Int) -> Unit) {
@@ -18,7 +32,8 @@ class DialogHelper @Inject constructor(private val builder: AlertDialog.Builder)
var selectedIndex = previousIndex
builder
.setTitle(R.string.select_starting_team)
- .setSingleChoiceItems(teams.map { it.toString() }.toTypedArray(), previousIndex) { _, which ->
+ .setSingleChoiceItems(teams.map { it.toString() }.toTypedArray(),
+ previousIndex) { _, which ->
selectedIndex = which
}
.setPositiveButton(android.R.string.ok) { dialog, _ ->
@@ -35,4 +50,68 @@ class DialogHelper @Inject constructor(private val builder: AlertDialog.Builder)
private fun onlyOneTeam(teams: Array) = teams.size == 1
private fun moreThanOneTeam(teams: Array) = teams.size > 1
+
+ fun showStreamDialog(done: (String) -> Unit, cancel: () -> Unit) {
+ val view = createCodeEditText()
+ val et = view.findViewById(R.id.enter)
+ et.maxLines = 1
+ et.inputType = InputType.TYPE_CLASS_NUMBER
+
+ builder
+ .setView(view)
+ .setPositiveButton(R.string.live_stream_connect) { dialog, _ ->
+ done(et.text.toString())
+ dialog.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { dialog, _ ->
+ cancel()
+ dialog.dismiss()
+ }
+ .create()
+ .show()
+ }
+
+ private fun createCodeEditText(): View {
+ return LayoutInflater.from(builder.context)
+ .inflate(R.layout.dialog_connect_stream, null, false)
+ }
+
+ fun showRatingDialog() {
+ builder
+ .setTitle(R.string.rating_title)
+ .setMessage(R.string.rating_message)
+ .setPositiveButton(android.R.string.ok) { dialog, _ ->
+ dialog.dismiss()
+ ratingPrefRepository.neverAskAgain()
+ tryLaunchMarket(builder.context)
+ }
+ .setNegativeButton(R.string.rating_not_now) { dialog, _ ->
+ dialog.dismiss()
+ }
+ .setNeutralButton(R.string.rating_never_ask_again) { dialog, _ ->
+ dialog.dismiss()
+ ratingPrefRepository.neverAskAgain()
+ }
+ .create()
+ .show()
+ }
+
+ private fun tryLaunchMarket(context: Context) {
+ val clean = context.packageName.removeSuffix(".dev")
+ val uri = Uri.parse("market://details?id=$clean")
+ val goToMarket = Intent(Intent.ACTION_VIEW, uri)
+ // To count with Play market backstack, After pressing back button,
+ // to taken back to our application, we need to add following flags to intent.
+ goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY or
+ Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
+ Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+ try {
+ context.startActivity(goToMarket)
+ } catch (e: ActivityNotFoundException) {
+ context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(
+ "http://play.google.com/store/apps/details?id=$clean")))
+ } catch (e: ActivityNotFoundException) {
+
+ }
+ }
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/PermissionHelper.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/PermissionHelper.kt
new file mode 100644
index 00000000..14ccb80d
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/PermissionHelper.kt
@@ -0,0 +1,61 @@
+package nl.entreco.dartsscorecard.base
+
+import android.Manifest
+import android.content.ActivityNotFoundException
+import android.content.Context
+import android.content.pm.PackageManager
+import android.support.design.widget.Snackbar
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.areAllPermissionsGranted
+import nl.entreco.dartsscorecard.di.streaming.StreamScope
+import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
+import nl.entreco.dartsscorecard.play.stream.StreamFragment
+import nl.entreco.dartsscorecard.startAppSettings
+import javax.inject.Inject
+
+class PermissionHelper @Inject constructor(
+ @ActivityScope private val context: Context,
+ @StreamScope private val streamFragment: StreamFragment
+) {
+
+ companion object {
+ internal const val CHECK_PERMISSIONS_AND_CONNECT_REQUEST_CODE = 1
+ private val NECESSARY_PERMISSIONS = arrayOf(Manifest.permission.CAMERA,
+ Manifest.permission.RECORD_AUDIO)
+ }
+
+ fun checkStreamingPermissionsAndConnect(done: () -> Unit) {
+ if (context.areAllPermissionsGranted(*NECESSARY_PERMISSIONS)) {
+ done()
+ } else {
+ streamFragment.requestPermissions(
+ arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO),
+ CHECK_PERMISSIONS_AND_CONNECT_REQUEST_CODE)
+ }
+ }
+
+ fun onStreamingPermissionResult(grantResults: IntArray, done: () -> Unit) {
+ val grantResult = grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }
+ if (grantResult) {
+ checkStreamingPermissionsAndConnect(done)
+ } else {
+ showNoPermissionsSnackbar()
+ }
+ }
+
+ private fun showNoPermissionsSnackbar() {
+ streamFragment.view?.let { view ->
+ Snackbar.make(view, R.string.msg_permissions, Snackbar.LENGTH_LONG)
+ .setAction(R.string.action_settings) {
+ try {
+ context.startAppSettings()
+ } catch (e: ActivityNotFoundException) {
+ streamFragment.showSnackbarMessage(
+ R.string.error_permissions_couldnt_start_settings,
+ Snackbar.LENGTH_LONG)
+ }
+ }
+ .show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt
index 941cb988..86fe1c8c 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/Styler.kt
@@ -11,24 +11,29 @@ import javax.inject.Inject
*/
class Styler @Inject constructor(private val prefs: SharedPreferences, private val activity: Activity) {
- enum class Style(@StyleRes val style: Int) {
- PDC_2018(R.style.Pdc_2018),
- BDO_2018(R.style.Bdo_2018),
- BDO(R.style.Bdo),
- PDC(R.style.Pdc);
+ enum class Style(val style: String) {
+ PDC_2018("Pdc_2018"),
+ BDO_2018("Bdo_2018"),
+ BDO("Bdo"),
+ PDC("Pdc");
}
fun get(): Int {
- return prefs.getInt("curStyle", Style.PDC_2018.style)
+ return when(prefs.getString("curStyle", Style.PDC_2018.style)){
+ Style.PDC_2018.style -> R.style.Pdc_2018
+ Style.BDO_2018.style -> R.style.Bdo_2018
+ Style.PDC.style -> R.style.Pdc
+ Style.BDO.style -> R.style.Bdo
+ else -> R.style.Pdc_2018
+ }
}
fun switch() {
- val curStyle = prefs.getInt("curStyle", Style.PDC_2018.style)
- prefs.edit().putInt("curStyle", swap(curStyle)).apply()
+ prefs.edit().putString("curStyle", swap(get())).apply()
activity.recreate()
}
- private fun swap(style: Int): Int {
+ private fun swap(style: Int): String {
return when (style) {
R.style.Pdc_2018 -> Style.BDO_2018.style
R.style.Bdo_2018 -> Style.PDC.style
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallback.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallback.kt
index 5e8b46a4..26f64b30 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallback.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallback.kt
@@ -22,10 +22,6 @@ abstract class SwipeToDeleteCallback(context: Context) : ItemTouchHelper.SimpleC
private val background = ColorDrawable()
private val backgroundColor = Color.parseColor("#D9534F") // Pale red
- override fun onMove(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?, target: RecyclerView.ViewHolder?): Boolean {
- return false
- }
-
override fun onChildDraw(canvas: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) {
val itemView = viewHolder.itemView
val itemHeight = itemView.bottom - itemView.top
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/ViewModelActivity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/ViewModelActivity.kt
index 44413956..b4aaf8ac 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/ViewModelActivity.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/base/ViewModelActivity.kt
@@ -14,7 +14,7 @@ import nl.entreco.dartsscorecard.App
import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.di.viewmodel.ViewModelComponent
import nl.entreco.dartsscorecard.di.viewmodel.ViewModelModule
-import nl.entreco.dartsscorecard.wtf.WtfActivity
+import nl.entreco.dartsscorecard.faq.WtfActivity
/**
* Created by Entreco on 14/11/2017.
@@ -28,7 +28,7 @@ abstract class ViewModelActivity : AppCompatActivity() {
@Suppress("UNCHECKED_CAST")
- inline fun ViewModelActivity.viewModelProvider(
+ inline fun viewModelProvider(
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
crossinline provider: () -> VM) = lazy(mode) {
ViewModelProviders.of(this, object : ViewModelProvider.Factory {
@@ -37,7 +37,7 @@ abstract class ViewModelActivity : AppCompatActivity() {
}).get(VM::class.java)
}
- inline fun ViewModelActivity.componentProvider(
+ inline fun componentProvider(
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.NONE,
crossinline provider: (ViewModelComponent) -> VM) = lazy(mode) {
val component = app.appComponent.plus(ViewModelModule(this))
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaActivity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaActivity.kt
index 945e6ff8..092eed29 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaActivity.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaActivity.kt
@@ -106,7 +106,6 @@ class BetaActivity : ViewModelActivity(), DonateCallback, BetaAnimator.Swapper {
recyclerView.setItemViewCacheSize(20)
recyclerView.layoutManager = GridLayoutManager(binding.root.context, 2)
recyclerView.itemAnimator = DefaultItemAnimator()
- recyclerView.isDrawingCacheEnabled = true
recyclerView.adapter = adapter
}
@@ -131,7 +130,8 @@ class BetaActivity : ViewModelActivity(), DonateCallback, BetaAnimator.Swapper {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when {
donateOk(requestCode, resultCode, data) -> donateViewModel.onMakeDonationSuccess(data)
- requestCode == REQ_CODE_DONATE -> donateViewModel.onMakeDonationFailed()
+ resultCode == Activity.RESULT_CANCELED -> donateViewModel.onMakeDonationFailed(true)
+ requestCode == REQ_CODE_DONATE -> donateViewModel.onMakeDonationFailed(false)
else -> super.onActivityResult(requestCode, resultCode, data)
}
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAdapter.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAdapter.kt
index 5e56eeed..74f1b4ae 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAdapter.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAdapter.kt
@@ -9,8 +9,8 @@ import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.base.TestableAdapter
import nl.entreco.dartsscorecard.databinding.BetaViewBinding
import nl.entreco.domain.beta.Feature
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import java.util.*
import javax.inject.Inject
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAnimator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAnimator.kt
index 985214bb..0c364cab 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAnimator.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaAnimator.kt
@@ -28,7 +28,7 @@ class BetaAnimator(binding: ActivityBetaBinding) {
}
init {
- appBar.addOnOffsetChangedListener { appBarLayout, verticalOffset -> animator.onOffsetChanged(appBarLayout, verticalOffset) }
+ appBar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, slideOffset -> animator.onOffsetChanged(appBarLayout, slideOffset) })
behaviour.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {
animator.onSlide(slideOffset)
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaBindings.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaBindings.kt
index d5b9ac33..729ec90c 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaBindings.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaBindings.kt
@@ -2,13 +2,12 @@ package nl.entreco.dartsscorecard.beta
import android.databinding.BindingAdapter
import android.net.Uri
-import android.os.Build
import android.text.Html
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.ImageView
import android.widget.TextView
-import nl.entreco.dartsscorecard.di.glide.GlideApp
+import nl.entreco.shared.libs.GlideApp
/**
* Created by entreco on 03/02/2018.
@@ -26,13 +25,13 @@ object BetaBindings {
}
}
-
@JvmStatic
@BindingAdapter("progress")
fun animateProgress(view: View, oldProgress: Float, progress: Float) {
view.pivotX = 0F
view.scaleX = oldProgress
- view.animate().scaleX(progress).setDuration(duration).setStartDelay(startDelay).setInterpolator(AccelerateDecelerateInterpolator()).start()
+ view.animate().scaleX(progress).setDuration(duration).setStartDelay(startDelay)
+ .setInterpolator(AccelerateDecelerateInterpolator()).start()
}
@Suppress("DEPRECATION")
@@ -40,11 +39,7 @@ object BetaBindings {
@BindingAdapter("textWithTags")
fun setTextWithTags(view: TextView, message: String?) {
if (message != null) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- view.text = Html.fromHtml(message, Html.FROM_HTML_MODE_COMPACT)
- } else {
- view.text = Html.fromHtml(message)
- }
+ view.text = Html.fromHtml(message, Html.FROM_HTML_MODE_COMPACT)
}
}
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaModel.kt
index edef2a9f..d0f5fe7a 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/BetaModel.kt
@@ -23,7 +23,7 @@ class BetaModel(val feature: Feature) {
private fun format(value: Int): String {
return when {
value < 1000 -> "$value"
- else -> "${value / 1000}k"
+ else -> "%.1f".format(value / 1000.0).removeSuffix(".0") + "k"
}
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModel.kt
index f075aa86..ace10c7f 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModel.kt
@@ -92,8 +92,8 @@ class DonateViewModel @Inject constructor(
private fun donationWithId(response: ConsumeDonationResponse) = donations.firstOrNull { it.sku == response.productId }
- fun onMakeDonationFailed() {
- analytics.trackPurchaseFailed(productId, "ActivityResult failed")
+ fun onMakeDonationFailed(cancelled: Boolean) {
+ analytics.trackPurchaseFailed(productId, if(cancelled) "Donation ActivityResult cancelled" else "Donation ActivityResult failed")
loading.set(false)
productId = ""
requiresConsumption.set(false)
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/application/AppModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/application/AppModule.kt
index f0fbcfaf..3bcaad5b 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/application/AppModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/application/AppModule.kt
@@ -1,20 +1,22 @@
package nl.entreco.dartsscorecard.di.application
import android.arch.persistence.room.Room
+import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import dagger.Module
import dagger.Provides
import nl.entreco.dartsscorecard.App
import nl.entreco.dartsscorecard.BuildConfig
-import nl.entreco.dartsscorecard.DscLogger
+import nl.entreco.dartsscorecard.AppLogger
import nl.entreco.data.analytics.FirebaseAnalytics
import nl.entreco.data.db.DscDatabase
import nl.entreco.domain.Analytics
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import javax.inject.Named
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings
import nl.entreco.dartsscorecard.R
+import java.util.*
/**
@@ -36,7 +38,7 @@ class AppModule(val app: App) {
@Provides
@ApplicationScope
fun provideLogger(): Logger {
- return DscLogger("Dsc")
+ return AppLogger("Dsc")
}
@Provides
@@ -53,6 +55,19 @@ class AppModule(val app: App) {
return FirebaseFirestore.getInstance()
}
+ @Provides
+ @ApplicationScope
+ fun provideFirebaseDatabase(): FirebaseDatabase {
+ return FirebaseDatabase.getInstance()
+ }
+
+ @Provides
+ @ApplicationScope
+ @Named("uuid")
+ fun provideUuid() : String {
+ return UUID.randomUUID().toString()
+ }
+
@Provides
@ApplicationScope
fun provideRemoteConfig(): FirebaseRemoteConfig {
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/archive/ArchiveModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/archive/ArchiveModule.kt
index 71148b80..46e90dcd 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/archive/ArchiveModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/archive/ArchiveModule.kt
@@ -5,7 +5,6 @@ import dagger.Provides
import nl.entreco.data.db.DscDatabase
import nl.entreco.data.db.profile.ArchiveServiceRepository
import nl.entreco.data.db.profile.ArchiveStatMapper
-import nl.entreco.domain.common.log.Logger
import nl.entreco.domain.repository.ArchiveRepository
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfComponent.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfComponent.kt
similarity index 55%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfComponent.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfComponent.kt
index b3a7698c..11c54b24 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfComponent.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfComponent.kt
@@ -1,8 +1,8 @@
-package nl.entreco.dartsscorecard.di.wtf
+package nl.entreco.dartsscorecard.di.faq
import dagger.Subcomponent
-import nl.entreco.dartsscorecard.wtf.WtfAdapter
-import nl.entreco.dartsscorecard.wtf.WtfViewModel
+import nl.entreco.dartsscorecard.faq.WtfAdapter
+import nl.entreco.dartsscorecard.faq.WtfViewModel
@WtfScope
@Subcomponent(modules = [(WtfModule::class)])
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfModule.kt
similarity index 52%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfModule.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfModule.kt
index 60db3918..85aed697 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfModule.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.di.wtf
+package nl.entreco.dartsscorecard.di.faq
import dagger.Module
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfScope.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfScope.kt
similarity index 70%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfScope.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfScope.kt
index 60b9eb56..bbb8e809 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/wtf/WtfScope.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/faq/WtfScope.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.di.wtf
+package nl.entreco.dartsscorecard.di.faq
import javax.inject.Scope
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Component.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Component.kt
index 491fd0a5..d670a443 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Component.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Component.kt
@@ -6,6 +6,7 @@ import nl.entreco.dartsscorecard.play.Play01ViewModel
import nl.entreco.dartsscorecard.play.input.InputViewModel
import nl.entreco.dartsscorecard.play.score.ScoreViewModel
import nl.entreco.dartsscorecard.play.live.LiveStatViewModel
+import nl.entreco.dartsscorecard.play.stream.ControlStreamViewModel
import nl.entreco.domain.play.finish.GetFinishUsecase
/**
@@ -17,6 +18,7 @@ interface Play01Component {
fun viewModel(): Play01ViewModel
fun navigator(): Play01Navigator
fun scoreViewModel(): ScoreViewModel
+ fun streamViewModel(): ControlStreamViewModel
fun inputViewModel(): InputViewModel
fun statViewModel(): LiveStatViewModel
fun finishUsecase(): GetFinishUsecase
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Module.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Module.kt
index c86da253..0a5b7296 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Module.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/play/Play01Module.kt
@@ -3,7 +3,6 @@ package nl.entreco.dartsscorecard.di.play
import android.content.ComponentName
import android.content.Context
import android.media.SoundPool
-import android.support.v7.app.AlertDialog
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import dagger.Module
import dagger.Provides
@@ -14,10 +13,12 @@ import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
import nl.entreco.dartsscorecard.play.Play01Activity
import nl.entreco.data.description.RemoteMatchDescriptionRepository
import nl.entreco.data.prefs.SharedAudioPrefRepo
+import nl.entreco.data.prefs.SharedRatingPrefRepo
import nl.entreco.data.sound.LocalSoundRepository
import nl.entreco.data.sound.SoundMapper
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.repository.MatchDescriptionRepository
+import nl.entreco.domain.repository.RatingPrefRepository
import nl.entreco.domain.repository.SoundRepository
/**
@@ -34,12 +35,6 @@ class Play01Module(private val activity: Play01Activity) {
return activity
}
- @Provides
- @Play01Scope
- fun provideAlertDialogBuilder(@ActivityScope context: Context): AlertDialog.Builder {
- return AlertDialog.Builder(context)
- }
-
@Provides
@Play01Scope
fun provideSoundMapper(): SoundMapper {
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceComponent.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceComponent.kt
index 4eb4dcf5..f4ee5703 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceComponent.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceComponent.kt
@@ -3,10 +3,13 @@ package nl.entreco.dartsscorecard.di.service
import dagger.Subcomponent
import nl.entreco.dartsscorecard.di.archive.ArchiveComponent
import nl.entreco.dartsscorecard.di.archive.ArchiveModule
+import nl.entreco.dartsscorecard.di.streaming.StreamingComponent
+import nl.entreco.dartsscorecard.di.streaming.StreamingModule
import nl.entreco.dartsscorecard.di.viewmodel.threading.ThreadingModule
@ServiceScope
@Subcomponent(modules = [(ServiceModule::class), (ThreadingModule::class)])
interface ServiceComponent {
fun plus(module: ArchiveModule): ArchiveComponent
+ fun plus(module: StreamingModule): StreamingComponent
}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceModule.kt
index c2792561..50b318d7 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/service/ServiceModule.kt
@@ -1,6 +1,48 @@
package nl.entreco.dartsscorecard.di.service
+import android.app.Service
+import android.content.Context
+import com.google.firebase.database.FirebaseDatabase
import dagger.Module
+import dagger.Provides
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.data.stream.FirebaseAnswersRepository
+import nl.entreco.data.stream.FirebaseIceRepository
+import nl.entreco.data.stream.FirebaseOffersRepository
+import nl.entreco.domain.repository.AnswersRepository
+import nl.entreco.domain.repository.IceRepository
+import nl.entreco.domain.repository.OffersRepository
+import nl.entreco.shared.log.Logger
+import javax.inject.Named
@Module
-class ServiceModule
\ No newline at end of file
+class ServiceModule(private val service: Service) {
+
+ @Provides
+ @ServiceScope
+ fun context(): Context = service
+
+ @Provides
+ @ServiceScope
+ fun provideIceRepository(@ApplicationScope db: FirebaseDatabase,
+ @ApplicationScope logger: Logger,
+ @ApplicationScope @Named("uuid") uuid: String): IceRepository {
+ return FirebaseIceRepository(db, logger, uuid)
+ }
+
+ @Provides
+ @ServiceScope
+ fun provideOffersRepository(@ApplicationScope db: FirebaseDatabase,
+ @ApplicationScope logger: Logger,
+ @ApplicationScope @Named("uuid") uuid: String): OffersRepository {
+ return FirebaseOffersRepository(db, logger, uuid)
+ }
+
+ @Provides
+ @ServiceScope
+ fun provideAnswersRepository(@ApplicationScope db: FirebaseDatabase,
+ @ApplicationScope logger: Logger,
+ @ApplicationScope @Named("uuid") uuid: String): AnswersRepository {
+ return FirebaseAnswersRepository(db, logger, uuid)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamComponent.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamComponent.kt
new file mode 100644
index 00000000..0250374c
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamComponent.kt
@@ -0,0 +1,12 @@
+package nl.entreco.dartsscorecard.di.streaming
+
+import dagger.Subcomponent
+import nl.entreco.dartsscorecard.base.PermissionHelper
+import nl.entreco.dartsscorecard.play.stream.StreamViewModel
+
+@StreamScope
+@Subcomponent(modules = [(StreamModule::class)])
+interface StreamComponent {
+ fun viewModel(): StreamViewModel
+ fun permissionHelper(): PermissionHelper
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamModule.kt
new file mode 100644
index 00000000..e13095c3
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamModule.kt
@@ -0,0 +1,42 @@
+package nl.entreco.dartsscorecard.di.streaming
+
+import dagger.Module
+import dagger.Provides
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.play.stream.StreamFragment
+import nl.entreco.dartsscorecard.streaming.WebRtcController
+import nl.entreco.shared.log.Logger
+import org.webrtc.CameraVideoCapturer
+import org.webrtc.SurfaceViewRenderer
+import javax.inject.Named
+
+@Module
+class StreamModule(private val fragment: StreamFragment,
+ private val listener: StreamFragment.Listener?,
+ private val localVideoView: SurfaceViewRenderer){
+
+ @Provides
+ @StreamScope
+ fun provideStreamingFragment() : StreamFragment {
+ return fragment
+ }
+
+ @Provides
+ @StreamScope
+ fun provideCameraSwitchHandler() : CameraVideoCapturer.CameraSwitchHandler {
+ return fragment
+ }
+
+ @Provides
+ @StreamScope
+ fun provideFragmentListener() : StreamFragment.Listener? {
+ return listener
+ }
+
+ @Provides
+ @StreamScope
+ @Named("local")
+ fun provideLocalVideoView() : SurfaceViewRenderer {
+ return localVideoView
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamScope.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamScope.kt
new file mode 100644
index 00000000..a2def613
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamScope.kt
@@ -0,0 +1,7 @@
+package nl.entreco.dartsscorecard.di.streaming
+
+import javax.inject.Scope
+
+@Scope
+@Retention(AnnotationRetention.RUNTIME)
+annotation class StreamScope
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingComponent.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingComponent.kt
new file mode 100644
index 00000000..37d82ad2
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingComponent.kt
@@ -0,0 +1,12 @@
+package nl.entreco.dartsscorecard.di.streaming
+
+import dagger.Subcomponent
+import nl.entreco.dartsscorecard.streaming.ReceivingController
+import nl.entreco.dartsscorecard.streaming.StreamingController
+
+@StreamingScope
+@Subcomponent(modules = [(StreamingModule::class)])
+interface StreamingComponent {
+ fun streamingController(): StreamingController
+ fun receivingController(): ReceivingController
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingModule.kt
new file mode 100644
index 00000000..1ed726ab
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingModule.kt
@@ -0,0 +1,82 @@
+package nl.entreco.dartsscorecard.di.streaming
+
+import android.content.Context
+import dagger.Module
+import dagger.Provides
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.service.ServiceScope
+import nl.entreco.dartsscorecard.streaming.WebRtcController
+import nl.entreco.domain.streaming.ice.FetchIceServerUsecase
+import nl.entreco.domain.streaming.ice.ListenForIceCandidatesUsecase
+import nl.entreco.domain.streaming.p2p.RemoveIceCandidateUsecase
+import nl.entreco.domain.streaming.p2p.SendIceCandidateUsecase
+import nl.entreco.shared.log.Logger
+import org.webrtc.*
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import java.util.concurrent.atomic.AtomicBoolean
+
+@Module
+class StreamingModule {
+
+ private val factoryInitialized = AtomicBoolean(false)
+
+ @Provides
+ @StreamingScope
+ fun provideSingleThreadExecutor(): ExecutorService {
+ return Executors.newSingleThreadExecutor()
+ }
+
+ @Provides
+ @StreamingScope
+ fun provideWebRtcController(@ApplicationScope logger: Logger,
+ @StreamingScope singleThread : ExecutorService,
+ @ServiceScope sendIceCandidateUsecase: SendIceCandidateUsecase,
+ @ServiceScope removeIceCandidateUsecase: RemoveIceCandidateUsecase,
+ @ServiceScope fetchIceServersUsecase: FetchIceServerUsecase,
+ @ServiceScope listenForIceServersUsecase: ListenForIceCandidatesUsecase,
+ @StreamingScope peerConnectionFactory: PeerConnectionFactory
+ ): WebRtcController {
+ return WebRtcController(logger, singleThread, sendIceCandidateUsecase, removeIceCandidateUsecase,
+ fetchIceServersUsecase, listenForIceServersUsecase, peerConnectionFactory)
+ }
+
+ @Provides
+ @StreamingScope
+ fun providePeerConnectionFactory(@ServiceScope context: Context): PeerConnectionFactory {
+ if (!factoryInitialized.get()) {
+ factoryInitialized.set(true)
+ PeerConnectionFactory.initialize(
+ PeerConnectionFactory.InitializationOptions.builder(context)
+ .setEnableInternalTracer(false) // Enabling tracker may cause crashes
+ .setEnableVideoHwAcceleration(true)
+ .createInitializationOptions())
+ }
+
+ val options = PeerConnectionFactory.Options()
+ return PeerConnectionFactory.builder().setOptions(options).createPeerConnectionFactory()
+ }
+
+ @Provides
+ @StreamingScope
+ fun provideVideoCameraCapturer(@ServiceScope context: Context): CameraVideoCapturer? {
+ val enumerator = if (isCamera2Supported(context)) Camera2Enumerator(
+ context) else Camera1Enumerator()
+ return createCameraCapturerWithFrontAsDefault(enumerator)
+ }
+
+ private fun isCamera2Supported(context: Context): Boolean {
+ return Camera2Enumerator.isSupported(context)
+ }
+
+ private fun createCameraCapturerWithFrontAsDefault(
+ enumerator: CameraEnumerator): CameraVideoCapturer? {
+ val (frontFacingCameras, backFacingAndOtherCameras) = enumerator.deviceNames
+ .partition { enumerator.isFrontFacing(it) }
+
+ return (frontFacingCameras.firstOrNull() ?: backFacingAndOtherCameras.firstOrNull())?.let {
+ enumerator.createCapturer(it, null)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingScope.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingScope.kt
new file mode 100644
index 00000000..8da1ee21
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/streaming/StreamingScope.kt
@@ -0,0 +1,7 @@
+package nl.entreco.dartsscorecard.di.streaming
+
+import javax.inject.Scope
+
+@Scope
+@Retention(AnnotationRetention.RUNTIME)
+annotation class StreamingScope
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvLaunchComponent.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvLaunchComponent.kt
new file mode 100644
index 00000000..0abbabfe
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvLaunchComponent.kt
@@ -0,0 +1,12 @@
+package nl.entreco.dartsscorecard.di.tv
+
+import dagger.Subcomponent
+import nl.entreco.dartsscorecard.tv.launch.LaunchTvNavigator
+import nl.entreco.dartsscorecard.tv.launch.LaunchTvViewModel
+
+@TvScope
+@Subcomponent(modules = [(TvLaunchModule::class)])
+interface TvLaunchComponent {
+ fun viewModel(): LaunchTvViewModel
+ fun navigator(): LaunchTvNavigator
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvLaunchModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvLaunchModule.kt
new file mode 100644
index 00000000..daa3950d
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvLaunchModule.kt
@@ -0,0 +1,16 @@
+package nl.entreco.dartsscorecard.di.tv
+
+import dagger.Module
+import dagger.Provides
+import org.webrtc.SurfaceViewRenderer
+import javax.inject.Named
+
+@Module
+class TvLaunchModule(private val remoteVideoView: SurfaceViewRenderer) {
+ @Provides
+ @TvScope
+ @Named("remote")
+ fun provideRemoteVideoView(): SurfaceViewRenderer {
+ return remoteVideoView
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvScope.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvScope.kt
new file mode 100644
index 00000000..660029c4
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/tv/TvScope.kt
@@ -0,0 +1,7 @@
+package nl.entreco.dartsscorecard.di.tv
+
+import javax.inject.Scope
+
+@Scope
+@Retention(AnnotationRetention.RUNTIME)
+annotation class TvScope
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelComponent.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelComponent.kt
index 433c0374..edd058b0 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelComponent.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelComponent.kt
@@ -17,8 +17,13 @@ import nl.entreco.dartsscorecard.di.viewmodel.api.FaqApiModule
import nl.entreco.dartsscorecard.di.viewmodel.api.FeatureApiModule
import nl.entreco.dartsscorecard.di.viewmodel.db.*
import nl.entreco.dartsscorecard.di.viewmodel.threading.ThreadingModule
-import nl.entreco.dartsscorecard.di.wtf.WtfComponent
-import nl.entreco.dartsscorecard.di.wtf.WtfModule
+import nl.entreco.dartsscorecard.di.faq.WtfComponent
+import nl.entreco.dartsscorecard.di.faq.WtfModule
+import nl.entreco.dartsscorecard.di.streaming.StreamComponent
+import nl.entreco.dartsscorecard.di.streaming.StreamModule
+import nl.entreco.dartsscorecard.di.tv.TvLaunchComponent
+import nl.entreco.dartsscorecard.di.tv.TvLaunchModule
+import nl.entreco.dartsscorecard.di.viewmodel.tv.TvModule
/**
* Created by Entreco on 14/11/2017.
@@ -26,12 +31,12 @@ import nl.entreco.dartsscorecard.di.wtf.WtfModule
@ActivityScope
@Subcomponent(modules = [(ViewModelModule::class), (ThreadingModule::class), (AdModule::class),
(GameDbModule::class), (PlayerDbModule::class), (TurnDbModule::class),
- (MetaDbModule::class), (StatDbModule::class), (FeatureApiModule::class), (FaqApiModule::class)])
+ (MetaDbModule::class), (StatDbModule::class), (FeatureApiModule::class),
+ (FaqApiModule::class), (TvModule::class)])
interface ViewModelComponent {
// Where can this be used
fun plus(module: LaunchModule): LaunchComponent
-
fun plus(module: BetaModule): BetaComponent
fun plus(module: WtfModule): WtfComponent
fun plus(module: Setup01Module): Setup01Component
@@ -40,4 +45,6 @@ interface ViewModelComponent {
fun plus(module: SelectProfileModule): SelectProfileComponent
fun plus(module: ProfileModule): ProfileComponent
fun plus(module: EditPlayerNameModule): EditPlayerNameComponent
+ fun plus(module: TvLaunchModule): TvLaunchComponent
+ fun plus(module: StreamModule) : StreamComponent
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModule.kt
index e80963ee..5293550f 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModule.kt
@@ -4,21 +4,39 @@ import android.arch.lifecycle.Lifecycle
import android.content.Context
import android.content.res.Resources
import android.support.v4.app.FragmentActivity
+import android.support.v4.app.FragmentManager
+import android.support.v7.app.AlertDialog
+import com.google.firebase.database.FirebaseDatabase
import dagger.Module
import dagger.Provides
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.play.Play01Scope
import nl.entreco.data.billing.BillingServiceConnection
import nl.entreco.data.billing.PlayStoreBillingRepository
+import nl.entreco.data.prefs.SharedRatingPrefRepo
+import nl.entreco.data.stream.FirebaseSignallingRepository
import nl.entreco.domain.repository.BillingRepository
+import nl.entreco.domain.repository.RatingPrefRepository
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.log.Logger
+import javax.inject.Named
/**
* Created by Entreco on 14/11/2017.
*/
@Module
class ViewModelModule(private val activity: FragmentActivity) {
+
+ private val prefs = activity.getSharedPreferences("rating", Context.MODE_PRIVATE)
+
@Provides
@ActivityScope
fun context(): Context = activity
+ @Provides
+ @ActivityScope
+ fun fragmentManager(): FragmentManager = activity.supportFragmentManager
+
@Provides
@ActivityScope
fun resources(): Resources = activity.resources
@@ -29,6 +47,18 @@ class ViewModelModule(private val activity: FragmentActivity) {
return activity.lifecycle
}
+ @Provides
+ @ActivityScope
+ fun provideRatingPreferences(): RatingPrefRepository {
+ return SharedRatingPrefRepo(prefs)
+ }
+
+ @Provides
+ @ActivityScope
+ fun provideAlertDialogBuilder(@ActivityScope context: Context): AlertDialog.Builder {
+ return AlertDialog.Builder(context)
+ }
+
@Provides
@ActivityScope
fun provideServiceConnection(): BillingServiceConnection {
@@ -40,4 +70,13 @@ class ViewModelModule(private val activity: FragmentActivity) {
fun provideBillingRepository(@ActivityScope context: Context, @ActivityScope serviceConnection: BillingServiceConnection): BillingRepository {
return PlayStoreBillingRepository(context, serviceConnection)
}
+
+ @Provides
+ @ActivityScope
+ fun provideSignallingRepository(@ApplicationScope db: FirebaseDatabase,
+ @ApplicationScope logger: Logger,
+ @ApplicationScope @Named(
+ "uuid") uuid: String): SignallingRepository {
+ return FirebaseSignallingRepository(db, logger, uuid)
+ }
}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FaqApiModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FaqApiModule.kt
index 98147d80..42ac5ac8 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FaqApiModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FaqApiModule.kt
@@ -4,7 +4,7 @@ import com.google.firebase.firestore.FirebaseFirestore
import dagger.Module
import dagger.Provides
import nl.entreco.data.wtf.RemoteWtfRepository
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.repository.WtfRepository
@Module
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModule.kt
index 4c779770..8083911c 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModule.kt
@@ -4,7 +4,7 @@ import com.google.firebase.firestore.FirebaseFirestore
import dagger.Module
import dagger.Provides
import nl.entreco.data.api.beta.RemoteFeatureRepository
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.repository.FeatureRepository
/**
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/db/PlayerDbModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/db/PlayerDbModule.kt
index 4f0ea736..0a9048fb 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/db/PlayerDbModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/db/PlayerDbModule.kt
@@ -25,5 +25,4 @@ class PlayerDbModule {
fun providePlayerRepository(db: DscDatabase, mapper: PlayerMapper): PlayerRepository {
return LocalPlayerRepository(db, mapper)
}
-
}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModule.kt
index 01950632..86e1c141 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModule.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModule.kt
@@ -4,10 +4,10 @@ import android.os.Handler
import android.os.Looper
import dagger.Module
import dagger.Provides
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.BgExecutor
-import nl.entreco.domain.common.executors.FgExecutor
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.BgExecutor
+import nl.entreco.shared.threading.FgExecutor
+import nl.entreco.shared.threading.Foreground
/**
* Created by Entreco on 17/12/2017.
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/tv/TvModule.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/tv/TvModule.kt
new file mode 100644
index 00000000..7c865c10
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/viewmodel/tv/TvModule.kt
@@ -0,0 +1,11 @@
+package nl.entreco.dartsscorecard.di.viewmodel.tv
+
+import dagger.Module
+import dagger.Provides
+import nl.entreco.dartsscorecard.di.tv.TvScope
+import org.webrtc.SurfaceViewRenderer
+import javax.inject.Named
+
+
+@Module
+class TvModule
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfActivity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfActivity.kt
similarity index 90%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfActivity.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfActivity.kt
index 45b473e3..32b6401d 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfActivity.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfActivity.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import android.content.Context
import android.content.Intent
@@ -14,10 +14,8 @@ import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.base.ViewModelActivity
import nl.entreco.dartsscorecard.databinding.ActivityWtfBinding
import nl.entreco.dartsscorecard.databinding.SearchbarBinding
-import nl.entreco.dartsscorecard.di.wtf.WtfComponent
-import nl.entreco.dartsscorecard.di.wtf.WtfModule
-import android.support.v4.content.ContextCompat
-import android.view.WindowManager
+import nl.entreco.dartsscorecard.di.faq.WtfComponent
+import nl.entreco.dartsscorecard.di.faq.WtfModule
import android.view.inputmethod.InputMethodManager
@@ -33,12 +31,12 @@ class WtfActivity : ViewModelActivity() {
object : JellyListener() {
override fun onCancelIconClicked() {
val searchField = searchBinding.searchField
- if (searchField.text.isEmpty()) {
+ if (searchField.text?.isEmpty() == true) {
binding.includeToolbar.toolbar.collapse()
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(searchField.windowToken, 0)
} else {
- searchField.text.clear()
+ searchField.text?.clear()
}
}
}
@@ -68,7 +66,6 @@ class WtfActivity : ViewModelActivity() {
recyclerView.setItemViewCacheSize(20)
recyclerView.layoutManager = GridLayoutManager(binding.root.context, 1)
recyclerView.itemAnimator = DefaultItemAnimator()
- recyclerView.isDrawingCacheEnabled = true
recyclerView.adapter = adapter
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfAdapter.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfAdapter.kt
similarity index 96%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfAdapter.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfAdapter.kt
index ba0bc25a..903a2351 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfAdapter.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfAdapter.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import android.arch.lifecycle.Observer
import android.databinding.DataBindingUtil
@@ -8,8 +8,8 @@ import android.view.ViewGroup
import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.base.TestableAdapter
import nl.entreco.dartsscorecard.databinding.WtfViewBinding
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.wtf.SubmitViewedItemRequest
import nl.entreco.domain.wtf.SubmitViewedItemUsecase
import nl.entreco.domain.wtf.WtfItem
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfDiffCalculator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfDiffCalculator.kt
similarity index 94%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfDiffCalculator.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfDiffCalculator.kt
index 4dfab971..1731d42b 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfDiffCalculator.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfDiffCalculator.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import android.support.v7.util.DiffUtil
import nl.entreco.domain.wtf.WtfItem
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfModel.kt
similarity index 97%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfModel.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfModel.kt
index 1ee12716..d9d74901 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfModel.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import android.content.ActivityNotFoundException
import android.content.Intent
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfSearchable.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfSearchable.kt
similarity index 62%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfSearchable.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfSearchable.kt
index 6d7682b1..07a218d6 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfSearchable.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfSearchable.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
interface WtfSearchable {
fun search(text: CharSequence)
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfToggler.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfToggler.kt
similarity index 70%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfToggler.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfToggler.kt
index a3c1205e..da8396a9 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfToggler.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfToggler.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import nl.entreco.domain.wtf.WtfItem
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfView.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfView.kt
similarity index 91%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfView.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfView.kt
index f95da599..1340cf1b 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfView.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfView.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import android.support.v7.widget.RecyclerView
import nl.entreco.dartsscorecard.databinding.WtfViewBinding
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfViewModel.kt
similarity index 86%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfViewModel.kt
rename to android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfViewModel.kt
index 1b2c9c11..e2bba1d8 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/wtf/WtfViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/faq/WtfViewModel.kt
@@ -1,11 +1,9 @@
-package nl.entreco.dartsscorecard.wtf
+package nl.entreco.dartsscorecard.faq
import android.arch.lifecycle.LifecycleOwner
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Observer
import nl.entreco.dartsscorecard.base.BaseViewModel
-import nl.entreco.domain.beta.Feature
-import nl.entreco.domain.purchases.connect.SubscribeToFeaturesUsecase
import nl.entreco.domain.wtf.SubscribeToWtfsUsecase
import nl.entreco.domain.wtf.WtfItem
import javax.inject.Inject
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/launch/LaunchViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/launch/LaunchViewModel.kt
index 9b6fb7df..683b94d3 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/launch/LaunchViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/launch/LaunchViewModel.kt
@@ -7,7 +7,6 @@ import nl.entreco.dartsscorecard.beta.BetaActivity
import nl.entreco.dartsscorecard.play.Play01Activity
import nl.entreco.dartsscorecard.profile.select.SelectProfileActivity
import nl.entreco.dartsscorecard.setup.Setup01Activity
-import nl.entreco.dartsscorecard.wtf.WtfActivity
import nl.entreco.domain.launch.FetchLatestGameResponse
import nl.entreco.domain.launch.RetrieveLatestGameUsecase
import nl.entreco.domain.setup.game.CreateGameResponse
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt
index 202883ef..eaeceb51 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Activity.kt
@@ -14,33 +14,42 @@ import nl.entreco.dartsscorecard.databinding.ActivityPlay01Binding
import nl.entreco.dartsscorecard.di.play.Play01Component
import nl.entreco.dartsscorecard.di.play.Play01Module
import nl.entreco.dartsscorecard.play.input.InputViewModel
-import nl.entreco.dartsscorecard.play.score.ScoreViewModel
import nl.entreco.dartsscorecard.play.live.LiveStatViewModel
+import nl.entreco.dartsscorecard.play.score.ScoreViewModel
+import nl.entreco.dartsscorecard.play.stream.StreamFragment
+import nl.entreco.dartsscorecard.play.stream.ControlStreamViewModel
import nl.entreco.domain.play.finish.GetFinishUsecase
import nl.entreco.domain.play.start.Play01Request
import nl.entreco.domain.setup.game.CreateGameResponse
+import nl.entreco.domain.streaming.Connected
+import nl.entreco.domain.streaming.ConnectionState
+import org.webrtc.PeerConnection
-class Play01Activity : ViewModelActivity() {
+class Play01Activity : ViewModelActivity(), StreamFragment.Listener {
+ private lateinit var binding: ActivityPlay01Binding
private val component: Play01Component by componentProvider { it.plus(Play01Module(this)) }
private val viewModel: Play01ViewModel by viewModelProvider { component.viewModel() }
private val scoreViewModel: ScoreViewModel by viewModelProvider { component.scoreViewModel() }
+ private val controlStreamViewModel: ControlStreamViewModel by viewModelProvider { component.streamViewModel() }
private val inputViewModel: InputViewModel by viewModelProvider { component.inputViewModel() }
private val statViewModel: LiveStatViewModel by viewModelProvider { component.statViewModel() }
private val finishUsecase: GetFinishUsecase by componentProvider { component.finishUsecase() }
private val navigator: Play01Navigator by lazy { component.navigator() }
+ private val animator: Play01Animator by lazy { Play01Animator(binding) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- val binding = DataBindingUtil.setContentView(this, R.layout.activity_play_01)
+ binding = DataBindingUtil.setContentView(this, R.layout.activity_play_01)
binding.viewModel = viewModel
binding.inputViewModel = inputViewModel
binding.statViewModel = statViewModel
+ binding.controlStreamViewModel = controlStreamViewModel
binding.scoreViewModel = scoreViewModel
binding.finishUsecase = finishUsecase
- binding.animator = Play01Animator(binding)
+ binding.animator = animator
binding.navigator = navigator
if (savedInstanceState == null) {
@@ -51,9 +60,27 @@ class Play01Activity : ViewModelActivity() {
resumeGame()
}
+ override fun onPleaseKillMe() {
+ controlStreamViewModel.sendDisconnect(navigator)
+ controlStreamViewModel.toggleStream(navigator, animator)
+ invalidateOptionsMenu()
+ }
+
+ override fun onConnectionStateChanged(connectionState: ConnectionState) {
+ controlStreamViewModel.connectionState(connectionState)
+ when(connectionState) {
+ // Add DataMessenger to ScoreViewModel
+ is Connected -> {
+ controlStreamViewModel.setStreamController(navigator.streamController())
+ viewModel.addRemoteListener(controlStreamViewModel)
+ }
+ }
+ }
+
override fun onDestroy() {
super.onDestroy()
viewModel.stop()
+ navigator.stop()
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
@@ -66,7 +93,8 @@ class Play01Activity : ViewModelActivity() {
}
private fun resumeGame() {
- viewModel.registerListeners(scoreViewModel, statViewModel, inputViewModel, scoreViewModel, inputViewModel)
+ viewModel.registerListeners(scoreViewModel, statViewModel, inputViewModel, scoreViewModel,
+ inputViewModel)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
@@ -76,11 +104,17 @@ class Play01Activity : ViewModelActivity() {
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
viewModel.initToggleMenuItem(menu)
+ menu?.findItem(R.id.menu_stream)?.setIcon(controlStreamViewModel.menuIcon())
+ menu?.findItem(R.id.menu_stream)?.setTitle(controlStreamViewModel.menuTitle())
return super.onPrepareOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
+ R.id.menu_stream -> {
+ controlStreamViewModel.toggleStream(navigator, animator)
+ invalidateOptionsMenu()
+ }
R.id.menu_play_settings -> {
swapStyle()
viewModel.loading.set(true)
@@ -92,6 +126,11 @@ class Play01Activity : ViewModelActivity() {
return super.onOptionsItemSelected(item)
}
+ override fun onBackPressed() {
+ super.onBackPressed()
+ finish()
+ }
+
companion object {
@JvmStatic
fun retrieveSetup(intent: Intent): Play01Request {
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Animator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Animator.kt
index bc07f75f..9f219535 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Animator.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Animator.kt
@@ -21,8 +21,9 @@ class Play01Animator(binding: ActivityPlay01Binding) {
private val pager = binding.includeMain.statPager
private val inputSheet = binding.includeInput.inputSheet
private val behaviour = BottomSheetBehavior.from(inputSheet)
- private val animator = Play01AnimatorHandler(binding.root, binding.includeScore.scoreSheet, binding.includeInput.fab, binding.includeMain.mainSheet, binding.includeMain.version,
- binding.includeInput.inputResume, pager, binding.includeScore.teamContainer, inputSheet, binding.root.includeScore.header, binding.root.includeScore.footer, binding.root.includeToolbar)
+ private val animator = Play01AnimatorHandler(binding.root, binding.includeScore.scoreSheet,binding.includeInput.fab, binding.includeMain.mainSheet, binding.includeMain.version,
+ binding.includeInput.inputResume, pager, binding.includeScore.teamContainer, inputSheet, binding.root.includeScore.header,
+ binding.root.includeScore.footer, binding.root.includeToolbar, binding.includeMain.control1, binding.includeMain.control2)
init {
animator.calculateHeightForScoreView()
@@ -53,7 +54,8 @@ class Play01Animator(binding: ActivityPlay01Binding) {
internal class Play01AnimatorHandler(private val root: View, private val scoreSheet: View, private val fab: View, private val mainSheet: View, private val version: View,
private val inputResume: View, private val pager: ViewPager, private val teamSheet: MaxHeightRecyclerView, private val inputSheet: View,
- private val scoreHeader: View, private val scoreFooter: View, private val toolbar: View) {
+ private val scoreHeader: View, private val scoreFooter: View, private val toolbar: View,
+ private val control1: View, private val control2: View) {
private var animatorPosition: Int = 0
internal var animator: LiveStatSlideAnimator? = null
@@ -63,7 +65,6 @@ class Play01Animator(binding: ActivityPlay01Binding) {
// Slide Out ScoreViewModel
scoreSheet.animate().alpha(slideOffset).translationY(-scoreSheet.height * (1 - slideOffset)).setDuration(0).start()
-
// Scale Fab Out Bottom/Top
fab.animate().scaleY(slideOffset).scaleX(slideOffset).setDuration(0).start()
@@ -71,6 +72,10 @@ class Play01Animator(binding: ActivityPlay01Binding) {
mainSheet.animate().alpha(1 - sqrt(slideOffset)).setDuration(0).start()
mainSheet.animate().translationY((slideOffset) * -100).setDuration(0).start()
+ // Fly In Stream Controls
+ animateState(control1.animate(), 1, slideOffset)
+ animateState(control2.animate(), 1, slideOffset)
+
// Also, Fly In Version
animateState(version.animate(), 8, slideOffset)
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Navigator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Navigator.kt
index becb07c1..304bd661 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Navigator.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01Navigator.kt
@@ -1,8 +1,11 @@
package nl.entreco.dartsscorecard.play
import android.support.design.widget.Snackbar
+import android.support.v4.app.FragmentManager
import android.view.View
import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.play.stream.StreamController
+import nl.entreco.dartsscorecard.play.stream.StreamFragment
import nl.entreco.dartsscorecard.profile.view.ProfileActivity
import nl.entreco.domain.model.players.Team
import javax.inject.Inject
@@ -12,6 +15,8 @@ import javax.inject.Inject
*/
class Play01Navigator @Inject constructor(private val activity: Play01Activity) {
+ private val fm : FragmentManager = activity.supportFragmentManager
+
fun gotoTeamProfile(view: View, team: Team) {
val teams = team.players.map { it.id }.filter { it > 0 }.toLongArray()
if (teams.isEmpty()) {
@@ -22,4 +27,26 @@ class Play01Navigator @Inject constructor(private val activity: Play01Activity)
ProfileActivity.launch(activity, view, teams)
}
}
+
+ fun attachVideoStream() {
+ fm.beginTransaction()
+ .add(R.id.streamContainer, StreamFragment(), StreamFragment.TAG)
+ .commit()
+ }
+
+ fun detachVideoStream() {
+ fm.findFragmentById(R.id.streamContainer)?.apply {
+ fm.beginTransaction()
+ .remove(this)
+ .commit()
+ }
+ }
+
+ fun streamController(): StreamController? {
+ return fm.findFragmentById(R.id.streamContainer) as? StreamController
+ }
+
+ fun stop() {
+ streamController()?.apply { sendDisconnect() }
+ }
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt
index b30d1792..1ca701b8 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/Play01ViewModel.kt
@@ -9,11 +9,11 @@ import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.ad.AdViewModel
import nl.entreco.dartsscorecard.base.BaseViewModel
import nl.entreco.dartsscorecard.base.DialogHelper
+import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier
import nl.entreco.dartsscorecard.play.score.TeamScoreListener
import nl.entreco.dartsscorecard.play.score.UiCallback
-import nl.entreco.domain.Analytics
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.dartsscorecard.play.stream.ControlStreamViewModel
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
@@ -31,8 +31,11 @@ import nl.entreco.domain.play.start.Play01Usecase
import nl.entreco.domain.play.stats.StoreTurnRequest
import nl.entreco.domain.play.stats.UndoTurnRequest
import nl.entreco.domain.play.stats.UndoTurnResponse
+import nl.entreco.domain.rating.AskForRatingResponse
+import nl.entreco.domain.rating.AskForRatingUsecase
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.settings.ScoreSettings
+import nl.entreco.shared.log.Logger
import javax.inject.Inject
/**
@@ -42,11 +45,13 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
private val revancheUsecase: RevancheUsecase,
private val gameListeners: Play01Listeners,
private val masterCaller: MasterCaller,
- private val dialogHelper: DialogHelper,
+ @ActivityScope private val dialogHelper: DialogHelper,
private val toggleSoundUsecase: ToggleSoundUsecase,
+ private val askForRatingUsecase: AskForRatingUsecase,
private val audioPrefRepository: AudioPrefRepository,
private val adViewModel: AdViewModel,
- private val logger: Logger) : BaseViewModel(), UiCallback, InputListener {
+ @ActivityScope private val logger: Logger) :
+ BaseViewModel(), UiCallback, InputListener {
val loading = ObservableBoolean(true)
val finished = ObservableBoolean(false)
@@ -57,7 +62,8 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
private var load: GameLoadedNotifier? = null
private var loaders: Array>? = null
- fun load(request: Play01Request, load: GameLoadedNotifier, vararg loaders: GameLoadedNotifier) {
+ fun load(request: Play01Request, load: GameLoadedNotifier,
+ vararg loaders: GameLoadedNotifier) {
this.load = load
this.loaders = arrayOf(*loaders)
this.playGameUsecase.loadGameAndStart(request,
@@ -72,13 +78,15 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
val nextTeam = (startIndex) % teams.size
revancheUsecase.recreateGameAndStart(RevancheRequest(request, teams, nextTeam),
{ revenge ->
- onGameOk(this.request.copy(gameId = revenge.game.id, startIndex = nextTeam), null, revenge)
+ onGameOk(this.request.copy(gameId = revenge.game.id, startIndex = nextTeam),
+ null, revenge)
},
onGameFailed(R.string.err_unable_to_revanche))
}
}
- private fun onGameOk(request: Play01Request, response: Play01Response?, revancheResponse: RevancheResponse?) {
+ private fun onGameOk(request: Play01Request, response: Play01Response?,
+ revancheResponse: RevancheResponse?) {
this.request = request
this.game = response?.game ?: revancheResponse!!.game
this.teams = response?.teams ?: revancheResponse!!.teams
@@ -86,7 +94,8 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
val settings = response?.settings ?: revancheResponse!!.settings
this.load?.onLoaded(teams, game.scores, settings, this)
this.loaders?.forEach {
- it.onLoaded(teams, game.scores, response ?: Play01Response(game, settings, teams, teamIds), null)
+ it.onLoaded(teams, game.scores,
+ response ?: Play01Response(game, settings, teams, teamIds), null)
}
}
@@ -98,8 +107,11 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
}
}
- fun registerListeners(scoreListener: ScoreListener, statListener: StatListener, specialEventListener: SpecialEventListener<*>, vararg playerListeners: PlayerListener) {
- gameListeners.registerListeners(scoreListener, statListener, specialEventListener, *playerListeners)
+ fun registerListeners(scoreListener: ScoreListener, statListener: StatListener,
+ specialEventListener: SpecialEventListener<*>,
+ vararg playerListeners: PlayerListener) {
+ gameListeners.registerListeners(scoreListener, statListener, specialEventListener,
+ *playerListeners)
}
override fun onLetsPlayDarts(listeners: List) {
@@ -150,7 +162,7 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
private fun storeTurn(turn: Turn, by: Player, next: Next) {
val turnRequest = StoreTurnRequest(by.id, game.id, turn, next.state)
val score = game.previousScore()
- val started = game.isNewMatchLegOrSet()
+// val started = game.isNewMatchLegOrSet()
val turnCounter = game.getTurnCount()
val breakMade = game.wasBreakMade(by)
val turnMeta = TurnMeta(by.id, turnCounter, score, breakMade)
@@ -163,11 +175,19 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
val gameFinished = next.state == State.MATCH
finished.set(gameFinished)
if (gameFinished) {
- playGameUsecase.markGameAsFinished(MarkGameAsFinishedRequest(gameId, teams.first { it.contains(winnerId) }.toTeamString()))
+ askForRatingUsecase.go(onShouldAskForRating(), {})
+ playGameUsecase.markGameAsFinished(MarkGameAsFinishedRequest(gameId,
+ teams.first { it.contains(winnerId) }.toTeamString()))
gameListeners.onGameFinished(gameId)
}
}
+ private fun onShouldAskForRating(): (AskForRatingResponse) -> Unit = { response ->
+ if (response.shouldAskForRating) {
+ dialogHelper.showRatingDialog()
+ }
+ }
+
private fun notifyListeners(next: Next, turn: Turn, by: Player, scores: Array) {
gameListeners.onTurnSubmitted(next, turn, by, scores)
}
@@ -189,7 +209,8 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
State.LEG -> adViewModel.provideInterstitial()
State.SET -> adViewModel.provideInterstitial()
State.MATCH -> adViewModel.provideInterstitial()
- else -> { /* ignore */ }
+ else -> { /* ignore */
+ }
}
}
@@ -198,7 +219,8 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
}
fun initToggleMenuItem(menu: Menu?) {
- menu?.findItem(R.id.menu_sound_settings)?.isChecked = audioPrefRepository.isMasterCallerEnabled()
+ menu?.findItem(R.id.menu_sound_settings)
+ ?.isChecked = audioPrefRepository.isMasterCallerEnabled()
}
fun toggleMasterCaller(item: MenuItem) {
@@ -211,4 +233,9 @@ class Play01ViewModel @Inject constructor(private val playGameUsecase: Play01Use
loaders = null
super.onCleared()
}
+
+ fun addRemoteListener(listener: ControlStreamViewModel) {
+ gameListeners.playerListeners.add(listener as PlayerListener)
+ gameListeners.scoreListeners.add(listener as ScoreListener)
+ }
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt
index f652986a..975b87e7 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/input/InputViewModel.kt
@@ -9,7 +9,7 @@ import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.base.BaseViewModel
import nl.entreco.dartsscorecard.play.Play01Animator
import nl.entreco.domain.Analytics
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.NoPlayer
import nl.entreco.domain.model.players.Player
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModel.kt
index fe081f41..069d9d99 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModel.kt
@@ -6,7 +6,7 @@ import nl.entreco.dartsscorecard.archive.ArchiveServiceLauncher
import nl.entreco.dartsscorecard.base.BaseViewModel
import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier
import nl.entreco.dartsscorecard.play.score.UiCallback
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.Score
import nl.entreco.domain.model.players.Team
import nl.entreco.domain.play.listeners.StatListener
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreBindings.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreBindings.kt
index e29752a5..7f927cfe 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreBindings.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreBindings.kt
@@ -26,7 +26,6 @@ object ScoreBindings {
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(recyclerView.context)
recyclerView.itemAnimator = null
- recyclerView.isDrawingCacheEnabled = true
recyclerView.adapter = adapter
adapter.clear()
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreViewModel.kt
index 5f92a373..49ea66f1 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/ScoreViewModel.kt
@@ -4,7 +4,6 @@ import android.databinding.ObservableArrayList
import android.databinding.ObservableField
import android.databinding.ObservableInt
import nl.entreco.dartsscorecard.base.BaseViewModel
-import nl.entreco.domain.common.log.Logger
import nl.entreco.domain.model.Next
import nl.entreco.domain.model.Score
import nl.entreco.domain.model.Turn
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreBindings.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreBindings.kt
index 31da06a2..1232e5e0 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreBindings.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/score/TeamScoreBindings.kt
@@ -1,7 +1,6 @@
package nl.entreco.dartsscorecard.play.score
import android.animation.ValueAnimator
-import android.app.ProgressDialog.show
import android.content.Context
import android.databinding.BindingAdapter
import android.graphics.Color
@@ -51,7 +50,8 @@ object TeamScoreBindings {
val diff = oldScore - score
when (diff) {
180 -> handle180(view)
- 0 -> { /* nothing */ }
+ 0 -> { /* nothing */
+ }
else -> clear(view)
}
}
@@ -105,9 +105,12 @@ object TeamScoreBindings {
view.setTarget(score.toLong())
view.measure(0, 0)
if (score <= 0) {
- view.animate().translationX(view.measuredWidth.toFloat() * 3).setInterpolator(AccelerateDecelerateInterpolator()).setDuration(DEFAULT_ANIMATION_TIME).start()
+ view.animate().translationX(view.measuredWidth.toFloat() * 3)
+ .setInterpolator(AccelerateDecelerateInterpolator())
+ .setDuration(DEFAULT_ANIMATION_TIME).start()
} else {
- view.animate().translationX(0f).setInterpolator(AccelerateDecelerateInterpolator()).setDuration(DEFAULT_ANIMATION_TIME).start()
+ view.animate().translationX(0f).setInterpolator(AccelerateDecelerateInterpolator())
+ .setDuration(DEFAULT_ANIMATION_TIME).start()
view.setTextColor(fromAttr(view.context, R.attr.scoreText))
}
}
@@ -122,7 +125,8 @@ object TeamScoreBindings {
target = if (w == 0F) 50F else w
}
- view.animate().translationX(target).setInterpolator(AccelerateDecelerateInterpolator()).setDuration(DEFAULT_ANIMATION_TIME).start()
+ view.animate().translationX(target).setInterpolator(AccelerateDecelerateInterpolator())
+ .setDuration(DEFAULT_ANIMATION_TIME).start()
}
@ColorInt
@@ -147,10 +151,12 @@ object TeamScoreBindings {
val startColor = colorToHex(view.currentTextColor)
val endColor = if (isCurrentTeam) "#FFFFFFFF" else "#aaFFFFFF"
if (startColor != endColor) {
- val valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f).setDuration(DEFAULT_ANIMATION_TIME)
+ val valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f)
+ .setDuration(DEFAULT_ANIMATION_TIME)
valueAnimator.addUpdateListener {
val fractionAnim = it.animatedValue as Float
- view.setTextColor(ColorUtils.blendARGB(Color.parseColor(startColor), Color.parseColor(endColor), fractionAnim))
+ view.setTextColor(ColorUtils.blendARGB(Color.parseColor(startColor),
+ Color.parseColor(endColor), fractionAnim))
}
valueAnimator.start()
}
@@ -171,7 +177,8 @@ object TeamScoreBindings {
private fun show(view: TextView) {
view.measure(0, 0)
- val animator = ValueAnimator.ofInt(view.width, view.measuredWidth).setDuration(DEFAULT_ANIMATION_TIME)
+ val animator = ValueAnimator.ofInt(view.width, view.measuredWidth)
+ .setDuration(DEFAULT_ANIMATION_TIME)
animator.addUpdateListener {
val lp = view.layoutParams
lp.width = it.animatedValue as Int
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/ControlStreamViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/ControlStreamViewModel.kt
new file mode 100644
index 00000000..78a73e41
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/ControlStreamViewModel.kt
@@ -0,0 +1,90 @@
+package nl.entreco.dartsscorecard.play.stream
+
+import android.databinding.ObservableBoolean
+import android.databinding.ObservableField
+import android.support.annotation.DrawableRes
+import android.support.annotation.StringRes
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.base.BaseViewModel
+import nl.entreco.dartsscorecard.di.play.Play01Scope
+import nl.entreco.dartsscorecard.play.Play01Animator
+import nl.entreco.dartsscorecard.play.Play01Navigator
+import nl.entreco.domain.model.Next
+import nl.entreco.domain.model.Score
+import nl.entreco.domain.model.Turn
+import nl.entreco.domain.model.players.Player
+import nl.entreco.domain.play.listeners.PlayerListener
+import nl.entreco.domain.play.listeners.ScoreListener
+import nl.entreco.domain.streaming.ConnectionState
+import nl.entreco.domain.streaming.Unknown
+import java.util.concurrent.atomic.AtomicBoolean
+import javax.inject.Inject
+
+
+class ControlStreamViewModel @Inject constructor() : BaseViewModel(), ScoreListener, PlayerListener {
+
+ private val isStreaming = AtomicBoolean(false)
+ val micEnabled = ObservableBoolean(true)
+ val isShowingFront = ObservableBoolean(true)
+ val state = ObservableField(Unknown)
+
+ fun toggleStream(navigator: Play01Navigator, animator: Play01Animator) {
+ if (isStreaming.get()) {
+ isStreaming.set(false)
+ animator.expand()
+ navigator.detachVideoStream()
+ sendDisconnect(navigator)
+ } else {
+ isStreaming.set(true)
+ animator.collapse()
+ navigator.attachVideoStream()
+ }
+ }
+
+ fun sendDisconnect(navigator: Play01Navigator){
+ navigator.streamController()?.sendDisconnect()
+ }
+
+ fun toggleCamera(navigator: Play01Navigator){
+ isShowingFront.set(!isShowingFront.get())
+ navigator.streamController()?.toggleCamera()
+ }
+
+ fun toggleMic(navigator: Play01Navigator){
+ micEnabled.set(!micEnabled.get())
+ navigator.streamController()?.toggleMic()
+ }
+
+ fun connectionState(connectionState: ConnectionState) {
+ state.set(connectionState)
+ }
+
+ @DrawableRes
+ fun menuIcon(): Int {
+ return if (isStreaming.get()) R.drawable.ic_live_stop else R.drawable.ic_live_start
+ }
+
+ @StringRes
+ fun menuTitle(): Int {
+ return if (isStreaming.get()) R.string.stream_stop else R.string.stream_start
+ }
+
+ private var streamController : StreamController? = null
+
+ fun setStreamController(streamController: StreamController?) {
+ this.streamController = streamController
+ }
+
+ override fun onDartThrown(turn: Turn, by: Player) {
+ this.streamController?.sendMessage("turn $turn by $by")
+ }
+
+ override fun onScoreChange(scores: Array, by: Player) {
+ this.streamController?.sendMessage("score $scores by $by")
+ }
+
+ override fun onNext(next: Next) {
+ this.streamController?.sendMessage("next $next")
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/ServiceLauncher.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/ServiceLauncher.kt
new file mode 100644
index 00000000..72bf677d
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/ServiceLauncher.kt
@@ -0,0 +1,40 @@
+package nl.entreco.dartsscorecard.play.stream
+
+import android.content.Context
+import android.content.ServiceConnection
+import android.widget.Toast
+import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
+import nl.entreco.dartsscorecard.streaming.ReceiverService
+import nl.entreco.dartsscorecard.streaming.StreamingService
+import org.webrtc.PeerConnection
+import javax.inject.Inject
+
+class ServiceLauncher @Inject constructor(@ActivityScope private val context: Context) {
+
+
+ fun launchStreamingService(serviceConnection: ServiceConnection) {
+ StreamingService.startService(context)
+ StreamingService.bindService(context, serviceConnection)
+ }
+
+ fun launchReceiverService(serviceConnection: ServiceConnection) {
+ ReceiverService.startService(context)
+ ReceiverService.bindService(context, serviceConnection)
+ }
+
+ fun unbindServiceConnection(serviceConnection: ServiceConnection) {
+ context.unbindService(serviceConnection)
+ }
+
+ fun criticalWebRTCServiceException(throwable: Throwable) {
+ Toast.makeText(context, "Critical error ${throwable.localizedMessage}", Toast.LENGTH_LONG).show()
+ }
+
+ fun connectionStateChange(iceConnectionState: PeerConnection.IceConnectionState?) {
+ Toast.makeText(context, "Connection State Change $iceConnectionState", Toast.LENGTH_LONG).show()
+ }
+
+ fun showError(msg: String){
+ Toast.makeText(context, "Error: $msg", Toast.LENGTH_LONG).show()
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamBinding.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamBinding.kt
new file mode 100644
index 00000000..10b3d182
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamBinding.kt
@@ -0,0 +1,66 @@
+package nl.entreco.dartsscorecard.play.stream
+
+import android.databinding.BindingAdapter
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import nl.entreco.dartsscorecard.R
+import nl.entreco.domain.streaming.*
+
+object StreamBinding {
+
+ @JvmStatic
+ @BindingAdapter("streamVisibility")
+ fun updateStreamVisibility(view: ViewGroup, state: ConnectionState) {
+ updateVisibility(state, view)
+ }
+
+ @JvmStatic
+ @BindingAdapter("streamState")
+ fun updateStreamState(view: TextView, state: ConnectionState) {
+ updateText(state, view)
+ updateDrawable(state, view)
+ updateVisibility(state, view)
+ }
+
+ private fun updateVisibility(state: ConnectionState, view: View) {
+ when (state) {
+ Unknown -> view.visibility = View.GONE
+ else -> view.visibility = View.VISIBLE
+ }
+ }
+
+ private fun updateText(state: ConnectionState, view: TextView) {
+ when (state) {
+ is Unknown -> view.text = "Unknown"
+ is Initializing -> view.text = "Init"
+ is ReadyToConnect -> view.text = "Ready to Stream"
+ is Connecting -> view.text = "Connecting"
+ is Connected -> view.text = "Streaming"
+ is Disconnecting -> view.text = "Disconnecting"
+ is Disconnected -> view.text = "Disconnected"
+ is Killing -> view.text = "Shutting down"
+ }
+ }
+
+ private fun updateDrawable(state: ConnectionState, view: TextView) {
+ when (state) {
+ is Unknown -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_connect, 0)
+ is Initializing -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_connect, 0)
+ is ReadyToConnect -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_stopped, 0)
+ is Connecting -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_live, 0)
+ is Connected -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_live, 0)
+ is Disconnecting -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_live, 0)
+ is Disconnected -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_stopped, 0)
+ is Killing -> view.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.stream_state_stopped, 0)
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamController.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamController.kt
new file mode 100644
index 00000000..017716d0
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamController.kt
@@ -0,0 +1,8 @@
+package nl.entreco.dartsscorecard.play.stream
+
+interface StreamController {
+ fun sendDisconnect()
+ fun toggleCamera()
+ fun toggleMic()
+ fun sendMessage(msg: String)
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamFragment.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamFragment.kt
new file mode 100644
index 00000000..8db884c7
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamFragment.kt
@@ -0,0 +1,140 @@
+package nl.entreco.dartsscorecard.play.stream
+
+import android.content.Context
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.base.BaseFragment
+import nl.entreco.dartsscorecard.base.PermissionHelper
+import nl.entreco.dartsscorecard.databinding.FragmentStreamBinding
+import nl.entreco.dartsscorecard.di.streaming.StreamModule
+import nl.entreco.domain.streaming.ConnectionState
+import org.webrtc.CameraVideoCapturer
+import java.util.concurrent.atomic.AtomicBoolean
+
+class StreamFragment : BaseFragment(), StreamController, CameraVideoCapturer.CameraSwitchHandler {
+
+ companion object {
+ val TAG: String = StreamFragment::class.java.name
+ }
+
+ interface Listener {
+ fun onPleaseKillMe()
+ fun onConnectionStateChanged(connectionState: ConnectionState)
+ }
+
+ private lateinit var binding: FragmentStreamBinding
+ private val component by componentProvider { it.plus(StreamModule(this, activityListener, binding.localVideoView)) }
+ private val viewModel by lazy { component.viewModel() }
+ private val permissionHelper by lazy { component.permissionHelper() }
+
+ private val isShowingFrontCamera = AtomicBoolean(true)
+ private var activityListener: StreamFragment.Listener? = null
+
+ override fun onAttach(context: Context?) {
+ super.onAttach(context)
+ activityListener = context as Listener
+ }
+
+ override fun onDetach() {
+ super.onDetach()
+ activityListener = null
+ binding.localVideoView.clearImage()
+ binding.localVideoView.release()
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ binding = DataBindingUtil.inflate(inflater, R.layout.fragment_stream, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ permissionHelper.checkStreamingPermissionsAndConnect { viewModel.attachService() }
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray) = when (requestCode) {
+ PermissionHelper.CHECK_PERMISSIONS_AND_CONNECT_REQUEST_CODE -> permissionHelper.onStreamingPermissionResult(
+ grantResults) { viewModel.attachService() }
+ else -> error("Unknown permission request code $requestCode")
+ }
+
+ override fun onStart() {
+ super.onStart()
+ viewModel.onStart()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ if (!activity?.isChangingConfigurations!!) {
+ viewModel.onStop()
+ viewModel.disconnect()
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ viewModel.onDestroy()
+ viewModel.disconnect()
+ }
+
+// override fun onSaveInstanceState(outState: Bundle) {
+// super.onSaveInstanceState(outState)
+// if (remoteVideoView.visibility == View.VISIBLE) {
+// outState.putBoolean(KEY_IN_CHAT, true)
+// }
+// }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ if (!activity?.isChangingConfigurations!!) viewModel.disconnect()
+ }
+
+// private fun initAlreadyRunningConnection() {
+//// showCamViews()
+// serviceConnection = object : ServiceConnection {
+// override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
+// onWebRtcServiceConnected((iBinder as (StreamingService.LocalBinder)).service)
+//// getPresenter().listenForDisconnectOrders()
+// // Listen for Disconnects
+// }
+//
+// override fun onServiceDisconnected(componentName: ComponentName) {
+// onWebRtcServiceDisconnected()
+// }
+// }
+// startAndBindWebRTCService(serviceConnection)
+// }
+
+ override fun sendDisconnect() {
+ viewModel.sendDisconnect()
+ }
+
+ override fun toggleCamera() {
+ viewModel.switchCamera()
+ }
+
+ override fun toggleMic() {
+ viewModel.toggleMic()
+ }
+
+ override fun sendMessage(msg: String) {
+ viewModel.sendMessage(msg)
+ }
+
+ override fun onCameraSwitchDone(p0: Boolean) {
+ isShowingFrontCamera.set(!isShowingFrontCamera.get())
+ activity?.invalidateOptionsMenu()
+
+ }
+
+ override fun onCameraSwitchError(p0: String?) {
+ activity?.invalidateOptionsMenu()
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamViewModel.kt
new file mode 100644
index 00000000..16e4db11
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/play/stream/StreamViewModel.kt
@@ -0,0 +1,187 @@
+package nl.entreco.dartsscorecard.play.stream
+
+import android.content.ComponentName
+import android.content.ServiceConnection
+import android.databinding.Observable
+import android.databinding.ObservableField
+import android.os.IBinder
+import nl.entreco.dartsscorecard.base.DialogHelper
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.streaming.StreamScope
+import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
+import nl.entreco.dartsscorecard.streaming.StreamingService
+import nl.entreco.dartsscorecard.streaming.StreamingServiceListener
+import nl.entreco.domain.streaming.*
+import nl.entreco.domain.streaming.receive.ListenForDisconnectsUsecase
+import nl.entreco.domain.streaming.send.RegisterStreamerRequest
+import nl.entreco.domain.streaming.send.RegisterStreamerResponse
+import nl.entreco.domain.streaming.send.RegisterStreamerUsecase
+import nl.entreco.shared.log.Logger
+import org.webrtc.CameraVideoCapturer
+import org.webrtc.PeerConnection
+import org.webrtc.SurfaceViewRenderer
+import javax.inject.Inject
+import javax.inject.Named
+
+class StreamViewModel @Inject constructor(
+ @ApplicationScope private val logger: Logger,
+ @ActivityScope private val dialogHelper: DialogHelper,
+ @StreamScope @Named("local") private val localVideoView: SurfaceViewRenderer,
+ @ApplicationScope private val serviceLauncher: ServiceLauncher,
+ private val registerStreamerUsecase: RegisterStreamerUsecase,
+ private val listenForDisconnectsUsecase: ListenForDisconnectsUsecase,
+ private val disconnectUsecase: DisconnectUsecase,
+ private val disconnectFromSignallingUsecase: DisconnectFromSignallingUsecase,
+ private val cameraSwitchHandler: CameraVideoCapturer.CameraSwitchHandler,
+ private val listener: StreamFragment.Listener?
+) : StreamingServiceListener {
+
+ private var remoteUuid: String? = null
+ private val connectionState = ObservableField(Unknown)
+ private val connectionChange = object : Observable.OnPropertyChangedCallback() {
+ override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
+ listener?.onConnectionStateChanged(connectionState.get()!!)
+ }
+ }
+
+ init {
+ connectionState.addOnPropertyChangedCallback(connectionChange)
+ }
+
+ private var service: StreamingService? = null
+ private val serviceConnection = object : ServiceConnection {
+ override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
+ onWebRtcServiceConnected((iBinder as (StreamingService.LocalBinder)).service)
+ dialogHelper.showStreamDialog(onCodeEntered(), onStreamCancelled())
+ }
+
+ override fun onServiceDisconnected(componentName: ComponentName) {
+ onWebRtcServiceDisconnected()
+ }
+ }
+
+ private fun onStreamCancelled(): () -> Unit = {
+ connectionState.set(Killing)
+ listener?.onPleaseKillMe()
+ }
+
+ private fun onCodeEntered(): (String) -> Unit {
+ return { code ->
+ connectionState.set(Connecting)
+ registerStreamerUsecase.go(RegisterStreamerRequest(code),
+ onRegisterSuccess(),
+ onRegisterFailed())
+ }
+ }
+
+ private fun onRegisterSuccess(): (RegisterStreamerResponse) -> Unit = { response ->
+ remoteUuid = response.uuid
+ service?.offerDevice(response.uuid)
+ listenForDisconnectsUsecase.go {
+ disconnect()
+ }
+ }
+
+ private fun onRegisterFailed(): (Throwable) -> Unit = { error ->
+ serviceLauncher.showError(error.localizedMessage)
+ connectionState.set(Killing)
+ listener?.onPleaseKillMe()
+ }
+
+ fun attachService() {
+ connectionState.set(Initializing)
+ serviceLauncher.launchStreamingService(serviceConnection)
+ }
+
+ private fun onWebRtcServiceConnected(service: StreamingService) {
+ logger.d("Service connected")
+ connectionState.set(ReadyToConnect)
+ this.service = service
+ service.attachLocalView(localVideoView)
+ service.attachServiceActionsListener(listener = this)
+ }
+
+ private fun onWebRtcServiceDisconnected() {
+ logger.d("Service disconnected")
+ connectionState.set(Disconnected)
+ }
+
+ override fun criticalWebRTCServiceException(throwable: Throwable) {
+ unbindService()
+ serviceLauncher.criticalWebRTCServiceException(throwable)
+ }
+
+ override fun connectionStateChange(iceConnectionState: PeerConnection.IceConnectionState?) {
+ serviceLauncher.connectionStateChange(iceConnectionState)
+ when (iceConnectionState) {
+ PeerConnection.IceConnectionState.CONNECTED -> {
+ connectionState.set(Connected)
+ }
+ PeerConnection.IceConnectionState.DISCONNECTED -> {
+// getView()?.showWillTryToRestartMsg()
+ connectionState.set(Disconnected)
+ disconnect()
+ }
+ else -> {
+ //no-op for now - could show or hide progress bars or messages on given event
+ }
+ }
+ }
+
+ fun onDestroy() {
+ service?.let {
+ it.detachViews()
+ unbindService()
+ }
+ }
+
+ private fun unbindService() {
+ service?.let {
+ it.detachServiceActionsListener()
+ serviceLauncher.unbindServiceConnection(serviceConnection)
+ service = null
+ localVideoView.clearImage()
+ localVideoView.release()
+ connectionState.set(Unknown)
+ }
+ }
+
+ fun sendDisconnect() {
+ connectionState.set(Disconnecting)
+ disconnectFromSignallingUsecase.go(DisconnectFromSignallingRequest(remoteUuid)) {
+ disconnect()
+ }
+ }
+
+ fun switchCamera() {
+ service?.switchCamera(cameraSwitchHandler)
+ }
+
+ fun toggleMic(){
+ service?.toggleMicrophone()
+ }
+
+ fun sendMessage(msg: String) {
+ service?.sendMessage(msg)
+ }
+
+ fun onStart() {
+ service?.hideBackground()
+ }
+
+ fun onStop() {
+ service?.showBackground()
+ }
+
+ fun disconnect() {
+ connectionState.set(Disconnecting)
+ disconnectUsecase.go{
+ connectionState.set(Disconnected)
+ connectionState.set(Unknown)
+ }
+ service?.let {
+ it.stopSelf()
+ unbindService()
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileActivity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileActivity.kt
index fbfbf138..dafcda50 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileActivity.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileActivity.kt
@@ -51,7 +51,6 @@ class SelectProfileActivity : ViewModelActivity() {
recyclerView.itemAnimator = DefaultItemAnimator()
recyclerView.setHasFixedSize(true)
recyclerView.setItemViewCacheSize(20)
- recyclerView.isDrawingCacheEnabled = true
addSwipeToDelete(binding, recyclerView)
recyclerView.adapter = adapter
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileAdapter.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileAdapter.kt
index 24115a9d..ad15f30b 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileAdapter.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileAdapter.kt
@@ -34,11 +34,12 @@ class SelectProfileAdapter(private val navigator: SelectProfileNavigator) : List
}
val diff: DiffUtil.ItemCallback = object : DiffUtil.ItemCallback() {
- override fun areItemsTheSame(oldItem: Profile?, newItem: Profile?): Boolean {
- return oldItem?.id == newItem?.id
+
+ override fun areItemsTheSame(oldItem: Profile, newItem: Profile): Boolean {
+ return oldItem.id == newItem.id
}
- override fun areContentsTheSame(oldItem: Profile?, newItem: Profile?): Boolean {
+ override fun areContentsTheSame(oldItem: Profile, newItem: Profile): Boolean {
return oldItem == newItem
}
}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileSwiper.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileSwiper.kt
index 28f60f30..9b932f3f 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileSwiper.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/select/SelectProfileSwiper.kt
@@ -9,7 +9,7 @@ import nl.entreco.dartsscorecard.base.SwipeToDeleteCallback
class SelectProfileSwiper(view: View, onSwiped: (Int) -> Unit, deleteAction: () -> Unit, undoAction: () -> Unit) : ItemTouchHelper(object : SwipeToDeleteCallback(view.context) {
- override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, p1: Int) {
onSwiped(viewHolder.adapterPosition)
val snack = Snackbar.make(view, R.string.confirm_delete_profile, Snackbar.LENGTH_LONG)
@@ -26,4 +26,8 @@ class SelectProfileSwiper(view: View, onSwiped: (Int) -> Unit, deleteAction: ()
})
snack.show()
}
+
+ override fun onMove(p0: RecyclerView, p1: RecyclerView.ViewHolder, p2: RecyclerView.ViewHolder): Boolean {
+ return false
+ }
})
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileAnimator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileAnimator.kt
index 02d8fa3e..fbf125c0 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileAnimator.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileAnimator.kt
@@ -22,9 +22,7 @@ class ProfileAnimator(binding: ActivityProfileBinding, inflater: TransitionInfla
private val revealAnimator = RevealAnimator(appBarLayout)
init {
- appBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
- animator.onOffsetChanged(appBarLayout, verticalOffset)
- }
+ appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { p0, p1 -> animator.onOffsetChanged(p0, p1) })
revealAnimator.setupEnterAnimation(inflater, window, true)
animator.startAlphaAnimation(title, 0, View.INVISIBLE)
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileBinding.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileBinding.kt
index ce9f43d2..537191b6 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileBinding.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileBinding.kt
@@ -5,7 +5,7 @@ import android.net.Uri
import android.widget.ImageView
import android.widget.TextView
import nl.entreco.dartsscorecard.R
-import nl.entreco.dartsscorecard.di.glide.GlideApp
+import nl.entreco.shared.libs.GlideApp
/**
* Created by entreco on 23/02/2018.
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileHeaderBehavior.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileHeaderBehavior.kt
index 41d97728..05de5a73 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileHeaderBehavior.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/profile/view/ProfileHeaderBehavior.kt
@@ -47,7 +47,7 @@ class ProfileHeaderBehavior(context: Context?, attrs: AttributeSet?) : Coordinat
finalLeftAvatarPadding = context.resources.getDimension(R.dimen.large)
}
- override fun layoutDependsOn(parent: CoordinatorLayout?, child: CircleImageView?, dependency: View?): Boolean {
+ override fun layoutDependsOn(parent: CoordinatorLayout, child: CircleImageView, dependency: View): Boolean {
return dependency is Toolbar || dependency is AppBarLayout
}
@@ -113,5 +113,4 @@ class ProfileHeaderBehavior(context: Context?, attrs: AttributeSet?) : Coordinat
changeBehaviorPoint = (child.height - customFinalHeight) / (2f * (startYPosition - finalYPosition))
}
}
-
}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/setup/Setup01ViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/setup/Setup01ViewModel.kt
index d18e8a8a..8353e304 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/setup/Setup01ViewModel.kt
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/setup/Setup01ViewModel.kt
@@ -1,7 +1,7 @@
package nl.entreco.dartsscorecard.setup
import nl.entreco.dartsscorecard.base.BaseViewModel
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.launch.ExtractTeamsRequest
import nl.entreco.domain.launch.ExtractTeamsResponse
import nl.entreco.domain.launch.ExtractTeamsUsecase
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/EglProvider.java b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/EglProvider.java
new file mode 100644
index 00000000..18155d95
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/EglProvider.java
@@ -0,0 +1,10 @@
+package nl.entreco.dartsscorecard.streaming;
+
+import org.webrtc.EglBase;
+
+class EglProvider {
+
+ static EglBase get(){
+ return EglBase.create();
+ }
+}
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceiverService.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceiverService.kt
new file mode 100644
index 00000000..f5c714c4
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceiverService.kt
@@ -0,0 +1,119 @@
+package nl.entreco.dartsscorecard.streaming
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.graphics.Color
+import android.os.Binder
+import android.os.Build
+import android.os.IBinder
+import android.support.v4.app.NotificationCompat
+import nl.entreco.dartsscorecard.App
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.di.service.ServiceModule
+import nl.entreco.dartsscorecard.di.streaming.StreamingModule
+import org.webrtc.SurfaceViewRenderer
+
+class ReceiverService: Service() {
+
+ companion object {
+ private const val CHANNEL_ID = "dsc_receiving_channel"
+ private const val NOTIF_ID = 301
+ private const val NOTIF_COLOR = "#A4B5CE"
+
+ fun startService(packageContext: Context) {
+ packageContext.startService(Intent(packageContext, ReceiverService::class.java))
+ }
+
+ fun bindService(context: Context, connection: ServiceConnection) {
+ context.bindService(Intent(context, ReceiverService::class.java), connection, 0)
+ }
+ }
+
+ private val app by lazy { application as App }
+ private val component by lazy { app.appComponent.plus(ServiceModule(this)) }
+ private val receivingController : ReceivingController by lazy { component.plus(StreamingModule()).receivingController()}
+ private val binder = LocalBinder()
+
+ private val notificationManager: NotificationManager by lazy {
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ }
+
+ private val notif by lazy {
+ NotificationCompat.Builder(baseContext, CHANNEL_ID)
+ .setOngoing(true)
+ .setContentTitle(getString(R.string.streaming_notif_title))
+ .setSmallIcon(R.drawable.ic_stat_name)
+ .setColor(Color.parseColor(NOTIF_COLOR))
+ .setBadgeIconType(R.mipmap.ic_launcher_foreground)
+ .setLocalOnly(true)
+ .setWhen(System.currentTimeMillis())
+ .setUsesChronometer(true)
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .setPriority(NotificationCompat.PRIORITY_LOW)
+ }
+
+ override fun onBind(intent: Intent?): IBinder = binder
+
+ override fun onCreate() {
+ super.onCreate()
+ receivingController.attachService(this)
+ }
+
+ override fun onDestroy() {
+ receivingController.detachService()
+ hideBackground()
+ super.onDestroy()
+ }
+
+ fun attachServiceActionsListener(listener: ReceivingServiceListener) {
+ receivingController.serviceListener = listener
+ }
+
+ fun detachServiceActionsListener() {
+ receivingController.serviceListener = null
+ }
+
+ fun attachRemoteView(remoteView: SurfaceViewRenderer) {
+ receivingController.attachRemoteView(remoteView)
+ }
+
+ fun onStop() {
+ hideBackground()
+ stopSelf()
+ }
+
+ fun detachViews() {
+ receivingController.detachViews()
+ }
+
+ fun showBackground(){
+ registerChannel()
+ notificationManager.notify(NOTIF_ID, notif.build())
+ }
+
+ fun hideBackground(){
+ notificationManager.cancel(NOTIF_ID)
+ }
+
+ private fun registerChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = getString(R.string.streaming_channel_name)
+ val desc = getString(R.string.streaming_channel_description)
+ val importance = NotificationManager.IMPORTANCE_MIN
+ val channel = NotificationChannel(CHANNEL_ID, name, importance)
+ channel.description = desc
+ // Register channel with the system
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+
+ inner class LocalBinder : Binder() {
+ val service: ReceiverService
+ get() = this@ReceiverService
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceivingController.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceivingController.kt
new file mode 100644
index 00000000..f68810da
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceivingController.kt
@@ -0,0 +1,146 @@
+package nl.entreco.dartsscorecard.streaming
+
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.service.ServiceScope
+import nl.entreco.dartsscorecard.di.streaming.StreamingScope
+import nl.entreco.dartsscorecard.streaming.constraints.OfferAnswerConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.WebRtcConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.addConstraints
+import nl.entreco.domain.streaming.ice.*
+import nl.entreco.shared.log.Logger
+import org.webrtc.MediaConstraints
+import org.webrtc.SessionDescription
+import org.webrtc.SurfaceViewRenderer
+import java.util.concurrent.ExecutorService
+import javax.inject.Inject
+
+class ReceivingController @Inject constructor(
+ @ApplicationScope private val logger: Logger,
+ @StreamingScope private val singleThreadExecutor: ExecutorService,
+ @StreamingScope private val webRtcController: WebRtcController,
+ @ServiceScope private val listenForOfferUsecase: ListenForOfferUsecase,
+ @ServiceScope private val sendAnswerUsecase: SendAnswerUsecase
+) {
+
+ private var service: ReceiverService? = null
+ var serviceListener: ReceivingServiceListener? = null
+ private var remoteUuid: String? = null
+
+ private lateinit var answeringPartyHandler: WebRtcAnsweringPartyHandler
+
+ private val offerAnswerConstraints by lazy {
+ WebRtcConstraints().apply {
+ addMandatoryConstraint(OfferAnswerConstraints.OFFER_TO_RECEIVE_AUDIO, true)
+ addMandatoryConstraint(OfferAnswerConstraints.OFFER_TO_RECEIVE_VIDEO, true)
+ }
+ }
+
+ init {
+ singleThreadExecutor.execute {
+ initialize()
+ }
+ }
+
+ private fun initialize() {
+ webRtcController.initializeReceiver()
+ }
+
+ fun attachService(service: ReceiverService) {
+ this.service = service
+ this.webRtcController.fetchIceServers(onServersRetrieved(), onCriticalError())
+ }
+
+ private fun onServersRetrieved(): (FetchIceServerResponse) -> Unit {
+ return { response ->
+ listenForOffers()
+ initializeWebRtcReceiver(response.iceServers,
+ object : WebRtcAnsweringPartyHandler.Listener {
+ override fun onError(error: String) {
+ logger.e("WEBRTC: Error in answering party: $error")
+ }
+
+ override fun onSuccess(localSessionDescription: SessionDescription) {
+ logger.w("WEBRTC: onSuccess $localSessionDescription")
+ sendAnswer(localSessionDescription)
+ }
+ })
+ }
+ }
+
+ private fun sendAnswer(localDescription: SessionDescription) {
+ val recipientUuid = remoteUuid ?: throw IllegalArgumentException(
+ "Remote uuid should be set first")
+ val session = DscSessionDescription(localDescription.type.ordinal,
+ localDescription.description)
+ sendAnswerUsecase.go(SendAnswerRequest(recipientUuid, session), onCriticalError())
+ }
+
+ private fun onCriticalError(): (Throwable) -> Unit = { err ->
+ serviceListener?.criticalWebRTCServiceException(err)
+ service?.onStop()
+ }
+
+ private fun initializeWebRtcReceiver(servers: List,
+ listener: WebRtcAnsweringPartyHandler.Listener) {
+ val peerConnection = webRtcController.createReceiverConnection(servers,
+ connectionChange = {
+ serviceListener?.connectionStateChange(it)
+ })
+
+ answeringPartyHandler = WebRtcAnsweringPartyHandler(logger, peerConnection!!,
+ getOfferAnswerConstraints(), listener)
+ }
+
+ private fun listenForOffers() {
+ listenForOfferUsecase.go({ response ->
+
+ logger.w("WEBRTC: listenForNewOffersWithUuid $response")
+
+ this.remoteUuid = response.senderUuid
+ webRtcController.listenForIceCandidate(response.senderUuid, onCriticalError())
+
+ val type = SessionDescription.Type.values()[response.sessionType]
+ val session = SessionDescription(type, response.sessionDescription)
+ handleRemoteOffer(session)
+
+ }, onCriticalError())
+ }
+
+ private fun handleRemoteOffer(remoteSessionDescription: SessionDescription) {
+ singleThreadExecutor.execute {
+ answeringPartyHandler.handleRemoteOffer(remoteSessionDescription)
+ }
+ }
+
+ /**
+ * Attach [SurfaceViewRenderer] to webrtc client used for rendering remote view.
+ */
+ fun attachRemoteView(remoteView: SurfaceViewRenderer) {
+ webRtcController.attachRemoteView(remoteView)
+ }
+
+ fun detachService() {
+ this.service = null
+ }
+
+ fun detachViews() {
+ webRtcController.detachViews()
+ }
+
+ /**
+ * Safety net in case the owner of an object forgets to call its explicit termination method.
+ * @see
+ * https://kotlinlang.org/docs/reference/java-interop.html#finalize
+ */
+ @Suppress("unused", "ProtectedInFinal")
+ protected fun finalize() {
+ if (!singleThreadExecutor.isShutdown) {
+ webRtcController.dispose()
+ singleThreadExecutor.shutdown()
+ }
+ }
+
+ private fun getOfferAnswerConstraints() = MediaConstraints().apply {
+ addConstraints(offerAnswerConstraints)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceivingServiceListener.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceivingServiceListener.kt
new file mode 100644
index 00000000..a58ef43d
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/ReceivingServiceListener.kt
@@ -0,0 +1,13 @@
+package nl.entreco.dartsscorecard.streaming
+
+import org.webrtc.PeerConnection
+
+interface ReceivingServiceListener {
+
+ /**
+ * When receiving this exception service is in unrecoverable state and will call stopSelf, bound view(if any) should unbind
+ */
+ fun criticalWebRTCServiceException(throwable: Throwable)
+
+ fun connectionStateChange(iceConnectionState: PeerConnection.IceConnectionState?)
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingController.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingController.kt
new file mode 100644
index 00000000..79fdaa6c
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingController.kt
@@ -0,0 +1,228 @@
+package nl.entreco.dartsscorecard.streaming
+
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.service.ServiceScope
+import nl.entreco.dartsscorecard.di.streaming.StreamingScope
+import nl.entreco.dartsscorecard.streaming.constraints.OfferAnswerConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.WebRtcConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.addConstraints
+import nl.entreco.domain.streaming.ice.*
+import nl.entreco.shared.log.Logger
+import org.webrtc.*
+import java.nio.ByteBuffer
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.atomic.AtomicBoolean
+import javax.inject.Inject
+
+class StreamingController @Inject constructor(
+ @ApplicationScope private val logger: Logger,
+ @StreamingScope private val singleThreadExecutor: ExecutorService,
+ @StreamingScope private val webRtcController: WebRtcController,
+ @ServiceScope private val listenForAnswersUsecase: ListenForAnswersUsecase,
+ @ServiceScope private val createOfferUsecase: CreateOfferUsecase,
+ @StreamingScope private val videoCameraCapturer: CameraVideoCapturer?) {
+
+ private var service: StreamingService? = null
+ var serviceListener: StreamingServiceListener? = null
+ private var remoteUuid: String? = null
+
+ private var dataChannel : DataChannel? = null
+
+ private var finishedInitializing = AtomicBoolean(false)
+ private var shouldCreateOffer = AtomicBoolean(false)
+
+ private lateinit var offeringPartyHandler: WebRtcOfferingPartyHandler
+
+ private val offerAnswerConstraints by lazy {
+ WebRtcConstraints().apply {
+ addMandatoryConstraint(OfferAnswerConstraints.OFFER_TO_RECEIVE_AUDIO, true)
+ addMandatoryConstraint(OfferAnswerConstraints.OFFER_TO_RECEIVE_VIDEO, true)
+ }
+ }
+
+ init {
+ singleThreadExecutor.execute {
+ initialize()
+ }
+ }
+
+ private fun initialize() {
+ webRtcController.initializeStreamer(videoCameraCapturer)
+ if (videoCameraCapturer != null) {
+ enableVideo(cameraEnabled, videoCameraCapturer)
+ }
+ }
+
+ fun attachService(service: StreamingService) {
+ this.service = service
+ this.webRtcController.fetchIceServers(onServersRetrieved(), onCriticalError())
+ }
+
+ private fun onServersRetrieved(): (FetchIceServerResponse) -> Unit {
+ return { response ->
+ initializeWebRtcStreamer(response.iceServers,
+ object : WebRtcOfferingPartyHandler.Listener {
+ override fun onError(error: String) {
+ logger.e("WEBRTC: Error in offering party: $error")
+ }
+
+ override fun onOfferRemoteDescription(
+ localSessionDescription: SessionDescription) {
+ logger.w("WEBRTC: onOfferRemoteDescription $localSessionDescription")
+ listenForAnswers()
+ sendOffer(localSessionDescription)
+ }
+ })
+ }
+ }
+
+
+ private fun initializeWebRtcStreamer(servers: List,
+ listener: WebRtcOfferingPartyHandler.Listener) {
+
+ val peerConnection = webRtcController.createStreamerConnection(servers,
+ connectionChange = {
+ if (it == PeerConnection.IceConnectionState.DISCONNECTED) {
+ restart()
+ }
+ serviceListener?.connectionStateChange(it)
+ })
+
+ val init = DataChannel.Init()
+ init.id = 501
+ dataChannel = peerConnection?.createDataChannel("match", init)
+ offeringPartyHandler = WebRtcOfferingPartyHandler(logger, peerConnection!!, listener)
+
+ if (shouldCreateOffer.get()) createOffer()
+ finishedInitializing.set(true)
+ }
+
+ private fun restart() {
+ singleThreadExecutor.execute {
+ offeringPartyHandler.createOffer(getOfferAnswerRestartConstraints())
+ }
+ }
+
+ private fun sendOffer(localDescription: SessionDescription) {
+ val recipientUuid = remoteUuid ?: throw IllegalArgumentException(
+ "Remote uuid should be set first")
+ val session = DscSessionDescription(localDescription.type.ordinal,
+ localDescription.description)
+ createOfferUsecase.go(CreateOfferRequest(recipientUuid, session), onCriticalError())
+ }
+
+ private fun createOffer() {
+ singleThreadExecutor.execute {
+ offeringPartyHandler.createOffer(getOfferAnswerConstraints())
+ }
+ }
+
+ private fun onCriticalError(): (Throwable) -> Unit = { err ->
+ serviceListener?.criticalWebRTCServiceException(err)
+ service?.onStop()
+ }
+
+ fun detachService() {
+ this.service = null
+ }
+
+ fun detachViews() {
+ webRtcController.detachViews()
+ }
+
+ fun offerDevice(deviceUuid: String) {
+ remoteUuid = deviceUuid
+ webRtcController.listenForIceCandidate(deviceUuid, onCriticalError())
+
+ if (finishedInitializing.get()) createOffer() else shouldCreateOffer.set(true)
+
+ }
+
+ fun attachLocalView(localView: SurfaceViewRenderer) {
+ webRtcController.attachLocalView(localView)
+ }
+
+ /**
+ * Safety net in case the owner of an object forgets to call its explicit termination method.
+ * @see
+ * https://kotlinlang.org/docs/reference/java-interop.html#finalize
+ */
+ @Suppress("unused", "ProtectedInFinal")
+ protected fun finalize() {
+ if (!singleThreadExecutor.isShutdown) {
+ dataChannel?.dispose()
+ webRtcController.dispose()
+ videoCameraCapturer?.dispose()
+ singleThreadExecutor.shutdown()
+ }
+ }
+
+ private val localVideoWidth: Int = 1280
+ private val localVideoHeight: Int = 720
+ private val localVideoFps: Int = 24
+ private var cameraEnabled = true
+ set(isEnabled) {
+ field = isEnabled
+ singleThreadExecutor.execute {
+ videoCameraCapturer?.let { enableVideo(isEnabled, it) }
+ }
+ }
+
+ private fun enableVideo(isEnabled: Boolean, videoCapturer: CameraVideoCapturer) {
+ if (isEnabled) {
+ videoCapturer.startCapture(localVideoWidth, localVideoHeight, localVideoFps)
+ } else {
+ videoCapturer.stopCapture()
+ }
+ }
+
+ private fun listenForAnswers() {
+ listenForAnswersUsecase.go({ response ->
+
+ logger.w("WEBRTC: Listen for Answers $response")
+
+ val type = SessionDescription.Type.values()[response.sessionType]
+ val sessionDescription = SessionDescription(type, response.sessionDescription)
+ handleRemoteAnswer(sessionDescription)
+
+ }, onCriticalError())
+
+ }
+
+ /**
+ * Handles received remote answer to our offer.
+ */
+ private fun handleRemoteAnswer(remoteSessionDescription: SessionDescription) {
+ singleThreadExecutor.execute {
+ offeringPartyHandler.handleRemoteAnswer(remoteSessionDescription)
+ }
+ }
+
+ /**
+ * Switches the camera to other if there is any available. By default front camera is used.
+ * @param cameraSwitchHandler allows listening for switch camera event
+ */
+ @JvmOverloads
+ fun switchCamera(cameraSwitchHandler: CameraVideoCapturer.CameraSwitchHandler? = null) {
+ singleThreadExecutor.execute {
+ videoCameraCapturer?.switchCamera(cameraSwitchHandler)
+ }
+ }
+
+ fun toggleMic() {
+ webRtcController.toggleMic()
+ }
+
+ fun sendMessage(msg: String) {
+ val buffer = DataChannel.Buffer(ByteBuffer.wrap(msg.toByteArray()), false)
+ dataChannel?.send(buffer)
+ }
+
+ private fun getOfferAnswerConstraints() = MediaConstraints().apply {
+ addConstraints(offerAnswerConstraints)
+ }
+
+ private fun getOfferAnswerRestartConstraints() = getOfferAnswerConstraints().apply {
+ mandatory.add(OfferAnswerConstraints.ICE_RESTART.toKeyValuePair(true))
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingService.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingService.kt
new file mode 100644
index 00000000..b432cda9
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingService.kt
@@ -0,0 +1,134 @@
+package nl.entreco.dartsscorecard.streaming
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.graphics.Color
+import android.os.Binder
+import android.os.Build
+import android.os.IBinder
+import android.support.v4.app.NotificationCompat
+import nl.entreco.dartsscorecard.App
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.di.service.ServiceModule
+import nl.entreco.dartsscorecard.di.streaming.StreamingModule
+import org.webrtc.CameraVideoCapturer
+import org.webrtc.SurfaceViewRenderer
+
+class StreamingService : Service() {
+
+ companion object {
+ private const val CHANNEL_ID = "dsc_streaming_channel"
+ private const val NOTIF_ID = 501
+ private const val NOTIF_COLOR = "#A4B5CE"
+
+ fun startService(packageContext: Context) {
+ packageContext.startService(Intent(packageContext, StreamingService::class.java))
+ }
+
+ fun bindService(context: Context, connection: ServiceConnection) {
+ context.bindService(Intent(context, StreamingService::class.java), connection, 0)
+ }
+ }
+
+ private val app by lazy { application as App }
+ private val component by lazy { app.appComponent.plus(ServiceModule(this)) }
+ private val streamingController: StreamingController by lazy { component.plus(StreamingModule()).streamingController() }
+ private val binder = LocalBinder()
+
+ private val notificationManager: NotificationManager by lazy {
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ }
+
+ private val notif by lazy {
+ NotificationCompat.Builder(baseContext, CHANNEL_ID)
+ .setOngoing(true)
+ .setContentTitle(getString(R.string.streaming_notif_title))
+ .setSmallIcon(R.drawable.ic_stat_name)
+ .setColor(Color.parseColor(NOTIF_COLOR))
+ .setBadgeIconType(R.mipmap.ic_launcher_foreground)
+ .setLocalOnly(true)
+ .setWhen(System.currentTimeMillis())
+ .setUsesChronometer(true)
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .setPriority(NotificationCompat.PRIORITY_LOW)
+ }
+
+ override fun onBind(intent: Intent?): IBinder = binder
+
+ override fun onCreate() {
+ super.onCreate()
+ streamingController.attachService(this)
+ }
+
+ override fun onDestroy() {
+ streamingController.detachService()
+ hideBackground()
+ super.onDestroy()
+ }
+
+ fun attachServiceActionsListener(listener: StreamingServiceListener) {
+ streamingController.serviceListener = listener
+ }
+
+ fun detachServiceActionsListener() {
+ streamingController.serviceListener = null
+ }
+
+ fun offerDevice(deviceUuid: String) {
+ streamingController.offerDevice(deviceUuid)
+ }
+
+ fun attachLocalView(localView: SurfaceViewRenderer) {
+ streamingController.attachLocalView(localView)
+ }
+
+ fun onStop() {
+ hideBackground()
+ stopSelf()
+ }
+
+ fun detachViews() {
+ streamingController.detachViews()
+ }
+
+ fun switchCamera(
+ handler: CameraVideoCapturer.CameraSwitchHandler? = null) = streamingController.switchCamera(
+ handler)
+
+ fun toggleMicrophone() = streamingController.toggleMic()
+
+ fun sendMessage(msg: String) {
+ streamingController.sendMessage(msg)
+ }
+
+ fun showBackground() {
+ registerChannel()
+ notificationManager.notify(NOTIF_ID, notif.build())
+ }
+
+ fun hideBackground() {
+ notificationManager.cancel(NOTIF_ID)
+ }
+
+ private fun registerChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = getString(R.string.streaming_channel_name)
+ val desc = getString(R.string.streaming_channel_description)
+ val importance = NotificationManager.IMPORTANCE_MIN
+ val channel = NotificationChannel(CHANNEL_ID, name, importance)
+ channel.description = desc
+ // Register channel with the system
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+
+ inner class LocalBinder : Binder() {
+ val service: StreamingService
+ get() = this@StreamingService
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingServiceListener.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingServiceListener.kt
new file mode 100644
index 00000000..fc969a42
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/StreamingServiceListener.kt
@@ -0,0 +1,13 @@
+package nl.entreco.dartsscorecard.streaming
+
+import org.webrtc.PeerConnection
+
+interface StreamingServiceListener {
+
+ /**
+ * When receiving this exception service is in unrecoverable state and will call stopSelf, bound view(if any) should unbind
+ */
+ fun criticalWebRTCServiceException(throwable: Throwable)
+
+ fun connectionStateChange(iceConnectionState: PeerConnection.IceConnectionState?)
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcAnsweringPartyHandler.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcAnsweringPartyHandler.kt
new file mode 100644
index 00000000..b9027cef
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcAnsweringPartyHandler.kt
@@ -0,0 +1,97 @@
+package nl.entreco.dartsscorecard.streaming
+
+import nl.entreco.shared.log.Logger
+import org.webrtc.MediaConstraints
+import org.webrtc.PeerConnection
+import org.webrtc.SdpObserver
+import org.webrtc.SessionDescription
+
+internal class WebRtcAnsweringPartyHandler(
+ private val logger: Logger,
+ private val peer: PeerConnection,
+ private val offerAnswerConstraints: MediaConstraints,
+ private val listener: Listener) {
+
+ interface Listener {
+ /**
+ * Triggered in case of internal errors.
+ */
+ fun onError(error: String)
+
+ /**
+ * Triggered when local session description from answering party is created.
+ * [localSessionDescription] object should be sent to the other party through established connection channel.
+ */
+ fun onSuccess(localSessionDescription: SessionDescription)
+ }
+
+ fun handleRemoteOffer(remoteSessionDescription: SessionDescription) {
+ peer.setRemoteDescription(object : SdpObserver{
+ override fun onSetFailure(error: String) {
+ logger.w("onSetFailure")
+ listener.onError(error)
+ }
+
+ override fun onSetSuccess() {
+ logger.w("onSetSuccess")
+ createAnswer()
+ }
+
+ override fun onCreateSuccess(p0: SessionDescription?) {
+ logger.w("onCreateSuccess")
+ }
+
+ override fun onCreateFailure(p0: String?) {
+ logger.w("onCreateFailure")
+ }
+ }, remoteSessionDescription)
+ }
+
+ private fun createAnswer() {
+
+ peer.createAnswer(object : SdpObserver {
+ override fun onSetFailure(p0: String?) {
+ logger.w("onSetFailure")
+ }
+
+ override fun onSetSuccess() {
+ logger.w("onSetSuccess")
+ }
+
+ override fun onCreateSuccess(sessionDescription: SessionDescription) {
+ logger.w("onCreateSuccess")
+ setLocalAnswerDescription(sessionDescription)
+ }
+
+ override fun onCreateFailure(error: String) {
+ logger.w("onCreateFailure")
+ listener.onError(error)
+ }
+
+ }, offerAnswerConstraints)
+ }
+
+ private fun setLocalAnswerDescription(sessionDescription: SessionDescription) {
+
+ peer.setLocalDescription(object : SdpObserver {
+
+ override fun onCreateSuccess(p0: SessionDescription?) {
+ logger.w("onCreateSuccess")
+ }
+
+ override fun onCreateFailure(p0: String?) {
+ logger.w("onCreateFailure")
+ }
+
+ override fun onSetSuccess() {
+ logger.w("onSetSuccess")
+ listener.onSuccess(sessionDescription)
+ }
+
+ override fun onSetFailure(error: String) {
+ logger.w("onSetFailure")
+ listener.onError(error)
+ }
+ }, sessionDescription)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcController.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcController.kt
new file mode 100644
index 00000000..6b529187
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcController.kt
@@ -0,0 +1,333 @@
+package nl.entreco.dartsscorecard.streaming
+
+import android.os.Handler
+import android.os.Looper
+import android.view.View
+import com.google.gson.GsonBuilder
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.service.ServiceScope
+import nl.entreco.dartsscorecard.di.streaming.StreamingScope
+import nl.entreco.dartsscorecard.streaming.constraints.BooleanAudioConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.IntegerAudioConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.WebRtcConstraints
+import nl.entreco.dartsscorecard.streaming.constraints.addConstraints
+import nl.entreco.domain.streaming.ice.*
+import nl.entreco.domain.streaming.p2p.RemoveIceCandidateRequest
+import nl.entreco.domain.streaming.p2p.RemoveIceCandidateUsecase
+import nl.entreco.domain.streaming.p2p.SendIceCandidateRequest
+import nl.entreco.domain.streaming.p2p.SendIceCandidateUsecase
+import nl.entreco.shared.log.Logger
+import org.webrtc.*
+import java.nio.ByteBuffer
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.atomic.AtomicInteger
+import javax.inject.Inject
+
+class WebRtcController @Inject constructor(
+ @ApplicationScope private val logger: Logger,
+ @StreamingScope private val singleThreadExecutor: ExecutorService,
+ @ServiceScope private val sendIceCandidateUsecase: SendIceCandidateUsecase,
+ @ServiceScope private val removeIceCandidateUsecase: RemoveIceCandidateUsecase,
+ @ServiceScope private val fetchIceServersUsecase: FetchIceServerUsecase,
+ @ServiceScope private val listenForIceServersUsecase: ListenForIceCandidatesUsecase,
+ @StreamingScope private val peerConnectionFactory: PeerConnectionFactory
+) {
+
+ private val counter = AtomicInteger(0)
+ private val eglBase = EglProvider.get()
+ private val mainThreadHandler = Handler(Looper.getMainLooper())
+ private val isPeerConnectionInitialized = AtomicBoolean(false)
+
+ private var peerConnection: PeerConnection? = null
+ private var localView: SurfaceViewRenderer? = null
+
+ private lateinit var audioSource: AudioSource
+ private lateinit var localAudioTrack: AudioTrack
+
+ private var videoSource: VideoSource? = null
+ private var localVideoTrack: VideoTrack? = null
+
+ private var remoteView: SurfaceViewRenderer? = null
+ private var remoteVideoTrack: VideoTrack? = null
+
+ fun initializeReceiver() {
+ audioSource = peerConnectionFactory.createAudioSource(getAudioMediaConstraints())
+ localAudioTrack = peerConnectionFactory.createAudioTrack(
+ getCounterStringValueAndIncrement(), audioSource)
+ }
+
+ fun initializeStreamer(videoCameraCapturer: CameraVideoCapturer?) {
+ if (videoCameraCapturer != null) {
+ peerConnectionFactory.setVideoHwAccelerationOptions(eglBase.eglBaseContext, eglBase.eglBaseContext)
+ videoSource = peerConnectionFactory.createVideoSource(videoCameraCapturer)
+ localVideoTrack = peerConnectionFactory.createVideoTrack(
+ counter.getAndIncrement().toString(), videoSource)
+ }
+
+ audioSource = peerConnectionFactory.createAudioSource(getAudioMediaConstraints())
+ localAudioTrack = peerConnectionFactory.createAudioTrack(
+ getCounterStringValueAndIncrement(), audioSource)
+ }
+
+ private fun getCounterStringValueAndIncrement() = counter.getAndIncrement().toString()
+
+ private val audioBooleanConstraints by lazy {
+ WebRtcConstraints().apply {
+ addMandatoryConstraint(BooleanAudioConstraints.DISABLE_AUDIO_PROCESSING, true)
+ }
+ }
+
+ private val audioIntegerConstraints by lazy {
+ WebRtcConstraints()
+ }
+
+ private fun getAudioMediaConstraints() = MediaConstraints().apply {
+ addConstraints(audioBooleanConstraints, audioIntegerConstraints)
+ }
+
+ fun fetchIceServers(done: (FetchIceServerResponse) -> Unit, fail: (Throwable) -> Unit) {
+ fetchIceServersUsecase.go(done, fail)
+ }
+
+ fun createReceiverConnection(servers: List,
+ connectionChange: (PeerConnection.IceConnectionState?) -> Unit): PeerConnection? {
+ val iceServers = servers.map { PeerConnection.IceServer.builder(it.uri).createIceServer() }
+ peerConnection = peerConnectionFactory.createPeerConnection(iceServers,
+ object : PeerConnection.Observer {
+ override fun onIceCandidate(iceCandidate: IceCandidate?) {
+ logger.w("PEER: onIceCandidate")
+ sendIceCandidate(iceCandidate)
+ }
+
+ override fun onDataChannel(p0: DataChannel?) {
+ logger.w("PEER: onDataChannel")
+ p0?.registerObserver(object : DataChannel.Observer{
+ override fun onMessage(p0: DataChannel.Buffer?) {
+ logger.w("PEER: onDataChannel onMessage: $p0")
+ val msg1 = p0?.data?.toString()
+ logger.w("PEER: onDataChannel onMessage: $msg1")
+ val ba = ByteArray(p0?.data?.capacity() ?: 0)
+ p0?.data?.get(ba)
+ val msg2 = String(ba)
+ logger.w("PEER: onDataChannel onMessage: $msg2")
+
+ val msg3 = p0?.data?.array()?.let {
+ String(it)
+ }
+ logger.w("PEER: onDataChannel onMessage: $msg3")
+ }
+
+ override fun onBufferedAmountChange(p0: Long) {
+ logger.w("PEER: onDataChannel onBufferedAmountChange: $p0")
+ }
+
+ override fun onStateChange() {
+ logger.w("PEER: onDataChannel onStateChange")
+ }
+ })
+ }
+
+ override fun onIceConnectionReceivingChange(p0: Boolean) {
+ logger.w("PEER: onIceConnectionReceivingChange")
+ }
+
+ override fun onIceConnectionChange(
+ iceConnectionState: PeerConnection.IceConnectionState?) {
+ logger.w("PEER: onIceConnectionChange")
+ logger.w("WEBRTC: onIceConnectionChange $iceConnectionState")
+ // NOTE: Restart is for StreamingController only
+ mainThreadHandler.post {
+ connectionChange(iceConnectionState)
+ }
+
+ }
+
+ override fun onIceGatheringChange(p0: PeerConnection.IceGatheringState?) {
+ logger.w("PEER: onIceGatheringChange")
+ }
+
+ override fun onAddStream(p0: MediaStream?) {
+ logger.w("PEER: onAddStream $p0")
+ if (p0?.videoTracks?.isNotEmpty() == true) {
+ onAddRemoteVideoStream(p0.videoTracks[0])
+ }
+ }
+
+ override fun onSignalingChange(p0: PeerConnection.SignalingState?) {
+ logger.w("PEER: onSignalingChange")
+ }
+
+ override fun onIceCandidatesRemoved(iceCandidates: Array?) {
+ logger.w("PEER: onIceCandidatesRemoved")
+ removeIceCandidates(iceCandidates)
+ }
+
+ override fun onRemoveStream(p0: MediaStream?) {
+ logger.w("PEER: onRemoveStream")
+ removeVideoStream()
+ }
+
+ override fun onRenegotiationNeeded() {
+ logger.w("PEER: onRenegotiationNeeded")
+ }
+
+ override fun onAddTrack(p0: RtpReceiver?, p1: Array?) {
+ logger.w("PEER: onAddTrack")
+ }
+ })
+
+ isPeerConnectionInitialized.set(true)
+ return peerConnection
+ }
+
+ fun createStreamerConnection(servers: List,
+ connectionChange: (PeerConnection.IceConnectionState?) -> Unit): PeerConnection? {
+ peerConnection = createReceiverConnection(servers, connectionChange)
+
+ val localMediaStream = peerConnectionFactory.createLocalMediaStream(
+ getCounterStringValueAndIncrement())
+ localMediaStream.addTrack(localAudioTrack)
+ localVideoTrack?.let { localMediaStream.addTrack(it) }
+ peerConnection?.addStream(localMediaStream)
+
+ return peerConnection
+ }
+
+ fun listenForIceCandidate(deviceUuid: String, fail: (Throwable) -> Unit) {
+ listenForIceServersUsecase.go(ListenForIceCandidatesRequest(deviceUuid), { response ->
+
+ val candidate = IceCandidate(response.candidate.sdpMid,
+ response.candidate.sdpMLineIndex, response.candidate.sdp)
+ if (response.shouldAdd) {
+ // Add DscIceCandidate to webRtc
+ addRemoteIceCandidate(candidate)
+ } else {
+ // Remove DscIceCandidate from webRtc
+ removeRemoteIceCandidate(arrayOf(candidate))
+ }
+
+ }, fail)
+ }
+
+ private fun onAddRemoteVideoStream(remoteVideoTrack: VideoTrack) {
+ singleThreadExecutor.execute {
+ this.remoteVideoTrack = remoteVideoTrack
+ remoteVideoTrack.addSink(remoteView)
+ }
+ }
+
+ private fun removeVideoStream() {
+ singleThreadExecutor.execute {
+ remoteVideoTrack = null
+ }
+ }
+
+
+ private fun sendIceCandidate(iceCandidate: IceCandidate?) {
+ iceCandidate?.let { ice ->
+ val candidate = DscIceCandidate(ice.sdpMid, ice.sdpMLineIndex, ice.sdp)
+ sendIceCandidateUsecase.go(SendIceCandidateRequest(candidate),
+ done = { logger.i("Added IceCandidate $candidate") },
+ fail = { logger.w("Unable to add IceCandidate $candidate") })
+ }
+ }
+
+ private fun removeIceCandidates(iceCandidates: Array?) {
+ iceCandidates?.let { ices ->
+ val candidates = ices.map { DscIceCandidate(it.sdpMid, it.sdpMLineIndex, it.sdp) }
+ .toTypedArray()
+ removeIceCandidateUsecase.go(RemoveIceCandidateRequest(candidates),
+ done = { logger.i("Removed IceCandidate $candidates") },
+ fail = { logger.w("Unable to Remove IceCandidates $candidates") })
+ }
+ }
+
+ /**
+ * Adds ice candidate from remote party to webrtc client
+ */
+ private fun addRemoteIceCandidate(iceCandidate: IceCandidate) {
+ singleThreadExecutor.execute {
+ peerConnection?.addIceCandidate(iceCandidate)
+ }
+ }
+
+ /**
+ * Removes ice candidates
+ */
+ private fun removeRemoteIceCandidate(iceCandidates: Array) {
+ singleThreadExecutor.execute {
+ peerConnection?.removeIceCandidates(iceCandidates)
+ }
+ }
+
+ fun toggleMic(){
+ singleThreadExecutor.execute {
+ localAudioTrack.setEnabled(!localAudioTrack.enabled())
+ }
+ }
+
+ fun attachLocalView(localView: SurfaceViewRenderer) {
+ mainThreadHandler.post {
+ localView.init(eglBase.eglBaseContext, null)
+ this@WebRtcController.localView = localView
+ singleThreadExecutor.execute {
+ localVideoTrack?.addSink(localView)
+ }
+ }
+ }
+
+ private fun detachLocalView() {
+ singleThreadExecutor.execute {
+ localVideoTrack?.removeSink(localView)
+ }
+ mainThreadHandler.post {
+ localView?.clearImage()
+ localView?.release()
+ localView = null
+ }
+ }
+
+ fun attachRemoteView(remoteView: SurfaceViewRenderer) {
+ mainThreadHandler.post {
+ remoteView.visibility = View.VISIBLE
+ remoteView.init(eglBase.eglBaseContext, null)
+ this@WebRtcController.remoteView = remoteView
+ singleThreadExecutor.execute {
+ remoteVideoTrack?.addSink(remoteView)
+ }
+ }
+ }
+
+ private fun detachRemoteView() {
+ mainThreadHandler.post {
+ remoteView?.clearImage()
+ remoteView?.release()
+ remoteView = null
+ }
+ singleThreadExecutor.execute {
+ remoteVideoTrack?.removeSink(remoteView)
+ }
+ }
+
+ fun detachViews() {
+ detachLocalView()
+ detachRemoteView()
+ }
+
+ fun dispose() {
+ singleThreadExecutor.execute {
+ if (isPeerConnectionInitialized.get()) {
+ peerConnection?.close()
+ peerConnection?.dispose()
+ }
+ eglBase.release()
+ audioSource.dispose()
+ videoSource?.dispose()
+ peerConnectionFactory.dispose()
+ }
+ singleThreadExecutor.shutdown()
+ }
+
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcOfferingPartyHandler.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcOfferingPartyHandler.kt
new file mode 100644
index 00000000..60b9dd02
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/WebRtcOfferingPartyHandler.kt
@@ -0,0 +1,84 @@
+package nl.entreco.dartsscorecard.streaming
+
+import nl.entreco.shared.log.Logger
+import org.webrtc.MediaConstraints
+import org.webrtc.PeerConnection
+import org.webrtc.SdpObserver
+import org.webrtc.SessionDescription
+
+internal class WebRtcOfferingPartyHandler (
+ private val logger: Logger,
+ private val peer: PeerConnection,
+ private val webRtcActionListener: Listener) {
+
+ interface Listener {
+ /**
+ * Triggered in case of internal errors.
+ */
+ fun onError(error: String)
+
+ /**
+ * Called when local session description from offering party is created.
+ * [localSessionDescription] object should be sent to the other party through established connection channel.
+ */
+ fun onOfferRemoteDescription(localSessionDescription: SessionDescription)
+ }
+
+ companion object {
+ private val TAG = WebRtcOfferingPartyHandler::class.java.simpleName
+ }
+
+ fun createOffer(offerAnswerConstraints: MediaConstraints) {
+ logger.d(TAG, "Creating offer with $offerAnswerConstraints")
+ peer.createOffer(object : SdpObserver {
+ override fun onCreateSuccess(localSessionDescription: SessionDescription) {
+ setLocalOfferDescription(localSessionDescription)
+ }
+
+ override fun onCreateFailure(error: String) {
+ webRtcActionListener.onError(error)
+ }
+
+ override fun onSetFailure(p0: String?) {}
+
+ override fun onSetSuccess() {}
+ }, offerAnswerConstraints)
+ }
+
+ private fun setLocalOfferDescription(localSessionDescription: SessionDescription) {
+ peer.setLocalDescription(object : SdpObserver {
+
+ override fun onSetSuccess() {
+ webRtcActionListener.onOfferRemoteDescription(localSessionDescription)
+ }
+
+ override fun onSetFailure(error: String) {
+ webRtcActionListener.onError(error)
+ }
+
+ override fun onCreateSuccess(p0: SessionDescription?) {}
+
+ override fun onCreateFailure(p0: String?) {}
+ }, localSessionDescription)
+ }
+
+ fun handleRemoteAnswer(remoteSessionDescription: SessionDescription) {
+ peer.setRemoteDescription(object : SdpObserver {
+ override fun onSetSuccess() {
+ logger.d(TAG, "Remote description from answer set successfully")
+ }
+
+ override fun onSetFailure(error: String) {
+ webRtcActionListener.onError(error)
+ }
+
+ override fun onCreateSuccess(p0: SessionDescription?) {
+ logger.w("onCreateSuccess")
+ }
+
+ override fun onCreateFailure(p0: String?) {
+ logger.w("onCreateFailure")
+ }
+ }, remoteSessionDescription)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/BooleanAudioConstraints.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/BooleanAudioConstraints.kt
new file mode 100644
index 00000000..d31d5387
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/BooleanAudioConstraints.kt
@@ -0,0 +1,23 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+/**
+ * Boolean value based audio constraints.
+ *
+ * @see
+ * Available constraints in media constraints interface implementation
+ */
+enum class BooleanAudioConstraints(override val constraintString: String) : WebRtcConstraint {
+ DISABLE_AUDIO_PROCESSING("echoCancellation"),
+ ECHO_CANCELLATION("googEchoCancellation"),
+ ECHO_CANCELLATION_2("googEchoCancellation2"),
+ DELAY_AGNOSTIC_ECHO_CANCELLATION("googDAEchoCancellation"),
+ AUTO_GAIN_CONTROL("googAutoGainControl"),
+ AUTO_GAIN_CONTROL_2("googAutoGainControl2"),
+ NOISE_SUPPRESSION("googNoiseSuppression"),
+ NOISE_SUPPRESSION_2("googNoiseSuppression2"),
+ INTELLIGIBILITY_ENHANCER("intelligibilityEnhancer"),
+ LEVEL_CONTROL("levelControl"),
+ HIGH_PASS_FILTER("googHighpassFilter"),
+ TYPING_NOISE_DETECTION("googTypingNoiseDetection"),
+ AUDIO_MIRRORING("googAudioMirroring")
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/IntegerAudioConstraints.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/IntegerAudioConstraints.kt
new file mode 100644
index 00000000..9634d5b9
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/IntegerAudioConstraints.kt
@@ -0,0 +1,11 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+/**
+ * Integer value based audio constraints.
+ *
+ * @see
+ * Available constraints in media constraints interface implementation
+ */
+enum class IntegerAudioConstraints(override val constraintString: String) : WebRtcConstraint {
+ LEVEL_CONTROL_INITIAL_PEAK_LEVEL_DBFS("levelControlInitialPeakLevelDBFS"),
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/MediaConstraintsExt.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/MediaConstraintsExt.kt
new file mode 100644
index 00000000..9922bca5
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/MediaConstraintsExt.kt
@@ -0,0 +1,14 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+import org.webrtc.MediaConstraints
+
+internal fun MediaConstraints.addConstraints(constraints: WebRtcConstraints<*, *>) {
+ mandatory.addAll(constraints.mandatoryKeyValuePairs)
+ optional.addAll(constraints.optionalKeyValuePairs)
+}
+
+internal fun MediaConstraints.addConstraints(vararg constraints: WebRtcConstraints<*, *>) {
+ constraints.forEach {
+ addConstraints(it)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/OfferAnswerConstraints.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/OfferAnswerConstraints.kt
new file mode 100644
index 00000000..b49be13a
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/OfferAnswerConstraints.kt
@@ -0,0 +1,25 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+enum class OfferAnswerConstraints(override val constraintString: String) :
+ WebRtcConstraint {
+
+ OFFER_TO_RECEIVE_AUDIO("OfferToReceiveAudio"),
+ OFFER_TO_RECEIVE_VIDEO("OfferToReceiveVideo"),
+ /**
+ * Many codec's and systems are capable of detecting "silence" and changing their behavior in this
+ * case by doing things such as not transmitting any media. In many cases, such as when dealing
+ * with emergency calling or sounds other than spoken voice, it is desirable to be able to turn
+ * off this behavior. This option allows the application to provide information about whether it
+ * wishes this type of processing enabled or disabled.
+ */
+ VOICE_ACTIVITY_DETECTION("VoiceActivityDetection"),
+ /**
+ * Tries to restart connection after it was in failed or disconnected state
+ */
+ ICE_RESTART("IceRestart"),
+ /**
+ * Google specific constraint for BUNDLE enable/disable.
+ */
+ GOOG_USE_RTP_MUX("googUseRtpMUX")
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/PeerConnectionConstraints.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/PeerConnectionConstraints.kt
new file mode 100644
index 00000000..c23eaa31
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/PeerConnectionConstraints.kt
@@ -0,0 +1,31 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+/**
+ * These constraints should be used during PeerConnection construction.
+ *
+ * @see
+ * Available constraints in media constraints interface implementation
+ */
+enum class PeerConnectionConstraints(override val constraintString: String) : WebRtcConstraint {
+ /**
+ * Enabling allows to stream between firefox and chrome
+ */
+ DTLS_SRTP_KEY_AGREEMENT_CONSTRAINT("DtlsSrtpKeyAgreement"),
+ ENABLE_RTP_DATA_CHANNELS("RtpDataChannels"),
+ /**
+ * Differentiated Services Code Point - DiffServ is a coarse-grained, class-based mechanism for traffic management.
+ * @see DSCP
+ */
+ GOOG_DSCP("googDscp"),
+ GOOG_IPV6("googIPv6"),
+ /**
+ * Video stops as soon as you don't have enough bandwidth for the video.
+ */
+ GOOG_SUSPEND_VIDEO("googSuspendBelowMinBitrate"),
+ GOOG_COMBINED_AUDIO_VIDEO_BWE("googCombinedAudioVideoBwe"),
+ /**
+ * Allow to reduce video quality when cpu usage is high
+ */
+ GOOG_CPU_OVERUSE_DETECTION("googCpuOveruseDetection"),
+ GOOG_PAYLOAD_PADDING("googPayloadPadding")
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/WebRtcConstraint.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/WebRtcConstraint.kt
new file mode 100644
index 00000000..d2de5688
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/WebRtcConstraint.kt
@@ -0,0 +1,10 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+import org.webrtc.MediaConstraints
+
+interface WebRtcConstraint {
+
+ val constraintString: String
+
+ fun toKeyValuePair(value: T) = MediaConstraints.KeyValuePair(constraintString, value.toString())
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/WebRtcConstraints.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/WebRtcConstraints.kt
new file mode 100644
index 00000000..cbb052c3
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/streaming/constraints/WebRtcConstraints.kt
@@ -0,0 +1,46 @@
+package nl.entreco.dartsscorecard.streaming.constraints
+
+open class WebRtcConstraints, E> {
+
+ private val mandatory: MutableMap, E> = mutableMapOf()
+ private val optional: MutableMap, E> = mutableMapOf()
+
+ internal val mandatoryKeyValuePairs
+ get() = toKeyValuePairs(mandatory)
+
+ internal val optionalKeyValuePairs
+ get() = toKeyValuePairs(optional)
+
+
+ /**
+ * Adds all constraints. If constraints are duplicated value from inserted collection will be used.
+ * @see [addAll]
+ */
+ operator fun plusAssign(other: WebRtcConstraints) = addAll(other)
+
+ /**
+ * Adds mandatory constraint. If constraint is already present new value will be used.
+ */
+ fun addMandatoryConstraint(constraint: T, value: E) {
+ mandatory[constraint] = value
+ }
+
+ /**
+ * Adds optional constraint. If constraint is already present new value will be used.
+ */
+ fun addOptionalConstraint(constraint: T, value: E) {
+ optional[constraint] = value
+ }
+
+ /**
+ * Adds all constraints. If constraints are duplicated value from inserted collection will be used.
+ */
+ fun addAll(other: WebRtcConstraints) {
+ mandatory.putAll(other.mandatory)
+ optional.putAll(other.optional)
+ }
+
+ private fun toKeyValuePairs(constraintsMap: Map, E>) = constraintsMap.map { (constraint, enabled) ->
+ constraint.toKeyValuePair(enabled)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/TvBinding.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/TvBinding.kt
new file mode 100644
index 00000000..530154df
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/TvBinding.kt
@@ -0,0 +1,14 @@
+package nl.entreco.dartsscorecard.tv
+
+import android.databinding.BindingAdapter
+import android.view.View
+import android.view.ViewGroup
+
+object TvBinding {
+
+ @JvmStatic
+ @BindingAdapter("showIf")
+ fun doShowViewIf(view: View, show: Boolean){
+ view.visibility = if(show) View.VISIBLE else View.GONE
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvActivity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvActivity.kt
new file mode 100644
index 00000000..7e5f9408
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvActivity.kt
@@ -0,0 +1,45 @@
+package nl.entreco.dartsscorecard.tv.launch
+
+import android.content.Context
+import android.content.Intent
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.base.ViewModelActivity
+import nl.entreco.dartsscorecard.databinding.ActivityTvLaunchBinding
+import nl.entreco.dartsscorecard.di.tv.TvLaunchModule
+
+class LaunchTvActivity : ViewModelActivity() {
+
+ private lateinit var binding: ActivityTvLaunchBinding
+ private val component by componentProvider { it.plus(TvLaunchModule(binding.remoteView)) }
+ private val viewModel by lazy { component.viewModel() }
+ private val navigator by lazy { component.navigator() }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = DataBindingUtil.setContentView(this, R.layout.activity_tv_launch)
+ binding.animator = LaunchTvAnimator(binding)
+ binding.viewModel = viewModel
+ binding.navigator = navigator
+ }
+
+ override fun onStart() {
+ super.onStart()
+ viewModel.onStart()
+ }
+
+ override fun onStop() {
+ viewModel.onStop()
+ viewModel.disconnect()
+ super.onStop()
+ }
+
+ companion object {
+ @JvmStatic
+ fun launch(context: Context) {
+ val intent = Intent(context, LaunchTvActivity::class.java)
+ context.startActivity(intent)
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvAnimator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvAnimator.kt
new file mode 100644
index 00000000..337bfc31
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvAnimator.kt
@@ -0,0 +1,43 @@
+package nl.entreco.dartsscorecard.tv.launch
+
+import android.view.View
+import android.view.animation.AccelerateDecelerateInterpolator
+import nl.entreco.dartsscorecard.databinding.ActivityTvLaunchBinding
+
+class LaunchTvAnimator(binding: ActivityTvLaunchBinding) {
+
+ private val animator = LaunchAnimatorHandler(
+ binding.includeLaunchHeader.lets,
+ binding.includeLaunchHeader.play,
+ binding.includeLaunchHeader.dart)
+
+ init {
+ animator.init()
+ }
+
+ internal class LaunchAnimatorHandler(private val lets: View, private val play: View,
+ private val darts: View) {
+
+ private val horizontalTranslation: Float = 800F
+ private val duration: Long = 250
+ private val durationTwice: Long = 500
+
+ init {
+ lets.also { it.translationX = -horizontalTranslation }
+ play.also { it.translationX = horizontalTranslation }
+ darts.also { it.translationX = -horizontalTranslation }
+ }
+
+
+ fun init() {
+ lets.animate().translationX(0F).setDuration(duration).setInterpolator(
+ AccelerateDecelerateInterpolator()).start()
+ play.animate().translationX(0F).setStartDelay(duration).setDuration(duration)
+ .setInterpolator(
+ AccelerateDecelerateInterpolator()).start()
+ darts.animate().translationX(0F).setStartDelay(durationTwice).setDuration(duration)
+ .setInterpolator(
+ AccelerateDecelerateInterpolator()).start()
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvBinding.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvBinding.kt
new file mode 100644
index 00000000..05ccce81
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvBinding.kt
@@ -0,0 +1,18 @@
+package nl.entreco.dartsscorecard.tv.launch
+
+import android.databinding.BindingAdapter
+import android.view.View
+import android.view.ViewGroup
+
+object LaunchTvBinding {
+
+ @JvmStatic
+ @BindingAdapter("attachMatch", "launchNavigator")
+ fun attachMatchFragmentToContainer(view: ViewGroup, attach: Boolean, navigator: LaunchTvNavigator){
+ if(attach){
+ navigator.attach()
+ } else {
+ navigator.detach()
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvNavigator.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvNavigator.kt
new file mode 100644
index 00000000..1e897562
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvNavigator.kt
@@ -0,0 +1,22 @@
+package nl.entreco.dartsscorecard.tv.launch
+
+import android.support.v4.app.FragmentManager
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.di.viewmodel.ActivityScope
+import nl.entreco.dartsscorecard.tv.match.MatchFragment
+import javax.inject.Inject
+
+class LaunchTvNavigator @Inject constructor(@ActivityScope private val fm: FragmentManager) {
+ fun attach() {
+// fm.beginTransaction()
+// .add(R.id.matchContainer, MatchFragment(), MatchFragment.TAG)
+// .commit()
+ }
+
+ fun detach() {
+// val frag = fm.findFragmentByTag(MatchFragment.TAG)
+// fm.beginTransaction()
+// .remove(frag)
+// .commit()
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvViewModel.kt
new file mode 100644
index 00000000..150221e7
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/launch/LaunchTvViewModel.kt
@@ -0,0 +1,150 @@
+package nl.entreco.dartsscorecard.tv.launch
+
+import android.content.ComponentName
+import android.content.ServiceConnection
+import android.databinding.ObservableBoolean
+import android.databinding.ObservableField
+import android.os.IBinder
+import nl.entreco.dartsscorecard.di.application.ApplicationScope
+import nl.entreco.dartsscorecard.di.tv.TvScope
+import nl.entreco.dartsscorecard.play.stream.ServiceLauncher
+import nl.entreco.dartsscorecard.streaming.ReceiverService
+import nl.entreco.dartsscorecard.streaming.ReceivingServiceListener
+import nl.entreco.domain.streaming.*
+import nl.entreco.domain.streaming.receive.ListenForDisconnectsUsecase
+import nl.entreco.domain.streaming.receive.RegisterReceiverRequest
+import nl.entreco.domain.streaming.receive.RegisterReceiverResponse
+import nl.entreco.domain.streaming.receive.RegisterReceiverUsecase
+import nl.entreco.shared.log.Logger
+import org.webrtc.PeerConnection
+import org.webrtc.SurfaceViewRenderer
+import javax.inject.Inject
+import javax.inject.Named
+
+class LaunchTvViewModel @Inject constructor(
+ @ApplicationScope private val logger: Logger,
+ @TvScope @Named("remote") private val remoteVideoView: SurfaceViewRenderer,
+ private val disconnectUsecase: DisconnectUsecase,
+ private val listenForDisconnectsUsecase: ListenForDisconnectsUsecase,
+ private val registerReceiverUsecase: RegisterReceiverUsecase,
+ @ApplicationScope private val serviceLauncher: ServiceLauncher
+) : ReceivingServiceListener {
+
+ val isLoading = ObservableBoolean(false)
+ val isStreaming = ObservableBoolean(false)
+ val registrationCode = ObservableField("")
+ val connectionState = ObservableField(Unknown)
+
+ init {
+ isLoading.set(true)
+ registerReceiverUsecase.go(RegisterReceiverRequest("todo -> maybe tv or some identifier"),
+ registrationOk(), registrationFailed())
+ }
+
+ private fun registrationOk(): (RegisterReceiverResponse) -> Unit = { response ->
+ listenForDisconnectOrders()
+ registrationCode.set(response.code)
+ isLoading.set(false)
+ attachService()
+ }
+
+ private fun registrationFailed(): (Throwable) -> Unit = {
+ isLoading.set(false)
+ connectionState.set(Killing)
+ }
+
+ private var service: ReceiverService? = null
+ private val serviceConnection = object : ServiceConnection {
+ override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
+ onWebRtcServiceConnected((iBinder as (ReceiverService.LocalBinder)).service)
+ }
+
+ override fun onServiceDisconnected(componentName: ComponentName) {
+ onWebRtcServiceDisconnected()
+ }
+ }
+
+ private fun listenForDisconnectOrders() {
+ listenForDisconnectsUsecase.go {
+ disconnect()
+ isLoading.set(true)
+ registerReceiverUsecase.go(RegisterReceiverRequest("todo -> maybe tv or some identifier"),
+ registrationOk(), registrationFailed())
+ }
+ }
+
+ private fun attachService() {
+ serviceLauncher.launchReceiverService(serviceConnection)
+ }
+
+ private fun onWebRtcServiceConnected(service: ReceiverService) {
+ logger.d("Service connected")
+ connectionState.set(ReadyToConnect)
+ this.service = service
+ service.attachRemoteView(remoteVideoView)
+ service.attachServiceActionsListener(listener = this)
+ }
+
+ private fun onWebRtcServiceDisconnected() {
+ logger.d("Service disconnected")
+ connectionState.set(Disconnected)
+ isStreaming.set(false)
+ }
+
+ override fun criticalWebRTCServiceException(throwable: Throwable) {
+ unbindService()
+ serviceLauncher.criticalWebRTCServiceException(throwable)
+ }
+
+ override fun connectionStateChange(iceConnectionState: PeerConnection.IceConnectionState?) {
+ serviceLauncher.connectionStateChange(iceConnectionState)
+ when (iceConnectionState) {
+ PeerConnection.IceConnectionState.CONNECTED -> {
+ connectionState.set(Connected)
+ isStreaming.set(true)
+ }
+ PeerConnection.IceConnectionState.DISCONNECTED -> {
+// getView()?.showWillTryToRestartMsg()
+ isStreaming.set(false)
+ connectionState.set(Disconnected)
+ service?.detachViews()
+
+ isLoading.set(true)
+ registerReceiverUsecase.go(RegisterReceiverRequest("todo -> maybe tv or some identifier"),
+ registrationOk(), registrationFailed())
+ }
+ else -> {
+ //no-op for now - could show or hide progress bars or messages on given event
+ }
+ }
+ }
+
+ private fun unbindService() {
+ service?.let {
+ it.detachServiceActionsListener()
+ serviceLauncher.unbindServiceConnection(serviceConnection)
+ service = null
+ connectionState.set(Unknown)
+ }
+ }
+
+ fun onStart() {
+ service?.hideBackground()
+ }
+
+ fun onStop() {
+ service?.showBackground()
+ }
+
+ fun disconnect() {
+ connectionState.set(Disconnecting)
+ disconnectUsecase.go{
+ connectionState.set(Disconnected)
+ }
+ service?.let {
+ it.stopSelf()
+ it.detachViews()
+ unbindService()
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/match/MatchFragment.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/match/MatchFragment.kt
new file mode 100644
index 00000000..a9ac1418
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/match/MatchFragment.kt
@@ -0,0 +1,24 @@
+package nl.entreco.dartsscorecard.tv.match
+
+import android.databinding.DataBindingUtil
+import android.os.Bundle
+import android.support.v17.leanback.app.BrandedSupportFragment
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import nl.entreco.dartsscorecard.R
+import nl.entreco.dartsscorecard.databinding.FragmentMatchBinding
+
+class MatchFragment : BrandedSupportFragment() {
+
+ companion object {
+ const val TAG : String = "MatchFragment"
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+ val binding = DataBindingUtil.inflate(inflater, R.layout.fragment_match, container, false)
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/match/MatchViewModel.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/match/MatchViewModel.kt
new file mode 100644
index 00000000..93b4c0d7
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/match/MatchViewModel.kt
@@ -0,0 +1,10 @@
+package nl.entreco.dartsscorecard.tv.match
+
+import android.databinding.ObservableField
+import android.databinding.ObservableInt
+
+class MatchViewModel {
+
+ val numSets = ObservableInt(3)
+ val description = ObservableField("This is description on the TV")
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/splash/SplashTvActivity.kt b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/splash/SplashTvActivity.kt
new file mode 100644
index 00000000..90ddbbd6
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/tv/splash/SplashTvActivity.kt
@@ -0,0 +1,13 @@
+package nl.entreco.dartsscorecard.tv.splash
+
+import android.os.Bundle
+import android.support.v4.app.FragmentActivity
+import nl.entreco.dartsscorecard.tv.launch.LaunchTvActivity
+
+class SplashTvActivity : FragmentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ LaunchTvActivity.launch(this)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/drawable-television/splash.xml b/android/DartsScorecard/app/src/main/res/drawable-television/splash.xml
new file mode 100644
index 00000000..eee198f1
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable-television/splash.xml
@@ -0,0 +1,16 @@
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/drawable-television/splash_bg.png b/android/DartsScorecard/app/src/main/res/drawable-television/splash_bg.png
new file mode 100644
index 00000000..71da8f29
Binary files /dev/null and b/android/DartsScorecard/app/src/main/res/drawable-television/splash_bg.png differ
diff --git a/android/DartsScorecard/app/src/main/res/drawable-television/tv_promo.png b/android/DartsScorecard/app/src/main/res/drawable-television/tv_promo.png
new file mode 100644
index 00000000..4675a788
Binary files /dev/null and b/android/DartsScorecard/app/src/main/res/drawable-television/tv_promo.png differ
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_camera_front.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_camera_front.xml
new file mode 100644
index 00000000..9a9f2ab0
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/ic_camera_front.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_camera_rear.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_camera_rear.xml
new file mode 100644
index 00000000..073b4e79
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/ic_camera_rear.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_launcher_background.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index d5fccc53..00000000
--- a/android/DartsScorecard/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_live_start.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_live_start.xml
new file mode 100644
index 00000000..c461273d
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/ic_live_start.xml
@@ -0,0 +1,12 @@
+
+
+
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_live_stop.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_live_stop.xml
new file mode 100644
index 00000000..5a131a3c
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/ic_live_stop.xml
@@ -0,0 +1,12 @@
+
+
+
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_mute.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_mute.xml
new file mode 100644
index 00000000..2092ea89
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/ic_mute.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_unmute.xml b/android/DartsScorecard/app/src/main/res/drawable/ic_unmute.xml
new file mode 100644
index 00000000..eb6feedb
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/ic_unmute.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/DartsScorecard/app/src/main/res/drawable/stream_state_connect.xml b/android/DartsScorecard/app/src/main/res/drawable/stream_state_connect.xml
new file mode 100644
index 00000000..6430e530
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/stream_state_connect.xml
@@ -0,0 +1,9 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/drawable/stream_state_live.xml b/android/DartsScorecard/app/src/main/res/drawable/stream_state_live.xml
new file mode 100644
index 00000000..a7bfd0d4
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/stream_state_live.xml
@@ -0,0 +1,9 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/drawable/stream_state_stopped.xml b/android/DartsScorecard/app/src/main/res/drawable/stream_state_stopped.xml
new file mode 100644
index 00000000..3894a1eb
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/drawable/stream_state_stopped.xml
@@ -0,0 +1,9 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/drawable/tv_promo.png b/android/DartsScorecard/app/src/main/res/drawable/tv_promo.png
new file mode 100644
index 00000000..4675a788
Binary files /dev/null and b/android/DartsScorecard/app/src/main/res/drawable/tv_promo.png differ
diff --git a/android/DartsScorecard/app/src/main/res/layout-television/activity_tv_launch.xml b/android/DartsScorecard/app/src/main/res/layout-television/activity_tv_launch.xml
new file mode 100644
index 00000000..b2b9051b
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/layout-television/activity_tv_launch.xml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/layout-television/fragment_match.xml b/android/DartsScorecard/app/src/main/res/layout-television/fragment_match.xml
new file mode 100644
index 00000000..cdc3c79a
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/layout-television/fragment_match.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/layout-television/play_tv_score.xml b/android/DartsScorecard/app/src/main/res/layout-television/play_tv_score.xml
new file mode 100644
index 00000000..a84b8ced
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/layout-television/play_tv_score.xml
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/layout-television/tv_score_view.xml b/android/DartsScorecard/app/src/main/res/layout-television/tv_score_view.xml
new file mode 100644
index 00000000..39cd60f3
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/layout-television/tv_score_view.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/layout/activity_launch.xml b/android/DartsScorecard/app/src/main/res/layout/activity_launch.xml
index 3b7e5db7..469ffd7a 100644
--- a/android/DartsScorecard/app/src/main/res/layout/activity_launch.xml
+++ b/android/DartsScorecard/app/src/main/res/layout/activity_launch.xml
@@ -23,7 +23,8 @@
+ android:layout_weight="1"
+ android:layout_gravity="center">
diff --git a/android/DartsScorecard/app/src/main/res/layout/activity_play_01.xml b/android/DartsScorecard/app/src/main/res/layout/activity_play_01.xml
index 948369bf..5ca48cf9 100644
--- a/android/DartsScorecard/app/src/main/res/layout/activity_play_01.xml
+++ b/android/DartsScorecard/app/src/main/res/layout/activity_play_01.xml
@@ -16,6 +16,10 @@
name="statViewModel"
type="nl.entreco.dartsscorecard.play.live.LiveStatViewModel" />
+
+
@@ -38,9 +42,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
app:animator="@{animator}"
- app:snack="@{viewModel.errorMsg}"
app:finished="@{viewModel.finished}"
- app:loading="@{viewModel.loading}">
+ app:loading="@{viewModel.loading}"
+ app:snack="@{viewModel.errorMsg}">
+
+
@@ -63,12 +73,14 @@
android:layout_marginStart="@dimen/def"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:navigator="@{navigator}"
- app:viewModel="@{statViewModel}" />
+ app:viewModel="@{statViewModel}"
+ app:controlStreamViewModel="@{controlStreamViewModel}"/>
+ type="nl.entreco.dartsscorecard.faq.WtfViewModel" />
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/layout/fragment_stream.xml b/android/DartsScorecard/app/src/main/res/layout/fragment_stream.xml
new file mode 100644
index 00000000..b1b61afa
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/layout/fragment_stream.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/layout/play_01_main.xml b/android/DartsScorecard/app/src/main/res/layout/play_01_main.xml
index f415af64..9f1e103c 100644
--- a/android/DartsScorecard/app/src/main/res/layout/play_01_main.xml
+++ b/android/DartsScorecard/app/src/main/res/layout/play_01_main.xml
@@ -9,6 +9,10 @@
name="viewModel"
type="nl.entreco.dartsscorecard.play.live.LiveStatViewModel" />
+
+
@@ -26,28 +30,72 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0"
+ android:animateLayoutChanges="true"
android:background="@drawable/stats_bg"
android:clipChildren="false"
android:clipToPadding="false"
tools:alpha="1">
+
+
+
+
+
+
+
+
+
+
+
+ type="nl.entreco.dartsscorecard.faq.WtfSearchable" />
+ type="nl.entreco.dartsscorecard.faq.WtfModel" />
@@ -19,6 +19,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/small"
+ android:padding="@dimen/small"
android:elevation="4dp">
-
+ android:id="@+id/menu_stream"
+ android:icon="@drawable/ic_live_start"
+ android:title="@string/stream_start"
+ android:visible="false"
+ app:showAsAction="always" />
-
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/values-nl/strings.xml b/android/DartsScorecard/app/src/main/res/values-nl/strings.xml
new file mode 100644
index 00000000..47b006f7
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/values-nl/strings.xml
@@ -0,0 +1,173 @@
+
+
+
+
+ First to %1$s
+ individueel
+ totaal
+ Set
+ Leg
+ No Score
+ Bust
+ Undo
+ Klik om te hervatten
+ Hervatten
+
+
+ Profiel Maken
+ Profiel selecteren
+ Speler selecteren
+ Profiel wijzigen
+ 01 Match instellen
+ Beta Features
+ @string/wtf
+
+
+ @string/resume
+ Start new 01
+ Profielen beheren
+ Beta
+ What the FAQ
+ Start Stream
+ Stop Stream
+ Camera and audio toegang is vereist om te Streamen
+ Kan app settings niet openen. Om permissies toe te kennen, ga je naar de instellingen van deze app.
+ Instellingen
+
+
+ STEM
+ %1$s STEMMEN
+ %1$s %2$s
+ You are AWESOME & will no longer see those annoying ads ;)
+ THNX
+ <p>Zodra deze feature <b>%1$s</b> stemmen heeft, zullen we de implementatie starten.</p><p>Alle donaties <b>verwijderen ook alle advertenties</b> in de app</p>
+ <b>Bekijk de video</b>
+
+
+ Selecteer spelers
+ Kies spelersnaam
+ Of kies een bestaande speler
+ Team
+ Kies x01 score
+ Start score
+ Aantal sets
+ Aantal legs
+ Annuleren
+ -
+ +
+ Doorgaan
+ Sponsored by
+ Powered by
+
+
+
+ Geniet je van Darts Scorecard?
+ Heb je even om de app te beoordelen?\nDat zouden we enorm waarderen
+ Nee
+ Nu ff niet
+
+
+ to throw
+ to throw first
+ Game on
+ Revanche?
+ Kies Team dat eerst mag gooien
+
+
+ Favoriete dubbel: %1$s
+ Spelersnaam
+ Favoriete dubbel
+ Profiel verwijderd
+
+
+ Hoeveel Darts heb je gebruikt?
+
+
+ Match Statistieken
+ Breaks Made
+ Dubbel Success
+ Hoogste Score
+ Hoogste Out
+ 180\'s
+ 140+
+ 100+
+ 60+
+ 20+
+ gemiddelde
+
+
+ Code invoeren
+ Streaming Service
+ Receiving Service
+ Start Streaming
+ Verbinden…
+ Connect
+ Live Stream
+ Enter code
+
+
+ Streaming
+ Uw camera beelden worden naar de tv gestreamed
+ Streaming to Television
+
+
+ Nog geen statistieken beschikbaar
+ Speel een volledige wedstrijd en check daana hier hoe je het doet
+ Matches Gespeeld
+ Totale gemiddelde
+ 1e 9 gemiddelde
+ Win %
+ Checkout %
+ #180\'s
+ #140+
+ #100+
+ #60+
+ #20+
+ #Bust/ Bounce/ NoScore
+
+
+ F.A.Q. doorzoeken
+
+
+ Statistieken archiveer Service
+ Archiveer statistieken
+ Bereken je stats en gemiddeldes
+ Nieuwe stats, gemiddeldes en hiscores aan het berekenen
+
+
+ BDO World Cup - halve finales
+ PDC World Cup - halve finales
+
+
+ Profielen van spelers die zijn verwijderd, kunnen niet worden bekeken
+ Kan match niet ophalen.
+ Je kunt je momenteel niet revancheren.
+ Speler niet aangemaakt.
+ Momenteel kun je geen donaties maken.
+ Kan de spelers lijst niet ophalen.
+ Kan momenteel de statistieken niet ophalen
+ Een speler met dezelfde naam bestaat al. Kies een andere naam
+ Ongeldige spelersnaam
+ Kies de gewenste spelersnaam
+ Nog geen profielen. Speel een Match, of voeg profielen toe met de + button
+ Deze speler doet al mee aan deze wedstrijd
+
+
+ delete
+ Submit darts
+ Add player
+ Enter Player name
+ Existing Players
+ Add profile picture
+ Vote for this feature
+ @string/number_of_sets
+ @string/number_of_legs
+ Plus 1 set
+ Minus 1 set
+ Plus 1 leg
+ Minus 1 leg
+ Player Profiles
+ FAQ items
+ Which features would you like to see added to the app
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/values-television/strings_tv.xml b/android/DartsScorecard/app/src/main/res/values-television/strings_tv.xml
new file mode 100644
index 00000000..85687bec
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/values-television/strings_tv.xml
@@ -0,0 +1,4 @@
+
+
+ Enter this code on your phone
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/values-television/styles_tv.xml b/android/DartsScorecard/app/src/main/res/values-television/styles_tv.xml
new file mode 100644
index 00000000..9ea93a84
--- /dev/null
+++ b/android/DartsScorecard/app/src/main/res/values-television/styles_tv.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/values/keys.xml b/android/DartsScorecard/app/src/main/res/values/keys.xml
index 37d1ef74..37a4d464 100644
--- a/android/DartsScorecard/app/src/main/res/values/keys.xml
+++ b/android/DartsScorecard/app/src/main/res/values/keys.xml
@@ -1,8 +1,8 @@
- ca-app-pub-3793327349392749~1846337901
- ca-app-pub-3793327349392749/2238054293
- ca-app-pub-3793327349392749/3337437992
- ca-app-pub-3793327349392749/9019610403
+ ca-app-pub-3793327349392749~1846337901
+ ca-app-pub-3793327349392749/2238054293
+ ca-app-pub-3793327349392749/3337437992
+ ca-app-pub-3793327349392749/9019610403
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/main/res/values/strings.xml b/android/DartsScorecard/app/src/main/res/values/strings.xml
index 55acdb22..98bb951a 100644
--- a/android/DartsScorecard/app/src/main/res/values/strings.xml
+++ b/android/DartsScorecard/app/src/main/res/values/strings.xml
@@ -1,5 +1,5 @@
- Darts Scorecard
+ Darts Scorecard
First to %1$s
@@ -28,6 +28,11 @@
Manage Profiles
Beta
What the FAQ
+ Start Stream
+ Stop Stream
+ Camera and audio access is needed to Stream
+ Couldn\'t open app settings. To grant permissions please visit settings of this app.
+ Settings
VOTE
@@ -54,6 +59,12 @@
Sponsored by
Powered by
+
+ Enjoying Darts Scorecard?
+ Do you have a second to rate our app?\nWe would really appreciate that
+ Nope
+ Not now
+
to throw
to throw first
@@ -62,7 +73,7 @@
Select Team to throw first
- Favourite double %1$s
+ Favourite double: %1$s
Player name
Favourite double
Profile deleted
@@ -83,6 +94,21 @@
20+
average
+
+ Enter Code
+ Streaming Service
+ Receiving Service
+ Start Streaming
+ Connecting…
+ Connect
+ Live Stream
+ Enter code
+
+
+ Streaming
+ Your camera output is being streamed to the TV
+ Streaming to Television
+
No stats available yet
Complete a game and come back here to see how you\'re doing
@@ -103,9 +129,9 @@
Archive Stats Service
- Archive stats
- Calculating stats & averages
- Calculating new stats, averages & hiscores
+ Archive stats
+ Calculating stats & averages
+ Calculating new stats, averages & hiscores
BDO World Cup - semi finals
diff --git a/android/DartsScorecard/app/src/main/res/values/strings_menu.xml b/android/DartsScorecard/app/src/main/res/values/strings_menu.xml
index 14a54790..c8d90b20 100644
--- a/android/DartsScorecard/app/src/main/res/values/strings_menu.xml
+++ b/android/DartsScorecard/app/src/main/res/values/strings_menu.xml
@@ -1,7 +1,7 @@
- Swap Theme
- Master Caller
- Done
- Edit
+ Swap Theme
+ Master Caller
+ Done
+ Edit
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscLoggerTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/AppLoggerTest.kt
similarity index 92%
rename from android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscLoggerTest.kt
rename to android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/AppLoggerTest.kt
index 85cee757..0f3c1a80 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscLoggerTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/AppLoggerTest.kt
@@ -5,13 +5,13 @@ import org.junit.Test
/**
* Created by Entreco on 17/12/2017.
*/
-class DscLoggerTest {
+class AppLoggerTest {
init {
- DscLogger.setEnabled(true)
+ AppLogger.setEnabled(true)
}
- private val subject = DscLogger("tag")
+ private val subject = AppLogger("tag")
@Test
fun `it should log 'd(msg)'`() {
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscNotLoggerTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscNotLoggerTest.kt
index 26639b71..36ebf4a0 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscNotLoggerTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/DscNotLoggerTest.kt
@@ -8,10 +8,10 @@ import org.junit.Test
class DscNotLoggerTest {
init {
- DscLogger.setEnabled(false)
+ AppLogger.setEnabled(false)
}
- private val subject = DscLogger("tag")
+ private val subject = AppLogger("tag")
@Test
fun `it should NOT log 'd(msg)' (and hence NOT crash)`() {
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestBackground.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestBackground.kt
index b49e867b..3d655962 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestBackground.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestBackground.kt
@@ -1,6 +1,6 @@
package nl.entreco.dartsscorecard
-import nl.entreco.domain.common.executors.Background
+import nl.entreco.shared.threading.Background
import java.util.concurrent.Future
import java.util.concurrent.FutureTask
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestForeground.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestForeground.kt
index 07f10be8..c33d9cd1 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestForeground.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/TestForeground.kt
@@ -1,6 +1,6 @@
package nl.entreco.dartsscorecard
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Foreground
class TestForeground : Foreground {
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/ad/AdViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/ad/AdViewModelTest.kt
index b79bc164..9b20f160 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/ad/AdViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/ad/AdViewModelTest.kt
@@ -3,7 +3,7 @@ package nl.entreco.dartsscorecard.ad
import android.arch.lifecycle.Lifecycle
import com.google.android.gms.ads.AdView
import com.nhaarman.mockito_kotlin.*
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.ad.FetchPurchasedItemsResponse
import nl.entreco.domain.ad.FetchPurchasedItemsUsecase
import nl.entreco.domain.purchases.connect.ConnectToBillingUsecase
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/DialogHelperTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/DialogHelperTest.kt
index e2a11536..f0ae14da 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/DialogHelperTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/DialogHelperTest.kt
@@ -3,6 +3,7 @@ package nl.entreco.dartsscorecard.base
import android.support.v7.app.AlertDialog
import com.nhaarman.mockito_kotlin.*
import nl.entreco.domain.model.players.Team
+import nl.entreco.domain.repository.RatingPrefRepository
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -18,10 +19,12 @@ class DialogHelperTest {
@Mock private lateinit var mockDialog: AlertDialog
@Mock private lateinit var mockBuilder: AlertDialog.Builder
@Mock private lateinit var mockSelect: (Int) -> Unit
+ @Mock private lateinit var mockRatingPrefs: RatingPrefRepository
private lateinit var subject: DialogHelper
private var givenTeams: MutableList = mutableListOf()
+
@Before
fun setUp() {
whenever(mockBuilder.create()).thenReturn(mockDialog)
@@ -29,7 +32,7 @@ class DialogHelperTest {
whenever(mockBuilder.setPositiveButton(any(), any())).thenReturn(mockBuilder)
whenever(mockBuilder.setSingleChoiceItems(anyArray(), any(), any())).thenReturn(mockBuilder)
whenever(mockBuilder.setTitle(any())).thenReturn(mockBuilder)
- subject = DialogHelper(mockBuilder)
+ subject = DialogHelper(mockBuilder, mockRatingPrefs)
}
@Test
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt
index 2e11c5eb..9c4de12e 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/StylerTest.kt
@@ -28,7 +28,7 @@ class StylerTest {
@Mock private lateinit var mockActivity: Activity
@InjectMocks private lateinit var subject: Styler
- @Captor private lateinit var styleCaptor: ArgumentCaptor
+ @Captor private lateinit var styleCaptor: ArgumentCaptor
@Test
fun `it should return 'PDC' style`() {
@@ -82,16 +82,16 @@ class StylerTest {
assertEquals(R.style.Bdo, actualStyle)
}
- private fun givenStyle(@StyleRes style: Int) {
- whenever(mockPrefs.getInt("curStyle", Styler.Style.PDC_2018.style)).thenReturn(style)
+ private fun givenStyle(style: String) {
+ whenever(mockPrefs.getString("curStyle", Styler.Style.PDC_2018.style)).thenReturn(style)
}
private fun whenSwapping(): Int {
whenever(mockPrefs.edit()).thenReturn(mockEditor)
- whenever(mockEditor.putInt(eq("curStyle"), any())).thenReturn(mockEditor)
+ whenever(mockEditor.putString(eq("curStyle"), any())).thenReturn(mockEditor)
subject.switch()
- verify(mockEditor).putInt(eq("curStyle"), styleCaptor.capture())
+ verify(mockEditor).putString(eq("curStyle"), styleCaptor.capture())
givenStyle(styleCaptor.value)
verify(mockActivity).recreate()
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallbackTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallbackTest.kt
index 01dad547..166f9705 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallbackTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/base/SwipeToDeleteCallbackTest.kt
@@ -59,7 +59,13 @@ class SwipeToDeleteCallbackTest {
class TestSwipeToDeleteCallback(context: Context) : SwipeToDeleteCallback(context){
val swiped = AtomicBoolean(false)
val drawed = AtomicBoolean(false)
- override fun onSwiped(viewHolder: RecyclerView.ViewHolder?, direction: Int) {
+
+ override fun onMove(p0: RecyclerView, p1: RecyclerView.ViewHolder,
+ p2: RecyclerView.ViewHolder): Boolean {
+ return false
+ }
+
+ override fun onSwiped(p0: RecyclerView.ViewHolder, p1: Int) {
swiped.set(true)
}
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/BetaModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/BetaModelTest.kt
index 4ee31bd6..cf97405a 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/BetaModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/BetaModelTest.kt
@@ -8,7 +8,17 @@ import org.junit.Test
* Created by entreco on 06/02/2018.
*/
class BetaModelTest {
- private val feature = Feature("reference", "title", "description", "http://url.com", "remarks", 10000, 500, "")
+ private val feat1 = Feature("reference", "title", "description", "http://url.com", "remarks", 10, 150, "")
+ private val feat2 = Feature("reference", "title", "description", "http://url.com", "remarks", 100, 150, "")
+ private val feat3 = Feature("reference", "title", "description", "http://url.com", "remarks", 500, 150, "")
+ private val feat4 = Feature("reference", "title", "description", "http://url.com", "remarks", 1000, 150, "")
+ private val feat5 = Feature("reference", "title", "description", "http://url.com", "remarks", 1500, 150, "")
+ private val feat6 = Feature("reference", "title", "description", "http://url.com", "remarks", 5555, 150, "")
+ private val feat7 = Feature("reference", "title", "description", "http://url.com", "remarks", 10000, 150, "")
+ private val feat8 = Feature("reference", "title", "description", "http://url.com", "remarks", 12000, 150, "")
+ private val feat9 = Feature("reference", "title", "description", "http://url.com", "remarks", 12345, 150, "")
+
+ private val feature = Feature("reference", "title", "description", "http://url.com", "remarks", 1500, 150, "")
private val subject = BetaModel(feature)
@Test
@@ -18,30 +28,47 @@ class BetaModelTest {
@Test
fun `it should set total`() {
- assertEquals("10k", subject.total)
+ assertEquals("1.5k", subject.total)
+ }
+
+ @Test
+ fun `it should set total (without decimals)`() {
+ assertEquals("10", BetaModel(feat1).total)
+ assertEquals("100", BetaModel(feat2).total)
+ assertEquals("500", BetaModel(feat3).total)
+ assertEquals("1k", BetaModel(feat4).total)
+ assertEquals("1.5k", BetaModel(feat5).total)
+ assertEquals("5.6k", BetaModel(feat6).total)
+ assertEquals("10k", BetaModel(feat7).total)
+ assertEquals("12k", BetaModel(feat8).total)
+ assertEquals("12.3k", BetaModel(feat9).total)
}
@Test
fun `it should set progress`() {
- assertEquals(0.05F, subject.progress.get())
+ assertEquals(0.1F, subject.progress.get())
}
@Test
fun `it should format remarks`() {
assertEquals("remarks", subject.remarks.get())
}
+
@Test
fun `it should set votable`() {
assertEquals(true, subject.votable.get())
}
+
@Test
fun `it should set description`() {
assertEquals("description", subject.description.get())
}
+
@Test
fun `it should set goal`() {
- assertEquals("500 / 10k", subject.goal.get())
+ assertEquals("150 / 1.5k", subject.goal.get())
}
+
@Test
fun `it should set image`() {
assertEquals("http://url.com", subject.image.get())
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModelTest.kt
index d405ff36..29a4c448 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/beta/donate/DonateViewModelTest.kt
@@ -135,7 +135,7 @@ class DonateViewModelTest {
fun `it should track Purchase Failed when make donation fails`() {
givenSubject()
whenMakingDonationFails()
- thenPurchaseFailedIstracked("ActivityResult failed")
+ thenPurchaseFailedIstracked("Donation ActivityResult failed")
}
@Test
@@ -253,7 +253,7 @@ class DonateViewModelTest {
}
private fun whenMakingDonationFails() {
- subject.onMakeDonationFailed()
+ subject.onMakeDonationFailed(false)
}
private fun whenConsumingDonationSucceeds(productId: String, responseCode: Int) {
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/application/AppModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/application/AppModuleTest.kt
index d17d6946..e91f784a 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/application/AppModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/application/AppModuleTest.kt
@@ -4,7 +4,7 @@ import android.content.Context
import com.nhaarman.mockito_kotlin.whenever
import nl.entreco.dartsscorecard.App
import nl.entreco.dartsscorecard.BuildConfig
-import nl.entreco.dartsscorecard.DscLogger
+import nl.entreco.dartsscorecard.AppLogger
import nl.entreco.data.analytics.FirebaseAnalytics
import org.junit.Assert.*
import org.junit.Before
@@ -40,7 +40,7 @@ class AppModuleTest {
@Test
fun provideLogger() {
- assertTrue(subject.provideLogger() is DscLogger)
+ assertTrue(subject.provideLogger() is AppLogger)
}
@Test
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/archive/ArchiveModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/archive/ArchiveModuleTest.kt
index aac040e7..b7968ed1 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/archive/ArchiveModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/archive/ArchiveModuleTest.kt
@@ -2,7 +2,6 @@ package nl.entreco.dartsscorecard.di.archive
import nl.entreco.data.db.DscDatabase
import nl.entreco.data.db.profile.ArchiveStatMapper
-import nl.entreco.domain.common.log.Logger
import org.junit.Assert.assertNotNull
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/play/Play01ModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/play/Play01ModuleTest.kt
index c29601e8..7f434f83 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/play/Play01ModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/play/Play01ModuleTest.kt
@@ -37,11 +37,6 @@ class Play01ModuleTest {
assertEquals(mockActivity, subject().provide01Activity())
}
- @Test(expected = NullPointerException::class)
- fun `it should provide AlertDialogBuilder`() {
- subject().provideAlertDialogBuilder(mockContext)
- }
-
@Test
fun `it should provide SoundRepository`() {
assertNotNull(subject().provideSoundRepository(mockContext, mockSoundPool, mockMapper, mockAudioPrefs))
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/service/ServiceModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/service/ServiceModuleTest.kt
index 1f0f49f4..783266b1 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/service/ServiceModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/service/ServiceModuleTest.kt
@@ -1,12 +1,19 @@
package nl.entreco.dartsscorecard.di.service
+import android.app.Service
import org.junit.Assert.*
import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnitRunner
+@RunWith(MockitoJUnitRunner::class)
class ServiceModuleTest{
+ @Mock private lateinit var mockService: Service
+
@Test
fun `can be created`() {
- assertNotNull(ServiceModule())
+ assertNotNull(ServiceModule(mockService))
}
}
\ No newline at end of file
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModuleTest.kt
index d43ccb86..1e21dae0 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/ViewModelModuleTest.kt
@@ -36,6 +36,12 @@ class ViewModelModuleTest {
assertEquals(mockActivity, subject.context())
}
+
+ @Test(expected = NullPointerException::class)
+ fun `it should provide AlertDialogBuilder`() {
+ subject.provideAlertDialogBuilder(mockContext)
+ }
+
@Test
fun `it should provide lifecycle`() {
whenever(mockActivity.lifecycle).thenReturn(mockLifeCycle)
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModuleTest.kt
index 1c36d26e..59d7ab2b 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/api/FeatureApiModuleTest.kt
@@ -4,7 +4,7 @@ import com.google.firebase.firestore.CollectionReference
import com.google.firebase.firestore.FirebaseFirestore
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.whenever
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import org.junit.Assert.assertNotNull
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModuleTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModuleTest.kt
index e1abdb71..50cefe96 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModuleTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/di/viewmodel/threading/ThreadingModuleTest.kt
@@ -1,8 +1,8 @@
package nl.entreco.dartsscorecard.di.viewmodel.threading
import android.os.Handler
-import nl.entreco.domain.common.executors.BgExecutor
-import nl.entreco.domain.common.executors.FgExecutor
+import nl.entreco.shared.threading.BgExecutor
+import nl.entreco.shared.threading.FgExecutor
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01AnimatorHandlerTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01AnimatorHandlerTest.kt
index 92104d80..81b971ff 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01AnimatorHandlerTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01AnimatorHandlerTest.kt
@@ -36,7 +36,7 @@ class Play01AnimatorHandlerTest {
whenever(mockAnimator.scaleY(any())).thenReturn(mockAnimator)
whenever(mockAnimator.scaleX(any())).thenReturn(mockAnimator)
whenever(mockAnimator.setDuration(any())).thenReturn(mockAnimator)
- subject = Play01Animator.Play01AnimatorHandler(mockView, mockView, mockView, mockView, mockView, mockView, mockViewPager, mockMaxHeightView, mockView, mockView, mockView, mockView)
+ subject = Play01Animator.Play01AnimatorHandler(mockView, mockView, mockView, mockView, mockView, mockView, mockViewPager, mockMaxHeightView, mockView, mockView, mockView, mockView, mockView, mockView)
}
@Test(expected = KotlinNullPointerException::class)
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01NavigatorTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01NavigatorTest.kt
index 9acd369a..272d2511 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01NavigatorTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01NavigatorTest.kt
@@ -1,8 +1,10 @@
package nl.entreco.dartsscorecard.play
+import android.support.v4.app.FragmentManager
import android.view.View
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.verify
+import com.nhaarman.mockito_kotlin.whenever
import nl.entreco.dartsscorecard.profile.view.ProfileActivity
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
@@ -20,6 +22,7 @@ class Play01NavigatorTest {
@Mock private lateinit var mockView: View
@Mock private lateinit var mockActivity: Play01Activity
+ @Mock private lateinit var mockFragmentManager: FragmentManager
private lateinit var subject: Play01Navigator
@Test(expected = NotAMockException::class)
@@ -37,6 +40,7 @@ class Play01NavigatorTest {
}
private fun givenSubject() {
+ whenever(mockActivity.supportFragmentManager).thenReturn(mockFragmentManager)
subject = Play01Navigator(mockActivity)
}
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelMasterCallerTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelMasterCallerTest.kt
index 52d044d9..de04eb7f 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelMasterCallerTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelMasterCallerTest.kt
@@ -10,7 +10,7 @@ import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.ad.AdViewModel
import nl.entreco.dartsscorecard.base.DialogHelper
import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
@@ -21,6 +21,7 @@ import nl.entreco.domain.play.revanche.RevancheUsecase
import nl.entreco.domain.play.start.Play01Request
import nl.entreco.domain.play.start.Play01Response
import nl.entreco.domain.play.start.Play01Usecase
+import nl.entreco.domain.rating.AskForRatingUsecase
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.settings.ScoreSettings
import org.junit.Assert.assertEquals
@@ -38,6 +39,7 @@ class Play01ViewModelMasterCallerTest {
@Mock private lateinit var mockMenu: Menu
@Mock private lateinit var mockMenuItem: MenuItem
@Mock private lateinit var mockPlayGameUsecase: Play01Usecase
+ @Mock private lateinit var mockAskForRatingUsecase: AskForRatingUsecase
@Mock private lateinit var mockToggleSoundUsecase: ToggleSoundUsecase
@Mock private lateinit var mockAudioPrefs: AudioPrefRepository
@Mock private lateinit var mockAdProvider: AdViewModel
@@ -97,7 +99,7 @@ class Play01ViewModelMasterCallerTest {
}
private fun givenGameAndRequest(vararg loaders: GameLoadedNotifier) {
- subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
+ subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAskForRatingUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
subject.load(mockRequest, mockGameLoaded, *loaders)
}
@@ -106,7 +108,6 @@ class Play01ViewModelMasterCallerTest {
val score = Score(501)
whenever(mockGame.id).thenReturn(1)
whenever(mockGame.previousScore()).thenReturn(score)
- whenever(mockGame.isNewMatchLegOrSet()).thenReturn(false)
whenever(mockGame.getTurnCount()).thenReturn(1)
whenever(mockGame.wasBreakMade(any())).thenReturn(false)
whenever(mockGame.next).thenReturn(Next(State.NORMAL, Team(arrayOf(player)), 0, player, score))
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelRevancheTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelRevancheTest.kt
index 10cb9f7d..6094cecc 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelRevancheTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelRevancheTest.kt
@@ -6,7 +6,7 @@ import com.nhaarman.mockito_kotlin.verify
import nl.entreco.dartsscorecard.ad.AdViewModel
import nl.entreco.dartsscorecard.base.DialogHelper
import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.Game
import nl.entreco.domain.model.players.Team
import nl.entreco.domain.play.mastercaller.MasterCaller
@@ -16,6 +16,7 @@ import nl.entreco.domain.play.revanche.RevancheUsecase
import nl.entreco.domain.play.start.Play01Request
import nl.entreco.domain.play.start.Play01Response
import nl.entreco.domain.play.start.Play01Usecase
+import nl.entreco.domain.rating.AskForRatingUsecase
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.settings.ScoreSettings
import org.junit.Test
@@ -36,6 +37,7 @@ class Play01ViewModelRevancheTest {
@Mock private lateinit var mockRevancheUsecase: RevancheUsecase
@Mock private lateinit var mockGameListeners: Play01Listeners
@Mock private lateinit var mockMasterCaller: MasterCaller
+ @Mock private lateinit var mockAskForRatingUsecase: AskForRatingUsecase
@Mock private lateinit var mockLoadNotifier: GameLoadedNotifier
@Mock private lateinit var mockDialogHelper: DialogHelper
@Mock private lateinit var mockLogger: Logger
@@ -59,7 +61,7 @@ class Play01ViewModelRevancheTest {
}
private fun givenFullyLoadedSubject() {
- subject = Play01ViewModel(mockPlay01Usecamse, mockRevancheUsecase, mockGameListeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
+ subject = Play01ViewModel(mockPlay01Usecamse, mockRevancheUsecase, mockGameListeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAskForRatingUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
subject.load(Play01Request(1, "1|2", 501, 1, 1, 1), mockLoadNotifier)
verify(mockPlay01Usecamse).loadGameAndStart(any(), doneCaptor.capture(), any())
doneCaptor.lastValue.invoke(Play01Response(mockGame, mockScoreSettings, arrayOf(team1, team2), "1|2"))
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelTest.kt
index 6bd5cc98..8684fc88 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelTest.kt
@@ -5,7 +5,7 @@ import nl.entreco.dartsscorecard.ad.AdViewModel
import nl.entreco.dartsscorecard.base.DialogHelper
import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier
import nl.entreco.dartsscorecard.play.score.TeamScoreListener
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
@@ -21,6 +21,7 @@ import nl.entreco.domain.play.start.MarkGameAsFinishedRequest
import nl.entreco.domain.play.start.Play01Request
import nl.entreco.domain.play.start.Play01Response
import nl.entreco.domain.play.start.Play01Usecase
+import nl.entreco.domain.rating.AskForRatingUsecase
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.settings.ScoreSettings
import nl.entreco.domain.setup.game.CreateGameRequest
@@ -46,6 +47,7 @@ class Play01ViewModelTest {
@Mock private lateinit var mockScore: Score
@Mock private lateinit var mockRequest: Play01Request
@Mock private lateinit var mockToggleSoundUsecase: ToggleSoundUsecase
+ @Mock private lateinit var mockAskForRatingUsecase: AskForRatingUsecase
@Mock private lateinit var mockAdProvider: AdViewModel
@Mock private lateinit var mockAudioPrefs: AudioPrefRepository
@Mock private lateinit var mockPlayGameUsecase: Play01Usecase
@@ -83,7 +85,7 @@ class Play01ViewModelTest {
@Test
fun `it should stop mastercaller on stop`() {
- subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
+ subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAskForRatingUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
subject.stop()
verify(mockMasterCaller).stop()
}
@@ -220,12 +222,12 @@ class Play01ViewModelTest {
game = Game(101, givenArbiter).start(0, givenTeams)
req = Play01Request(gameId, teamIds, createGameRequest.startScore, createGameRequest.startIndex, createGameRequest.numLegs, createGameRequest.numSets)
givenTeamScoreListeners = listOf(mockTeamScoreListener, mockTeamScoreListener)
- subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
+ subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAskForRatingUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
subject.load(req, mockCreatedNotifier, *loaders)
}
private fun givenFullyLoadedMockGame() {
- subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
+ subject = Play01ViewModel(mockPlayGameUsecase, mockRevancheUsecase, mock01Listeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAskForRatingUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
subject.load(mockRequest, mockCreatedNotifier)
verify(mockPlayGameUsecase).loadGameAndStart(any(), doneCaptor.capture(), any())
doneCaptor.firstValue.invoke(Play01Response(mockGame, mockScoreSettings, givenTeams, teamIds))
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt
index 7345f121..cc92708a 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/Play01ViewModelUndoTest.kt
@@ -4,7 +4,7 @@ import com.nhaarman.mockito_kotlin.*
import nl.entreco.dartsscorecard.ad.AdViewModel
import nl.entreco.dartsscorecard.base.DialogHelper
import nl.entreco.dartsscorecard.play.score.GameLoadedNotifier
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.Game
import nl.entreco.domain.model.players.Team
import nl.entreco.domain.play.mastercaller.MasterCaller
@@ -15,6 +15,7 @@ import nl.entreco.domain.play.start.Play01Response
import nl.entreco.domain.play.start.Play01Usecase
import nl.entreco.domain.play.stats.UndoTurnRequest
import nl.entreco.domain.play.stats.UndoTurnResponse
+import nl.entreco.domain.rating.AskForRatingUsecase
import nl.entreco.domain.repository.AudioPrefRepository
import nl.entreco.domain.settings.ScoreSettings
import org.junit.Assert.assertEquals
@@ -36,6 +37,7 @@ class Play01ViewModelUndoTest {
@Mock private lateinit var mockResponse: Play01Response
@Mock private lateinit var mockAdProvider: AdViewModel
@Mock private lateinit var mockToggleSoundUsecase: ToggleSoundUsecase
+ @Mock private lateinit var mockAskForRatingUsecase: AskForRatingUsecase
@Mock private lateinit var mockAudioPrefs: AudioPrefRepository
@Mock private lateinit var mockLoad: GameLoadedNotifier
@Mock private lateinit var mockLoaders: GameLoadedNotifier
@@ -82,7 +84,7 @@ class Play01ViewModelUndoTest {
whenever(mockResponse.teamIds).thenReturn("")
whenever(mockResponse.settings).thenReturn(mockSettings)
- subject = Play01ViewModel(mockPlay01Usecase, mockRevancheUsecase, mockGameListeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
+ subject = Play01ViewModel(mockPlay01Usecase, mockRevancheUsecase, mockGameListeners, mockMasterCaller, mockDialogHelper, mockToggleSoundUsecase, mockAskForRatingUsecase, mockAudioPrefs, mockAdProvider, mockLogger)
subject.load(mockRequest, mockLoad, mockLoaders)
verify(mockPlay01Usecase).loadGameAndStart(eq(mockRequest), load.capture(), any())
load.lastValue.invoke(mockResponse)
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputViewModelTest.kt
index e3cf4086..f80f0d86 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/input/InputViewModelTest.kt
@@ -5,7 +5,7 @@ import com.nhaarman.mockito_kotlin.*
import nl.entreco.dartsscorecard.R
import nl.entreco.dartsscorecard.play.Play01Animator
import nl.entreco.domain.Analytics
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.NoPlayer
import nl.entreco.domain.model.players.Player
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModelTest.kt
index 2c0c7057..5d3039e3 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/live/LiveStatViewModelTest.kt
@@ -2,7 +2,7 @@ package nl.entreco.dartsscorecard.play.live
import com.nhaarman.mockito_kotlin.*
import nl.entreco.dartsscorecard.archive.ArchiveServiceLauncher
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.Game
import nl.entreco.domain.model.LiveStat
import nl.entreco.domain.model.Score
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/ScoreViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/ScoreViewModelTest.kt
index 4833dd72..59fb7ec2 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/ScoreViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/play/score/ScoreViewModelTest.kt
@@ -2,7 +2,6 @@ package nl.entreco.dartsscorecard.play.score
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.verifyZeroInteractions
-import nl.entreco.domain.common.log.Logger
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
@@ -11,7 +10,6 @@ import nl.entreco.domain.settings.ScoreSettings
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
-import org.junit.runner.Description
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
diff --git a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/Setup01ViewModelTest.kt b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/Setup01ViewModelTest.kt
index be0c25c3..e5bca00b 100644
--- a/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/Setup01ViewModelTest.kt
+++ b/android/DartsScorecard/app/src/test/java/nl/entreco/dartsscorecard/setup/Setup01ViewModelTest.kt
@@ -1,7 +1,7 @@
package nl.entreco.dartsscorecard.setup
import com.nhaarman.mockito_kotlin.*
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.launch.ExtractTeamsRequest
import nl.entreco.domain.launch.ExtractTeamsResponse
import nl.entreco.domain.launch.ExtractTeamsUsecase
diff --git a/android/DartsScorecard/build.gradle b/android/DartsScorecard/build.gradle
index db8b5f29..bc3886ed 100644
--- a/android/DartsScorecard/build.gradle
+++ b/android/DartsScorecard/build.gradle
@@ -1,6 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
-
apply from: 'scripts/dependencies.gradle'
repositories {
@@ -31,6 +30,7 @@ allprojects {
google()
jcenter()
maven { url "https://jitpack.io" }
+ maven { url "https://dl.bintray.com/netguru/maven/" }
}
}
diff --git a/android/DartsScorecard/data/build.gradle b/android/DartsScorecard/data/build.gradle
index a8ab1150..03d70371 100644
--- a/android/DartsScorecard/data/build.gradle
+++ b/android/DartsScorecard/data/build.gradle
@@ -11,16 +11,21 @@ android {
dependencies {
implementation project(":domain")
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
- implementation "com.google.firebase:firebase-core:$firebase"
- implementation "com.google.firebase:firebase-firestore:$firebase"
- implementation "com.google.firebase:firebase-config:$firebase"
+ implementation project(":shared")
+
+ // Annotation Processing
+ kapt "android.arch.persistence.room:compiler:$room"
+
+ // Implementation
+ implementation "com.google.firebase:firebase-core:$fbCore"
+ implementation "com.google.firebase:firebase-firestore:$fbStore"
+ implementation "com.google.firebase:firebase-config:$fbConfig"
+ implementation "com.google.firebase:firebase-database:$fbDatabase"
+ implementation "android.arch.persistence.room:runtime:$room"
+
implementation "com.android.support:appcompat-v7:$support"
implementation "com.android.support:exifinterface:$support"
implementation "android.arch.lifecycle:livedata:$architecture"
- implementation "android.arch.persistence.room:runtime:$room"
- kapt "android.arch.persistence.room:compiler:$room"
-
implementation "com.google.code.gson:gson:$gson"
testImplementation "junit:junit:$junit"
diff --git a/android/DartsScorecard/data/proguard-rules.pro b/android/DartsScorecard/data/proguard-rules.pro
index f1b42451..c8de4dbe 100644
--- a/android/DartsScorecard/data/proguard-rules.pro
+++ b/android/DartsScorecard/data/proguard-rules.pro
@@ -19,3 +19,69 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+
+# Base Settings from Dev
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontskipnonpubliclibraryclassmembers
+-dontpreverify
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+-keepattributes LineNumberTable,SourceFile,Signature,*Annotation*,Exceptions,InnerClasses
+
+# Crashlytics
+-keepattributes *Annotation*
+-keepattributes SourceFile,LineNumberTable
+-keep public class * extends java.lang.Exception
+
+# Okio
+-dontwarn okio.**
+-dontnote okio.**
+
+# OkHttp
+-dontwarn okhttp3.**
+
+# Billing
+-keep class com.android.vending.billing.**
+
+# Glide
+-keep public class * implements com.bumptech.glide.module.GlideModule
+-keep public class * extends com.bumptech.glide.module.AppGlideModule
+-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
+ **[] $VALUES;
+ public *;
+}
+
+# Databinding
+-keepclasseswithmembernames interface android.databinding.DataBindingComponent
+-dontwarn android.databinding.DataBindingComponent
+-dontnote android.databinding.DataBindingComponent
+-keep class android.databinding.DataBinderMapper
+-dontwarn android.databinding.DataBinderMapper
+-dontnote android.databinding.DataBinderMapper
+
+# WebRtc
+-keep class org.webrtc.** { *; }
+-dontnote org.apache.http.**
+-dontwarn org.apache.http.**
+-dontnote android.net.http.*
+-dontwarn android.net.http.**
+-dontnote org.apache.commons.codec.**
+-dontwarn org.apache.commons.codec.**
+
+# Keep native methods
+-keepclassmembers class * {
+ native ;
+}
+
+#GMS
+-keep class com.google.android.gms.common.api.internal.BasePendingResult$ReleasableResultGuardian
+-keep class com.google.android.gms.** { *; }
+-dontwarn com.google.android.gms.**
+
+-keepnames @pcom.google.android.gms.common.annotation.KeepName class *
+
+-keepclassmembernames class * {
+ @com.google.android.gms.common.annotation.KeepName *;
+}
+
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/api/beta/RemoteFeatureRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/api/beta/RemoteFeatureRepository.kt
index 9cef7b8b..676a80aa 100644
--- a/android/DartsScorecard/data/src/main/java/nl/entreco/data/api/beta/RemoteFeatureRepository.kt
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/api/beta/RemoteFeatureRepository.kt
@@ -1,7 +1,7 @@
package nl.entreco.data.api.beta
import com.google.firebase.firestore.*
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.beta.Feature
import nl.entreco.domain.repository.FeatureRepository
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/billing/PlayStoreBillingRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/billing/PlayStoreBillingRepository.kt
index adfd92cf..9461bf21 100644
--- a/android/DartsScorecard/data/src/main/java/nl/entreco/data/billing/PlayStoreBillingRepository.kt
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/billing/PlayStoreBillingRepository.kt
@@ -63,7 +63,7 @@ class PlayStoreBillingRepository(private val context: Context, private val servi
return if (bundle?.getInt(FETCH_RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
- bundle.getStringArrayList(EXTRA_DETAILS_LIST).mapNotNull { response ->
+ bundle.getStringArrayList(EXTRA_DETAILS_LIST)!!.mapNotNull { response ->
val donation = gson.fromJson(response, DonationApiData::class.java)
val votes = donations.getVotes(donation.productId)
@@ -81,7 +81,7 @@ class PlayStoreBillingRepository(private val context: Context, private val servi
val bundle = service.getService()?.getBuyIntent(apiVersion, packageName, buy.sku(), buy.type(), payload)
return if (bundle?.getInt(BUY_RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
- val intent: PendingIntent = bundle.getParcelable(EXTRA_BUY_INTENT)
+ val intent: PendingIntent = bundle.getParcelable(EXTRA_BUY_INTENT)!!
MakeDonationResponse(intent, payload)
} else {
@@ -100,7 +100,7 @@ class PlayStoreBillingRepository(private val context: Context, private val servi
val bundle = service.getService()?.getPurchases(apiVersion, packageName, purchases.type(), purchases.token())
return if (bundle?.getInt(QUERY_RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK) {
- bundle.getStringArrayList(EXTRA_INAPP_PURCHASE_ITEM_LIST)
+ bundle.getStringArrayList(EXTRA_INAPP_PURCHASE_ITEM_LIST)!!
} else {
throw Throwable("Unable to getPurchases(), $bundle")
}
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/db/game/LocalGameRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/db/game/LocalGameRepository.kt
index 8a5ebdae..aec921c3 100644
--- a/android/DartsScorecard/data/src/main/java/nl/entreco/data/db/game/LocalGameRepository.kt
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/db/game/LocalGameRepository.kt
@@ -69,6 +69,6 @@ class LocalGameRepository(db: DscDatabase, private val mapper: Mapper
FileOutputStream(output).use { output ->
- input.copyTo(output)
+ input?.copyTo(output)
}
}
}
@@ -53,7 +54,7 @@ class LocalImageRepository(private val context: Context, private val contentReso
private fun getPhotoOrientation(uri: Uri): Float {
contentResolver.openInputStream(uri).use { input ->
- val exif = ExifInterface(input)
+ val exif = if (input != null) ExifInterface(input) else return 0F
return when (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)) {
ExifInterface.ORIENTATION_ROTATE_270 -> 270F
ExifInterface.ORIENTATION_ROTATE_180 -> 180F
@@ -76,11 +77,13 @@ class LocalImageRepository(private val context: Context, private val contentReso
val shortSide = min(width, height) / 2
val src = Rect(0, 0, width, height)
- val dst = Rect(src.centerX() - shortSide, src.centerY() - shortSide, src.centerX() + shortSide, src.centerY() + shortSide)
+ val dst = Rect(src.centerX() - shortSide, src.centerY() - shortSide,
+ src.centerX() + shortSide, src.centerY() + shortSide)
val matrix = Matrix()
matrix.postRotate(degrees)
- val tmp = Bitmap.createBitmap(bitmap, dst.left, dst.top, dst.width(), dst.height(), matrix, true)
+ val tmp = Bitmap.createBitmap(bitmap, dst.left, dst.top, dst.width(), dst.height(), matrix,
+ true)
val resized = Bitmap.createScaledBitmap(tmp, size.toInt(), size.toInt(), true)
@@ -90,7 +93,8 @@ class LocalImageRepository(private val context: Context, private val contentReso
return resized
}
- private fun determineSampleSize(options: BitmapFactory.Options, startScale: Int, size: Float): Int {
+ private fun determineSampleSize(options: BitmapFactory.Options, startScale: Int,
+ size: Float): Int {
var scale = startScale
while (options.outWidth / scale / 2 >= size && options.outHeight / scale / 2 >= size) {
scale *= 2
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/prefs/SharedRatingPrefRepo.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/prefs/SharedRatingPrefRepo.kt
new file mode 100644
index 00000000..8670fb67
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/prefs/SharedRatingPrefRepo.kt
@@ -0,0 +1,22 @@
+package nl.entreco.data.prefs
+
+import android.content.SharedPreferences
+import nl.entreco.data.prefs.SharedAudioPrefRepo.Companion.PREF_MASTER_CALLER
+import nl.entreco.domain.repository.RatingPrefRepository
+
+class SharedRatingPrefRepo(private val prefs: SharedPreferences) : RatingPrefRepository {
+
+ companion object {
+ const val PREF_SHOULD_ASK_RATING: String = "PREF_rating"
+ }
+
+ override fun neverAskAgain() {
+ prefs.edit().apply{
+ putBoolean(PREF_SHOULD_ASK_RATING, false)
+ }.apply()
+ }
+
+ override fun shouldAskToRateApp(): Boolean {
+ return prefs.getBoolean(PREF_SHOULD_ASK_RATING, true)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/DisconnectFirebaseData.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/DisconnectFirebaseData.kt
new file mode 100644
index 00000000..385e764c
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/DisconnectFirebaseData.kt
@@ -0,0 +1,9 @@
+package nl.entreco.data.stream
+
+import android.support.annotation.Keep
+import com.google.firebase.firestore.IgnoreExtraProperties
+import com.google.gson.annotations.SerializedName
+
+@Keep
+@IgnoreExtraProperties
+internal data class DisconnectFirebaseData(@SerializedName("from") val from: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseAnswersRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseAnswersRepository.kt
new file mode 100644
index 00000000..00509ebd
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseAnswersRepository.kt
@@ -0,0 +1,55 @@
+package nl.entreco.data.stream
+
+import com.google.firebase.database.DataSnapshot
+import com.google.firebase.database.DatabaseError
+import com.google.firebase.database.FirebaseDatabase
+import com.google.firebase.database.ValueEventListener
+import nl.entreco.domain.repository.AnswersRepository
+import nl.entreco.domain.streaming.ice.DscSessionDescription
+import nl.entreco.shared.log.Logger
+
+class FirebaseAnswersRepository(
+ private val db: FirebaseDatabase,
+ private val logger: Logger,
+ private val currentDeviceUuid: String
+) : AnswersRepository {
+
+ companion object {
+ private const val ANSWERS_PATH = "answers/"
+ }
+
+ private fun deviceAnswersPath(uuid: String) = ANSWERS_PATH.plus(uuid)
+
+ override fun create(recipientUuid: String, localSessionDescription: DscSessionDescription) {
+ val reference = db.getReference(deviceAnswersPath(recipientUuid))
+ reference.onDisconnect().removeValue()
+
+ val aha = SessionDescriptionFirebaseApiData()
+ aha.uuid = currentDeviceUuid
+ aha.type = localSessionDescription.type
+ aha.description = localSessionDescription.description
+
+ logger.w("WEBRTC: create Answer $aha")
+
+ reference.setValue(aha)
+ }
+
+ override fun listenForNewAnswers(onChange: (DscSessionDescription) -> Unit) {
+ val reference = db.getReference(deviceAnswersPath(currentDeviceUuid))
+ val valueListener = object :
+ ValueEventListener {
+
+ override fun onCancelled(p0: DatabaseError) {}
+
+ override fun onDataChange(p0: DataSnapshot) {
+ p0.getValue(SessionDescriptionFirebaseApiData::class.java)?.let { description ->
+
+ logger.w("WEBRTC: listenForNewAnswers $description")
+ val session = DscSessionDescription(description.type, description.description ?: "")
+ onChange(session)
+ }
+ }
+ }
+ reference.addValueEventListener(valueListener)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseIceRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseIceRepository.kt
new file mode 100644
index 00000000..5d9c8e36
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseIceRepository.kt
@@ -0,0 +1,104 @@
+package nl.entreco.data.stream
+
+import com.google.firebase.database.*
+import nl.entreco.domain.repository.IceRepository
+import nl.entreco.domain.streaming.ice.DscIceCandidate
+import nl.entreco.domain.streaming.ice.DscIceServer
+import nl.entreco.shared.log.Logger
+
+class FirebaseIceRepository(private val db: FirebaseDatabase,
+ private val logger: Logger,
+ private val currentDeviceUuid: String) : IceRepository {
+
+ companion object {
+ private const val ICE_SERVERS_PATH = "ice_servers"
+ private const val ICE_CANDIDATES_PATH = "ice_candidates/"
+ }
+
+ private val mapper by lazy { IceCandidateMapper() }
+ private fun deviceIceCandidatesPath(uuid: String) = ICE_CANDIDATES_PATH.plus(uuid)
+
+ override fun fetchIceServers(done: (List) -> Unit) {
+ db.getReference(ICE_SERVERS_PATH)
+ .addListenerForSingleValueEvent(object : ValueEventListener {
+ override fun onCancelled(p0: DatabaseError) {
+ done(emptyList())
+ }
+
+ override fun onDataChange(p0: DataSnapshot) {
+ val genericTypeIndicator = object :
+ GenericTypeIndicator>() {}
+ val servers = p0.getValue(genericTypeIndicator)
+ done(mapper.map(servers))
+ }
+ })
+ }
+
+ override fun send(candidate: DscIceCandidate, done:(Boolean)->Unit) {
+ val reference = db.getReference(deviceIceCandidatesPath(currentDeviceUuid))
+ with(reference) {
+ onDisconnect().removeValue()
+ push().setValue(mapper.map(candidate)){ dbError, _ ->
+ if(dbError != null){
+ done(false)
+ } else {
+ done(true)
+ }
+ }
+ }
+ }
+
+ override fun remove(iceCandidatesToRemove: Array, done: (Boolean) -> Unit) {
+ val iceCandidatesToRemoveList = mapper.map(iceCandidatesToRemove).toMutableList()
+ val reference = db.getReference(deviceIceCandidatesPath(currentDeviceUuid))
+
+ reference.runTransaction(object : Transaction.Handler {
+ override fun doTransaction(mutableData: MutableData): Transaction.Result {
+ val typeIndicator = object : GenericTypeIndicator>() {}
+ val currentIceCandidatesInFirebaseMap = mutableData.getValue(typeIndicator) ?:
+ return Transaction.success(mutableData)
+
+
+ for ((key, value) in currentIceCandidatesInFirebaseMap) {
+ if (iceCandidatesToRemoveList.remove(value)) {
+ currentIceCandidatesInFirebaseMap.remove(key)
+ }
+ }
+ mutableData.value = currentIceCandidatesInFirebaseMap
+ return Transaction.success(mutableData)
+ }
+
+ override fun onComplete(databaseError: DatabaseError?, committed: Boolean, p2: DataSnapshot?) {
+ if (committed) {
+ done(true)
+ } else {
+ done(false)
+ }
+ }
+ })
+ }
+
+ override fun listenForIceCandidates(remoteUuid: String, add: (DscIceCandidate) -> Unit,
+ remove: (DscIceCandidate) -> Unit) {
+ db.getReference(deviceIceCandidatesPath(remoteUuid))
+ .addChildEventListener(object : ChildEventListener {
+ override fun onCancelled(p0: DatabaseError) {}
+
+ override fun onChildMoved(p0: DataSnapshot, p1: String?) {}
+
+ override fun onChildChanged(p0: DataSnapshot, p1: String?) {}
+
+ override fun onChildAdded(p0: DataSnapshot, p1: String?) {
+ p0.getValue(IceCandidateFirebaseApiData::class.java)?.let {
+ add(mapper.map(it))
+ }
+ }
+
+ override fun onChildRemoved(p0: DataSnapshot) {
+ p0.getValue(IceCandidateFirebaseApiData::class.java)?.let {
+ remove(mapper.map(it))
+ }
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseOffersRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseOffersRepository.kt
new file mode 100644
index 00000000..716d1aaf
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseOffersRepository.kt
@@ -0,0 +1,53 @@
+package nl.entreco.data.stream
+
+import com.google.firebase.database.DataSnapshot
+import com.google.firebase.database.DatabaseError
+import com.google.firebase.database.FirebaseDatabase
+import com.google.firebase.database.ValueEventListener
+import nl.entreco.domain.repository.OffersRepository
+import nl.entreco.domain.streaming.ice.DscSessionDescription
+import nl.entreco.shared.log.Logger
+
+class FirebaseOffersRepository(private val db: FirebaseDatabase,
+ private val logger: Logger,
+ private val currentDeviceUuid: String) : OffersRepository {
+
+ companion object {
+ private const val OFFERS_PATH = "offers/"
+ }
+
+ private fun deviceOffersPath(uuid: String) = OFFERS_PATH.plus(uuid)
+
+ override fun create(recipientUuid: String, localSessionDescription: DscSessionDescription) {
+ val reference = db.getReference(deviceOffersPath(recipientUuid))
+ reference.onDisconnect().removeValue()
+
+ val aha = SessionDescriptionFirebaseApiData()
+ aha.uuid = currentDeviceUuid
+ aha.type = localSessionDescription.type
+ aha.description = localSessionDescription.description
+
+ logger.w("WEBRTC: create Offer $aha")
+
+ reference.setValue(aha)
+ }
+
+ override fun listenForNewOffersWithUuid(onChange: (String, DscSessionDescription) -> Unit) {
+ val reference = db.getReference(deviceOffersPath(currentDeviceUuid))
+ val valueListener = object : ValueEventListener {
+
+ override fun onCancelled(p0: DatabaseError) {}
+
+ override fun onDataChange(p0: DataSnapshot) {
+ p0.getValue(SessionDescriptionFirebaseApiData::class.java)?.let { description ->
+
+ logger.w("WEBRTC: listenForNewOffersWithUuid $description")
+ val session = DscSessionDescription(description.type, description.description ?: "")
+ onChange(description.uuid, session)
+
+ }
+ }
+ }
+ reference.addValueEventListener(valueListener)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseSignallingRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseSignallingRepository.kt
new file mode 100644
index 00000000..079fa9b3
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/FirebaseSignallingRepository.kt
@@ -0,0 +1,150 @@
+package nl.entreco.data.stream
+
+import com.google.firebase.database.*
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.log.Logger
+
+class FirebaseSignallingRepository(private val db: FirebaseDatabase,
+ private val logger: Logger,
+ private val currentDeviceUuid: String) : SignallingRepository {
+
+ companion object {
+ private const val RECEIVER_DEVICES_PATH = "receiving_devices/"
+ private const val STREAMER_DEVICES_PATH = "streaming_devices/"
+ private const val DISCONNECT_PATH = "should_disconnect/"
+ }
+
+ private val onlineReceivers = RECEIVER_DEVICES_PATH.plus(currentDeviceUuid)
+ private val onlineStreamers = STREAMER_DEVICES_PATH.plus(currentDeviceUuid)
+ private fun deviceDisconnectPath(uuid: String) = DISCONNECT_PATH.plus(uuid)
+
+ init {
+ logger.w("UUID: $currentDeviceUuid")
+ logger.w("UUID: onlineReceivers $onlineReceivers")
+ }
+
+
+ override fun connect() {
+ db.goOnline()
+ }
+
+ override fun disconnect() {
+ db.goOffline()
+ }
+
+ override fun listenForDisconnects(done: () -> Unit) {
+ disconnecter = Disconnecter(done)
+ disconnecter?.let {
+ db.getReference(deviceDisconnectPath(currentDeviceUuid))
+ .addChildEventListener(it)
+ }
+ }
+
+ override fun stopListenForDisconnects() {
+ disconnecter?.let {
+ db.getReference(deviceDisconnectPath(currentDeviceUuid))
+ .removeEventListener(it)
+ }
+ disconnecter = null
+ }
+
+ override fun sendDisconnectOrderToOtherParty(uuid: String, done: () -> Unit) {
+ val reference = db.getReference(deviceDisconnectPath(uuid))
+ reference.setValue(DisconnectFirebaseData(currentDeviceUuid)) { databaseError, _ ->
+ if (databaseError != null) {
+ logger.e(databaseError.toString())
+ } else {
+ logger.e("Disconnected Order ")
+ }
+
+ done()
+ }
+ }
+
+ override fun cleanDisconnectOrders(done: () -> Unit, fail: (Throwable) -> Unit) {
+ val reference = db.getReference(deviceDisconnectPath(currentDeviceUuid))
+ reference.onDisconnect().removeValue()
+ reference.removeValue { dbError, _ ->
+ if (dbError != null) {
+ fail(dbError.toException())
+ } else {
+ done()
+ }
+ }
+ }
+
+ override fun setReceiverOnline(connectCode: String, done: (String) -> Unit,
+ fail: (Throwable) -> Unit) {
+ val firebaseOnlineReference = db.getReference(onlineReceivers)
+ with(firebaseOnlineReference) {
+ onDisconnect().removeValue()
+ setValue(ReceiverFirebaseApiData(connectCode, false)) { _, _ ->
+ done(connectCode)
+ }
+ }
+ }
+
+ override fun setStreamerOnline(connectCode: String, done: (String?) -> Unit,
+ fail: (Throwable) -> Unit) {
+ val firebaseOnlineReference = db.getReference(onlineStreamers)
+ with(firebaseOnlineReference) {
+ onDisconnect().removeValue()
+ setValue(StreamerFirebaseData(connectCode, true)) { _, _ ->
+ findReceiverDevice(connectCode, done, fail)
+ }
+ }
+ }
+
+ private fun findReceiverDevice(connectCode: String, done: (String?) -> Unit,
+ fail: (Throwable) -> Unit) {
+ var receiverUuid: String? = null
+ db.getReference(RECEIVER_DEVICES_PATH).runTransaction(object : Transaction.Handler {
+ override fun doTransaction(mutableData: MutableData): Transaction.Result {
+ val genericTypeIndicator = object :
+ GenericTypeIndicator>() {}
+ val availableDevices = mutableData.getValue(genericTypeIndicator)
+ ?: return Transaction.success(mutableData)
+ if (!availableDevices.isEmpty()) {
+ receiverUuid = deleteDeviceFromAvailable(connectCode, availableDevices)
+ mutableData.value = availableDevices
+ }
+
+ return Transaction.success(mutableData)
+ }
+
+ private fun deleteDeviceFromAvailable(connectCode: String,
+ availableDevices: MutableMap): String? {
+ val remoteDeviceUuid = availableDevices.entries.firstOrNull { it.value.code == connectCode }
+ ?.key
+ logger.d("Device number $remoteDeviceUuid was chosen because of code $connectCode.")
+ availableDevices.remove(remoteDeviceUuid)
+ return remoteDeviceUuid
+ }
+
+ override fun onComplete(databaseError: DatabaseError?, completed: Boolean,
+ p2: DataSnapshot?) {
+ if (databaseError != null) {
+ fail(databaseError.toException())
+ } else if (completed) {
+ done(receiverUuid)
+ }
+ }
+ })
+ }
+
+ private var disconnecter: ChildEventListener? = null
+
+ private class Disconnecter(private val done: () -> Unit) : ChildEventListener {
+ override fun onCancelled(p0: DatabaseError) {}
+
+ override fun onChildMoved(p0: DataSnapshot, p1: String?) {}
+
+ override fun onChildChanged(p0: DataSnapshot, p1: String?) {}
+
+ override fun onChildAdded(p0: DataSnapshot, p1: String?) {
+ done()
+ }
+
+ override fun onChildRemoved(p0: DataSnapshot) {}
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceCandidateFirebaseApiData.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceCandidateFirebaseApiData.kt
new file mode 100644
index 00000000..80c6348a
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceCandidateFirebaseApiData.kt
@@ -0,0 +1,19 @@
+package nl.entreco.data.stream
+
+import android.support.annotation.Keep
+import com.google.firebase.firestore.IgnoreExtraProperties
+import com.google.gson.annotations.SerializedName
+
+@Keep
+@IgnoreExtraProperties
+internal data class IceCandidateFirebaseApiData(
+
+ @SerializedName("sdpMid")
+ var sdpMid: String = "",
+
+ @SerializedName("sdpMLineIndex")
+ var sdpMLineIndex: Int = -1,
+
+ @SerializedName("sdp")
+ var sdp: String = ""
+)
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceCandidateMapper.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceCandidateMapper.kt
new file mode 100644
index 00000000..de1caa7b
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceCandidateMapper.kt
@@ -0,0 +1,34 @@
+package nl.entreco.data.stream
+
+import nl.entreco.domain.streaming.ice.DscIceCandidate
+import nl.entreco.domain.streaming.ice.DscIceServer
+
+internal class IceCandidateMapper {
+ internal fun map(servers: ArrayList?): List {
+ return servers?.mapNotNull { map(it) } ?: emptyList()
+ }
+
+ private fun map(apiData: IceServerFirebaseApiData): DscIceServer? {
+ return if (apiData.uri?.isNotBlank() == true) {
+ DscIceServer(apiData.uri)
+ } else {
+ null
+ }
+ }
+
+ internal fun map(apiData: IceCandidateFirebaseApiData): DscIceCandidate {
+ return DscIceCandidate(apiData.sdpMid, apiData.sdpMLineIndex, apiData.sdp)
+ }
+
+ internal fun map(data: DscIceCandidate) : IceCandidateFirebaseApiData {
+ val candidate = IceCandidateFirebaseApiData()
+ candidate.sdp = data.sdp
+ candidate.sdpMLineIndex = data.sdpMLineIndex
+ candidate.sdpMid = data.sdpMid
+ return candidate
+ }
+
+ internal fun map(data: Array) : List {
+ return data.map { map(it) }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceServerFirebaseApiData.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceServerFirebaseApiData.kt
new file mode 100644
index 00000000..b992f66d
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/IceServerFirebaseApiData.kt
@@ -0,0 +1,18 @@
+package nl.entreco.data.stream
+
+import android.support.annotation.Keep
+import com.google.firebase.firestore.IgnoreExtraProperties
+import com.google.firebase.firestore.PropertyName
+
+@Keep
+@IgnoreExtraProperties
+internal data class IceServerFirebaseApiData(
+ @PropertyName("uri")
+ val uri: String? = null,
+
+ @PropertyName("username")
+ val username: String? = null,
+
+ @PropertyName("password")
+ val password: String? = null
+)
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/ReceiverFirebaseApiData.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/ReceiverFirebaseApiData.kt
new file mode 100644
index 00000000..65c5ba1c
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/ReceiverFirebaseApiData.kt
@@ -0,0 +1,16 @@
+package nl.entreco.data.stream
+
+import android.support.annotation.Keep
+import com.google.firebase.firestore.IgnoreExtraProperties
+import com.google.firebase.firestore.PropertyName
+
+@Keep
+@IgnoreExtraProperties
+internal data class ReceiverFirebaseApiData(
+
+ @PropertyName("code")
+ val code: String = "",
+
+ @PropertyName("inCall")
+ val inCall: Boolean = false
+)
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/SessionDescriptionFirebaseApiData.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/SessionDescriptionFirebaseApiData.kt
new file mode 100644
index 00000000..8686ecd5
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/SessionDescriptionFirebaseApiData.kt
@@ -0,0 +1,19 @@
+package nl.entreco.data.stream
+
+import android.support.annotation.Keep
+import com.google.firebase.firestore.IgnoreExtraProperties
+import com.google.firebase.firestore.PropertyName
+
+@Keep
+@IgnoreExtraProperties
+internal data class SessionDescriptionFirebaseApiData(
+
+ @PropertyName("uuid")
+ var uuid: String = "",
+
+ @PropertyName("type")
+ var type: Int = 0,
+
+ @PropertyName("description")
+ var description: String? = null
+)
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/StreamerFirebaseData.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/StreamerFirebaseData.kt
new file mode 100644
index 00000000..a8b8d0e1
--- /dev/null
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/stream/StreamerFirebaseData.kt
@@ -0,0 +1,14 @@
+package nl.entreco.data.stream
+
+import android.support.annotation.Keep
+import com.google.firebase.firestore.IgnoreExtraProperties
+import com.google.firebase.firestore.PropertyName
+
+@Keep
+@IgnoreExtraProperties
+internal data class StreamerFirebaseData(
+ @PropertyName("code")
+ val code: String,
+ @PropertyName("inCall")
+ val inCall: Boolean = false
+)
\ No newline at end of file
diff --git a/android/DartsScorecard/data/src/main/java/nl/entreco/data/wtf/RemoteWtfRepository.kt b/android/DartsScorecard/data/src/main/java/nl/entreco/data/wtf/RemoteWtfRepository.kt
index 4d3d3204..11510dee 100644
--- a/android/DartsScorecard/data/src/main/java/nl/entreco/data/wtf/RemoteWtfRepository.kt
+++ b/android/DartsScorecard/data/src/main/java/nl/entreco/data/wtf/RemoteWtfRepository.kt
@@ -1,7 +1,7 @@
package nl.entreco.data.wtf
import com.google.firebase.firestore.*
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.repository.WtfRepository
import nl.entreco.domain.wtf.WtfItem
diff --git a/android/DartsScorecard/data/src/test/java/nl/entreco/data/api/beta/RemoteFeatureRepositoryTest.kt b/android/DartsScorecard/data/src/test/java/nl/entreco/data/api/beta/RemoteFeatureRepositoryTest.kt
index 4f0025de..21abe0f3 100644
--- a/android/DartsScorecard/data/src/test/java/nl/entreco/data/api/beta/RemoteFeatureRepositoryTest.kt
+++ b/android/DartsScorecard/data/src/test/java/nl/entreco/data/api/beta/RemoteFeatureRepositoryTest.kt
@@ -3,7 +3,7 @@ package nl.entreco.data.api.beta
import com.google.firebase.firestore.CollectionReference
import com.google.firebase.firestore.FirebaseFirestore
import com.nhaarman.mockito_kotlin.whenever
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.beta.Feature
import org.junit.Assert.*
import org.junit.Ignore
diff --git a/android/DartsScorecard/data/src/test/java/nl/entreco/data/play/local/LocalGameRepositoryTest.kt b/android/DartsScorecard/data/src/test/java/nl/entreco/data/play/local/LocalGameRepositoryTest.kt
index 0d860ebe..52efdb07 100644
--- a/android/DartsScorecard/data/src/test/java/nl/entreco/data/play/local/LocalGameRepositoryTest.kt
+++ b/android/DartsScorecard/data/src/test/java/nl/entreco/data/play/local/LocalGameRepositoryTest.kt
@@ -102,7 +102,7 @@ class LocalGameRepositoryTest {
fun `it should return finished game count (10)`() {
givenFinishedGames(4)
whenCountingFinishedGames()
- thenNumberOfFinishedGamesIs(0)
+ thenNumberOfFinishedGamesIs(4)
}
private fun givenExistingGames() {
diff --git a/android/DartsScorecard/domain/build.gradle b/android/DartsScorecard/domain/build.gradle
index 8d310468..fa8b8c6b 100644
--- a/android/DartsScorecard/domain/build.gradle
+++ b/android/DartsScorecard/domain/build.gradle
@@ -10,7 +10,8 @@ android {
}
dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
+ implementation project(":shared")
+
implementation "com.android.support:support-annotations:$support"
implementation "com.google.dagger:dagger:$daggerVersion"
implementation "com.google.code.gson:gson:$gson"
diff --git a/android/DartsScorecard/domain/proguard-rules.pro b/android/DartsScorecard/domain/proguard-rules.pro
index f1b42451..c8de4dbe 100644
--- a/android/DartsScorecard/domain/proguard-rules.pro
+++ b/android/DartsScorecard/domain/proguard-rules.pro
@@ -19,3 +19,69 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+
+# Base Settings from Dev
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontskipnonpubliclibraryclassmembers
+-dontpreverify
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+-keepattributes LineNumberTable,SourceFile,Signature,*Annotation*,Exceptions,InnerClasses
+
+# Crashlytics
+-keepattributes *Annotation*
+-keepattributes SourceFile,LineNumberTable
+-keep public class * extends java.lang.Exception
+
+# Okio
+-dontwarn okio.**
+-dontnote okio.**
+
+# OkHttp
+-dontwarn okhttp3.**
+
+# Billing
+-keep class com.android.vending.billing.**
+
+# Glide
+-keep public class * implements com.bumptech.glide.module.GlideModule
+-keep public class * extends com.bumptech.glide.module.AppGlideModule
+-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
+ **[] $VALUES;
+ public *;
+}
+
+# Databinding
+-keepclasseswithmembernames interface android.databinding.DataBindingComponent
+-dontwarn android.databinding.DataBindingComponent
+-dontnote android.databinding.DataBindingComponent
+-keep class android.databinding.DataBinderMapper
+-dontwarn android.databinding.DataBinderMapper
+-dontnote android.databinding.DataBinderMapper
+
+# WebRtc
+-keep class org.webrtc.** { *; }
+-dontnote org.apache.http.**
+-dontwarn org.apache.http.**
+-dontnote android.net.http.*
+-dontwarn android.net.http.**
+-dontnote org.apache.commons.codec.**
+-dontwarn org.apache.commons.codec.**
+
+# Keep native methods
+-keepclassmembers class * {
+ native ;
+}
+
+#GMS
+-keep class com.google.android.gms.common.api.internal.BasePendingResult$ReleasableResultGuardian
+-keep class com.google.android.gms.** { *; }
+-dontwarn com.google.android.gms.**
+
+-keepnames @pcom.google.android.gms.common.annotation.KeepName class *
+
+-keepclassmembernames class * {
+ @com.google.android.gms.common.annotation.KeepName *;
+}
+
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/BaseUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/BaseUsecase.kt
index 456eb817..0f063af7 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/BaseUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/BaseUsecase.kt
@@ -1,7 +1,7 @@
package nl.entreco.domain
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
/**
* Created by Entreco on 17/12/2017.
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/ad/FetchPurchasedItemsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/ad/FetchPurchasedItemsUsecase.kt
index 8ce2ebb6..c28e63aa 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/ad/FetchPurchasedItemsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/ad/FetchPurchasedItemsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.ad
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.BillingRepository
import nl.entreco.domain.repository.GameRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/ConsumeDonationUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/ConsumeDonationUsecase.kt
index fbace94b..8324668f 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/ConsumeDonationUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/ConsumeDonationUsecase.kt
@@ -3,8 +3,8 @@ package nl.entreco.domain.beta.donations
import com.google.gson.GsonBuilder
import com.google.gson.annotations.SerializedName
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.BillingRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/FetchDonationsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/FetchDonationsUsecase.kt
index 8f1c6e0e..226a1968 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/FetchDonationsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/FetchDonationsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.beta.donations
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.BillingRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/MakeDonationUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/MakeDonationUsecase.kt
index b2ada61b..b06bc10b 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/MakeDonationUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/donations/MakeDonationUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.beta.donations
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.BillingRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/vote/SubmitVoteUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/vote/SubmitVoteUsecase.kt
index 15905941..482da236 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/vote/SubmitVoteUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/beta/vote/SubmitVoteUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.beta.vote
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.FeatureRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/ExtractTeamsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/ExtractTeamsUsecase.kt
index 83d79af1..73f98518 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/ExtractTeamsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/ExtractTeamsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.launch
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.repository.PlayerRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/RetrieveLatestGameUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/RetrieveLatestGameUsecase.kt
index d50ad568..c56eae57 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/RetrieveLatestGameUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/launch/RetrieveLatestGameUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.launch
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.GameRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/description/FetchMatchDescriptionUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/description/FetchMatchDescriptionUsecase.kt
index 7f5ff853..d09e9fd0 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/description/FetchMatchDescriptionUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/description/FetchMatchDescriptionUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.description
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.MatchDescriptionRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/finish/GetFinishUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/finish/GetFinishUsecase.kt
index 1a96cb6e..efad6e20 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/finish/GetFinishUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/finish/GetFinishUsecase.kt
@@ -2,9 +2,8 @@ package nl.entreco.domain.play.finish
import android.support.annotation.VisibleForTesting
import android.support.annotation.WorkerThread
-import nl.entreco.domain.common.executors.Background
+import nl.entreco.shared.threading.Background
import nl.entreco.domain.model.Dart
-import java.nio.file.Files.find
import java.util.concurrent.Future
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/MasterCaller.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/MasterCaller.kt
index 66788e5a..905bbc36 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/MasterCaller.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/MasterCaller.kt
@@ -1,9 +1,9 @@
package nl.entreco.domain.play.mastercaller
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.log.Logger
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.log.Logger
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.SoundRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/ToggleSoundUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/ToggleSoundUsecase.kt
index ee29cf5f..c93f4e17 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/ToggleSoundUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/mastercaller/ToggleSoundUsecase.kt
@@ -1,15 +1,15 @@
package nl.entreco.domain.play.mastercaller
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.AudioPrefRepository
import javax.inject.Inject
/**
* Created by entreco on 14/03/2018.
*/
-class ToggleSoundUsecase @Inject constructor(private val audioPrefRepository: AudioPrefRepository,bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+class ToggleSoundUsecase @Inject constructor(private val audioPrefRepository: AudioPrefRepository, bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
fun toggle(){
onBackground({
val toggled = !audioPrefRepository.isMasterCallerEnabled()
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/revanche/RevancheUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/revanche/RevancheUsecase.kt
index d529faca..54fccbfa 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/revanche/RevancheUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/revanche/RevancheUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.revanche
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.GameRepository
import nl.entreco.domain.settings.ScoreSettings
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt
index 1f1eb3ee..6ad10a1f 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/MarkGameAsFinishedUsecase.kt
@@ -2,8 +2,8 @@ package nl.entreco.domain.play.start
import nl.entreco.domain.Analytics
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.GameRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/Play01Usecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/Play01Usecase.kt
index 9b9e1103..723a5138 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/Play01Usecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/Play01Usecase.kt
@@ -1,6 +1,6 @@
package nl.entreco.domain.play.start
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.TurnMeta
import nl.entreco.domain.play.stats.*
import nl.entreco.domain.settings.ScoreSettings
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveGameUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveGameUsecase.kt
index 140bacaa..92599299 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveGameUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveGameUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.start
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.GameRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTeamsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTeamsUsecase.kt
index 2df530ab..158e20d2 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTeamsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTeamsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.start
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.model.players.DeletedPlayer
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTurnsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTurnsUsecase.kt
index c7f8f6c4..6c6e6d27 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTurnsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/start/RetrieveTurnsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.start
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.TurnRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchGameStatsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchGameStatsUsecase.kt
index 81eb27e5..f8e1942c 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchGameStatsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchGameStatsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.stats
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.LiveStatRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchLiveStatUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchLiveStatUsecase.kt
index 168ab5e1..26c11751 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchLiveStatUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/FetchLiveStatUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.stats
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.LiveStatRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreMetaUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreMetaUsecase.kt
index a73f8cea..923798be 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreMetaUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreMetaUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.stats
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.play.ScoreEstimator
import nl.entreco.domain.repository.MetaRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreTurnUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreTurnUsecase.kt
index 8cc83207..9e2dfe84 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreTurnUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/StoreTurnUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.stats
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.model.Dart
import nl.entreco.domain.model.State
import nl.entreco.domain.model.Turn
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/UndoTurnUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/UndoTurnUsecase.kt
index f7de4f87..b4157055 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/UndoTurnUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/play/stats/UndoTurnUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.stats
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.GameRepository
import nl.entreco.domain.repository.MetaRepository
import nl.entreco.domain.repository.TurnRepository
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/archive/ArchiveStatsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/archive/ArchiveStatsUsecase.kt
index 72ff0095..d2ab7638 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/archive/ArchiveStatsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/archive/ArchiveStatsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.profile.archive
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.ArchiveRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileStatsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileStatsUsecase.kt
index a074a913..9060d41b 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileStatsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileStatsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.profile.fetch
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.ProfileStatRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileUsecase.kt
index 5aa55b7d..c2dc97c1 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/fetch/FetchProfileUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.profile.fetch
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.ProfileInfoRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/update/UpdateProfileUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/update/UpdateProfileUsecase.kt
index 11cdd838..aa148e20 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/update/UpdateProfileUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/profile/update/UpdateProfileUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.profile.update
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.ImageRepository
import nl.entreco.domain.repository.ProfileInfoRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/ConnectToBillingUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/ConnectToBillingUsecase.kt
index d3fa4725..aa35950d 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/ConnectToBillingUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/ConnectToBillingUsecase.kt
@@ -2,8 +2,8 @@ package nl.entreco.domain.purchases.connect
import android.support.annotation.UiThread
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.BillingRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/SubscribeToFeaturesUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/SubscribeToFeaturesUsecase.kt
index bae6e6a0..173af2a5 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/SubscribeToFeaturesUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/purchases/connect/SubscribeToFeaturesUsecase.kt
@@ -2,8 +2,8 @@ package nl.entreco.domain.purchases.connect
import nl.entreco.domain.BaseUsecase
import nl.entreco.domain.beta.Feature
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.FeatureRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/rating/AskForRatingResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/rating/AskForRatingResponse.kt
new file mode 100644
index 00000000..80064e06
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/rating/AskForRatingResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.rating
+
+data class AskForRatingResponse(val shouldAskForRating: Boolean)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/rating/AskForRatingUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/rating/AskForRatingUsecase.kt
new file mode 100644
index 00000000..19ee1054
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/rating/AskForRatingUsecase.kt
@@ -0,0 +1,25 @@
+package nl.entreco.domain.rating
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.GameRepository
+import nl.entreco.domain.repository.RatingPrefRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class AskForRatingUsecase @Inject constructor(
+ private val ratingPrefRepository: RatingPrefRepository,
+ private val gameRepository: GameRepository, bg: Background, fg: Foreground) :
+ BaseUsecase(bg, fg) {
+
+ fun go(done: (AskForRatingResponse) -> Unit, fail: (Throwable) -> Unit) {
+ onBackground({
+ var shouldRateApp = false
+ if (ratingPrefRepository.shouldAskToRateApp()) {
+ val finishedGames = gameRepository.countFinishedGames()
+ shouldRateApp = finishedGames >= 5
+ }
+ onUi { done(AskForRatingResponse(shouldRateApp)) }
+ }, fail)
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/AnswersRepository.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/AnswersRepository.kt
new file mode 100644
index 00000000..c6e5f58b
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/AnswersRepository.kt
@@ -0,0 +1,12 @@
+package nl.entreco.domain.repository
+
+import android.support.annotation.WorkerThread
+import nl.entreco.domain.streaming.ice.DscSessionDescription
+
+interface AnswersRepository {
+ @WorkerThread
+ fun create(recipientUuid: String, localSessionDescription: DscSessionDescription)
+
+ @WorkerThread
+ fun listenForNewAnswers(onChange:(DscSessionDescription)->Unit)
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/IceRepository.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/IceRepository.kt
new file mode 100644
index 00000000..31765afd
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/IceRepository.kt
@@ -0,0 +1,19 @@
+package nl.entreco.domain.repository
+
+import android.support.annotation.WorkerThread
+import nl.entreco.domain.streaming.ice.DscIceCandidate
+import nl.entreco.domain.streaming.ice.DscIceServer
+
+interface IceRepository {
+ @WorkerThread
+ fun fetchIceServers(done: (List) -> Unit)
+
+ @WorkerThread
+ fun listenForIceCandidates(remoteUuid: String, add:(DscIceCandidate)->Unit, remove: (DscIceCandidate)->Unit)
+
+ @WorkerThread
+ fun send(candidate: DscIceCandidate, done:(Boolean)->Unit)
+
+ @WorkerThread
+ fun remove(iceCandidatesToRemove: Array, done: (Boolean)->Unit)
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/OffersRepository.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/OffersRepository.kt
new file mode 100644
index 00000000..582cf238
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/OffersRepository.kt
@@ -0,0 +1,14 @@
+package nl.entreco.domain.repository
+
+import android.support.annotation.WorkerThread
+import nl.entreco.domain.streaming.ice.DscSessionDescription
+
+interface OffersRepository {
+
+ @WorkerThread
+ fun create(recipientUuid: String, localSessionDescription: DscSessionDescription)
+
+ @WorkerThread
+ fun listenForNewOffersWithUuid(onChange:(String, DscSessionDescription)->Unit)
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/RatingPrefRepository.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/RatingPrefRepository.kt
new file mode 100644
index 00000000..e47835a6
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/RatingPrefRepository.kt
@@ -0,0 +1,6 @@
+package nl.entreco.domain.repository
+
+interface RatingPrefRepository {
+ fun neverAskAgain()
+ fun shouldAskToRateApp() : Boolean
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/SignallingRepository.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/SignallingRepository.kt
new file mode 100644
index 00000000..9d9166a0
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/repository/SignallingRepository.kt
@@ -0,0 +1,12 @@
+package nl.entreco.domain.repository
+
+interface SignallingRepository {
+ fun connect()
+ fun disconnect()
+ fun listenForDisconnects(done: () -> Unit)
+ fun stopListenForDisconnects()
+ fun cleanDisconnectOrders(done: () -> Unit, fail: (Throwable) -> Unit)
+ fun setStreamerOnline(connectCode: String, done: (String?) -> Unit, fail: (Throwable) -> Unit)
+ fun setReceiverOnline(connectCode: String, done: (String) -> Unit, fail: (Throwable) -> Unit)
+ fun sendDisconnectOrderToOtherParty(uuid: String, done: () -> Unit)
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt
index 4d68e50c..a2393953 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/game/CreateGameUsecase.kt
@@ -2,8 +2,8 @@ package nl.entreco.domain.setup.game
import nl.entreco.domain.Analytics
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.GameRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/CreatePlayerUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/CreatePlayerUsecase.kt
index c276b7a1..6e88c31f 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/CreatePlayerUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/CreatePlayerUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.setup.players
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.PlayerPrefs
import nl.entreco.domain.repository.PlayerRepository
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/DeletePlayerUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/DeletePlayerUsecase.kt
index c8713f56..8508e735 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/DeletePlayerUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/DeletePlayerUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.setup.players
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.PlayerRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/FetchExistingPlayersUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/FetchExistingPlayersUsecase.kt
index b016e249..8a6e42e2 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/FetchExistingPlayersUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/setup/players/FetchExistingPlayersUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.setup.players
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.PlayerRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ConnectionState.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ConnectionState.kt
new file mode 100644
index 00000000..905c3d06
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ConnectionState.kt
@@ -0,0 +1,12 @@
+package nl.entreco.domain.streaming
+
+sealed class ConnectionState
+
+object Unknown : ConnectionState()
+object Initializing : ConnectionState()
+object ReadyToConnect : ConnectionState()
+object Connecting : ConnectionState()
+object Connected : ConnectionState()
+object Disconnecting : ConnectionState()
+object Disconnected : ConnectionState()
+object Killing : ConnectionState()
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectFromSignallingRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectFromSignallingRequest.kt
new file mode 100644
index 00000000..0b70b6f7
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectFromSignallingRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming
+
+data class DisconnectFromSignallingRequest (val uuid: String?)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectFromSignallingUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectFromSignallingUsecase.kt
new file mode 100644
index 00000000..eed700c2
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectFromSignallingUsecase.kt
@@ -0,0 +1,33 @@
+package nl.entreco.domain.streaming
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.log.Logger
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class DisconnectFromSignallingUsecase @Inject constructor(
+ private val logger: Logger,
+ private val signallingRepository: SignallingRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: DisconnectFromSignallingRequest, done: () -> Unit) {
+ onBackground({
+
+ if(request.uuid != null) {
+ signallingRepository.sendDisconnectOrderToOtherParty(request.uuid) {
+ done()
+ }
+ } else {
+ done()
+ }
+ }, onError())
+ }
+
+ private fun onError(): (Throwable) -> Unit {
+ return {
+ logger.w(it.localizedMessage)
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectUsecase.kt
new file mode 100644
index 00000000..08acce11
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/DisconnectUsecase.kt
@@ -0,0 +1,30 @@
+package nl.entreco.domain.streaming
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.log.Logger
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class DisconnectUsecase @Inject constructor(
+ private val logger: Logger,
+ private val signallingRepository: SignallingRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(done:()->Unit) {
+ onBackground({
+
+ signallingRepository.disconnect()
+ signallingRepository.stopListenForDisconnects()
+ onUi(done)
+
+ }, onError())
+ }
+
+ private fun onError(): (Throwable) -> Unit {
+ return {
+ logger.w(it.localizedMessage)
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferRequest.kt
new file mode 100644
index 00000000..478ac499
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class CreateOfferRequest(val recipientUuid: String, val description: DscSessionDescription)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferResponse.kt
new file mode 100644
index 00000000..70181dc8
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class CreateOfferResponse(val todo: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferUsecase.kt
new file mode 100644
index 00000000..7f9c157c
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/CreateOfferUsecase.kt
@@ -0,0 +1,21 @@
+package nl.entreco.domain.streaming.ice
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.OffersRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class CreateOfferUsecase @Inject constructor(
+ private val respository: OffersRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: CreateOfferRequest,
+ fail: (Throwable) -> Unit) {
+ onBackground({
+ respository.create(request.recipientUuid, request.description)
+ }, fail)
+
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscIceCandidate.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscIceCandidate.kt
new file mode 100644
index 00000000..882e65f5
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscIceCandidate.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class DscIceCandidate(val sdpMid: String, val sdpMLineIndex: Int, val sdp: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscIceServer.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscIceServer.kt
new file mode 100644
index 00000000..193a06d2
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscIceServer.kt
@@ -0,0 +1,5 @@
+package nl.entreco.domain.streaming.ice
+
+data class DscIceServer(val uri: String,
+ val username: String? = null,
+ val password: String? = null)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscSessionDescription.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscSessionDescription.kt
new file mode 100644
index 00000000..a0d57db8
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/DscSessionDescription.kt
@@ -0,0 +1,4 @@
+package nl.entreco.domain.streaming.ice
+
+data class DscSessionDescription(val type: Int,
+ val description: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/FetchIceServerResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/FetchIceServerResponse.kt
new file mode 100644
index 00000000..ccd7ffc8
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/FetchIceServerResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class FetchIceServerResponse(val iceServers: List)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/FetchIceServerUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/FetchIceServerUsecase.kt
new file mode 100644
index 00000000..cb81dfe4
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/FetchIceServerUsecase.kt
@@ -0,0 +1,24 @@
+package nl.entreco.domain.streaming.ice
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.IceRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class FetchIceServerUsecase @Inject constructor(
+ private val iceRepository: IceRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(
+ done: (FetchIceServerResponse) -> Unit,
+ fail: (Throwable) -> Unit) {
+
+ onBackground({
+ iceRepository.fetchIceServers { servers ->
+ onUi { done(FetchIceServerResponse(servers)) }
+ }
+ }, fail)
+
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForAnswersResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForAnswersResponse.kt
new file mode 100644
index 00000000..9b8f5d9d
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForAnswersResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class ListenForAnswersResponse(val sessionType: Int, val sessionDescription: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForAnswersUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForAnswersUsecase.kt
new file mode 100644
index 00000000..e8f5ddf8
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForAnswersUsecase.kt
@@ -0,0 +1,26 @@
+package nl.entreco.domain.streaming.ice
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.AnswersRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class ListenForAnswersUsecase @Inject constructor(
+ private val repository: AnswersRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(done: (ListenForAnswersResponse) -> Unit,
+ fail: (Throwable) -> Unit) {
+ onBackground({
+
+ repository.listenForNewAnswers { change ->
+ val response = ListenForAnswersResponse(change.type, change.description)
+ onUi { done(response) }
+ }
+
+ }, fail)
+
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesRequest.kt
new file mode 100644
index 00000000..b785e7e7
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class ListenForIceCandidatesRequest(val uuid: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesResponse.kt
new file mode 100644
index 00000000..340406a4
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class ListenForIceCandidatesResponse(val candidate: DscIceCandidate, val shouldAdd: Boolean)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesUsecase.kt
new file mode 100644
index 00000000..b241fbd9
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForIceCandidatesUsecase.kt
@@ -0,0 +1,32 @@
+package nl.entreco.domain.streaming.ice
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.IceRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class ListenForIceCandidatesUsecase @Inject constructor(
+ private val repository: IceRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: ListenForIceCandidatesRequest,
+ done: (ListenForIceCandidatesResponse) -> Unit,
+ fail: (Throwable) -> Unit) {
+
+ onBackground({
+
+ repository.listenForIceCandidates(request.uuid,
+ shouldAdd(done, true),
+ shouldAdd(done, false))
+
+ }, fail)
+
+ }
+
+ private fun shouldAdd(
+ done: (ListenForIceCandidatesResponse) -> Unit,
+ add: Boolean): (DscIceCandidate) -> Unit =
+ { done(ListenForIceCandidatesResponse(it, add)) }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferRequest.kt
new file mode 100644
index 00000000..82c5cab7
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class ListenForOfferRequest(val todo: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferResponse.kt
new file mode 100644
index 00000000..89be4618
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class ListenForOfferResponse(val senderUuid: String, val sessionType: Int, val sessionDescription: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferUsecase.kt
new file mode 100644
index 00000000..ada6449b
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/ListenForOfferUsecase.kt
@@ -0,0 +1,26 @@
+package nl.entreco.domain.streaming.ice
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.OffersRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class ListenForOfferUsecase @Inject constructor(
+ private val respository: OffersRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(done: (ListenForOfferResponse) -> Unit,
+ fail: (Throwable) -> Unit) {
+ onBackground({
+
+ respository.listenForNewOffersWithUuid { senderUuid, session ->
+ val response = ListenForOfferResponse(senderUuid, session.type, session.description)
+ onUi { done(response) }
+ }
+
+ }, fail)
+
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/SendAnswerRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/SendAnswerRequest.kt
new file mode 100644
index 00000000..b108b67b
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/SendAnswerRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.ice
+
+data class SendAnswerRequest(val recipientUuid: String, val localSessionDescription: DscSessionDescription)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/SendAnswerUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/SendAnswerUsecase.kt
new file mode 100644
index 00000000..bae559c5
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/ice/SendAnswerUsecase.kt
@@ -0,0 +1,19 @@
+package nl.entreco.domain.streaming.ice
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.AnswersRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class SendAnswerUsecase @Inject constructor(
+ private val respository: AnswersRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: SendAnswerRequest, fail: (Throwable) -> Unit) {
+ onBackground({
+ respository.create(request.recipientUuid, request.localSessionDescription)
+ }, fail)
+
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateRequest.kt
new file mode 100644
index 00000000..a4867bcc
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateRequest.kt
@@ -0,0 +1,5 @@
+package nl.entreco.domain.streaming.p2p
+
+import nl.entreco.domain.streaming.ice.DscIceCandidate
+
+data class RemoveIceCandidateRequest(val candidates: Array)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateResponse.kt
new file mode 100644
index 00000000..9daaad42
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.p2p
+
+data class RemoveIceCandidateResponse(val todo: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateUsecase.kt
new file mode 100644
index 00000000..a85c91bb
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/RemoveIceCandidateUsecase.kt
@@ -0,0 +1,28 @@
+package nl.entreco.domain.streaming.p2p
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.IceRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class RemoveIceCandidateUsecase @Inject constructor(
+ private val iceRepository: IceRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: RemoveIceCandidateRequest, done: (RemoveIceCandidateResponse) -> Unit, fail: (Throwable) -> Unit) {
+ onBackground({
+
+ iceRepository.remove(request.candidates) { success ->
+ if (success) {
+ onUi { done(RemoveIceCandidateResponse("done")) }
+ } else {
+ onUi { fail(IllegalStateException("Unable to add IceCandiate")) }
+ }
+ }
+
+ }, fail)
+
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateRequest.kt
new file mode 100644
index 00000000..36986ab3
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateRequest.kt
@@ -0,0 +1,5 @@
+package nl.entreco.domain.streaming.p2p
+
+import nl.entreco.domain.streaming.ice.DscIceCandidate
+
+data class SendIceCandidateRequest(val candidate: DscIceCandidate)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateResponse.kt
new file mode 100644
index 00000000..aeede225
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.p2p
+
+data class SendIceCandidateResponse(val todo: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateUsecase.kt
new file mode 100644
index 00000000..69a66895
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/p2p/SendIceCandidateUsecase.kt
@@ -0,0 +1,28 @@
+package nl.entreco.domain.streaming.p2p
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.IceRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class SendIceCandidateUsecase @Inject constructor(
+ private val iceRepository: IceRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: SendIceCandidateRequest, done: (SendIceCandidateResponse) -> Unit, fail: (Throwable) -> Unit) {
+ onBackground({
+
+ iceRepository.send(request.candidate) { success ->
+ if (success) {
+ onUi { done(SendIceCandidateResponse("done")) }
+ } else {
+ onUi { fail(IllegalStateException("Unable to add IceCandiate")) }
+ }
+ }
+
+ }, fail)
+
+ }
+
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/ListenForDisconnectsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/ListenForDisconnectsUsecase.kt
new file mode 100644
index 00000000..bcfc55f3
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/ListenForDisconnectsUsecase.kt
@@ -0,0 +1,29 @@
+package nl.entreco.domain.streaming.receive
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.log.Logger
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class ListenForDisconnectsUsecase @Inject constructor(
+ private val logger: Logger,
+ private val signallingRepository: SignallingRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(done: () -> Unit) {
+ onBackground({
+ signallingRepository.cleanDisconnectOrders({}, {})
+ signallingRepository.listenForDisconnects {
+ onUi(done)
+ }
+ }, onError())
+ }
+
+ private fun onError(): (Throwable) -> Unit {
+ return {
+ logger.w("Listen for Disconnects error :$it")
+ }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverRequest.kt
new file mode 100644
index 00000000..8607aa22
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.receive
+
+data class RegisterReceiverRequest(val extra: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverResponse.kt
new file mode 100644
index 00000000..a83e3d81
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.receive
+
+data class RegisterReceiverResponse(val code: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverUsecase.kt
new file mode 100644
index 00000000..f39eaff8
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/receive/RegisterReceiverUsecase.kt
@@ -0,0 +1,47 @@
+package nl.entreco.domain.streaming.receive
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import java.util.*
+import javax.inject.Inject
+
+class RegisterReceiverUsecase @Inject constructor(
+ private val signallingRepository: SignallingRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ private var connectCode = ""
+
+ fun go(request: RegisterReceiverRequest, done: (RegisterReceiverResponse) -> Unit,
+ fail: (Throwable) -> Unit) {
+
+ onBackground({
+
+ signallingRepository.connect()
+ signallingRepository.cleanDisconnectOrders(onDisconnectSuccess(done, fail),
+ onError("error disconnecting orders", fail))
+ }, fail)
+
+ }
+
+ private fun onDisconnectSuccess(
+ done: (RegisterReceiverResponse) -> Unit,
+ fail: (Throwable) -> Unit): () -> Unit = {
+ connectCode = (0..4).map { Random().nextInt(9) }.joinToString("") { it.toString() }
+ signallingRepository.setReceiverOnline(
+ connectCode,
+ onFoundDevice(done),
+ onError("error find online device", fail))
+ }
+
+ private fun onFoundDevice(done: (RegisterReceiverResponse) -> Unit): (String) -> Unit {
+ return { code ->
+ onUi { done(RegisterReceiverResponse(code)) }
+ }
+ }
+
+ private fun onError(msg: String, fail: (Throwable) -> Unit): (Throwable) -> Unit = { err ->
+ onUi { fail(IllegalArgumentException(msg)) }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerRequest.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerRequest.kt
new file mode 100644
index 00000000..a946fb7f
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerRequest.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.send
+
+data class RegisterStreamerRequest(val deviceId: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerResponse.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerResponse.kt
new file mode 100644
index 00000000..4c73e567
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerResponse.kt
@@ -0,0 +1,3 @@
+package nl.entreco.domain.streaming.send
+
+data class RegisterStreamerResponse(val uuid: String)
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerUsecase.kt
new file mode 100644
index 00000000..02b435e1
--- /dev/null
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/streaming/send/RegisterStreamerUsecase.kt
@@ -0,0 +1,51 @@
+package nl.entreco.domain.streaming.send
+
+import nl.entreco.domain.BaseUsecase
+import nl.entreco.domain.repository.SignallingRepository
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
+import javax.inject.Inject
+
+class RegisterStreamerUsecase @Inject constructor(
+ private val signallingRepository: SignallingRepository,
+ bg: Background, fg: Foreground) : BaseUsecase(bg, fg) {
+
+ fun go(request: RegisterStreamerRequest, done: (RegisterStreamerResponse) -> Unit,
+ fail: (Throwable) -> Unit) {
+
+ onBackground({
+
+ signallingRepository.connect()
+ signallingRepository.cleanDisconnectOrders(onDisconnectSuccess(request, done, fail), onError("error disconnecting orders", fail))
+ }, onError("Unknown error", fail))
+
+ }
+
+ private fun onDisconnectSuccess(request: RegisterStreamerRequest,
+ done: (RegisterStreamerResponse) -> Unit,
+ fail: (Throwable) -> Unit): () -> Unit = {
+ // done
+ // Start UseCase that listens for Disconnects
+ // signallingRepository.listenForDisconnectOrders(request.onDisconnect)
+ signallingRepository.setStreamerOnline(request.deviceId,
+ onFoundDevice(done, fail),
+ onError("error find online device", fail))
+ }
+
+ private fun onFoundDevice(done: (RegisterStreamerResponse) -> Unit,
+ fail: (Throwable) -> Unit): (String?) -> Unit {
+ return { uuid ->
+ if (uuid != null) {
+ // Bingo -> connect to the mofo
+ onUi { done(RegisterStreamerResponse(uuid)) }
+ } else {
+ // Device Not Found
+ onUi { fail(IllegalArgumentException("No device found")) }
+ }
+ }
+ }
+
+ private fun onError(msg: String, fail: (Throwable) -> Unit): (Throwable) -> Unit = { err ->
+ onUi { fail(IllegalArgumentException(msg)) }
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubmitViewedItemUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubmitViewedItemUsecase.kt
index a2c74e1d..5215b3a6 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubmitViewedItemUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubmitViewedItemUsecase.kt
@@ -2,8 +2,8 @@ package nl.entreco.domain.wtf
import nl.entreco.domain.Analytics
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.WtfRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubscribeToWtfsUsecase.kt b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubscribeToWtfsUsecase.kt
index 046804a6..a8e3f44b 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubscribeToWtfsUsecase.kt
+++ b/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/wtf/SubscribeToWtfsUsecase.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.wtf
import nl.entreco.domain.BaseUsecase
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.repository.WtfRepository
import javax.inject.Inject
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/BgExecutorTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/BgExecutorTest.kt
index 26e12864..a84efa94 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/BgExecutorTest.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/BgExecutorTest.kt
@@ -1,6 +1,7 @@
package nl.entreco.domain.common.executors
import com.nhaarman.mockito_kotlin.verify
+import nl.entreco.shared.threading.BgExecutor
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/FgExecutorTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/FgExecutorTest.kt
index 90408d7a..9aa1717b 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/FgExecutorTest.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/FgExecutorTest.kt
@@ -2,6 +2,7 @@ package nl.entreco.domain.common.executors
import android.os.Handler
import com.nhaarman.mockito_kotlin.verify
+import nl.entreco.shared.threading.FgExecutor
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestBackground.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestBackground.kt
index 7e4f6832..c3e2039b 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestBackground.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestBackground.kt
@@ -1,5 +1,6 @@
package nl.entreco.domain.common.executors
+import nl.entreco.shared.threading.Background
import java.util.concurrent.Future
import java.util.concurrent.FutureTask
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestForeground.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestForeground.kt
index 366ffe7f..2657b473 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestForeground.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/common/executors/TestForeground.kt
@@ -1,5 +1,7 @@
package nl.entreco.domain.common.executors
+import nl.entreco.shared.threading.Foreground
+
/**
* Created by Entreco on 12/12/2017.
*/
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/finish/GetFinishUsecaseTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/finish/GetFinishUsecaseTest.kt
index e06c5d32..c68d4b9d 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/finish/GetFinishUsecaseTest.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/finish/GetFinishUsecaseTest.kt
@@ -1,7 +1,7 @@
package nl.entreco.domain.play.finish
import com.nhaarman.mockito_kotlin.verify
-import nl.entreco.domain.common.executors.Background
+import nl.entreco.shared.threading.Background
import nl.entreco.domain.common.executors.TestBackground
import nl.entreco.domain.model.Dart
import nl.entreco.domain.model.Score
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/mastercaller/MasterCallerTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/mastercaller/MasterCallerTest.kt
index 982a59c6..f5d1366c 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/mastercaller/MasterCallerTest.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/mastercaller/MasterCallerTest.kt
@@ -3,7 +3,7 @@ package nl.entreco.domain.play.mastercaller
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.verify
import com.nhaarman.mockito_kotlin.whenever
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.common.executors.TestBackground
import nl.entreco.domain.common.executors.TestForeground
import nl.entreco.domain.repository.SoundRepository
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/Play01UsecaseTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/Play01UsecaseTest.kt
index 60bd125e..cd0923b9 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/Play01UsecaseTest.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/start/Play01UsecaseTest.kt
@@ -1,7 +1,7 @@
package nl.entreco.domain.play.start
import com.nhaarman.mockito_kotlin.*
-import nl.entreco.domain.common.log.Logger
+import nl.entreco.shared.log.Logger
import nl.entreco.domain.model.*
import nl.entreco.domain.model.players.Player
import nl.entreco.domain.model.players.Team
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/stats/StoreTurnUsecaseTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/stats/StoreTurnUsecaseTest.kt
index f08d0793..0894eeb5 100644
--- a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/stats/StoreTurnUsecaseTest.kt
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/play/stats/StoreTurnUsecaseTest.kt
@@ -1,8 +1,8 @@
package nl.entreco.domain.play.stats
import com.nhaarman.mockito_kotlin.*
-import nl.entreco.domain.common.executors.Background
-import nl.entreco.domain.common.executors.Foreground
+import nl.entreco.shared.threading.Background
+import nl.entreco.shared.threading.Foreground
import nl.entreco.domain.common.executors.TestBackground
import nl.entreco.domain.common.executors.TestForeground
import nl.entreco.domain.model.Dart
diff --git a/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/rating/AskForRatingUsecaseTest.kt b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/rating/AskForRatingUsecaseTest.kt
new file mode 100644
index 00000000..855b335b
--- /dev/null
+++ b/android/DartsScorecard/domain/src/test/java/nl/entreco/domain/rating/AskForRatingUsecaseTest.kt
@@ -0,0 +1,76 @@
+package nl.entreco.domain.rating
+
+import com.nhaarman.mockito_kotlin.verify
+import com.nhaarman.mockito_kotlin.whenever
+import nl.entreco.domain.common.executors.TestBackground
+import nl.entreco.domain.common.executors.TestForeground
+import nl.entreco.domain.repository.GameRepository
+import nl.entreco.domain.repository.RatingPrefRepository
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnitRunner
+
+@RunWith(MockitoJUnitRunner::class)
+class AskForRatingUsecaseTest {
+
+ private val bg = TestBackground()
+ private val fg = TestForeground()
+ @Mock private lateinit var mockFail: (Throwable) -> Unit
+ @Mock private lateinit var mockDone: (AskForRatingResponse) -> Unit
+ @Mock private lateinit var mockGameRepo: GameRepository
+ @Mock private lateinit var mockRatePrefsRepo: RatingPrefRepository
+ private lateinit var subject: AskForRatingUsecase
+ private var givenRatedBefore: Boolean = false
+ private var givenGamesFinished: Int = 0
+
+
+ @Before
+ fun setUp() {
+ subject = AskForRatingUsecase(mockRatePrefsRepo, mockGameRepo, bg, fg)
+ }
+
+ @Test
+ fun `it should ask for rating when not asked before and more than 3 games finished`() {
+ givenRatedBefore(false)
+ givenGamesFinished(5)
+ thenShouldAskForRating(true)
+ }
+
+ @Test
+ fun `it should NOT ask for rating when asked before and more than 3 games finished`() {
+ givenRatedBefore(true)
+ givenGamesFinished(5)
+ thenShouldAskForRating(false)
+ }
+
+ @Test
+ fun `it should NOT ask for rating when not asked before but no games finished`() {
+ givenRatedBefore(false)
+ givenGamesFinished(0)
+ thenShouldAskForRating(false)
+ }
+
+ @Test
+ fun `it should NOT ask for rating when not asked before and more than 3 games finished`() {
+ givenRatedBefore(true)
+ givenGamesFinished(0)
+ thenShouldAskForRating(false)
+ }
+
+ private fun givenRatedBefore(rated: Boolean) {
+ givenRatedBefore = rated
+ }
+
+ private fun givenGamesFinished(finished: Int) {
+ givenGamesFinished = finished
+ }
+
+ private fun thenShouldAskForRating(expected: Boolean) {
+ whenever(mockRatePrefsRepo.shouldAskToRateApp()).thenReturn(!givenRatedBefore)
+ whenever(mockGameRepo.countFinishedGames()).thenReturn(givenGamesFinished)
+ subject.go(mockDone, mockFail)
+ verify(mockDone).invoke(AskForRatingResponse(expected))
+ }
+}
\ No newline at end of file
diff --git a/android/DartsScorecard/gradle.properties b/android/DartsScorecard/gradle.properties
index bc57493f..83d3ebc1 100644
--- a/android/DartsScorecard/gradle.properties
+++ b/android/DartsScorecard/gradle.properties
@@ -9,7 +9,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx4096m
+org.gradle.jvmargs=-Xmx3000m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
diff --git a/android/DartsScorecard/gradle/wrapper/gradle-wrapper.properties b/android/DartsScorecard/gradle/wrapper/gradle-wrapper.properties
index c3bdbcdf..99467343 100644
--- a/android/DartsScorecard/gradle/wrapper/gradle-wrapper.properties
+++ b/android/DartsScorecard/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Mar 28 20:41:11 CEST 2018
+#Fri Aug 17 21:46:33 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/android/DartsScorecard/scripts/android_common.gradle b/android/DartsScorecard/scripts/android_common.gradle
index fbb54841..839a6e20 100644
--- a/android/DartsScorecard/scripts/android_common.gradle
+++ b/android/DartsScorecard/scripts/android_common.gradle
@@ -31,6 +31,13 @@ android {
testOptions {
unitTests.returnDefaultValues = true
+ unitTests.all {
+ jvmArgs '-noverify'
+ }
+ }
+
+ dataBinding {
+ enabled = true
}
configurations.all {
@@ -39,4 +46,8 @@ android {
resolutionStrategy.force "com.android.support:support-media-compat:$support"
resolutionStrategy.force "com.android.support:customtabs:$support"
}
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
}
\ No newline at end of file
diff --git a/android/DartsScorecard/scripts/dependencies.gradle b/android/DartsScorecard/scripts/dependencies.gradle
index 8921cb8d..03946967 100644
--- a/android/DartsScorecard/scripts/dependencies.gradle
+++ b/android/DartsScorecard/scripts/dependencies.gradle
@@ -34,35 +34,43 @@ ext.versionName = { ->
ext {
- kotlinVersion = '1.2.51'
- gradleVersion = '3.1.3'
- gmsVersion = '3.2.0'
+ kotlinVersion = '1.2.61'
+ gradleVersion = '3.2.0-beta05'
+ gmsVersion = '4.0.1'
dexCountVersion = '0.8.2'
detektVersion = '1.0.0.RC7'
jacocoCoverageVersion = '0.4.0'
coverallsVersion = '2.8.2'
- fabricVersion = '1.25.1'
+ fabricVersion = '1.25.4'
- androidCompileSdkVersion = 27
- androidMinSdkVersion = 23
- androidTargetSdkVersion = 27
+ androidCompileSdkVersion = 28
+ androidMinSdkVersion = 24
+ androidTargetSdkVersion = 28
versionCode = versionCode()
versionName = versionName()
dependencies = [
- support = '27.1.1',
+ support = '28.0.0-rc01',
daggerVersion = '2.13',
constraint = '1.1.2',
architecture = '1.1.1',
- room = '1.1.0',
- firebase = '15.0.0',
- glide = '4.7.1',
+ room = '1.1.1',
+ fbAds = '15.0.1',
+ fbCore = '16.0.3',
+ fbStore = '17.1.0',
+ fbConfig = '16.0.0',
+ fbDatabase = '16.0.1',
+ glide = '4.8.0',
circleImageView = '2.2.0',
jelly = 'v1.0',
crash = '2.9.1@aar',
gson = '2.8.2',
- leakCanary = '1.5.4',
+// webRtc = '1.0.20284',
+ webRtc = '1.0.22672',
+// webRtc = '1.0.24180',
+// webRtc = '1.0.24277',
+ leakCanary = '1.6.1',
junit = '4.12',
mockito = '2.12.0',
mockitoKotlin = '1.5.0',
diff --git a/android/DartsScorecard/scripts/tasks.gradle b/android/DartsScorecard/scripts/tasks.gradle
index 3fe441af..5d0e703b 100644
--- a/android/DartsScorecard/scripts/tasks.gradle
+++ b/android/DartsScorecard/scripts/tasks.gradle
@@ -1,9 +1,9 @@
task checkDebug(type: GradleBuild) {
group "Dsc"
- tasks = ['app:testDebugUnitTest', 'data:testDebugUnitTest', 'domain:testDebugUnitTest', 'app:jacocoDebugReport', 'domain:jacocoDebugReport', 'data:jacocoDebugReport', 'lintDebug', 'detektCheck']
+ tasks = ['app:testDebugUnitTest', 'data:testDebugUnitTest', 'domain:testDebugUnitTest', 'lintDebug', 'detektCheck']
}
task checkRelease(type: GradleBuild) {
group "Dsc"
- tasks = ['app:testReleaseUnitTest', 'data:testReleaseUnitTest', 'domain:testReleaseUnitTest', 'app:jacocoDebugReport', 'domain:jacocoDebugReport', 'data:jacocoDebugReport', 'lintRelease', 'detektCheck']
+ tasks = []
}
\ No newline at end of file
diff --git a/android/DartsScorecard/settings.gradle b/android/DartsScorecard/settings.gradle
index 5f094eb8..dfb1ec23 100644
--- a/android/DartsScorecard/settings.gradle
+++ b/android/DartsScorecard/settings.gradle
@@ -1 +1 @@
-include ':app', ':domain', ':data'
+include ':app', ':domain', ':data', ':shared'
diff --git a/android/DartsScorecard/shared/.gitignore b/android/DartsScorecard/shared/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/android/DartsScorecard/shared/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/android/DartsScorecard/shared/build.gradle b/android/DartsScorecard/shared/build.gradle
new file mode 100644
index 00000000..7fd9bd70
--- /dev/null
+++ b/android/DartsScorecard/shared/build.gradle
@@ -0,0 +1,24 @@
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
+apply plugin: 'kotlin-android-extensions'
+apply from: '../scripts/coverage_library.gradle'
+apply from: '../scripts/android_common.gradle'
+
+android {
+ defaultPublishConfig "debug"
+}
+
+dependencies {
+ // Annotation Processing
+ kapt "com.github.bumptech.glide:compiler:$glide"
+
+ // Implementation
+ implementation "com.android.support:appcompat-v7:$support"
+ implementation "com.google.code.gson:gson:$gson"
+ implementation "com.github.bumptech.glide:glide:$glide"
+
+ testImplementation "junit:junit:$junit"
+ testImplementation "org.mockito:mockito-core:$mockito"
+ testImplementation "com.nhaarman:mockito-kotlin-kt1.1:$mockitoKotlin"
+}
diff --git a/android/DartsScorecard/shared/proguard-rules.pro b/android/DartsScorecard/shared/proguard-rules.pro
new file mode 100644
index 00000000..5e5a8566
--- /dev/null
+++ b/android/DartsScorecard/shared/proguard-rules.pro
@@ -0,0 +1,42 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+
+
+# Databinding
+-keepclasseswithmembernames interface android.databinding.DataBindingComponent
+-dontwarn android.databinding.DataBindingComponent
+-dontnote android.databinding.DataBindingComponent
+-keep class android.databinding.DataBinderMapper
+-dontwarn android.databinding.DataBinderMapper
+-dontnote android.databinding.DataBinderMapper
+
+#GMS
+-keep class com.google.android.gms.common.api.internal.BasePendingResult$ReleasableResultGuardian
+-keep class com.google.android.gms.** { *; }
+-dontwarn com.google.android.gms.**
+
+-keepnames @pcom.google.android.gms.common.annotation.KeepName class *
+
+-keepclassmembernames class * {
+ @com.google.android.gms.common.annotation.KeepName *;
+}
+
diff --git a/android/DartsScorecard/shared/src/main/AndroidManifest.xml b/android/DartsScorecard/shared/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..16130945
--- /dev/null
+++ b/android/DartsScorecard/shared/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
diff --git a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/glide/GlideModule.kt b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/libs/GlideModule.kt
similarity index 77%
rename from android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/glide/GlideModule.kt
rename to android/DartsScorecard/shared/src/main/java/nl/entreco/shared/libs/GlideModule.kt
index 4a81f929..47c7620c 100644
--- a/android/DartsScorecard/app/src/main/java/nl/entreco/dartsscorecard/di/glide/GlideModule.kt
+++ b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/libs/GlideModule.kt
@@ -1,4 +1,4 @@
-package nl.entreco.dartsscorecard.di.glide
+package nl.entreco.shared.libs
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/log/Logger.kt b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/log/Logger.kt
similarity index 93%
rename from android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/log/Logger.kt
rename to android/DartsScorecard/shared/src/main/java/nl/entreco/shared/log/Logger.kt
index 915f5288..b7d0dac3 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/log/Logger.kt
+++ b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/log/Logger.kt
@@ -1,4 +1,4 @@
-package nl.entreco.domain.common.log
+package nl.entreco.shared.log
/**
* Created by Entreco on 27/11/2017.
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/Background.kt b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/Background.kt
similarity index 77%
rename from android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/Background.kt
rename to android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/Background.kt
index 0aa33473..212f8caf 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/Background.kt
+++ b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/Background.kt
@@ -1,4 +1,4 @@
-package nl.entreco.domain.common.executors
+package nl.entreco.shared.threading
import java.util.concurrent.Future
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/BgExecutor.kt b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/BgExecutor.kt
similarity index 79%
rename from android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/BgExecutor.kt
rename to android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/BgExecutor.kt
index 4a66a13a..e08f88dd 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/BgExecutor.kt
+++ b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/BgExecutor.kt
@@ -1,4 +1,4 @@
-package nl.entreco.domain.common.executors
+package nl.entreco.shared.threading
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@@ -7,7 +7,8 @@ import java.util.concurrent.Future
/**
* Created by Entreco on 12/12/2017.
*/
-class BgExecutor(private val bg: ExecutorService = Executors.newSingleThreadExecutor()) : Background {
+class BgExecutor(private val bg: ExecutorService = Executors.newSingleThreadExecutor()) :
+ Background {
override fun post(runnable: Runnable): Future<*>? {
return bg.submit(runnable)
}
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/FgExecutor.kt b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/FgExecutor.kt
similarity index 77%
rename from android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/FgExecutor.kt
rename to android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/FgExecutor.kt
index 7ea9c990..1c2d8ce3 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/FgExecutor.kt
+++ b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/FgExecutor.kt
@@ -1,4 +1,4 @@
-package nl.entreco.domain.common.executors
+package nl.entreco.shared.threading
import android.os.Handler
import android.os.Looper
@@ -6,7 +6,8 @@ import android.os.Looper
/**
* Created by Entreco on 12/12/2017.
*/
-class FgExecutor(private val fg: Handler = Handler(Looper.getMainLooper())) : Foreground {
+class FgExecutor(private val fg: Handler = Handler(Looper.getMainLooper())) :
+ Foreground {
override fun post(runnable: Runnable) {
fg.post(runnable)
diff --git a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/Foreground.kt b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/Foreground.kt
similarity index 70%
rename from android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/Foreground.kt
rename to android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/Foreground.kt
index bb2be116..3af853ee 100644
--- a/android/DartsScorecard/domain/src/main/java/nl/entreco/domain/common/executors/Foreground.kt
+++ b/android/DartsScorecard/shared/src/main/java/nl/entreco/shared/threading/Foreground.kt
@@ -1,4 +1,4 @@
-package nl.entreco.domain.common.executors
+package nl.entreco.shared.threading
/**
* Created by Entreco on 12/12/2017.
diff --git a/android/DartsScorecard/app/src/main/res/drawable/ic_entreco_black_bg.xml b/android/DartsScorecard/shared/src/main/res/drawable/ic_entreco_black_bg.xml
similarity index 100%
rename from android/DartsScorecard/app/src/main/res/drawable/ic_entreco_black_bg.xml
rename to android/DartsScorecard/shared/src/main/res/drawable/ic_entreco_black_bg.xml
diff --git a/android/DartsScorecard/app/src/main/res/layout/include_launch_header.xml b/android/DartsScorecard/shared/src/main/res/layout/include_launch_header.xml
similarity index 91%
rename from android/DartsScorecard/app/src/main/res/layout/include_launch_header.xml
rename to android/DartsScorecard/shared/src/main/res/layout/include_launch_header.xml
index 83408e52..3c737668 100644
--- a/android/DartsScorecard/app/src/main/res/layout/include_launch_header.xml
+++ b/android/DartsScorecard/shared/src/main/res/layout/include_launch_header.xml
@@ -2,10 +2,9 @@
+ android:gravity="center_horizontal">
+
\ No newline at end of file
diff --git a/design/live_stop.svg b/design/live_stop.svg
new file mode 100644
index 00000000..501d507b
--- /dev/null
+++ b/design/live_stop.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/design/playstore.sketch b/design/playstore.sketch
index 32253c7c..945e48c3 100644
Binary files a/design/playstore.sketch and b/design/playstore.sketch differ
diff --git a/design/tv_promo.png b/design/tv_promo.png
new file mode 100644
index 00000000..4675a788
Binary files /dev/null and b/design/tv_promo.png differ
diff --git a/design/tv_promo.sketch b/design/tv_promo.sketch
new file mode 100644
index 00000000..29d550b8
Binary files /dev/null and b/design/tv_promo.sketch differ