From 8c9c4569b4dbd3196ecdd9bada4363b3c8a21763 Mon Sep 17 00:00:00 2001 From: domonkosadam Date: Fri, 4 Oct 2024 15:24:56 +0200 Subject: [PATCH 01/38] Increase version --- apps/student/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/student/build.gradle b/apps/student/build.gradle index 8968eb85dc..b4859efac8 100644 --- a/apps/student/build.gradle +++ b/apps/student/build.gradle @@ -40,8 +40,8 @@ android { applicationId "com.instructure.candroid" minSdkVersion Versions.MIN_SDK targetSdkVersion Versions.TARGET_SDK - versionCode = 266 - versionName = '7.5.3' + versionCode = 267 + versionName = '7.6.0' vectorDrawables.useSupportLibrary = true multiDexEnabled = true From 540a9b9f19d2f3106c1721541dc9036ab3b011d2 Mon Sep 17 00:00:00 2001 From: domonkosadam Date: Fri, 4 Oct 2024 15:56:36 +0200 Subject: [PATCH 02/38] Increase version --- apps/flutter_parent/pubspec.yaml | 2 +- apps/parent/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/flutter_parent/pubspec.yaml b/apps/flutter_parent/pubspec.yaml index 9f1ace5fff..2c30a63c85 100644 --- a/apps/flutter_parent/pubspec.yaml +++ b/apps/flutter_parent/pubspec.yaml @@ -25,7 +25,7 @@ description: Canvas Parent # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 3.11.0+51 +version: 3.12.0+52 module: androidX: true diff --git a/apps/parent/build.gradle b/apps/parent/build.gradle index ce64c3d77b..d3a39b1be3 100644 --- a/apps/parent/build.gradle +++ b/apps/parent/build.gradle @@ -39,8 +39,8 @@ android { applicationId "com.instructure.parentapp" minSdkVersion Versions.MIN_SDK targetSdkVersion Versions.TARGET_SDK - versionCode 50 - versionName "3.10.0" + versionCode 52 + versionName "3.12.0" buildConfigField "boolean", "IS_TESTING", "false" testInstrumentationRunner 'com.instructure.parentapp.ui.espresso.ParentHiltTestRunner' From 577497bc7a7d49096673ad34631a19870eb94d89 Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:11:41 +0200 Subject: [PATCH 03/38] [MBL-17947][Parent] Fixed student colors and theme colors (#2579) refs: MBL-17947 affects: Parent release note: none * Fixed student colors in Parent. * Fix theme color changes. * Fixed color issues when changing student color. * Some color fixes. * Fixed tests. * Fixed tests. * Resolved conflicts. * Fixed some student colors and PR comments. --- .../addstudent/AddStudentViewModel.kt | 7 ++-- .../features/alerts/list/AlertsViewModel.kt | 18 +++++++- .../alerts/settings/AlertSettingsScreen.kt | 7 +++- .../alerts/settings/AlertSettingsViewModel.kt | 4 +- .../calendar/ParentCalendarFragment.kt | 5 ++- .../courses/details/CourseDetailsFragment.kt | 4 +- .../courses/details/CourseDetailsViewModel.kt | 4 +- .../features/courses/list/CoursesViewModel.kt | 19 ++++++++- .../dashboard/AddStudentItemViewModel.kt | 12 +++++- .../features/dashboard/DashboardFragment.kt | 6 ++- .../features/dashboard/DashboardViewModel.kt | 16 +++++-- .../dashboard/SelectedStudentHolder.kt | 9 ++++ .../features/grades/ParentGradesBehaviour.kt | 4 +- .../parentapp/features/main/MainActivity.kt | 10 +++++ .../managestudents/ManageStudentViewModel.kt | 11 ++--- .../StudentColorPickerDialog.kt | 3 +- .../parentapp/features/splash/SplashAction.kt | 3 ++ .../features/splash/SplashFragment.kt | 3 ++ .../features/splash/SplashViewModel.kt | 5 +-- .../addstudent/AddStudentViewModelTest.kt | 4 ++ .../alerts/list/AlertsViewModelTest.kt | 36 +++++++++++++--- .../courses/list/CoursesViewModelTest.kt | 42 ++++++++++++++----- .../dashboard/DashboardViewModelTest.kt | 18 +++++--- .../dashboard/TestSelectStudentHolder.kt | 7 +++- .../ManageStudentsViewModelTest.kt | 26 ++++++------ .../features/splash/SplashViewModelTest.kt | 6 +-- libs/pandares/src/main/res/values/colors.xml | 13 +++--- .../features/inbox/utils/InboxMessageView.kt | 2 +- .../utils/CanvasContextExtensions.kt | 2 +- .../pandautils/utils/ColorKeeper.kt | 32 ++++++++------ .../pandautils/utils/ThemePrefs.kt | 12 +++++- 31 files changed, 253 insertions(+), 97 deletions(-) diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/addstudent/AddStudentViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/addstudent/AddStudentViewModel.kt index 2e01d1fbb4..59acb7b5e2 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/addstudent/AddStudentViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/addstudent/AddStudentViewModel.kt @@ -19,7 +19,8 @@ package com.instructure.parentapp.features.addstudent import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.ColorKeeper +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.features.dashboard.SelectedStudentHolder import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -40,7 +41,7 @@ class AddStudentViewModel @Inject constructor( private val _uiState = MutableStateFlow( AddStudentUiState( - color = selectedStudentHolder.selectedStudentState.value.color, + color = selectedStudentHolder.selectedStudentState.value.studentColor, actionHandler = this::handleAction ) ) @@ -53,7 +54,7 @@ class AddStudentViewModel @Inject constructor( viewModelScope.launch { selectedStudentHolder.selectedStudentChangedFlow.collectLatest { user -> _uiState.value = _uiState.value.copy( - color = user.color + color = user.studentColor ) } } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/list/AlertsViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/list/AlertsViewModel.kt index 1dcdf95ed6..35232d8064 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/list/AlertsViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/list/AlertsViewModel.kt @@ -22,7 +22,7 @@ import com.instructure.canvasapi2.models.Alert import com.instructure.canvasapi2.models.AlertThreshold import com.instructure.canvasapi2.models.AlertWorkflowState import com.instructure.canvasapi2.models.User -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.R import com.instructure.parentapp.features.dashboard.AlertCountUpdater import com.instructure.parentapp.features.dashboard.SelectedStudentHolder @@ -58,6 +58,20 @@ class AlertsViewModel @Inject constructor( studentChanged(it) } } + + viewModelScope.launch { + selectedStudentHolder.selectedStudentColorChanged.collect { + updateColor() + } + } + } + + private fun updateColor() { + selectedStudent?.let { student -> + _uiState.update { + it.copy(studentColor = student.studentColor) + } + } } private suspend fun studentChanged(student: User?) { @@ -65,7 +79,7 @@ class AlertsViewModel @Inject constructor( selectedStudent = student _uiState.update { it.copy( - studentColor = student.color, + studentColor = student.studentColor, isLoading = true ) } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsScreen.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsScreen.kt index c7ccb3f520..c0e4bd116d 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsScreen.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsScreen.kt @@ -99,7 +99,7 @@ fun AlertSettingsScreen( navIconRes = R.drawable.ic_back_arrow, navigationActionClick = navigationActionClick, backgroundColor = Color(uiState.userColor), - textColor = colorResource(id = R.color.white), + textColor = colorResource(id = R.color.textLightest), actions = { var showMenu by remember { mutableStateOf(false) } var showConfirmationDialog by remember { mutableStateOf(false) } @@ -113,7 +113,10 @@ fun AlertSettingsScreen( } } OverflowMenu( + modifier = Modifier + .background(color = colorResource(id = R.color.backgroundLightestElevated)), showMenu = showMenu, + iconColor = colorResource(id = R.color.textLightest), onDismissRequest = { showMenu = !showMenu }) { DropdownMenuItem( modifier = Modifier.testTag("deleteMenuItem"), @@ -123,7 +126,7 @@ fun AlertSettingsScreen( showConfirmationDialog = true } }) { - Text(text = stringResource(id = R.string.delete)) + Text(text = stringResource(id = R.string.delete), color = colorResource(id = R.color.textDarkest)) } } } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsViewModel.kt index 9f8d14306b..253e725a71 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/alerts/settings/AlertSettingsViewModel.kt @@ -23,7 +23,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics import com.instructure.canvasapi2.models.AlertType import com.instructure.canvasapi2.models.User import com.instructure.pandautils.utils.Const -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.R import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.channels.Channel @@ -50,7 +50,7 @@ class AlertSettingsViewModel @Inject constructor( avatarUrl = student.avatarUrl.orEmpty(), studentName = student.shortName ?: student.name, studentPronouns = student.pronouns, - userColor = student.color, + userColor = student.studentColor, actionHandler = this::handleAction ) ) diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/calendar/ParentCalendarFragment.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/calendar/ParentCalendarFragment.kt index d3c2000ef0..79116692bc 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/calendar/ParentCalendarFragment.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/calendar/ParentCalendarFragment.kt @@ -21,7 +21,7 @@ import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import com.instructure.pandautils.features.calendar.BaseCalendarFragment import com.instructure.pandautils.utils.ViewStyler -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.features.dashboard.SelectedStudentHolder import com.instructure.parentapp.util.ParentPrefs import dagger.hilt.android.AndroidEntryPoint @@ -47,7 +47,8 @@ class ParentCalendarFragment : BaseCalendarFragment() { } override fun applyTheme() { - val color = ParentPrefs.currentStudent.color + val student = ParentPrefs.currentStudent + val color = student.studentColor ViewStyler.setStatusBarDark(requireActivity(), color) } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsFragment.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsFragment.kt index 8d0805de3e..8db4d30f08 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsFragment.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsFragment.kt @@ -30,7 +30,7 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.instructure.pandautils.utils.ViewStyler import com.instructure.pandautils.utils.collectOneOffEvents -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.util.ParentPrefs import dagger.hilt.android.AndroidEntryPoint @@ -58,7 +58,7 @@ class CourseDetailsFragment : Fragment() { } private fun applyTheme() { - val color = ParentPrefs.currentStudent.color + val color = ParentPrefs.currentStudent.studentColor ViewStyler.setStatusBarDark(requireActivity(), color) } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsViewModel.kt index 3ca0c29f43..92b4005d10 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/courses/details/CourseDetailsViewModel.kt @@ -24,8 +24,8 @@ import com.instructure.canvasapi2.models.Course import com.instructure.canvasapi2.models.Tab import com.instructure.canvasapi2.utils.weave.catch import com.instructure.canvasapi2.utils.weave.tryLaunch -import com.instructure.pandautils.utils.color import com.instructure.pandautils.utils.orDefault +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.util.ParentPrefs import com.instructure.parentapp.util.navigation.Navigation import dagger.hilt.android.lifecycle.HiltViewModel @@ -62,7 +62,7 @@ class CourseDetailsViewModel @Inject constructor( _uiState.update { it.copy( isLoading = true, - studentColor = parentPrefs.currentStudent.color + studentColor = parentPrefs.currentStudent.studentColor ) } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/courses/list/CoursesViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/courses/list/CoursesViewModel.kt index 64bfd88241..23a5c1cdb2 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/courses/list/CoursesViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/courses/list/CoursesViewModel.kt @@ -22,7 +22,8 @@ import androidx.lifecycle.viewModelScope import com.instructure.canvasapi2.models.User import com.instructure.canvasapi2.utils.weave.catch import com.instructure.canvasapi2.utils.weave.tryLaunch -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.ColorKeeper +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.features.dashboard.SelectedStudentHolder import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.channels.Channel @@ -55,11 +56,25 @@ class CoursesViewModel @Inject constructor( studentChanged(it) } } + + viewModelScope.launch { + selectedStudentHolder.selectedStudentColorChanged.collect { + updateColor() + } + } + } + + private fun updateColor() { + selectedStudent?.let { student -> + _uiState.update { + it.copy(studentColor = student.studentColor) + } + } } private fun loadCourses(forceRefresh: Boolean = false) { viewModelScope.tryLaunch { - val color = selectedStudent.color + val color = selectedStudent.studentColor _uiState.update { it.copy( diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/AddStudentItemViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/AddStudentItemViewModel.kt index a4909add2f..6663ee6422 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/AddStudentItemViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/AddStudentItemViewModel.kt @@ -16,13 +16,21 @@ */ package com.instructure.parentapp.features.dashboard import androidx.annotation.ColorInt +import androidx.databinding.BaseObservable +import androidx.databinding.Bindable import com.instructure.pandautils.mvvm.ItemViewModel import com.instructure.parentapp.R +import com.instructure.parentapp.BR data class AddStudentItemViewModel( - @ColorInt val color: Int, + @Bindable @ColorInt var color: Int, val onAddStudentClicked: () -> Unit -) : ItemViewModel { +) : BaseObservable(), ItemViewModel { override val viewType: Int = StudentListViewType.ADD_STUDENT.viewType override val layoutId = R.layout.item_add_student + + fun updateColor(@ColorInt color: Int) { + this.color = color + notifyPropertyChanged(BR.color) + } } \ No newline at end of file diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardFragment.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardFragment.kt index 45757d6dbe..b63a6bbbe9 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardFragment.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardFragment.kt @@ -53,6 +53,7 @@ import com.instructure.pandautils.utils.onClick import com.instructure.pandautils.utils.setGone import com.instructure.pandautils.utils.setVisible import com.instructure.pandautils.utils.showThemed +import com.instructure.pandautils.utils.studentColor import com.instructure.pandautils.utils.toPx import com.instructure.parentapp.R import com.instructure.parentapp.databinding.FragmentDashboardBinding @@ -281,7 +282,7 @@ class DashboardFragment : Fragment(), NavigationCallbacks { } private fun setupAppColors(student: User?) { - val color = student.color + val color = student.studentColor if (binding.toolbar.background == null) { binding.toolbar.setBackgroundColor(color) } else { @@ -297,6 +298,7 @@ class DashboardFragment : Fragment(), NavigationCallbacks { binding.unreadCountBadge.setTextColor(color) binding.bottomNav.getOrCreateBadge(R.id.alerts).backgroundColor = color + viewModel.updateColor(color) } private fun openNavigationDrawer() { @@ -318,7 +320,7 @@ class DashboardFragment : Fragment(), NavigationCallbacks { ParentLogoutTask(LogoutTask.Type.LOGOUT).execute() } .setNegativeButton(android.R.string.cancel, null) - .showThemed(ParentPrefs.currentStudent.color) + .showThemed(ParentPrefs.currentStudent.studentColor) } private fun onSwitchUsers() { diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardViewModel.kt index 26546a7e07..68d999ec21 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/DashboardViewModel.kt @@ -20,6 +20,7 @@ package com.instructure.parentapp.features.dashboard import android.annotation.SuppressLint import android.content.Context import android.content.Intent +import androidx.annotation.ColorInt import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -32,6 +33,7 @@ import com.instructure.loginapi.login.util.PreviousUsersUtils import com.instructure.pandautils.mvvm.ViewState import com.instructure.pandautils.utils.color import com.instructure.pandautils.utils.orDefault +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.R import com.instructure.parentapp.features.alerts.list.AlertsRepository import com.instructure.parentapp.util.ParentPrefs @@ -181,7 +183,7 @@ class DashboardViewModel @Inject constructor( val studentItemsWithAddStudent = if (studentItems.isNotEmpty()) { studentItems + AddStudentItemViewModel( - selectedStudent.color, + selectedStudent.studentColor, ::addStudent ) } else { @@ -223,7 +225,7 @@ class DashboardViewModel @Inject constructor( selectedStudent = student, studentItems = it.studentItems.map { item -> if (item is AddStudentItemViewModel) { - item.copy(color = student.color) + item.copy(color = student.studentColor) } else { item } @@ -246,8 +248,8 @@ class DashboardViewModel @Inject constructor( } private suspend fun updateAlertCount() { - _data.value.selectedStudent?.id?.let { - val alertCount = alertsRepository.getUnreadAlertCount(it) + _data.value.selectedStudent?.id?.let { selectedStudentId -> + val alertCount = alertsRepository.getUnreadAlertCount(selectedStudentId) _data.update { it.copy( alertCount = alertCount @@ -261,4 +263,10 @@ class DashboardViewModel @Inject constructor( it.copy(studentSelectorExpanded = !it.studentSelectorExpanded) } } + + fun updateColor(@ColorInt color: Int) { + _data.value.studentItems.find { it is AddStudentItemViewModel }?.let { addStudentItem -> + (addStudentItem as AddStudentItemViewModel).updateColor(color) + } + } } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/SelectedStudentHolder.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/SelectedStudentHolder.kt index 0992d1a9e0..dbc291d4c9 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/SelectedStudentHolder.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/dashboard/SelectedStudentHolder.kt @@ -29,7 +29,9 @@ import kotlinx.coroutines.flow.asStateFlow interface SelectedStudentHolder { val selectedStudentState: StateFlow val selectedStudentChangedFlow: SharedFlow + val selectedStudentColorChanged: SharedFlow suspend fun updateSelectedStudent(user: User) + suspend fun selectedStudentColorChanged() } class SelectedStudentHolderImpl : SelectedStudentHolder { @@ -39,8 +41,15 @@ class SelectedStudentHolderImpl : SelectedStudentHolder { private val _selectedStudentChangedFlow = MutableSharedFlow() override val selectedStudentChangedFlow: SharedFlow = _selectedStudentChangedFlow.asSharedFlow() + private val _selectedStudentColorChanged = MutableSharedFlow() + override val selectedStudentColorChanged: SharedFlow = _selectedStudentColorChanged.asSharedFlow() + override suspend fun updateSelectedStudent(user: User) { _selectedStudentState.value = user _selectedStudentChangedFlow.emit(user) } + + override suspend fun selectedStudentColorChanged() { + _selectedStudentColorChanged.emit(Unit) + } } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/grades/ParentGradesBehaviour.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/grades/ParentGradesBehaviour.kt index 833551ce77..660a80f3cd 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/grades/ParentGradesBehaviour.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/grades/ParentGradesBehaviour.kt @@ -18,7 +18,7 @@ package com.instructure.parentapp.features.grades import com.instructure.pandautils.features.grades.GradesBehaviour -import com.instructure.pandautils.utils.color +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.util.ParentPrefs @@ -26,5 +26,5 @@ class ParentGradesBehaviour( parentPrefs: ParentPrefs ) : GradesBehaviour { - override val canvasContextColor = parentPrefs.currentStudent.color + override val canvasContextColor = parentPrefs.currentStudent.studentColor } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/main/MainActivity.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/main/MainActivity.kt index b794d87545..a4a308450b 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/main/MainActivity.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/main/MainActivity.kt @@ -19,6 +19,7 @@ package com.instructure.parentapp.features.main import android.content.Context import android.content.Intent +import android.content.res.Configuration import android.net.Uri import android.os.Bundle import android.util.Log @@ -29,7 +30,9 @@ import androidx.navigation.fragment.NavHostFragment import com.instructure.pandautils.binding.viewBinding import com.instructure.pandautils.features.inbox.list.OnUnreadCountInvalidated import com.instructure.pandautils.interfaces.NavigationCallbacks +import com.instructure.pandautils.utils.ColorKeeper import com.instructure.pandautils.utils.Const +import com.instructure.pandautils.utils.ThemePrefs import com.instructure.parentapp.R import com.instructure.parentapp.databinding.ActivityMainBinding import com.instructure.parentapp.features.dashboard.InboxCountUpdater @@ -56,9 +59,16 @@ class MainActivity : AppCompatActivity(), OnUnreadCountInvalidated { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) + setupTheme() setupNavigation() } + private fun setupTheme() { + ThemePrefs.reapplyCanvasTheme(this) + val nightModeFlags: Int = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + ColorKeeper.darkTheme = nightModeFlags == Configuration.UI_MODE_NIGHT_YES + } + override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) handleDeeplink(intent?.data) diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/ManageStudentViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/ManageStudentViewModel.kt index 19b87a1f2a..2070005ad5 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/ManageStudentViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/ManageStudentViewModel.kt @@ -18,16 +18,15 @@ package com.instructure.parentapp.features.managestudents import android.content.Context -import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.instructure.canvasapi2.models.User import com.instructure.canvasapi2.utils.weave.catch import com.instructure.canvasapi2.utils.weave.tryLaunch import com.instructure.pandautils.utils.ColorKeeper -import com.instructure.pandautils.utils.createThemedColor import com.instructure.pandautils.utils.orDefault import com.instructure.parentapp.R +import com.instructure.parentapp.features.dashboard.SelectedStudentHolder import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.channels.Channel @@ -43,7 +42,8 @@ import javax.inject.Inject class ManageStudentViewModel @Inject constructor( @ApplicationContext private val context: Context, private val colorKeeper: ColorKeeper, - private val repository: ManageStudentsRepository + private val repository: ManageStudentsRepository, + private val selectedStudentHolder: SelectedStudentHolder ) : ViewModel() { private val _uiState = MutableStateFlow(ManageStudentsUiState()) @@ -75,7 +75,7 @@ class ManageStudentViewModel @Inject constructor( colorKeeper.userColors.map { UserColor( colorRes = it, - color = createThemedColor(context.getColor(it)), + color = colorKeeper.createThemedColor(context.getColor(it)), contentDescriptionRes = userColorContentDescriptionMap[it].orDefault() ) } @@ -120,7 +120,7 @@ class ManageStudentViewModel @Inject constructor( private fun saveStudentColor(studentId: Long, selected: UserColor) { viewModelScope.tryLaunch { val contextId = "user_$studentId" - val color = ContextCompat.getColor(context, selected.colorRes) + val color = context.getColor(selected.colorRes) _uiState.update { it.copy( @@ -148,6 +148,7 @@ class ManageStudentViewModel @Inject constructor( } else { showSavingError() } + selectedStudentHolder.selectedStudentColorChanged() } catch { showSavingError() } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/StudentColorPickerDialog.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/StudentColorPickerDialog.kt index 3bea79a5bf..1303bef2d8 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/StudentColorPickerDialog.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/managestudents/StudentColorPickerDialog.kt @@ -57,7 +57,6 @@ import com.instructure.canvasapi2.utils.ContextKeeper import com.instructure.pandautils.R import com.instructure.pandautils.utils.ColorKeeper import com.instructure.pandautils.utils.ThemePrefs -import com.instructure.pandautils.utils.createThemedColor @Composable @@ -183,7 +182,7 @@ fun StudentColorPickerDialogPreview() { val colors = ColorKeeper.userColors.map { UserColor( colorRes = it, - color = createThemedColor(context.getColor(it)), + color = ColorKeeper.createThemedColor(context.getColor(it)), contentDescriptionRes = 0 ) } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashAction.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashAction.kt index fe76d7d5e5..4302195cec 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashAction.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashAction.kt @@ -17,9 +17,12 @@ package com.instructure.parentapp.features.splash +import com.instructure.canvasapi2.models.CanvasTheme + sealed class SplashAction { data object LocaleChanged : SplashAction() data object InitialDataLoadingFinished : SplashAction() data object NavigateToNotAParentScreen : SplashAction() + data class ApplyTheme(val canvasTheme: CanvasTheme) : SplashAction() } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashFragment.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashFragment.kt index 3d3946067b..72fd396258 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashFragment.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashFragment.kt @@ -37,6 +37,7 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.instructure.canvasapi2.utils.LocaleUtils import com.instructure.loginapi.login.view.CanvasLoadingView +import com.instructure.pandautils.utils.ThemePrefs import com.instructure.pandautils.utils.collectOneOffEvents import com.instructure.parentapp.R import com.instructure.parentapp.util.navigation.Navigation @@ -92,6 +93,8 @@ class SplashFragment : Fragment() { findNavController().popBackStack() navigation.navigate(activity, navigation.notAParent) } + + is SplashAction.ApplyTheme -> ThemePrefs.applyCanvasTheme(action.canvasTheme, requireContext()) } } diff --git a/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashViewModel.kt b/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashViewModel.kt index dbb8f658f4..e67060e5ab 100644 --- a/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashViewModel.kt +++ b/apps/parent/src/main/java/com/instructure/parentapp/features/splash/SplashViewModel.kt @@ -39,8 +39,7 @@ class SplashViewModel @Inject constructor( @ApplicationContext private val context: Context, private val repository: SplashRepository, private val apiPrefs: ApiPrefs, - private val colorKeeper: ColorKeeper, - private val themePrefs: ThemePrefs, + private val colorKeeper: ColorKeeper ) : ViewModel() { private val _events = Channel() @@ -59,7 +58,7 @@ class SplashViewModel @Inject constructor( colors?.let { colorKeeper.addToCache(it) } val theme = repository.getTheme() - theme?.let { themePrefs.applyCanvasTheme(it, context) } + theme?.let { _events.send(SplashAction.ApplyTheme(it)) } val students = repository.getStudents() if (students.isEmpty()) { diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/addstudent/AddStudentViewModelTest.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/addstudent/AddStudentViewModelTest.kt index 922646d562..22b21604d1 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/addstudent/AddStudentViewModelTest.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/addstudent/AddStudentViewModelTest.kt @@ -16,12 +16,14 @@ */ package com.instructure.parentapp.features.addstudent +import android.content.Context import android.graphics.Color import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.instructure.canvasapi2.utils.ContextKeeper import com.instructure.canvasapi2.utils.DataResult import com.instructure.pandautils.utils.ColorKeeper import com.instructure.pandautils.utils.ThemedColor @@ -59,11 +61,13 @@ class AddStudentViewModelTest { private val selectedStudentHolder: SelectedStudentHolder = mockk(relaxed = true) private val repository: AddStudentRepository = mockk(relaxed = true) private val crashlytics: FirebaseCrashlytics = mockk(relaxed = true) + private val context: Context = mockk(relaxed = true) @Before fun setup() { lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) Dispatchers.setMain(testDispatcher) + ContextKeeper.appContext = context mockkObject(ColorKeeper) every { ColorKeeper.getOrGenerateUserColor(any()) } returns ThemedColor(Color.BLACK) diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/alerts/list/AlertsViewModelTest.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/alerts/list/AlertsViewModelTest.kt index 6b2a857a37..9fd097e3ad 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/alerts/list/AlertsViewModelTest.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/alerts/list/AlertsViewModelTest.kt @@ -27,8 +27,7 @@ import com.instructure.canvasapi2.models.AlertType import com.instructure.canvasapi2.models.AlertWorkflowState import com.instructure.canvasapi2.models.ThresholdWorkflowState import com.instructure.canvasapi2.models.User -import com.instructure.pandautils.utils.ColorKeeper -import com.instructure.pandautils.utils.ThemedColor +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.R import com.instructure.parentapp.features.dashboard.AlertCountUpdater import com.instructure.parentapp.features.dashboard.TestSelectStudentHolder @@ -36,7 +35,7 @@ import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk -import io.mockk.mockkObject +import io.mockk.mockkStatic import io.mockk.unmockkAll import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -76,9 +75,8 @@ class AlertsViewModelTest { fun setup() { lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) Dispatchers.setMain(testDispatcher) + mockkStatic(User::studentColor) - mockkObject(ColorKeeper) - every { ColorKeeper.getOrGenerateUserColor(any()) } returns ThemedColor(1, 1) coEvery { repository.getAlertThresholdForStudent(any(), any()) } returns emptyList() } @@ -91,6 +89,7 @@ class AlertsViewModelTest { @Test fun `Load alerts on student change`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -180,6 +179,7 @@ class AlertsViewModelTest { @Test fun `Empty state`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 coEvery { repository.getAlertsForStudent(student.id, any()) @@ -217,6 +217,7 @@ class AlertsViewModelTest { @Test fun `Error state if getting alerts fail`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 coEvery { repository.getAlertsForStudent(student.id, any()) @@ -238,6 +239,7 @@ class AlertsViewModelTest { @Test fun `Refresh data`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -299,6 +301,7 @@ class AlertsViewModelTest { @Test fun `Dismiss alert`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -361,6 +364,7 @@ class AlertsViewModelTest { @Test fun `Dismiss error resets event`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -422,6 +426,7 @@ class AlertsViewModelTest { @Test fun `Undo dismissal`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -488,6 +493,7 @@ class AlertsViewModelTest { @Test fun `Undo does not reset event on error`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -552,6 +558,7 @@ class AlertsViewModelTest { @Test fun `Navigate to URL`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -611,6 +618,7 @@ class AlertsViewModelTest { @Test fun `Navigation to alert marks it read`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -673,6 +681,7 @@ class AlertsViewModelTest { @Test fun `If marking the alert read fails the alert will remain read until refresh`() = runTest { val student = User(1L) + every { student.studentColor } returns 1 val alerts = listOf( Alert( @@ -730,6 +739,23 @@ class AlertsViewModelTest { } + @Test + fun `Change color when student color is changed`() = runTest { + val student = User(1L) + mockkStatic(User::studentColor) + every { student.studentColor } returns 1 + createViewModel() + selectedStudentFlow.emit(student) + + assertEquals(1, viewModel.uiState.value.studentColor) + + every { student.studentColor } returns 2 + selectedStudentHolder.selectedStudentColorChanged() + + assertEquals(2, viewModel.uiState.value.studentColor) + unmockkAll() + } + private fun createViewModel() { viewModel = AlertsViewModel(repository, selectedStudentHolder, alertCountUpdater) diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/courses/list/CoursesViewModelTest.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/courses/list/CoursesViewModelTest.kt index dc9fd84412..499a29c85d 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/courses/list/CoursesViewModelTest.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/courses/list/CoursesViewModelTest.kt @@ -23,14 +23,13 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry import com.instructure.canvasapi2.models.Course import com.instructure.canvasapi2.models.User -import com.instructure.pandautils.utils.ColorKeeper -import com.instructure.pandautils.utils.ThemedColor +import com.instructure.pandautils.utils.studentColor import com.instructure.parentapp.features.dashboard.TestSelectStudentHolder import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every import io.mockk.mockk -import io.mockk.mockkObject +import io.mockk.mockkStatic import io.mockk.unmockkAll import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -42,7 +41,7 @@ import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.setMain import org.junit.After -import org.junit.Assert +import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test @@ -68,9 +67,8 @@ class CoursesViewModelTest { @Before fun setup() { lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) + mockkStatic(User::studentColor) Dispatchers.setMain(testDispatcher) - mockkObject(ColorKeeper) - every { ColorKeeper.getOrGenerateUserColor(any()) } returns ThemedColor(1, 1) } @After @@ -84,6 +82,7 @@ class CoursesViewModelTest { val student = User(1L) coEvery { repository.getCourses(student.id, any()) } returns listOf(Course(id = 1L, name = "Course 1", courseCode = "code-1")) every { courseGradeFormatter.getGradeText(any(), any()) } returns "A+" + every { student.studentColor } returns 1 createViewModel() selectedStudentFlow.emit(student) @@ -102,7 +101,7 @@ class CoursesViewModelTest { studentColor = 1 ) - Assert.assertEquals(expectedState, viewModel.uiState.value) + assertEquals(expectedState, viewModel.uiState.value) } @Test @@ -115,6 +114,7 @@ class CoursesViewModelTest { ) coEvery { repository.getCourses(any(), any()) } returns courses every { courseGradeFormatter.getGradeText(any(), any()) } returns "A+" + every { student.studentColor } returns 1 createViewModel() selectedStudentFlow.emit(student) @@ -133,13 +133,14 @@ class CoursesViewModelTest { studentColor = 1 ) - Assert.assertEquals(expectedState, viewModel.uiState.value) + assertEquals(expectedState, viewModel.uiState.value) } @Test fun `Error load courses`() = runTest { val student = User(1L) coEvery { repository.getCourses(student.id, any()) } throws Exception() + every { student.studentColor } returns 1 createViewModel() selectedStudentFlow.emit(student) @@ -150,13 +151,15 @@ class CoursesViewModelTest { studentColor = 1 ) - Assert.assertEquals(expectedState, viewModel.uiState.value) + assertEquals(expectedState, viewModel.uiState.value) } @Test fun `Refresh reloads courses`() = runTest { createViewModel() - selectedStudentHolder.updateSelectedStudent(User(1L)) + val student = User(1L) + selectedStudentHolder.updateSelectedStudent(student) + every { student.studentColor } returns 1 viewModel.handleAction(CoursesAction.Refresh) @@ -175,7 +178,24 @@ class CoursesViewModelTest { viewModel.handleAction(CoursesAction.CourseTapped(1L)) val expected = CoursesViewModelAction.NavigateToCourseDetails(1L) - Assert.assertEquals(expected, events.last()) + assertEquals(expected, events.last()) + } + + @Test + fun `Change color when student color is changed`() = runTest { + val student = User(1L) + mockkStatic(User::studentColor) + every { student.studentColor } returns 1 + createViewModel() + selectedStudentFlow.emit(student) + + assertEquals(1, viewModel.uiState.value.studentColor) + + every { student.studentColor } returns 2 + selectedStudentHolder.selectedStudentColorChanged() + + assertEquals(2, viewModel.uiState.value.studentColor) + unmockkAll() } private fun createViewModel() { diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/DashboardViewModelTest.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/DashboardViewModelTest.kt index a169edf660..1829651849 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/DashboardViewModelTest.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/DashboardViewModelTest.kt @@ -19,7 +19,6 @@ package com.instructure.parentapp.features.dashboard import android.content.Context import android.content.Intent -import android.graphics.Color import android.net.Uri import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.lifecycle.Lifecycle @@ -33,8 +32,6 @@ import com.instructure.canvasapi2.utils.ContextKeeper import com.instructure.loginapi.login.model.SignedInUser import com.instructure.loginapi.login.util.PreviousUsersUtils import com.instructure.pandautils.mvvm.ViewState -import com.instructure.pandautils.utils.ColorKeeper -import com.instructure.pandautils.utils.ThemedColor import com.instructure.parentapp.R import com.instructure.parentapp.features.alerts.list.AlertsRepository import com.instructure.parentapp.util.ParentPrefs @@ -90,8 +87,6 @@ class DashboardViewModelTest { @Before fun setup() { every { savedStateHandle.get(KEY_DEEP_LINK_INTENT) } returns null - mockkObject(ColorKeeper) - every { ColorKeeper.getOrGenerateUserColor(any()) } returns ThemedColor(Color.BLUE) lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) Dispatchers.setMain(testDispatcher) ContextKeeper.appContext = context @@ -275,6 +270,19 @@ class DashboardViewModelTest { assertEquals(DashboardViewModelAction.NavigateDeepLink(uri), events.first()) } + @Test + fun `Update color updates add student item color`() { + val students = listOf(User(id = 1L), User(id = 2L)) + coEvery { repository.getStudents(any()) } returns students + + createViewModel() + + val items = viewModel.data.value.studentItems + viewModel.updateColor(123) + + assertEquals(123, (items[2] as AddStudentItemViewModel).color) + } + private fun createViewModel() { viewModel = DashboardViewModel( context = context, diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/TestSelectStudentHolder.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/TestSelectStudentHolder.kt index ae5bceb205..d4758c4712 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/TestSelectStudentHolder.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/dashboard/TestSelectStudentHolder.kt @@ -25,9 +25,14 @@ import kotlinx.coroutines.flow.SharedFlow class TestSelectStudentHolder( override val selectedStudentState: MutableStateFlow, - override val selectedStudentChangedFlow: SharedFlow = MutableSharedFlow() + override val selectedStudentChangedFlow: SharedFlow = MutableSharedFlow(), + override val selectedStudentColorChanged: SharedFlow = MutableSharedFlow() ) : SelectedStudentHolder { override suspend fun updateSelectedStudent(user: User) { selectedStudentState.emit(user) } + + override suspend fun selectedStudentColorChanged() { + (selectedStudentColorChanged as MutableSharedFlow).emit(Unit) + } } diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/managestudents/ManageStudentsViewModelTest.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/managestudents/ManageStudentsViewModelTest.kt index 63704fa24b..790bd493ec 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/managestudents/ManageStudentsViewModelTest.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/managestudents/ManageStudentsViewModelTest.kt @@ -28,8 +28,8 @@ import com.instructure.canvasapi2.utils.ContextKeeper import com.instructure.pandautils.utils.ColorKeeper import com.instructure.pandautils.utils.ColorUtils import com.instructure.pandautils.utils.ThemedColor -import com.instructure.pandautils.utils.createThemedColor import com.instructure.parentapp.R +import com.instructure.parentapp.features.dashboard.SelectedStudentHolder import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every @@ -49,6 +49,7 @@ import org.junit.After import org.junit.Assert import org.junit.Before import org.junit.Rule +import org.junit.Test @ExperimentalCoroutinesApi @@ -64,6 +65,7 @@ class ManageStudentsViewModelTest { private val context: Context = mockk(relaxed = true) private val repository: ManageStudentsRepository = mockk(relaxed = true) private val colorKeeper: ColorKeeper = spyk() + private val selectedStudentHolder: SelectedStudentHolder = mockk(relaxed = true) private lateinit var viewModel: ManageStudentViewModel @@ -76,7 +78,7 @@ class ManageStudentsViewModelTest { every { ColorUtils.correctContrastForText(any(), any()) } answers { firstArg() } every { ColorUtils.correctContrastForButtonBackground(any(), any(), any()) } answers { firstArg() } every { context.getColor(any()) } answers { firstArg() } - every { createThemedColor(any()) } answers { ThemedColor(firstArg()) } + every { colorKeeper.createThemedColor(any()) } answers { ThemedColor(firstArg()) } } @After @@ -85,7 +87,7 @@ class ManageStudentsViewModelTest { unmockkObject(ColorUtils) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Load students`() { val students = listOf(User(id = 1, shortName = "Student 1", pronouns = "He/Him")) val expectedState = ManageStudentsUiState( @@ -101,7 +103,7 @@ class ManageStudentsViewModelTest { Assert.assertEquals(expectedState, viewModel.uiState.value) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Load students error`() { val expectedState = ManageStudentsUiState(isLoadError = true) coEvery { repository.getStudents(any()) } throws Exception() @@ -111,7 +113,7 @@ class ManageStudentsViewModelTest { Assert.assertEquals(expectedState, viewModel.uiState.value) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Load students empty`() { val expectedState = ManageStudentsUiState(isLoading = false, isLoadError = false, studentListItems = emptyList()) coEvery { repository.getStudents(any()) } returns emptyList() @@ -121,7 +123,7 @@ class ManageStudentsViewModelTest { Assert.assertEquals(expectedState, viewModel.uiState.value) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Navigate to alert settings screen`() = runTest { coEvery { repository.getStudents(any()) } returns listOf(User(id = 1)) createViewModel() @@ -137,7 +139,7 @@ class ManageStudentsViewModelTest { Assert.assertEquals(expected, events.last()) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Refresh reloads students`() { createViewModel() @@ -146,7 +148,7 @@ class ManageStudentsViewModelTest { coVerify { repository.getStudents(true) } } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Show color picker dialog`() { val userColors = listOf( UserColor( @@ -198,7 +200,7 @@ class ManageStudentsViewModelTest { Assert.assertEquals(expected, viewModel.uiState.value) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Hide color picker dialog`() = runTest { every { colorKeeper.userColors } returns emptyList() @@ -211,7 +213,7 @@ class ManageStudentsViewModelTest { Assert.assertFalse(viewModel.uiState.value.colorPickerDialogUiState.showColorPickerDialog) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Save student color`() { val expectedUiState = ManageStudentsUiState( colorPickerDialogUiState = ColorPickerDialogUiState(), @@ -237,7 +239,7 @@ class ManageStudentsViewModelTest { Assert.assertEquals(expectedUiState, viewModel.uiState.value) } - //@Test - Gonna be fixed when new student colors will be added + @Test fun `Save student color error`() { val expectedUiState = ManageStudentsUiState( colorPickerDialogUiState = ColorPickerDialogUiState(isSavingColorError = true), @@ -264,6 +266,6 @@ class ManageStudentsViewModelTest { } private fun createViewModel() { - viewModel = ManageStudentViewModel(context, colorKeeper, repository) + viewModel = ManageStudentViewModel(context, colorKeeper, repository, selectedStudentHolder) } } diff --git a/apps/parent/src/test/java/com/instructure/parentapp/features/splash/SplashViewModelTest.kt b/apps/parent/src/test/java/com/instructure/parentapp/features/splash/SplashViewModelTest.kt index 69695cb976..ec0f8c6f4e 100644 --- a/apps/parent/src/test/java/com/instructure/parentapp/features/splash/SplashViewModelTest.kt +++ b/apps/parent/src/test/java/com/instructure/parentapp/features/splash/SplashViewModelTest.kt @@ -62,7 +62,6 @@ class SplashViewModelTest { private val repository: SplashRepository = mockk(relaxed = true) private val apiPrefs: ApiPrefs = mockk(relaxed = true) private val colorKeeper: ColorKeeper = mockk(relaxed = true) - private val themePrefs: ThemePrefs = mockk(relaxed = true) private lateinit var viewModel: SplashViewModel @@ -96,7 +95,6 @@ class SplashViewModelTest { coVerify { apiPrefs.user = user } coVerify { colorKeeper.addToCache(colors) } - coVerify { themePrefs.applyCanvasTheme(theme, context) } val events = mutableListOf() backgroundScope.launch(testDispatcher) { @@ -104,6 +102,7 @@ class SplashViewModelTest { } Assert.assertEquals(SplashAction.InitialDataLoadingFinished, events.last()) + Assert.assertEquals(SplashAction.ApplyTheme(theme), events.first()) } @Test @@ -166,8 +165,7 @@ class SplashViewModelTest { context = context, repository = repository, apiPrefs = apiPrefs, - colorKeeper = colorKeeper, - themePrefs = themePrefs, + colorKeeper = colorKeeper ) } } diff --git a/libs/pandares/src/main/res/values/colors.xml b/libs/pandares/src/main/res/values/colors.xml index d834d83f45..6f94a34c3b 100644 --- a/libs/pandares/src/main/res/values/colors.xml +++ b/libs/pandares/src/main/res/values/colors.xml @@ -151,12 +151,13 @@ #9C9C9C - #FF007BC2 - #FF5F4DCE - #FFBF32A4 - #FFE9162E - #FFD34503 - #FF008A12 + + #2573DF + #27872B + #BF5811 + #C54396 + #9E58BD + #ED0000 #2ca3de diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/features/inbox/utils/InboxMessageView.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/features/inbox/utils/InboxMessageView.kt index 2e7edde159..a3663c69f6 100644 --- a/libs/pandautils/src/main/java/com/instructure/pandautils/features/inbox/utils/InboxMessageView.kt +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/features/inbox/utils/InboxMessageView.kt @@ -140,7 +140,7 @@ private fun InboxMessageDetailsView( onClick = { messageState.message?.let { actionHandler( MessageAction.Reply(it) ) } }, colors = ButtonDefaults.buttonColors( backgroundColor = colorResource(id = R.color.backgroundLightest), - contentColor = Color(ThemePrefs.brandColor) + contentColor = Color(ThemePrefs.textButtonColor) ), contentPadding = PaddingValues(start = 0.dp, top = 8.dp, end = 8.dp, bottom = 8.dp), content = { diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/CanvasContextExtensions.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/CanvasContextExtensions.kt index 07913cc152..4da3be2bac 100644 --- a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/CanvasContextExtensions.kt +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/CanvasContextExtensions.kt @@ -36,7 +36,7 @@ val CanvasContext?.lightColor: Int get() { } @get:ColorInt -val User?.color: Int get() { +val User?.studentColor: Int get() { val themedColor = ColorKeeper.getOrGenerateUserColor(this) return if (ColorKeeper.darkTheme) themedColor.dark else themedColor.light } diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ColorKeeper.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ColorKeeper.kt index 7eafdaa06c..4fa1d7cca1 100644 --- a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ColorKeeper.kt +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ColorKeeper.kt @@ -76,6 +76,11 @@ object ColorKeeper : PrefManager(PREFERENCE_FILE_NAME) { } } + /** + * Gets the themed color associated with the given [User] if it exists, otherwise generates a new color + * This should be used directly only in special cases where we need a [ThemedColor] object instead of a specific color. + * To get user color use [User.studentColor] + * **/ fun getOrGenerateUserColor(user: User?): ThemedColor { return if (user == null) { ThemedColor(ThemePrefs.primaryColor) @@ -122,6 +127,19 @@ object ColorKeeper : PrefManager(PREFERENCE_FILE_NAME) { cachedThemedColors += contextId to createThemedColor(color) } + fun createThemedColor(@ColorInt color: Int): ThemedColor { + // There are some custom colors that we can map to a specific dark variant. For others we use our accessibility algorithm. + val entry = lightDarkColorMap.entries.find { it.key == color } + if (entry != null) { + return ThemedColor(entry.key, entry.value) + } + + val light = ColorUtils.correctContrastForText(color, ContextKeeper.appContext.getColor(R.color.white)) + val dark = ColorUtils.correctContrastForText(color, ContextKeeper.appContext.getColor(R.color.textOnColorDark)) + + return ThemedColor(light, dark) + } + /** * Generates a colored drawable * @param context An Android Context @@ -247,20 +265,8 @@ object ColorApiHelper { suspend fun awaitSync(): Boolean = suspendCancellableCoroutine { cr -> performSync { cr.resumeSafely(it) } } } -fun createThemedColor(@ColorInt color: Int): ThemedColor { - // There are some custom colors that we can map to a specific dark variant. For others we use our accessibility algorithm. - val entry = lightDarkColorMap.entries.find { it.key == color } - if (entry != null) { - return ThemedColor(entry.key, entry.value) - } - - val light = ColorUtils.correctContrastForText(color, ContextKeeper.appContext.getColor(R.color.white)) - val dark = ColorUtils.correctContrastForText(color, ContextKeeper.appContext.getColor(R.color.textOnColorDark)) - - return ThemedColor(light, dark) -} - // There are some custom colors that we can map to a specific dark variant. For others we use our accessibility algorithm. +// Since the student colors in the Parent app are using some of these colors we don't add them, because that would be a duplicate entry in the map. private val lightDarkColorMap: Map = mapOf( ContextKeeper.appContext.getColor(R.color.courseColor1light) to ContextKeeper.appContext.getColor(R.color.courseColor1dark), ContextKeeper.appContext.getColor(R.color.courseColor2light) to ContextKeeper.appContext.getColor(R.color.courseColor2dark), diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ThemePrefs.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ThemePrefs.kt index 36a61a6d20..2e4f83213c 100644 --- a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ThemePrefs.kt +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/ThemePrefs.kt @@ -26,6 +26,7 @@ import com.instructure.canvasapi2.utils.IntPref import com.instructure.canvasapi2.utils.PrefManager import com.instructure.canvasapi2.utils.StringPref import com.instructure.pandautils.R +import dagger.hilt.android.qualifiers.ActivityContext const val MIN_CONTRAST_FOR_BUTTONS = 3.0 const val MIN_CONTRAST_FOR_TEXT = 4.5 @@ -63,6 +64,8 @@ object ThemePrefs : PrefManager("CanvasTheme") { var themeSelectionShown by BooleanPref() + private var canvasTheme: CanvasTheme? = null + override fun keepBaseProps() = listOf(::appTheme, ::themeSelectionShown) override fun onClearPrefs() { @@ -97,7 +100,13 @@ object ThemePrefs : PrefManager("CanvasTheme") { } - fun applyCanvasTheme(theme: CanvasTheme, context: Context) { + // This should not be called with application context. + fun reapplyCanvasTheme(@ActivityContext context: Context) { + applyCanvasTheme(canvasTheme ?: return, context) + } + + // This should not be called with application context. + fun applyCanvasTheme(theme: CanvasTheme, @ActivityContext context: Context) { val tempBrandColor = parseColor(theme.brand, brandColor) // ic-brand-primary - Primary Brand Color brandColor = ColorUtils.correctContrastForText(tempBrandColor, context.getColor(R.color.backgroundLightestElevated)) @@ -112,6 +121,7 @@ object ThemePrefs : PrefManager("CanvasTheme") { logoUrl = theme.logoUrl isThemeApplied = true + canvasTheme = theme } private fun parseColor(hexColor: String, defaultColor: Int): Int { From f1d3f2ed5f66287141057626d4ac60652fa525a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Muller?= Date: Mon, 7 Oct 2024 14:56:29 +0200 Subject: [PATCH 04/38] Remove Multidex usages (#2568) Since the min SDK is at least 21, it is no longer necessary to use the Multidex library. See the following for more info: https://developer.android.com/build/multidex#mdex-on-l --- InstrumentationTests/app/build.gradle | 2 -- .../instructure/instrumentationtests/AppManager.java | 12 ++---------- .../instrumentationtests/robo/RoboTestCase.java | 3 +-- apps/student/build.gradle | 1 - apps/teacher/build.gradle | 1 - foosball/app/build.gradle | 1 - 6 files changed, 3 insertions(+), 17 deletions(-) diff --git a/InstrumentationTests/app/build.gradle b/InstrumentationTests/app/build.gradle index 7b90a045bc..e9c5e0ddd0 100644 --- a/InstrumentationTests/app/build.gradle +++ b/InstrumentationTests/app/build.gradle @@ -64,10 +64,8 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' }) compile rootProject.ext.supportDependencies.appCompat - compile 'com.android.support:multidex:1.0.1' testCompile "org.robolectric:robolectric:3.2.2" - testCompile 'org.robolectric:shadows-multidex:3.0' testCompile "org.robolectric:shadows-play-services:3.0" testCompile "org.robolectric:shadows-support-v4:3.0" diff --git a/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java b/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java index bef79b3c10..4b98307eec 100644 --- a/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java +++ b/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java @@ -16,16 +16,8 @@ package instructure.instrumentationtests; -import android.content.Context; -import android.support.multidex.MultiDex; -import android.support.multidex.MultiDexApplication; +import android.app.Application; -public class AppManager extends MultiDexApplication { - - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - MultiDex.install(this); - } +public class AppManager extends Application { } diff --git a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java b/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java index 645f67f840..169dbe7b4b 100644 --- a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java +++ b/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java @@ -25,12 +25,11 @@ import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -import org.robolectric.shadows.multidex.ShadowMultiDex; import instructure.instrumentationtests.BuildConfig; @RunWith(RoboTestRunner.class) -@Config(constants = BuildConfig.class, shadows = ShadowMultiDex.class, sdk = RoboTestRunner.DEFAULT_SDK) +@Config(constants = BuildConfig.class, sdk = RoboTestRunner.DEFAULT_SDK) public abstract class RoboTestCase extends TestCase { private RoboAppManager mApplication; diff --git a/apps/student/build.gradle b/apps/student/build.gradle index 8968eb85dc..b3df9a528b 100644 --- a/apps/student/build.gradle +++ b/apps/student/build.gradle @@ -44,7 +44,6 @@ android { versionName = '7.5.3' vectorDrawables.useSupportLibrary = true - multiDexEnabled = true testInstrumentationRunner 'com.instructure.student.espresso.StudentHiltTestRunner' testInstrumentationRunnerArguments disableAnalytics: 'true' buildConfigField "boolean", "IS_TESTING", "false" diff --git a/apps/teacher/build.gradle b/apps/teacher/build.gradle index 47567726dd..8a300f1144 100644 --- a/apps/teacher/build.gradle +++ b/apps/teacher/build.gradle @@ -42,7 +42,6 @@ android { versionCode = 70 versionName = '1.33.0' vectorDrawables.useSupportLibrary = true - multiDexEnabled true testInstrumentationRunner 'com.instructure.teacher.ui.espresso.TeacherHiltTestRunner' testInstrumentationRunnerArguments disableAnalytics: 'true' diff --git a/foosball/app/build.gradle b/foosball/app/build.gradle index 846fc64a87..ee76984e5b 100644 --- a/foosball/app/build.gradle +++ b/foosball/app/build.gradle @@ -34,7 +34,6 @@ android { versionCode rootProject.ext.versionCode versionName rootProject.ext.versionName vectorDrawables.useSupportLibrary = true - multiDexEnabled true buildConfigField "String", "FIREBASE_USERNAME", "\"$firebase_tab_username\"" buildConfigField "String", "FIREBASE_PASSWORD", "\"$firebase_tab_password\"" From e692350a9ee01b75f1c280a121ed51ff1fe867e5 Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:31:30 +0200 Subject: [PATCH 05/38] [MBL-17888][Parent] Fixed help menu serialization #2586 refs: MBL-17888 affects: Parent release note: Fixed an issue where help links wouldn't load in some cases --- apps/flutter_parent/lib/models/help_link.dart | 8 +- .../lib/models/help_link.g.dart | 73 +++++++++++-------- .../lib/screens/help/help_screen.dart | 24 +++--- .../screens/help/help_screen_interactor.dart | 1 + .../help/help_screen_interactor_test.dart | 23 ++++++ 5 files changed, 81 insertions(+), 48 deletions(-) diff --git a/apps/flutter_parent/lib/models/help_link.dart b/apps/flutter_parent/lib/models/help_link.dart index 467ed5b648..af8241783a 100644 --- a/apps/flutter_parent/lib/models/help_link.dart +++ b/apps/flutter_parent/lib/models/help_link.dart @@ -28,18 +28,18 @@ abstract class HelpLink implements Built { factory HelpLink([void Function(HelpLinkBuilder) updates]) = _$HelpLink; - String get id; + String? get id; String get type; @BuiltValueField(wireName: 'available_to') BuiltList get availableTo; - String get url; + String? get url; - String get text; + String? get text; - String get subtext; + String? get subtext; } class AvailableTo extends EnumClass { diff --git a/apps/flutter_parent/lib/models/help_link.g.dart b/apps/flutter_parent/lib/models/help_link.g.dart index a596b2cb39..e9bd162ddf 100644 --- a/apps/flutter_parent/lib/models/help_link.g.dart +++ b/apps/flutter_parent/lib/models/help_link.g.dart @@ -55,22 +55,38 @@ class _$HelpLinkSerializer implements StructuredSerializer { Iterable serialize(Serializers serializers, HelpLink object, {FullType specifiedType = FullType.unspecified}) { final result = [ - 'id', - serializers.serialize(object.id, specifiedType: const FullType(String)), 'type', serializers.serialize(object.type, specifiedType: const FullType(String)), 'available_to', serializers.serialize(object.availableTo, specifiedType: const FullType(BuiltList, const [const FullType(AvailableTo)])), - 'url', - serializers.serialize(object.url, specifiedType: const FullType(String)), - 'text', - serializers.serialize(object.text, specifiedType: const FullType(String)), - 'subtext', - serializers.serialize(object.subtext, - specifiedType: const FullType(String)), ]; + Object? value; + value = object.id; + + result + ..add('id') + ..add( + serializers.serialize(value, specifiedType: const FullType(String))); + value = object.url; + + result + ..add('url') + ..add( + serializers.serialize(value, specifiedType: const FullType(String))); + value = object.text; + + result + ..add('text') + ..add( + serializers.serialize(value, specifiedType: const FullType(String))); + value = object.subtext; + + result + ..add('subtext') + ..add( + serializers.serialize(value, specifiedType: const FullType(String))); return result; } @@ -88,7 +104,7 @@ class _$HelpLinkSerializer implements StructuredSerializer { switch (key) { case 'id': result.id = serializers.deserialize(value, - specifiedType: const FullType(String))! as String; + specifiedType: const FullType(String)) as String?; break; case 'type': result.type = serializers.deserialize(value, @@ -102,15 +118,15 @@ class _$HelpLinkSerializer implements StructuredSerializer { break; case 'url': result.url = serializers.deserialize(value, - specifiedType: const FullType(String))! as String; + specifiedType: const FullType(String)) as String?; break; case 'text': result.text = serializers.deserialize(value, - specifiedType: const FullType(String))! as String; + specifiedType: const FullType(String)) as String?; break; case 'subtext': result.subtext = serializers.deserialize(value, - specifiedType: const FullType(String))! as String; + specifiedType: const FullType(String)) as String?; break; } } @@ -138,36 +154,32 @@ class _$AvailableToSerializer implements PrimitiveSerializer { class _$HelpLink extends HelpLink { @override - final String id; + final String? id; @override final String type; @override final BuiltList availableTo; @override - final String url; + final String? url; @override - final String text; + final String? text; @override - final String subtext; + final String? subtext; factory _$HelpLink([void Function(HelpLinkBuilder)? updates]) => (new HelpLinkBuilder()..update(updates))._build(); _$HelpLink._( - {required this.id, + {this.id, required this.type, required this.availableTo, - required this.url, - required this.text, - required this.subtext}) + this.url, + this.text, + this.subtext}) : super._() { - BuiltValueNullFieldError.checkNotNull(id, r'HelpLink', 'id'); BuiltValueNullFieldError.checkNotNull(type, r'HelpLink', 'type'); BuiltValueNullFieldError.checkNotNull( availableTo, r'HelpLink', 'availableTo'); - BuiltValueNullFieldError.checkNotNull(url, r'HelpLink', 'url'); - BuiltValueNullFieldError.checkNotNull(text, r'HelpLink', 'text'); - BuiltValueNullFieldError.checkNotNull(subtext, r'HelpLink', 'subtext'); } @override @@ -279,16 +291,13 @@ class HelpLinkBuilder implements Builder { try { _$result = _$v ?? new _$HelpLink._( - id: BuiltValueNullFieldError.checkNotNull(id, r'HelpLink', 'id'), + id: id, type: BuiltValueNullFieldError.checkNotNull( type, r'HelpLink', 'type'), availableTo: availableTo.build(), - url: BuiltValueNullFieldError.checkNotNull( - url, r'HelpLink', 'url'), - text: BuiltValueNullFieldError.checkNotNull( - text, r'HelpLink', 'text'), - subtext: BuiltValueNullFieldError.checkNotNull( - subtext, r'HelpLink', 'subtext')); + url: url, + text: text, + subtext: subtext); } catch (_) { late String _$failedField; try { diff --git a/apps/flutter_parent/lib/screens/help/help_screen.dart b/apps/flutter_parent/lib/screens/help/help_screen.dart index 4e468a5720..4d2ca0edf1 100644 --- a/apps/flutter_parent/lib/screens/help/help_screen.dart +++ b/apps/flutter_parent/lib/screens/help/help_screen.dart @@ -65,8 +65,8 @@ class _HelpScreenState extends State { List _generateLinks(List? links) { List helpLinks = List.from(links?.map( (l) => ListTile( - title: Text(l.text, style: Theme.of(context).textTheme.titleMedium), - subtitle: Text(l.subtext, style: Theme.of(context).textTheme.bodySmall), + title: Text(l.text ?? '', style: Theme.of(context).textTheme.titleMedium), + subtitle: Text(l.subtext ?? '', style: Theme.of(context).textTheme.bodySmall), onTap: () => _linkClick(l), ), ) ?? []); @@ -84,7 +84,7 @@ class _HelpScreenState extends State { } void _linkClick(HelpLink link) { - String url = link.url; + String url = link.url ?? ''; if (url[0] == '#') { // Internal link if (url.contains('#create_ticket')) { @@ -93,24 +93,24 @@ class _HelpScreenState extends State { // Custom for Android _showShareLove(); } - } else if (link.id.contains('submit_feature_idea')) { + } else if (link.id?.contains('submit_feature_idea') == true) { _showRequestFeature(); - } else if (link.url.startsWith('tel:+')) { + } else if (url.startsWith('tel:+')) { // Support phone links: https://community.canvaslms.com/docs/DOC-12664-4214610054 - locator().launchPhone(link.url); - } else if (link.url.startsWith('mailto:')) { + locator().launchPhone(url); + } else if (url.startsWith('mailto:')) { // Support mailto links: https://community.canvaslms.com/docs/DOC-12664-4214610054 - locator().launchEmail(link.url); - } else if (link.url.contains('cases.canvaslms.com/liveagentchat')) { + locator().launchEmail(url); + } else if (url.contains('cases.canvaslms.com/liveagentchat')) { // Chat with Canvas Support - Doesn't seem work properly with WebViews, so we kick it out // to the external browser - locator().launch(link.url); - } else if (link.id.contains('search_the_canvas_guides')) { + locator().launch(url); + } else if (link.id?.contains('search_the_canvas_guides') == true) { // Send them to the mobile Canvas guides _showSearch(); } else { // External url - locator().launch(link.url); + locator().launch(url); } } diff --git a/apps/flutter_parent/lib/screens/help/help_screen_interactor.dart b/apps/flutter_parent/lib/screens/help/help_screen_interactor.dart index cc143cd67d..3fdc29789b 100644 --- a/apps/flutter_parent/lib/screens/help/help_screen_interactor.dart +++ b/apps/flutter_parent/lib/screens/help/help_screen_interactor.dart @@ -34,6 +34,7 @@ class HelpScreenInteractor { link.availableTo.contains(AvailableTo.user)); List filterObserverLinks(BuiltList list) => list + .where((link) => link.url != null && link.text != null) .where((link) => link.availableTo.contains(AvailableTo.observer) || link.availableTo.contains(AvailableTo.user)) diff --git a/apps/flutter_parent/test/screens/help/help_screen_interactor_test.dart b/apps/flutter_parent/test/screens/help/help_screen_interactor_test.dart index 00178d1d4a..2b827e1103 100644 --- a/apps/flutter_parent/test/screens/help/help_screen_interactor_test.dart +++ b/apps/flutter_parent/test/screens/help/help_screen_interactor_test.dart @@ -96,6 +96,21 @@ void main() { observerLinks); }); + test('filterObserverLinks only returns links that has text and url', () async { + var validLinks = [ + createHelpLink(availableTo: [AvailableTo.observer]), + createHelpLink(availableTo: [AvailableTo.user]), + ]; + + var invalidLinks = [ + createNullableHelpLink(url: 'url', availableTo: [AvailableTo.observer]), + createNullableHelpLink(text: 'text', availableTo: [AvailableTo.observer]), + ]; + + expect(HelpScreenInteractor().filterObserverLinks(BuiltList.from([...validLinks, ...invalidLinks])), + validLinks); + }); + test('custom list is returned if there are any custom lists', () async { var api = MockHelpLinksApi(); var customLinks = [ @@ -144,3 +159,11 @@ HelpLink createHelpLink({String? id, String? text, String? url, List? availableTo}) => HelpLink((b) => b + ..id = id + ..type = '' + ..availableTo = ListBuilder(availableTo != null ? availableTo : []) + ..url = url + ..text = text + ..subtext = 'subtext'); \ No newline at end of file From cc0fb83282066b56331f4228469d99cab1c80444 Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:10:43 +0200 Subject: [PATCH 06/38] Fixed file list back button issue. #2589 --- .../features/files/list/FileListFragment.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt b/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt index 3362b53079..19c840750e 100644 --- a/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt +++ b/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt @@ -20,6 +20,8 @@ package com.instructure.student.features.files.list import android.content.DialogInterface import android.content.res.Configuration import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.view.LayoutInflater import android.view.MenuItem import android.view.View @@ -310,12 +312,14 @@ class FileListFragment : ParentFragment(), Bookmarkable, FileUploadDialogParent private fun themeToolbar() = with(binding) { // We style the toolbar white for user files - if (canvasContext.type == CanvasContext.Type.USER) { - ViewStyler.themeProgressBar(fileLoadingProgressBar, ThemePrefs.primaryTextColor) - ViewStyler.themeToolbarColored(requireActivity(), toolbar, ThemePrefs.primaryColor, ThemePrefs.primaryTextColor) - } else { - ViewStyler.themeProgressBar(fileLoadingProgressBar, requireContext().getColor(R.color.white)) - ViewStyler.themeToolbarColored(requireActivity(), toolbar, canvasContext) + Handler(Looper.getMainLooper()).post { + if (canvasContext.type == CanvasContext.Type.USER) { + ViewStyler.themeProgressBar(fileLoadingProgressBar, ThemePrefs.brandColor) + ViewStyler.themeToolbarColored(requireActivity(), toolbar, ThemePrefs.primaryColor, ThemePrefs.brandColor) + } else { + ViewStyler.themeProgressBar(fileLoadingProgressBar, requireContext().getColor(R.color.textLightest)) + ViewStyler.themeToolbarColored(requireActivity(), toolbar, canvasContext) + } } } From 465503ddd469b8e2183ab2c502e1cd897f5736c9 Mon Sep 17 00:00:00 2001 From: Kristof Deak <92309696+kdeakinstructure@users.noreply.github.com> Date: Thu, 10 Oct 2024 18:43:10 +0200 Subject: [PATCH 07/38] [MBL-17974][Student] - Handle 0 value in assignment reminder custom dialog (#2590) * Handle 0 value in assignment reminder custom dialog refs: MBL-17974 affects: Student release note: Handle 0 value in assignment reminder custom dialog * PR changes. * Remove unnecessary condition. --- .../features/assignments/reminder/CustomReminderDialog.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/student/src/main/java/com/instructure/student/features/assignments/reminder/CustomReminderDialog.kt b/apps/student/src/main/java/com/instructure/student/features/assignments/reminder/CustomReminderDialog.kt index 311829ba1f..17a5381254 100644 --- a/apps/student/src/main/java/com/instructure/student/features/assignments/reminder/CustomReminderDialog.kt +++ b/apps/student/src/main/java/com/instructure/student/features/assignments/reminder/CustomReminderDialog.kt @@ -26,6 +26,7 @@ import androidx.core.widget.doAfterTextChanged import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels import com.instructure.pandautils.utils.ThemePrefs +import com.instructure.pandautils.utils.orDefault import com.instructure.student.R import com.instructure.student.databinding.DialogCustomReminderBinding import com.instructure.student.features.assignments.details.AssignmentDetailsViewModel @@ -77,7 +78,7 @@ class CustomReminderDialog : DialogFragment() { } private fun updateButtonState(button: Button) { - button.isEnabled = binding.choices.checkedRadioButtonId != -1 && binding.quantity.text.isNotEmpty() + button.isEnabled = binding.choices.checkedRadioButtonId != -1 && binding.quantity.text.toString().toIntOrNull().orDefault() > 0 } companion object { From 7996e916962a45f69d6303f52d23baa87391e2de Mon Sep 17 00:00:00 2001 From: domonkosadam Date: Fri, 11 Oct 2024 10:40:00 +0200 Subject: [PATCH 08/38] Increase version --- apps/student/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/student/build.gradle b/apps/student/build.gradle index b4859efac8..5c5e3b363b 100644 --- a/apps/student/build.gradle +++ b/apps/student/build.gradle @@ -40,8 +40,8 @@ android { applicationId "com.instructure.candroid" minSdkVersion Versions.MIN_SDK targetSdkVersion Versions.TARGET_SDK - versionCode = 267 - versionName = '7.6.0' + versionCode = 268 + versionName = '7.6.1' vectorDrawables.useSupportLibrary = true multiDexEnabled = true From 458fa668c99bab919c764a12224dc766d418399c Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:32:46 +0200 Subject: [PATCH 09/38] [MBL-18002][Student] Fix file list crash and file header color #2593 refs: MBL-18002 affects: Student release note: none --- .../student/features/files/list/FileListFragment.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt b/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt index 19c840750e..52ea6555a6 100644 --- a/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt +++ b/apps/student/src/main/java/com/instructure/student/features/files/list/FileListFragment.kt @@ -313,9 +313,10 @@ class FileListFragment : ParentFragment(), Bookmarkable, FileUploadDialogParent private fun themeToolbar() = with(binding) { // We style the toolbar white for user files Handler(Looper.getMainLooper()).post { + if (!isAdded) return@post if (canvasContext.type == CanvasContext.Type.USER) { - ViewStyler.themeProgressBar(fileLoadingProgressBar, ThemePrefs.brandColor) - ViewStyler.themeToolbarColored(requireActivity(), toolbar, ThemePrefs.primaryColor, ThemePrefs.brandColor) + ViewStyler.themeProgressBar(fileLoadingProgressBar, ThemePrefs.primaryTextColor) + ViewStyler.themeToolbarColored(requireActivity(), toolbar, ThemePrefs.primaryColor, ThemePrefs.primaryTextColor) } else { ViewStyler.themeProgressBar(fileLoadingProgressBar, requireContext().getColor(R.color.textLightest)) ViewStyler.themeToolbarColored(requireActivity(), toolbar, canvasContext) From 5fec9da19c0ab2b295479d1bced1fa2b3ded077e Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:50:16 +0200 Subject: [PATCH 10/38] Fixed text color in Global announcements (#2595) --- .../instructure/student/fragment/InternalWebviewFragment.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/student/src/main/java/com/instructure/student/fragment/InternalWebviewFragment.kt b/apps/student/src/main/java/com/instructure/student/fragment/InternalWebviewFragment.kt index 6ed6c3cff0..917a2fc2cb 100644 --- a/apps/student/src/main/java/com/instructure/student/fragment/InternalWebviewFragment.kt +++ b/apps/student/src/main/java/com/instructure/student/fragment/InternalWebviewFragment.kt @@ -273,7 +273,11 @@ open class InternalWebviewFragment : ParentFragment() { override fun applyTheme() = with(binding) { toolbar.title = title() toolbar.setupAsBackButton(this@InternalWebviewFragment) - ViewStyler.themeToolbarColored(requireActivity(), toolbar, canvasContext) + if (canvasContext.type != CanvasContext.Type.COURSE || canvasContext.type != CanvasContext.Type.GROUP) { + ViewStyler.themeToolbarColored(requireActivity(), toolbar, ThemePrefs.primaryColor, ThemePrefs.primaryTextColor) + } else { + ViewStyler.themeToolbarColored(requireActivity(), toolbar, canvasContext) + } } override fun title(): String = title ?: canvasContext.name ?: "" From 9335de4550d5b436f30af422801e4a0bffa9ed0d Mon Sep 17 00:00:00 2001 From: Tamas Kozmer Date: Mon, 14 Oct 2024 09:03:47 +0200 Subject: [PATCH 11/38] Stubbed flaky e2e tests. --- .../java/com/instructure/student/ui/e2e/k5/HomeroomE2ETest.kt | 2 ++ .../student/ui/e2e/offline/OfflineDiscussionsE2ETest.kt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/k5/HomeroomE2ETest.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/k5/HomeroomE2ETest.kt index ed32b8e2e2..830e9ee26c 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/k5/HomeroomE2ETest.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/k5/HomeroomE2ETest.kt @@ -22,6 +22,7 @@ import com.instructure.canvas.espresso.E2E import com.instructure.canvas.espresso.FeatureCategory import com.instructure.canvas.espresso.Priority import com.instructure.canvas.espresso.SecondaryFeatureCategory +import com.instructure.canvas.espresso.Stub import com.instructure.canvas.espresso.TestCategory import com.instructure.canvas.espresso.TestMetaData import com.instructure.dataseeding.api.AssignmentsApi @@ -48,6 +49,7 @@ class HomeroomE2ETest : StudentTest() { override fun enableAndConfigureAccessibilityChecks() = Unit + @Stub // TODO: Investigate flaky test @E2E @Test @TestMetaData(Priority.MANDATORY, FeatureCategory.CANVAS_FOR_ELEMENTARY, TestCategory.E2E, SecondaryFeatureCategory.HOMEROOM) diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineDiscussionsE2ETest.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineDiscussionsE2ETest.kt index 814edaf48e..e956b0267c 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineDiscussionsE2ETest.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineDiscussionsE2ETest.kt @@ -22,6 +22,7 @@ import com.instructure.canvas.espresso.FeatureCategory import com.instructure.canvas.espresso.OfflineE2E import com.instructure.canvas.espresso.Priority import com.instructure.canvas.espresso.SecondaryFeatureCategory +import com.instructure.canvas.espresso.Stub import com.instructure.canvas.espresso.TestCategory import com.instructure.canvas.espresso.TestMetaData import com.instructure.canvas.espresso.checkToastText @@ -45,6 +46,7 @@ class OfflineDiscussionsE2ETest : StudentTest() { override fun enableAndConfigureAccessibilityChecks() = Unit + @Stub // TODO: Investigate flaky test @OfflineE2E @Test @TestMetaData(Priority.MANDATORY, FeatureCategory.DISCUSSIONS, TestCategory.E2E, SecondaryFeatureCategory.OFFLINE_MODE) From 09ea582ed947c052b99894a0280251b6d1ec50a3 Mon Sep 17 00:00:00 2001 From: Tamas Kozmer Date: Mon, 14 Oct 2024 09:37:48 +0200 Subject: [PATCH 12/38] Stub flaky interaction tests. --- .../common/interaction/CreateUpdateEventInteractionTest.kt | 4 +++- .../common/interaction/CreateUpdateToDoInteractionTest.kt | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateEventInteractionTest.kt b/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateEventInteractionTest.kt index be83158f72..a7f9cbaede 100644 --- a/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateEventInteractionTest.kt +++ b/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateEventInteractionTest.kt @@ -18,6 +18,7 @@ package com.instructure.canvas.espresso.common.interaction import com.instructure.canvas.espresso.CanvasComposeTest +import com.instructure.canvas.espresso.Stub import com.instructure.canvas.espresso.common.pages.compose.CalendarEventCreateEditPage import com.instructure.canvas.espresso.common.pages.compose.CalendarEventDetailsPage import com.instructure.canvas.espresso.common.pages.compose.CalendarScreenPage @@ -220,6 +221,7 @@ abstract class CreateUpdateEventInteractionTest : CanvasComposeTest() { } @Test + @Stub("This test is flaky, depends on the time of day") fun assertUpdatedFrom() { val data = initData() val user = getLoggedInUser() @@ -248,7 +250,7 @@ abstract class CreateUpdateEventInteractionTest : CanvasComposeTest() { calendarEventDetailsPage.assertEventDateContains(expectedTime!!) } - @Test + @Stub("This test is flaky, depends on the time of day") fun assertUpdatedTo() { val data = initData() val user = getLoggedInUser() diff --git a/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateToDoInteractionTest.kt b/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateToDoInteractionTest.kt index b8cde1f491..dd233e220f 100644 --- a/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateToDoInteractionTest.kt +++ b/automation/espresso/src/main/kotlin/com/instructure/canvas/espresso/common/interaction/CreateUpdateToDoInteractionTest.kt @@ -18,6 +18,7 @@ package com.instructure.canvas.espresso.common.interaction import com.instructure.canvas.espresso.CanvasComposeTest +import com.instructure.canvas.espresso.Stub import com.instructure.canvas.espresso.common.pages.compose.CalendarScreenPage import com.instructure.canvas.espresso.common.pages.compose.CalendarToDoCreateUpdatePage import com.instructure.canvas.espresso.common.pages.compose.CalendarToDoDetailsPage @@ -172,6 +173,7 @@ abstract class CreateUpdateToDoInteractionTest : CanvasComposeTest() { } @Test + @Stub("This test is flaky, depends on the time of day") fun assertUpdatedTime() { val data = initData() val user = getLoggedInUser() From 6c23fa250367e90fa810d22d62e7f0be4e3df3c7 Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:59:51 +0200 Subject: [PATCH 13/38] [MBL-17911][Student] Reply/edit options viewable in closed discussions when acting as student (#2592) refs: MBL-17911 affects: Student release note: none * Fixed authenticated url for discussion details. * Call getAuthenticatedSessionMasquerading everywhere when masquerading. * Removed unused import. --- .../course/ElementaryCourseViewModel.kt | 9 +-------- .../canvasapi2/managers/OAuthManager.kt | 17 +++++++---------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/apps/student/src/main/java/com/instructure/student/features/elementary/course/ElementaryCourseViewModel.kt b/apps/student/src/main/java/com/instructure/student/features/elementary/course/ElementaryCourseViewModel.kt index a7d7536165..1c06c98fee 100644 --- a/apps/student/src/main/java/com/instructure/student/features/elementary/course/ElementaryCourseViewModel.kt +++ b/apps/student/src/main/java/com/instructure/student/features/elementary/course/ElementaryCourseViewModel.kt @@ -157,14 +157,7 @@ class ElementaryCourseViewModel @Inject constructor( else -> it.htmlUrl ?: "" } - val authenticatedUrl = if (apiPrefs.isStudentView) { - apiPrefs.user?.let { - oauthManager.getAuthenticatedSessionMasqueradingAsync(url, apiPrefs.user!!.id) - .await().dataOrNull?.sessionUrl - } ?: url - } else { - oauthManager.getAuthenticatedSessionAsync(url).await().dataOrNull?.sessionUrl - } + val authenticatedUrl = oauthManager.getAuthenticatedSessionAsync(url).await().dataOrNull?.sessionUrl ElementaryCourseTab(it.tabId, drawable, it.label, authenticatedUrl ?: url) } diff --git a/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/managers/OAuthManager.kt b/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/managers/OAuthManager.kt index dcaaefc643..c14f354dee 100644 --- a/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/managers/OAuthManager.kt +++ b/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/managers/OAuthManager.kt @@ -22,6 +22,7 @@ import com.instructure.canvasapi2.builders.RestBuilder import com.instructure.canvasapi2.builders.RestParams import com.instructure.canvasapi2.models.AuthenticatedSession import com.instructure.canvasapi2.models.OAuthTokenResponse +import com.instructure.canvasapi2.utils.ApiPrefs import com.instructure.canvasapi2.utils.DataResult import com.instructure.canvasapi2.utils.Logger import com.instructure.canvasapi2.utils.weave.apiAsync @@ -53,16 +54,12 @@ object OAuthManager { val adapter = RestBuilder(callback) val params = RestParams(isForceReadFromNetwork = true) Logger.d("targetURL to be authed: $targetUrl") - OAuthAPI.getAuthenticatedSession(targetUrl, params, adapter, callback) - } - - fun getAuthenticatedSessionMasqueradingAsync(targetUrl: String, userId: Long) = apiAsync { getAuthenticatedSessionMasquerading(targetUrl, userId, it) } - - fun getAuthenticatedSessionMasquerading(targetUrl: String, userId: Long, callback: StatusCallback) { - val adapter = RestBuilder(callback) - val params = RestParams(isForceReadFromNetwork = true) - Logger.d("targetURL to be authed: $targetUrl") - OAuthAPI.getAuthenticatedSessionMasquerading(targetUrl, userId, params, adapter, callback) + val userId = ApiPrefs.user?.id + if (ApiPrefs.isMasquerading && userId != null) { + OAuthAPI.getAuthenticatedSessionMasquerading(targetUrl, userId, params, adapter, callback) + } else { + OAuthAPI.getAuthenticatedSession(targetUrl, params, adapter, callback) + } } fun getAuthenticatedSessionSynchronous(targetUrl: String): String? { From 3e946f79dca252dcadb3c56872b37115b3419798 Mon Sep 17 00:00:00 2001 From: domonkosadam <53480952+domonkosadam@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:18:19 +0200 Subject: [PATCH 14/38] [MBL-17945][Student][Parent] Filter hidden New Quizzes in the Grades list (#2591) refs: MBL-17945 affects: Student, Parent release note: Hidden New Quizzes are now not displayed in the Grades list --- .../flutter_parent/lib/models/assignment.dart | 3 + .../lib/models/assignment.g.dart | 30 +++++++- .../courses/details/course_details_model.dart | 2 +- .../features/grades/GradesListRepository.kt | 11 ++- .../grades/GradesListRepositoryTest.kt | 76 ++++++++++++++++++- .../canvasapi2/models/Assignment.kt | 7 +- .../canvasapi2/models/ObserveeAssignment.kt | 10 ++- .../features/grades/GradesViewModel.kt | 3 +- .../utils/AssignmentGroupExtensions.kt | 23 ++++++ .../features/grades/GradesViewModelTest.kt | 60 +++++++++++++++ 10 files changed, 209 insertions(+), 16 deletions(-) create mode 100644 libs/pandautils/src/main/java/com/instructure/pandautils/utils/AssignmentGroupExtensions.kt diff --git a/apps/flutter_parent/lib/models/assignment.dart b/apps/flutter_parent/lib/models/assignment.dart index 3947713bdf..db39f7be6d 100644 --- a/apps/flutter_parent/lib/models/assignment.dart +++ b/apps/flutter_parent/lib/models/assignment.dart @@ -119,6 +119,9 @@ abstract class Assignment implements Built { @BuiltValueField(wireName: 'submission_types') BuiltList? get submissionTypes; + @BuiltValueField(wireName: 'hide_in_gradebook') + bool? get isHiddenInGradeBook; + static void _initializeBuilder(AssignmentBuilder b) => b ..pointsPossible = 0.0 ..useRubricForGrading = false diff --git a/apps/flutter_parent/lib/models/assignment.g.dart b/apps/flutter_parent/lib/models/assignment.g.dart index 4b4ce37fd5..dd5c864e4c 100644 --- a/apps/flutter_parent/lib/models/assignment.g.dart +++ b/apps/flutter_parent/lib/models/assignment.g.dart @@ -248,6 +248,11 @@ class _$AssignmentSerializer implements StructuredSerializer { ..add(serializers.serialize(value, specifiedType: const FullType( BuiltList, const [const FullType(SubmissionTypes)]))); + value = object.isHiddenInGradeBook; + + result + ..add('hide_in_gradebook') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); return result; } @@ -382,6 +387,10 @@ class _$AssignmentSerializer implements StructuredSerializer { BuiltList, const [const FullType(SubmissionTypes)]))! as BuiltList); break; + case 'hide_in_gradebook': + result.isHiddenInGradeBook = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool?; + break; } } @@ -523,6 +532,8 @@ class _$Assignment extends Assignment { final bool isStudioEnabled; @override final BuiltList? submissionTypes; + @override + final bool? isHiddenInGradeBook; factory _$Assignment([void Function(AssignmentBuilder)? updates]) => (new AssignmentBuilder()..update(updates))._build(); @@ -556,7 +567,8 @@ class _$Assignment extends Assignment { required this.moderatedGrading, required this.anonymousGrading, required this.isStudioEnabled, - this.submissionTypes}) + this.submissionTypes, + this.isHiddenInGradeBook}) : super._() { BuiltValueNullFieldError.checkNotNull(id, r'Assignment', 'id'); BuiltValueNullFieldError.checkNotNull( @@ -626,7 +638,8 @@ class _$Assignment extends Assignment { moderatedGrading == other.moderatedGrading && anonymousGrading == other.anonymousGrading && isStudioEnabled == other.isStudioEnabled && - submissionTypes == other.submissionTypes; + submissionTypes == other.submissionTypes && + isHiddenInGradeBook == other.isHiddenInGradeBook; } @override @@ -661,6 +674,7 @@ class _$Assignment extends Assignment { _$hash = $jc(_$hash, anonymousGrading.hashCode); _$hash = $jc(_$hash, isStudioEnabled.hashCode); _$hash = $jc(_$hash, submissionTypes.hashCode); + _$hash = $jc(_$hash, isHiddenInGradeBook.hashCode); _$hash = $jf(_$hash); return _$hash; } @@ -696,7 +710,8 @@ class _$Assignment extends Assignment { ..add('moderatedGrading', moderatedGrading) ..add('anonymousGrading', anonymousGrading) ..add('isStudioEnabled', isStudioEnabled) - ..add('submissionTypes', submissionTypes)) + ..add('submissionTypes', submissionTypes) + ..add('isHiddenInGradeBook', isHiddenInGradeBook)) .toString(); } } @@ -838,6 +853,11 @@ class AssignmentBuilder implements Builder { set submissionTypes(ListBuilder? submissionTypes) => _$this._submissionTypes = submissionTypes; + bool? _isHiddenInGradeBook; + bool? get isHiddenInGradeBook => _$this._isHiddenInGradeBook; + set isHiddenInGradeBook(bool? isHiddenInGradeBook) => + _$this._isHiddenInGradeBook = isHiddenInGradeBook; + AssignmentBuilder() { Assignment._initializeBuilder(this); } @@ -874,6 +894,7 @@ class AssignmentBuilder implements Builder { _anonymousGrading = $v.anonymousGrading; _isStudioEnabled = $v.isStudioEnabled; _submissionTypes = $v.submissionTypes?.toBuilder(); + _isHiddenInGradeBook = $v.isHiddenInGradeBook; _$v = null; } return this; @@ -936,7 +957,8 @@ class AssignmentBuilder implements Builder { moderatedGrading: BuiltValueNullFieldError.checkNotNull(moderatedGrading, r'Assignment', 'moderatedGrading'), anonymousGrading: BuiltValueNullFieldError.checkNotNull(anonymousGrading, r'Assignment', 'anonymousGrading'), isStudioEnabled: BuiltValueNullFieldError.checkNotNull(isStudioEnabled, r'Assignment', 'isStudioEnabled'), - submissionTypes: _submissionTypes?.build()); + submissionTypes: _submissionTypes?.build(), + isHiddenInGradeBook: isHiddenInGradeBook); } catch (_) { late String _$failedField; try { diff --git a/apps/flutter_parent/lib/screens/courses/details/course_details_model.dart b/apps/flutter_parent/lib/screens/courses/details/course_details_model.dart index d51733c091..3e1148424b 100644 --- a/apps/flutter_parent/lib/screens/courses/details/course_details_model.dart +++ b/apps/flutter_parent/lib/screens/courses/details/course_details_model.dart @@ -84,7 +84,7 @@ class CourseDetailsModel extends BaseModel { final groupFuture = _interactor() .loadAssignmentGroups(courseId, student?.id, _nextGradingPeriod?.id, forceRefresh: forceRefresh).then((groups) async { // Remove unpublished assignments to match web - return groups?.map((group) => (group.toBuilder()..assignments.removeWhere((assignment) => !assignment.published)).build()).toList(); + return groups?.map((group) => (group.toBuilder()..assignments.removeWhere((assignment) => !assignment.published || assignment.isHiddenInGradeBook == true)).build()).toList(); }); final gradingPeriodsFuture = diff --git a/apps/student/src/main/java/com/instructure/student/features/grades/GradesListRepository.kt b/apps/student/src/main/java/com/instructure/student/features/grades/GradesListRepository.kt index 75d6c9088a..dfc4555751 100644 --- a/apps/student/src/main/java/com/instructure/student/features/grades/GradesListRepository.kt +++ b/apps/student/src/main/java/com/instructure/student/features/grades/GradesListRepository.kt @@ -17,10 +17,15 @@ package com.instructure.student.features.grades -import com.instructure.canvasapi2.models.* +import com.instructure.canvasapi2.models.AssignmentGroup +import com.instructure.canvasapi2.models.Course +import com.instructure.canvasapi2.models.Enrollment +import com.instructure.canvasapi2.models.GradingPeriod +import com.instructure.canvasapi2.models.Submission import com.instructure.pandautils.repository.Repository import com.instructure.pandautils.utils.FeatureFlagProvider import com.instructure.pandautils.utils.NetworkStateProvider +import com.instructure.pandautils.utils.filterHiddenAssignments import com.instructure.student.features.grades.datasource.GradesListDataSource import com.instructure.student.features.grades.datasource.GradesListLocalDataSource import com.instructure.student.features.grades.datasource.GradesListNetworkDataSource @@ -46,7 +51,7 @@ class GradesListRepository( scopeToStudent: Boolean, forceNetwork: Boolean ): List { - return dataSource().getAssignmentGroupsWithAssignmentsForGradingPeriod(courseId, gradingPeriodId, scopeToStudent, forceNetwork) + return dataSource().getAssignmentGroupsWithAssignmentsForGradingPeriod(courseId, gradingPeriodId, scopeToStudent, forceNetwork).filterHiddenAssignments() } suspend fun getSubmissionsForMultipleAssignments( @@ -79,6 +84,6 @@ class GradesListRepository( courseId: Long, forceNetwork: Boolean, ): List { - return dataSource().getAssignmentGroupsWithAssignments(courseId, forceNetwork) + return dataSource().getAssignmentGroupsWithAssignments(courseId, forceNetwork).filterHiddenAssignments() } } diff --git a/apps/student/src/test/java/com/instructure/student/features/grades/GradesListRepositoryTest.kt b/apps/student/src/test/java/com/instructure/student/features/grades/GradesListRepositoryTest.kt index ca0ade55d9..96b8b54a9d 100644 --- a/apps/student/src/test/java/com/instructure/student/features/grades/GradesListRepositoryTest.kt +++ b/apps/student/src/test/java/com/instructure/student/features/grades/GradesListRepositoryTest.kt @@ -17,8 +17,12 @@ package com.instructure.student.features.grades -import com.instructure.canvasapi2.models.* -import com.instructure.pandautils.utils.FEATURE_FLAG_OFFLINE +import com.instructure.canvasapi2.models.Assignment +import com.instructure.canvasapi2.models.AssignmentGroup +import com.instructure.canvasapi2.models.Course +import com.instructure.canvasapi2.models.Enrollment +import com.instructure.canvasapi2.models.GradingPeriod +import com.instructure.canvasapi2.models.Submission import com.instructure.pandautils.utils.FeatureFlagProvider import com.instructure.pandautils.utils.NetworkStateProvider import com.instructure.student.features.grades.datasource.GradesListLocalDataSource @@ -138,6 +142,40 @@ class GradesListRepositoryTest { assertEquals(offlineExpected, result) } + @Test + fun `Get assignment groups with assignments for grading period if there are hidden assignments and device is online`() = runTest { + val onlineExpected = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3)))) + val onlineResult = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1), Assignment(2, isHiddenInGradeBook = true))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3), Assignment(4, isHiddenInGradeBook = true)))) + val offlineExpected = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7)))) + val offlineResult = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5), Assignment(6, isHiddenInGradeBook = true))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7), Assignment(8, isHiddenInGradeBook = true)))) + + every { networkStateProvider.isOnline() } returns true + coEvery { networkDataSource.getAssignmentGroupsWithAssignmentsForGradingPeriod(any(), any(), any(), any()) } returns onlineResult + coEvery { localDataSource.getAssignmentGroupsWithAssignmentsForGradingPeriod(any(), any(), any(), any()) } returns offlineResult + + val result = repository.getAssignmentGroupsWithAssignmentsForGradingPeriod(1, 1, scopeToStudent = true, forceNetwork = true) + + coVerify { networkDataSource.getAssignmentGroupsWithAssignmentsForGradingPeriod(1, 1, scopeToStudent = true, forceNetwork = true) } + assertEquals(onlineExpected, result) + } + + @Test + fun `Get assignment groups with assignments for grading period if there are hidden assignments and device is offline`() = runTest { + val onlineExpected = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3)))) + val onlineResult = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1), Assignment(2, isHiddenInGradeBook = true))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3), Assignment(4, isHiddenInGradeBook = true)))) + val offlineExpected = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7)))) + val offlineResult = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5), Assignment(6, isHiddenInGradeBook = true))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7), Assignment(8, isHiddenInGradeBook = true)))) + + every { networkStateProvider.isOnline() } returns false + coEvery { networkDataSource.getAssignmentGroupsWithAssignmentsForGradingPeriod(any(), any(), any(), any()) } returns onlineResult + coEvery { localDataSource.getAssignmentGroupsWithAssignmentsForGradingPeriod(any(), any(), any(), any()) } returns offlineResult + + val result = repository.getAssignmentGroupsWithAssignmentsForGradingPeriod(1, 1, scopeToStudent = true, forceNetwork = true) + + coVerify { localDataSource.getAssignmentGroupsWithAssignmentsForGradingPeriod(1, 1, scopeToStudent = true, forceNetwork = true) } + assertEquals(offlineExpected, result) + } + @Test fun `Get submissions for multiple assignments if device is online`() = runTest { val onlineExpected = listOf(Submission(1)) @@ -287,4 +325,38 @@ class GradesListRepositoryTest { coVerify { localDataSource.getAssignmentGroupsWithAssignments(1, true) } assertEquals(offlineExpected, result) } + + @Test + fun `Get assignment groups with assignments if there are hidden assignments and device is online`() = runTest { + val onlineExpected = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3)))) + val onlineResult = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1), Assignment(2, isHiddenInGradeBook = true))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3), Assignment(4, isHiddenInGradeBook = true)))) + val offlineExpected = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7)))) + val offlineResult = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5), Assignment(6, isHiddenInGradeBook = true))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7), Assignment(8, isHiddenInGradeBook = true)))) + + every { networkStateProvider.isOnline() } returns true + coEvery { networkDataSource.getAssignmentGroupsWithAssignments(any(), any()) } returns onlineResult + coEvery { localDataSource.getAssignmentGroupsWithAssignments(any(), any()) } returns offlineResult + + val result = repository.getAssignmentGroupsWithAssignments(1, true) + + coVerify { networkDataSource.getAssignmentGroupsWithAssignments(1, true) } + assertEquals(onlineExpected, result) + } + + @Test + fun `Get assignment groups with assignments if there are hidden assignments and device is offline`() = runTest { + val onlineExpected = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3)))) + val onlineResult = listOf(AssignmentGroup(id = 1, assignments = listOf(Assignment(1), Assignment(2, isHiddenInGradeBook = true))), AssignmentGroup(id = 2, assignments = listOf(Assignment(3), Assignment(4, isHiddenInGradeBook = true)))) + val offlineExpected = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7)))) + val offlineResult = listOf(AssignmentGroup(id = 3, assignments = listOf(Assignment(5), Assignment(6, isHiddenInGradeBook = true))), AssignmentGroup(id = 4, assignments = listOf(Assignment(7), Assignment(8, isHiddenInGradeBook = true)))) + + every { networkStateProvider.isOnline() } returns false + coEvery { networkDataSource.getAssignmentGroupsWithAssignments(any(), any()) } returns onlineResult + coEvery { localDataSource.getAssignmentGroupsWithAssignments(any(), any()) } returns offlineResult + + val result = repository.getAssignmentGroupsWithAssignments(1, true) + + coVerify { localDataSource.getAssignmentGroupsWithAssignments(1, true) } + assertEquals(offlineExpected, result) + } } diff --git a/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/Assignment.kt b/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/Assignment.kt index e6236d28bd..7d39b15a15 100644 --- a/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/Assignment.kt +++ b/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/Assignment.kt @@ -23,7 +23,8 @@ import com.google.gson.annotations.SerializedName import com.instructure.canvasapi2.R import com.instructure.canvasapi2.utils.toDate import kotlinx.parcelize.Parcelize -import java.util.* +import java.util.Date +import java.util.Locale @Parcelize data class Assignment( @@ -112,7 +113,9 @@ data class Assignment( @SerializedName("anonymous_submissions") val anonymousSubmissions: Boolean = false, @SerializedName("omit_from_final_grade") - val omitFromFinalGrade: Boolean = false + val omitFromFinalGrade: Boolean = false, + @SerializedName("hide_in_gradebook") + val isHiddenInGradeBook: Boolean = false ) : CanvasModel() { override val comparisonDate get() = dueDate override val comparisonString get() = dueAt diff --git a/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/ObserveeAssignment.kt b/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/ObserveeAssignment.kt index 9c59384300..c3686240cb 100644 --- a/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/ObserveeAssignment.kt +++ b/libs/canvas-api-2/src/main/java/com/instructure/canvasapi2/models/ObserveeAssignment.kt @@ -97,7 +97,9 @@ data class ObserveeAssignment( val anonymousGrading: Boolean = false, @SerializedName("allowed_attempts") val allowedAttempts: Long = -1, // API gives -1 for unlimited submissions - var isStudioEnabled: Boolean = false + var isStudioEnabled: Boolean = false, + @SerializedName("hide_in_gradebook") + val isHiddenInGradeBook: Boolean = false ) : CanvasModel() { override val comparisonDate get() = dueAt.toDate() override val comparisonString get() = dueAt @@ -150,7 +152,8 @@ data class ObserveeAssignment( moderatedGrading = this.moderatedGrading, anonymousGrading = this.anonymousGrading, allowedAttempts = this.allowedAttempts, - isStudioEnabled = this.isStudioEnabled + isStudioEnabled = this.isStudioEnabled, + isHiddenInGradeBook = this.isHiddenInGradeBook ) } else { return null @@ -200,6 +203,7 @@ data class ObserveeAssignment( moderatedGrading = moderatedGrading, anonymousGrading = anonymousGrading, allowedAttempts = allowedAttempts, - isStudioEnabled = isStudioEnabled + isStudioEnabled = isStudioEnabled, + isHiddenInGradeBook = isHiddenInGradeBook ) } \ No newline at end of file diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/features/grades/GradesViewModel.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/features/grades/GradesViewModel.kt index 530b30ed93..b831e35d3b 100644 --- a/libs/pandautils/src/main/java/com/instructure/pandautils/features/grades/GradesViewModel.kt +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/features/grades/GradesViewModel.kt @@ -31,6 +31,7 @@ import com.instructure.canvasapi2.utils.weave.catch import com.instructure.canvasapi2.utils.weave.tryLaunch import com.instructure.pandautils.R import com.instructure.pandautils.features.grades.gradepreferences.SortBy +import com.instructure.pandautils.utils.filterHiddenAssignments import com.instructure.pandautils.utils.getGrade import com.instructure.pandautils.utils.orDefault import dagger.hilt.android.lifecycle.HiltViewModel @@ -89,7 +90,7 @@ class GradesViewModel @Inject constructor( this@GradesViewModel.course = course val gradingPeriods = repository.loadGradingPeriods(courseId, forceRefresh) val selectedGradingPeriodId = _uiState.value.gradePreferencesUiState.selectedGradingPeriod?.id - val assignmentGroups = repository.loadAssignmentGroups(courseId, selectedGradingPeriodId, forceRefresh) + val assignmentGroups = repository.loadAssignmentGroups(courseId, selectedGradingPeriodId, forceRefresh).filterHiddenAssignments() val enrollments = repository.loadEnrollments(courseId, selectedGradingPeriodId, forceRefresh) courseGrade = repository.getCourseGrade(course, repository.studentId, enrollments, selectedGradingPeriodId) diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/utils/AssignmentGroupExtensions.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/AssignmentGroupExtensions.kt new file mode 100644 index 0000000000..9af9a891e0 --- /dev/null +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/utils/AssignmentGroupExtensions.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2024 - present Instructure, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.instructure.pandautils.utils + +import com.instructure.canvasapi2.models.AssignmentGroup + +fun List.filterHiddenAssignments(): List { + return this.map { it.copy(assignments = it.assignments.filterNot { it.isHiddenInGradeBook }) } +} \ No newline at end of file diff --git a/libs/pandautils/src/test/java/com/instructure/pandautils/features/grades/GradesViewModelTest.kt b/libs/pandautils/src/test/java/com/instructure/pandautils/features/grades/GradesViewModelTest.kt index 4d7cb58d4f..6e16a79f65 100644 --- a/libs/pandautils/src/test/java/com/instructure/pandautils/features/grades/GradesViewModelTest.kt +++ b/libs/pandautils/src/test/java/com/instructure/pandautils/features/grades/GradesViewModelTest.kt @@ -692,6 +692,66 @@ class GradesViewModelTest { Assert.assertEquals(expected, viewModel.uiState.value) } + @Test + fun `Filter hidden grades in Grade list`() { + coEvery { gradesRepository.loadCourse(1, any()) } returns Course(id = 1, name = "Course 1") + coEvery { gradesRepository.loadGradingPeriods(1, any()) } returns emptyList() + coEvery { gradesRepository.loadEnrollments(1, any(), any()) } returns listOf() + coEvery { gradesRepository.loadAssignmentGroups(1, any(), any()) } returns listOf( + AssignmentGroup( + id = 1, + name = "Group 1", + assignments = listOf( + Assignment( + id = 1, + name = "Assignment 1", + submissionTypesRaw = listOf( + SubmissionType.ONLINE_TEXT_ENTRY.rawValue() + ) + ), + Assignment( + id = 2, + name = "Assignment 2", + submissionTypesRaw = listOf( + SubmissionType.ONLINE_TEXT_ENTRY.rawValue() + ), + isHiddenInGradeBook = true + ), + ) + ) + ) + + createViewModel() + + val expected = GradesUiState( + isLoading = false, + canvasContextColor = 1, + gradePreferencesUiState = GradePreferencesUiState( + canvasContextColor = 1, + courseName = "Course 1" + ), + items = listOf( + AssignmentGroupUiState( + id = 2, + name = "Undated Assignments", + expanded = true, + assignments = listOf( + AssignmentUiState( + id = 1, + iconRes = R.drawable.ic_assignment, + name = "Assignment 1", + dueDate = "No due date", + submissionStateLabel = SubmissionStateLabel.NOT_SUBMITTED, + displayGrade = DisplayGrade("") + ) + ) + ) + ) + ) + + Assert.assertEquals(expected, viewModel.uiState.value) + } + private fun createViewModel() { viewModel = GradesViewModel(context, gradesBehaviour, gradesRepository, gradeFormatter, savedStateHandle) } From 411e28f51f033105db317147d82bc5eed91899b4 Mon Sep 17 00:00:00 2001 From: Tamas Kozmer <72397075+tamaskozmer@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:22:36 +0200 Subject: [PATCH 15/38] Remove legacy stuff from repo (#2598) * Removed unused legacy projects. * Updated project README.md * Change git workflow README.md * Updated vault reference. * Moved test users to qa flavor so it won't break the open source build. * Added dummy test users to don't break open source build. * Removed unnecessary Flutter student translations and modified translation file so we won't import those. * Updated vault ref. --- InstrumentationTests/.gitignore | 46 -- InstrumentationTests/app/.gitignore | 46 -- InstrumentationTests/app/build.gradle | 80 --- InstrumentationTests/app/proguard-rules.pro | 17 - .../ExampleInstrumentedTest.java | 42 -- .../app/src/main/AndroidManifest.xml | 30 - .../instrumentationtests/AppManager.java | 23 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3418 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2206 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4842 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7718 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10486 -> 0 bytes .../app/src/main/res/values/colors.xml | 22 - .../app/src/main/res/values/strings.xml | 19 - .../app/src/main/res/values/styles.xml | 27 - .../instrumentationtests/SampleTest.java | 48 -- .../robo/RoboAppManager.java | 32 - .../robo/RoboTestCase.java | 54 -- .../robo/RoboTestRunner.java | 114 ---- .../src/test/resources/robolectric.properties | 17 - InstrumentationTests/build.gradle | 66 -- InstrumentationTests/gradle | 1 - InstrumentationTests/gradlew | 1 - InstrumentationTests/gradlew.bat | 90 --- InstrumentationTests/settings.gradle | 16 - README.md | 34 +- android-vault | 2 +- apps/student/build.gradle | 11 +- apps/teacher/build.gradle | 11 +- docs/git-workflow/README.md | 26 +- foosball/.gitignore | 73 --- foosball/adb_foos.py | 113 ---- foosball/app/.gitignore | 51 -- foosball/app/build.gradle | 129 ---- foosball/app/proguard-rules.pro | 17 - foosball/app/src/main/AndroidManifest.xml | 48 -- .../activities/ChangeAvatarActivity.kt | 288 --------- .../activities/EditUserActivity.kt | 130 ---- .../androidfoosball/utils/Const.kt | 30 - .../androidfoosball/utils/Extensions.kt | 253 -------- .../androidfoosball/utils/PrefUtils.kt | 62 -- .../androidfoosball/views/ConfirmPinDialog.kt | 189 ------ .../androidfoosball/views/CropOverlay.kt | 109 ---- .../androidfoosball/views/PinButton.kt | 72 --- .../androidfoosball/views/PinPad.kt | 41 -- .../views/UserInitialsDrawable.kt | 62 -- .../ic_arrow_back_grey_700_36dp.png | Bin 267 -> 0 bytes .../ic_backspace_grey_500_48dp.png | Bin 685 -> 0 bytes .../res/drawable-hdpi/ic_close_white_48dp.png | Bin 462 -> 0 bytes .../src/main/res/drawable-hdpi/sadpanda.png | Bin 27917 -> 0 bytes .../ic_arrow_back_grey_700_36dp.png | Bin 212 -> 0 bytes .../ic_backspace_grey_500_48dp.png | Bin 485 -> 0 bytes .../res/drawable-mdpi/ic_close_white_48dp.png | Bin 329 -> 0 bytes .../src/main/res/drawable-mdpi/sadpanda.png | Bin 22255 -> 0 bytes .../ic_arrow_back_grey_700_36dp.png | Bin 374 -> 0 bytes .../ic_backspace_grey_500_48dp.png | Bin 910 -> 0 bytes .../drawable-xhdpi/ic_close_white_48dp.png | Bin 601 -> 0 bytes .../src/main/res/drawable-xhdpi/sadpanda.png | Bin 47026 -> 0 bytes .../ic_arrow_back_grey_700_36dp.png | Bin 409 -> 0 bytes .../ic_backspace_grey_500_48dp.png | Bin 1358 -> 0 bytes .../drawable-xxhdpi/ic_close_white_48dp.png | Bin 865 -> 0 bytes .../src/main/res/drawable-xxhdpi/sadpanda.png | Bin 76943 -> 0 bytes .../ic_arrow_back_grey_700_36dp.png | Bin 537 -> 0 bytes .../ic_backspace_grey_500_48dp.png | Bin 1796 -> 0 bytes .../drawable-xxxhdpi/ic_close_white_48dp.png | Bin 1026 -> 0 bytes .../main/res/drawable/light_gray_circle.xml | 24 - .../main/res/drawable/vd_add_black_24dp.xml | 4 - .../res/drawable/vd_group_add_white_48dp.xml | 4 - .../res/drawable/vd_search_black_24dp.xml | 4 - .../drawable/vd_volume_up_grey_500_18dp.xml | 4 - .../res/layout/activity_change_avatar.xml | 99 --- .../main/res/layout/activity_edit_player.xml | 202 ------- .../src/main/res/layout/adapter_foos_rank.xml | 102 ---- .../main/res/layout/adapter_time_waster.xml | 110 ---- .../main/res/layout/dialog_confirm_pin.xml | 102 ---- .../main/res/layout/dialog_team_picker.xml | 73 --- .../main/res/layout/dialog_user_picker.xml | 73 --- .../app/src/main/res/layout/view_pin_pad.xml | 91 --- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 4942 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 3031 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 6979 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 10988 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 15643 -> 0 bytes .../app/src/main/res/values-w820dp/dimens.xml | 25 - foosball/app/src/main/res/values/attrs.xml | 45 -- foosball/app/src/main/res/values/colors.xml | 30 - foosball/app/src/main/res/values/dimens.xml | 27 - foosball/app/src/main/res/values/strings.xml | 143 ----- foosball/app/src/main/res/values/styles.xml | 59 -- foosball/app/src/main/res/xml/file_paths.xml | 24 - foosball/app/src/phone/AndroidManifest.xml | 100 ---- .../activities/BaseFireBaseActivity.kt | 53 -- .../activities/NfcReadActivity.kt | 155 ----- .../activities/PrimaryActivity.kt | 205 ------- .../activities/SignInActivity.kt | 208 ------- .../adapters/TableFireRecyclerAdapter.kt | 49 -- .../decorators/SpacesItemDecoration.kt | 44 -- .../fragments/TableFragment.kt | 69 --- .../androidfoosball/fragments/UserFragment.kt | 171 ------ .../holders/TableViewHolder.kt | 133 ---- .../interfaces/FragmentCallbacks.kt | 30 - .../interfaces/TextEditCallback.kt | 25 - .../androidfoosball/ktmodels/User.kt | 36 -- .../androidfoosball/models/Game.kt | 29 - .../androidfoosball/models/Table.kt | 42 -- .../androidfoosball/models/TableTeam.kt | 30 - .../androidfoosball/models/Team.kt | 31 - .../androidfoosball/models/User.kt | 33 - .../FireBasePushNotificationService.kt | 92 --- .../androidfoosball/utils/AnimUtils.kt | 67 --- .../androidfoosball/utils/Commentator.kt | 34 -- .../androidfoosball/utils/FireUtils.kt | 99 --- .../androidfoosball/utils/Prefs.kt | 27 - .../androidfoosball/wear/WearService.kt | 87 --- .../res/drawable-hdpi/ic_check_white_48dp.png | Bin 426 -> 0 bytes .../res/drawable-hdpi/ic_close_white_48dp.png | Bin 462 -> 0 bytes .../res/drawable-hdpi/ic_shortcut_tables.png | Bin 1720 -> 0 bytes .../drawable-hdpi/ic_status_notification.png | Bin 885 -> 0 bytes .../src/phone/res/drawable-hdpi/sadpanda.png | Bin 27917 -> 0 bytes .../res/drawable-mdpi/ic_check_white_48dp.png | Bin 297 -> 0 bytes .../res/drawable-mdpi/ic_close_white_48dp.png | Bin 329 -> 0 bytes .../res/drawable-mdpi/ic_shortcut_tables.png | Bin 1187 -> 0 bytes .../drawable-mdpi/ic_status_notification.png | Bin 576 -> 0 bytes .../src/phone/res/drawable-mdpi/sadpanda.png | Bin 22255 -> 0 bytes .../drawable-xhdpi/ic_check_white_48dp.png | Bin 516 -> 0 bytes .../drawable-xhdpi/ic_close_white_48dp.png | Bin 601 -> 0 bytes .../res/drawable-xhdpi/ic_shortcut_tables.png | Bin 2231 -> 0 bytes .../drawable-xhdpi/ic_status_notification.png | Bin 1060 -> 0 bytes .../src/phone/res/drawable-xhdpi/sadpanda.png | Bin 47026 -> 0 bytes .../drawable-xxhdpi/ic_check_white_48dp.png | Bin 645 -> 0 bytes .../drawable-xxhdpi/ic_close_white_48dp.png | Bin 865 -> 0 bytes .../drawable-xxhdpi/ic_shortcut_tables.png | Bin 3383 -> 0 bytes .../ic_status_notification.png | Bin 1789 -> 0 bytes .../phone/res/drawable-xxhdpi/sadpanda.png | Bin 76943 -> 0 bytes .../drawable-xxxhdpi/ic_check_white_48dp.png | Bin 860 -> 0 bytes .../drawable-xxxhdpi/ic_close_white_48dp.png | Bin 1026 -> 0 bytes .../drawable-xxxhdpi/ic_shortcut_tables.png | Bin 4442 -> 0 bytes .../ic_status_notification.png | Bin 2788 -> 0 bytes .../vd_check_circle_green_800_24dp.xml | 4 - .../app/src/phone/res/drawable/vd_done.xml | 14 - .../app/src/phone/res/drawable/vd_edit.xml | 14 - .../res/drawable/vd_person_add_black.xml | 4 - .../layout/activity_leaderboard_tablet.xml | 30 - .../phone/res/layout/activity_main_tablet.xml | 290 --------- .../phone/res/layout/activity_nfc_read.xml | 171 ------ .../src/phone/res/layout/activity_primary.xml | 93 --- .../src/phone/res/layout/activity_sign_in.xml | 31 - .../res/layout/adapter_leaderboard_tablet.xml | 62 -- .../src/phone/res/layout/adapter_table.xml | 306 ---------- .../phone/res/layout/adapter_user_dialog.xml | 45 -- .../src/phone/res/layout/fragment_tables.xml | 30 - .../src/phone/res/layout/fragment_user.xml | 288 --------- .../app/src/phone/res/menu/menu_logout.xml | 31 - .../src/phone/res/mipmap-hdpi/ic_launcher.png | Bin 4942 -> 0 bytes .../src/phone/res/mipmap-mdpi/ic_launcher.png | Bin 3031 -> 0 bytes .../phone/res/mipmap-xhdpi/ic_launcher.png | Bin 6979 -> 0 bytes .../phone/res/mipmap-xxhdpi/ic_launcher.png | Bin 10988 -> 0 bytes .../phone/res/mipmap-xxxhdpi/ic_launcher.png | Bin 15643 -> 0 bytes .../src/phone/res/values-w820dp/dimens.xml | 25 - foosball/app/src/phone/res/values/colors.xml | 29 - foosball/app/src/phone/res/values/dimens.xml | 28 - foosball/app/src/phone/res/values/strings.xml | 66 -- foosball/app/src/phone/res/values/styles.xml | 50 -- .../app/src/phone/res/xml-v25/shortcuts.xml | 18 - foosball/app/src/tablet/AndroidManifest.xml | 88 --- .../com/instructure/androidfoosball/App.kt | 52 -- .../activities/CreateCutThroatGameActivity.kt | 166 ----- .../activities/CreateGameActivity.kt | 257 -------- .../activities/CreatePlayerActivity.kt | 101 ---- .../activities/CreateTableKingGameActivity.kt | 147 ----- .../CreateTeamTwisterGameActivity.kt | 147 ----- .../activities/CutThroatGameActivity.kt | 211 ------- .../activities/EloDialogActivity.kt | 56 -- .../activities/GameActivity.kt | 395 ------------ .../activities/LeaderboardActivity.kt | 218 ------- .../activities/MainActivity.kt | 167 ------ .../activities/SyncActivity.kt | 123 ---- .../activities/TableKingGameActivity.kt | 222 ------- .../activities/TeamTwisterGameActivity.kt | 209 ------- .../adapters/FoosRankLeaderboardAdapter.kt | 45 -- .../adapters/LeaderboardAdapter.kt | 40 -- .../androidfoosball/adapters/TeamAdapter.kt | 65 -- .../adapters/TeamLeaderboardAdapter.kt | 40 -- .../adapters/TimeWasterLeaderboardAdapter.kt | 50 -- .../androidfoosball/adapters/UserAdapter.kt | 77 --- .../holders/FoosRankViewHolder.kt | 40 -- .../holders/LeaderboardViewHolder.kt | 43 -- .../holders/TeamLeaderboardViewHolder.kt | 53 -- .../holders/TimeWasterViewHolder.kt | 39 -- .../androidfoosball/ktmodels/CustomTeam.kt | 50 -- .../androidfoosball/ktmodels/CutThroatGame.kt | 40 -- .../ktmodels/CutThroatPlayer.kt | 24 - .../androidfoosball/ktmodels/Game.kt | 88 --- .../androidfoosball/ktmodels/GameStatus.kt | 23 - .../androidfoosball/ktmodels/Goal.kt | 24 - .../androidfoosball/ktmodels/ITeam.kt | 42 -- .../androidfoosball/ktmodels/IncomingData.kt | 24 - .../androidfoosball/ktmodels/Round.kt | 65 -- .../androidfoosball/ktmodels/Table.kt | 48 -- .../androidfoosball/ktmodels/TableKingGame.kt | 80 --- .../androidfoosball/ktmodels/TableSide.kt | 25 - .../androidfoosball/ktmodels/Team.kt | 25 - .../ktmodels/TeamTwisterGame.kt | 74 --- .../ktmodels/TeamWithPoints.kt | 28 - .../androidfoosball/ktmodels/User.kt | 42 -- .../androidfoosball/push/PushIntentService.kt | 76 --- .../androidfoosball/receivers/GoalReceiver.kt | 57 -- .../services/FoosballSyncService.kt | 194 ------ .../androidfoosball/utils/Commentator.kt | 385 ------------ .../androidfoosball/utils/Prefs.kt | 25 - .../androidfoosball/utils/QRView.kt | 72 --- .../androidfoosball/utils/RankingUtils.kt | 74 --- .../androidfoosball/utils/TabletExtensions.kt | 164 ----- .../androidfoosball/views/CountdownCircle.kt | 91 --- .../views/CutThroatPlayerView.kt | 51 -- .../views/CutThroatPlayersLayout.kt | 129 ---- .../androidfoosball/views/EloGraphView.kt | 200 ------- .../androidfoosball/views/GameTimer.kt | 77 --- .../androidfoosball/views/PlayerView.kt | 53 -- .../androidfoosball/views/PlayersLayout.kt | 133 ---- .../views/TableRequestedDialog.kt | 87 --- .../androidfoosball/views/TeamLayout.kt | 148 ----- .../views/WinCutThroatGameDialog.kt | 109 ---- .../androidfoosball/views/WinGameDialog.kt | 122 ---- .../androidfoosball/views/WinRoundDialog.kt | 108 ---- .../views/WinTableKingGameDialog.kt | 106 ---- .../views/WinTeamTwisterGameDialog.kt | 85 --- .../res/drawable-hdpi/ic_check_blue_48dp.png | Bin 429 -> 0 bytes .../drawable-hdpi/ic_stars_amber_400_36dp.png | Bin 907 -> 0 bytes .../res/drawable-hdpi/ic_undo_black_24dp.png | Bin 322 -> 0 bytes .../res/drawable-mdpi/ic_check_blue_48dp.png | Bin 300 -> 0 bytes .../drawable-mdpi/ic_stars_amber_400_36dp.png | Bin 624 -> 0 bytes .../res/drawable-mdpi/ic_undo_black_24dp.png | Bin 223 -> 0 bytes .../res/drawable-xhdpi/ic_check_blue_48dp.png | Bin 519 -> 0 bytes .../ic_stars_amber_400_36dp.png | Bin 1217 -> 0 bytes .../res/drawable-xhdpi/ic_undo_black_24dp.png | Bin 395 -> 0 bytes .../drawable-xxhdpi/ic_check_blue_48dp.png | Bin 653 -> 0 bytes .../ic_stars_amber_400_36dp.png | Bin 1896 -> 0 bytes .../drawable-xxhdpi/ic_undo_black_24dp.png | Bin 566 -> 0 bytes .../drawable-xxxhdpi/ic_check_blue_48dp.png | Bin 864 -> 0 bytes .../ic_stars_amber_400_36dp.png | Bin 2540 -> 0 bytes .../drawable-xxxhdpi/ic_undo_black_24dp.png | Bin 752 -> 0 bytes .../res/drawable/bg_serving_indicator.xml | 26 - .../drawable/circle_outline_blue_medium.xml | 26 - .../drawable/circle_outline_medium_white.xml | 26 - .../drawable/circle_outline_red_medium.xml | 26 - .../res/drawable/circle_outline_thin.xml | 27 - .../src/tablet/res/drawable/circle_white.xml | 24 - .../res/drawable/vd_person_add_black.xml | 4 - .../res/drawable/vd_person_add_white_24dp.xml | 4 - .../res/drawable/vd_star_amber_a400_48dp.xml | 4 - .../drawable/vd_swap_horiz_accent_48dp.xml | 4 - .../app/src/tablet/res/drawable/vd_trophy.xml | 59 -- .../activity_create_cut_throat_game.xml | 227 ------- .../res/layout/activity_create_game.xml | 298 --------- .../res/layout/activity_create_player.xml | 143 ----- .../activity_create_table_king_game.xml | 185 ------ .../activity_create_team_twister_game.xml | 185 ------ .../tablet/res/layout/activity_elo_layout.xml | 87 --- .../layout/activity_foos_rank_leaderboard.xml | 77 --- .../src/tablet/res/layout/activity_game.xml | 478 --------------- .../res/layout/activity_game_cut_throat.xml | 243 -------- .../res/layout/activity_leaderboard.xml | 285 --------- .../src/tablet/res/layout/activity_main.xml | 205 ------- .../src/tablet/res/layout/activity_sync.xml | 39 -- .../res/layout/activity_table_king_game.xml | 345 ----------- .../res/layout/activity_team_twister_game.xml | 345 ----------- .../tablet/res/layout/adapter_leaderboard.xml | 115 ---- .../tablet/res/layout/adapter_team_dialog.xml | 50 -- .../res/layout/adapter_team_leaderboard.xml | 126 ---- .../tablet/res/layout/adapter_user_dialog.xml | 46 -- .../res/layout/dialog_table_requested.xml | 158 ----- .../src/tablet/res/layout/dialog_win_game.xml | 215 ------- .../res/layout/dialog_win_game_cut_throat.xml | 146 ----- .../tablet/res/layout/dialog_win_round.xml | 184 ------ .../res/layout/dialog_win_table_king.xml | 136 ----- .../res/layout/dialog_win_team_twister.xml | 295 --------- .../tablet/res/layout/elo_dialog_layout.xml | 30 - .../res/layout/layout_cut_throat_players.xml | 57 -- .../src/tablet/res/layout/layout_players.xml | 57 -- .../res/layout/view_cut_throat_player.xml | 64 -- .../app/src/tablet/res/layout/view_player.xml | 64 -- .../tablet/res/layout/view_team_layout.xml | 117 ---- .../res/layout/view_team_layout_vertical.xml | 120 ---- .../src/tablet/res/values-w820dp/dimens.xml | 25 - foosball/app/src/tablet/res/values/attrs.xml | 22 - foosball/app/src/tablet/res/values/dimens.xml | 24 - .../app/src/tablet/res/values/strings.xml | 20 - foosball/build.gradle | 61 -- foosball/buildSrc/.gitignore | 1 - foosball/buildSrc/build.gradle.kts | 1 - foosball/buildSrc/src | 1 - foosball/gradle | 1 - foosball/gradlew | 1 - foosball/settings.gradle | 20 - foosball/wear/.gitignore | 1 - foosball/wear/build.gradle | 53 -- foosball/wear/proguard-rules.pro | 17 - foosball/wear/src/main/AndroidManifest.xml | 53 -- .../androidfoosball/wear/TableCardFragment.kt | 56 -- .../androidfoosball/wear/WearActivity.kt | 185 ------ .../wear/WinLossCardFragment.kt | 57 -- .../src/main/res/layout/activity_wear.xml | 31 - .../src/main/res/layout/fragment_table.xml | 61 -- .../src/main/res/layout/fragment_win_loss.xml | 61 -- .../main/res/layout/rect_activity_wear.xml | 41 -- .../main/res/layout/round_activity_wear.xml | 41 -- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 5233 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 3231 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 7548 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 12103 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 17779 -> 0 bytes foosball/wear/src/main/res/values/dimens.xml | 23 - foosball/wear/src/main/res/values/strings.xml | 31 - foosball/wear/src/main/res/values/styles.xml | 30 - foosball/wearutils/.gitignore | 1 - foosball/wearutils/build.gradle | 59 -- foosball/wearutils/proguard-rules.pro | 17 - .../wearutils/ExampleInstrumentedTest.kt | 46 -- .../wearutils/src/main/AndroidManifest.xml | 28 - .../com/instructure/wearutils/WearClient.kt | 186 ------ .../com/instructure/wearutils/WearConst.kt | 30 - .../wearutils/interfaces/DataReceived.kt | 25 - .../wearutils/interfaces/DataRequest.kt | 25 - .../wearutils/interfaces/WearableCallbacks.kt | 28 - .../instructure/wearutils/models/DataPage.kt | 73 --- .../instructure/wearutils/models/DataRow.kt | 40 -- .../wearutils/services/BaseWearService.kt | 104 ---- .../drawable-hdpi/ic_foosball_watermark.png | Bin 9285 -> 0 bytes .../ic_foosball_watermark_small.png | Bin 1732 -> 0 bytes .../drawable-mdpi/ic_foosball_watermark.png | Bin 5375 -> 0 bytes .../ic_foosball_watermark_small.png | Bin 1099 -> 0 bytes .../drawable-xhdpi/ic_foosball_watermark.png | Bin 13789 -> 0 bytes .../ic_foosball_watermark_small.png | Bin 2337 -> 0 bytes .../drawable-xxhdpi/ic_foosball_watermark.png | Bin 21018 -> 0 bytes .../ic_foosball_watermark_small.png | Bin 3746 -> 0 bytes .../ic_foosball_watermark.png | Bin 33758 -> 0 bytes .../ic_foosball_watermark_small.png | Bin 5429 -> 0 bytes .../src/main/res/drawable/page_bg_1.xml | 25 - .../src/main/res/drawable/page_bg_2.xml | 25 - .../wearutils/src/main/res/values/colors.xml | 29 - .../wearutils/src/main/res/values/strings.xml | 22 - .../instructure/wearutils/ExampleUnitTest.kt | 37 -- .../lib/l10n/res/intl_ar.arb | 460 -------------- .../lib/l10n/res/intl_ca.arb | 460 -------------- .../lib/l10n/res/intl_cy.arb | 460 -------------- .../lib/l10n/res/intl_da.arb | 460 -------------- .../lib/l10n/res/intl_da_instk12.arb | 460 -------------- .../lib/l10n/res/intl_de.arb | 460 -------------- .../lib/l10n/res/intl_en_AU.arb | 460 -------------- .../lib/l10n/res/intl_en_AU_unimelb.arb | 460 -------------- .../lib/l10n/res/intl_en_CA.arb | 447 -------------- .../lib/l10n/res/intl_en_CY.arb | 460 -------------- .../lib/l10n/res/intl_en_GB.arb | 460 -------------- .../lib/l10n/res/intl_en_GB_instukhe.arb | 460 -------------- .../lib/l10n/res/intl_es.arb | 460 -------------- .../lib/l10n/res/intl_es_ES.arb | 460 -------------- .../lib/l10n/res/intl_fi.arb | 460 -------------- .../lib/l10n/res/intl_fr.arb | 460 -------------- .../lib/l10n/res/intl_fr_CA.arb | 460 -------------- .../lib/l10n/res/intl_ga.arb | 460 -------------- .../lib/l10n/res/intl_hi.arb | 460 -------------- .../lib/l10n/res/intl_ht.arb | 460 -------------- .../lib/l10n/res/intl_id.arb | 460 -------------- .../lib/l10n/res/intl_is.arb | 460 -------------- .../lib/l10n/res/intl_it.arb | 460 -------------- .../lib/l10n/res/intl_ja.arb | 460 -------------- .../lib/l10n/res/intl_mi.arb | 460 -------------- .../lib/l10n/res/intl_ms.arb | 460 -------------- .../lib/l10n/res/intl_nb.arb | 460 -------------- .../lib/l10n/res/intl_nb_instk12.arb | 460 -------------- .../lib/l10n/res/intl_nl.arb | 460 -------------- .../lib/l10n/res/intl_pl.arb | 460 -------------- .../lib/l10n/res/intl_pt_BR.arb | 460 -------------- .../lib/l10n/res/intl_pt_PT.arb | 460 -------------- .../lib/l10n/res/intl_ru.arb | 460 -------------- .../lib/l10n/res/intl_sl.arb | 460 -------------- .../lib/l10n/res/intl_sv.arb | 460 -------------- .../lib/l10n/res/intl_sv_instk12.arb | 460 -------------- .../lib/l10n/res/intl_th.arb | 460 -------------- .../lib/l10n/res/intl_vi.arb | 460 -------------- .../lib/l10n/res/intl_zh.arb | 460 -------------- .../lib/l10n/res/intl_zh_HK.arb | 460 -------------- .../lib/l10n/res/intl_zh_Hans.arb | 460 -------------- .../lib/l10n/res/intl_zh_Hant.arb | 460 -------------- open_source_data/student/private.properties | 8 + open_source_data/teacher/private.properties | 8 + refooz_2_lose/.gitignore | 13 - refooz_2_lose/.metadata | 8 - refooz_2_lose/BarcodeScanPlugin/CHANGELOG.md | 13 - refooz_2_lose/BarcodeScanPlugin/README.md | 35 -- .../BarcodeScanPlugin/android/.gitignore | 8 - .../BarcodeScanPlugin/android/build.gradle | 51 -- .../android/gradle.properties | 1 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../BarcodeScanPlugin/android/gradlew | 160 ----- .../BarcodeScanPlugin/android/gradlew.bat | 90 --- .../BarcodeScanPlugin/android/settings.gradle | 1 - .../android/src/main/AndroidManifest.xml | 3 - .../barcodescan/BarcodeScanPlugin.kt | 52 -- .../barcodescan/BarcodeScannerActivity.kt | 107 ---- .../BarcodeScanPlugin/ios/.gitignore | 31 - .../BarcodeScanPlugin/ios/Assets/.gitkeep | 0 .../ios/Classes/BarcodeScanPlugin.h | 9 - .../ios/Classes/BarcodeScanPlugin.m | 43 -- .../Classes/BarcodeScannerViewController.h | 16 - .../Classes/BarcodeScannerViewController.m | 126 ---- .../BarcodeScannerViewControllerDelegate.h | 14 - .../ios/barcode_scan.podspec | 21 - .../BarcodeScanPlugin/lib/barcode_scan.dart | 10 - refooz_2_lose/BarcodeScanPlugin/pubspec.yaml | 49 -- refooz_2_lose/README.md | 8 - refooz_2_lose/android/.gitignore | 10 - refooz_2_lose/android/app/build.gradle | 67 --- .../android/app/google-services.json | 144 ----- .../android/app/src/main/AndroidManifest.xml | 59 -- .../instructure/refooz2lose/MainActivity.kt | 48 -- .../main/res/drawable/launch_background.xml | 12 - .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 4942 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 3031 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 6979 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 10988 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 15643 -> 0 bytes .../app/src/main/res/values/styles.xml | 14 - refooz_2_lose/android/build.gradle | 32 - refooz_2_lose/android/debug.keystore | Bin 1268 -> 0 bytes refooz_2_lose/android/gradle.properties | 1 - .../android/gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - refooz_2_lose/android/gradlew | 160 ----- refooz_2_lose/android/gradlew.bat | 90 --- refooz_2_lose/android/settings.gradle | 15 - refooz_2_lose/images/sad_panda.png | Bin 76943 -> 0 bytes refooz_2_lose/ios/.gitignore | 42 -- .../ios/Flutter/AppFrameworkInfo.plist | 30 - refooz_2_lose/ios/Flutter/Debug.xcconfig | 2 - refooz_2_lose/ios/Flutter/Release.xcconfig | 2 - refooz_2_lose/ios/Podfile | 78 --- refooz_2_lose/ios/Podfile.lock | 159 ----- .../ios/Runner.xcodeproj/project.pbxproj | 566 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/xcschemes/Runner.xcscheme | 93 --- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - refooz_2_lose/ios/Runner/AppDelegate.swift | 13 - .../AppIcon.appiconset/Contents.json | 122 ---- .../Icon-App-1024x1024@1x.png | Bin 11112 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 564 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 1588 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 1025 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 1716 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 1920 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 1283 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 1895 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 2665 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 3831 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 1888 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 3294 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 3612 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 -- .../ios/Runner/Base.lproj/Main.storyboard | 26 - .../ios/Runner/GoogleService-Info.plist | 40 -- refooz_2_lose/ios/Runner/Info.plist | 67 --- .../ios/Runner/Runner-Bridging-Header.h | 1 - refooz_2_lose/ios/Runner/Runner.entitlements | 5 - refooz_2_lose/lib/main.dart | 238 -------- refooz_2_lose/lib/models/FoozTable.dart | 71 --- refooz_2_lose/lib/pages/assignment_page.dart | 123 ---- refooz_2_lose/lib/pages/login_page.dart | 101 ---- refooz_2_lose/lib/pages/tables_page.dart | 49 -- refooz_2_lose/lib/pages/user_page.dart | 74 --- refooz_2_lose/lib/ui/ColorParser.dart | 41 -- refooz_2_lose/lib/ui/FoozTheme.dart | 47 -- refooz_2_lose/lib/widgets/TableTile.dart | 225 ------- .../lib/widgets/user_header_widget.dart | 128 ---- .../lib/widgets/user_message_widget.dart | 126 ---- refooz_2_lose/pubspec.yaml | 66 -- refooz_2_lose/test/widget_test.dart | 29 - training/README.md | 35 -- translations/projects.json | 7 - 488 files changed, 48 insertions(+), 44138 deletions(-) delete mode 100644 InstrumentationTests/.gitignore delete mode 100644 InstrumentationTests/app/.gitignore delete mode 100644 InstrumentationTests/app/build.gradle delete mode 100644 InstrumentationTests/app/proguard-rules.pro delete mode 100644 InstrumentationTests/app/src/androidTest/java/instructure/instrumentationtests/ExampleInstrumentedTest.java delete mode 100644 InstrumentationTests/app/src/main/AndroidManifest.xml delete mode 100644 InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java delete mode 100644 InstrumentationTests/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 InstrumentationTests/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 InstrumentationTests/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 InstrumentationTests/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 InstrumentationTests/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 InstrumentationTests/app/src/main/res/values/colors.xml delete mode 100644 InstrumentationTests/app/src/main/res/values/strings.xml delete mode 100644 InstrumentationTests/app/src/main/res/values/styles.xml delete mode 100644 InstrumentationTests/app/src/test/java/instructure/instrumentationtests/SampleTest.java delete mode 100644 InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboAppManager.java delete mode 100644 InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java delete mode 100644 InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestRunner.java delete mode 100644 InstrumentationTests/app/src/test/resources/robolectric.properties delete mode 100644 InstrumentationTests/build.gradle delete mode 120000 InstrumentationTests/gradle delete mode 120000 InstrumentationTests/gradlew delete mode 100644 InstrumentationTests/gradlew.bat delete mode 100644 InstrumentationTests/settings.gradle delete mode 100644 foosball/.gitignore delete mode 100644 foosball/adb_foos.py delete mode 100644 foosball/app/.gitignore delete mode 100644 foosball/app/build.gradle delete mode 100644 foosball/app/proguard-rules.pro delete mode 100644 foosball/app/src/main/AndroidManifest.xml delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/activities/ChangeAvatarActivity.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/activities/EditUserActivity.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/utils/Const.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/utils/Extensions.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/utils/PrefUtils.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/views/ConfirmPinDialog.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/views/CropOverlay.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/views/PinButton.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/views/PinPad.kt delete mode 100644 foosball/app/src/main/java/com/instructure/androidfoosball/views/UserInitialsDrawable.kt delete mode 100644 foosball/app/src/main/res/drawable-hdpi/ic_arrow_back_grey_700_36dp.png delete mode 100644 foosball/app/src/main/res/drawable-hdpi/ic_backspace_grey_500_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-hdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-hdpi/sadpanda.png delete mode 100644 foosball/app/src/main/res/drawable-mdpi/ic_arrow_back_grey_700_36dp.png delete mode 100644 foosball/app/src/main/res/drawable-mdpi/ic_backspace_grey_500_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-mdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-mdpi/sadpanda.png delete mode 100644 foosball/app/src/main/res/drawable-xhdpi/ic_arrow_back_grey_700_36dp.png delete mode 100644 foosball/app/src/main/res/drawable-xhdpi/ic_backspace_grey_500_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-xhdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-xhdpi/sadpanda.png delete mode 100644 foosball/app/src/main/res/drawable-xxhdpi/ic_arrow_back_grey_700_36dp.png delete mode 100644 foosball/app/src/main/res/drawable-xxhdpi/ic_backspace_grey_500_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-xxhdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-xxhdpi/sadpanda.png delete mode 100644 foosball/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_grey_700_36dp.png delete mode 100644 foosball/app/src/main/res/drawable-xxxhdpi/ic_backspace_grey_500_48dp.png delete mode 100644 foosball/app/src/main/res/drawable-xxxhdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/main/res/drawable/light_gray_circle.xml delete mode 100644 foosball/app/src/main/res/drawable/vd_add_black_24dp.xml delete mode 100644 foosball/app/src/main/res/drawable/vd_group_add_white_48dp.xml delete mode 100644 foosball/app/src/main/res/drawable/vd_search_black_24dp.xml delete mode 100644 foosball/app/src/main/res/drawable/vd_volume_up_grey_500_18dp.xml delete mode 100644 foosball/app/src/main/res/layout/activity_change_avatar.xml delete mode 100644 foosball/app/src/main/res/layout/activity_edit_player.xml delete mode 100644 foosball/app/src/main/res/layout/adapter_foos_rank.xml delete mode 100644 foosball/app/src/main/res/layout/adapter_time_waster.xml delete mode 100644 foosball/app/src/main/res/layout/dialog_confirm_pin.xml delete mode 100644 foosball/app/src/main/res/layout/dialog_team_picker.xml delete mode 100644 foosball/app/src/main/res/layout/dialog_user_picker.xml delete mode 100644 foosball/app/src/main/res/layout/view_pin_pad.xml delete mode 100755 foosball/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100755 foosball/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100755 foosball/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100755 foosball/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100755 foosball/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 foosball/app/src/main/res/values-w820dp/dimens.xml delete mode 100644 foosball/app/src/main/res/values/attrs.xml delete mode 100644 foosball/app/src/main/res/values/colors.xml delete mode 100644 foosball/app/src/main/res/values/dimens.xml delete mode 100644 foosball/app/src/main/res/values/strings.xml delete mode 100644 foosball/app/src/main/res/values/styles.xml delete mode 100644 foosball/app/src/main/res/xml/file_paths.xml delete mode 100644 foosball/app/src/phone/AndroidManifest.xml delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/activities/BaseFireBaseActivity.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/activities/NfcReadActivity.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/activities/PrimaryActivity.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/activities/SignInActivity.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/adapters/TableFireRecyclerAdapter.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/decorators/SpacesItemDecoration.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/TableFragment.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/UserFragment.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/holders/TableViewHolder.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/FragmentCallbacks.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/TextEditCallback.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/ktmodels/User.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/models/Game.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/models/Table.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/models/TableTeam.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/models/Team.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/models/User.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/services/FireBasePushNotificationService.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/utils/AnimUtils.kt delete mode 100755 foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Commentator.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/utils/FireUtils.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Prefs.kt delete mode 100644 foosball/app/src/phone/java/com/instructure/androidfoosball/wear/WearService.kt delete mode 100644 foosball/app/src/phone/res/drawable-hdpi/ic_check_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-hdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-hdpi/ic_shortcut_tables.png delete mode 100755 foosball/app/src/phone/res/drawable-hdpi/ic_status_notification.png delete mode 100644 foosball/app/src/phone/res/drawable-hdpi/sadpanda.png delete mode 100644 foosball/app/src/phone/res/drawable-mdpi/ic_check_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-mdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-mdpi/ic_shortcut_tables.png delete mode 100755 foosball/app/src/phone/res/drawable-mdpi/ic_status_notification.png delete mode 100644 foosball/app/src/phone/res/drawable-mdpi/sadpanda.png delete mode 100644 foosball/app/src/phone/res/drawable-xhdpi/ic_check_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-xhdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-xhdpi/ic_shortcut_tables.png delete mode 100755 foosball/app/src/phone/res/drawable-xhdpi/ic_status_notification.png delete mode 100644 foosball/app/src/phone/res/drawable-xhdpi/sadpanda.png delete mode 100644 foosball/app/src/phone/res/drawable-xxhdpi/ic_check_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-xxhdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-xxhdpi/ic_shortcut_tables.png delete mode 100755 foosball/app/src/phone/res/drawable-xxhdpi/ic_status_notification.png delete mode 100644 foosball/app/src/phone/res/drawable-xxhdpi/sadpanda.png delete mode 100644 foosball/app/src/phone/res/drawable-xxxhdpi/ic_check_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-xxxhdpi/ic_close_white_48dp.png delete mode 100644 foosball/app/src/phone/res/drawable-xxxhdpi/ic_shortcut_tables.png delete mode 100755 foosball/app/src/phone/res/drawable-xxxhdpi/ic_status_notification.png delete mode 100644 foosball/app/src/phone/res/drawable/vd_check_circle_green_800_24dp.xml delete mode 100644 foosball/app/src/phone/res/drawable/vd_done.xml delete mode 100644 foosball/app/src/phone/res/drawable/vd_edit.xml delete mode 100644 foosball/app/src/phone/res/drawable/vd_person_add_black.xml delete mode 100644 foosball/app/src/phone/res/layout/activity_leaderboard_tablet.xml delete mode 100644 foosball/app/src/phone/res/layout/activity_main_tablet.xml delete mode 100644 foosball/app/src/phone/res/layout/activity_nfc_read.xml delete mode 100644 foosball/app/src/phone/res/layout/activity_primary.xml delete mode 100644 foosball/app/src/phone/res/layout/activity_sign_in.xml delete mode 100644 foosball/app/src/phone/res/layout/adapter_leaderboard_tablet.xml delete mode 100644 foosball/app/src/phone/res/layout/adapter_table.xml delete mode 100644 foosball/app/src/phone/res/layout/adapter_user_dialog.xml delete mode 100644 foosball/app/src/phone/res/layout/fragment_tables.xml delete mode 100644 foosball/app/src/phone/res/layout/fragment_user.xml delete mode 100644 foosball/app/src/phone/res/menu/menu_logout.xml delete mode 100755 foosball/app/src/phone/res/mipmap-hdpi/ic_launcher.png delete mode 100755 foosball/app/src/phone/res/mipmap-mdpi/ic_launcher.png delete mode 100755 foosball/app/src/phone/res/mipmap-xhdpi/ic_launcher.png delete mode 100755 foosball/app/src/phone/res/mipmap-xxhdpi/ic_launcher.png delete mode 100755 foosball/app/src/phone/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 foosball/app/src/phone/res/values-w820dp/dimens.xml delete mode 100644 foosball/app/src/phone/res/values/colors.xml delete mode 100644 foosball/app/src/phone/res/values/dimens.xml delete mode 100644 foosball/app/src/phone/res/values/strings.xml delete mode 100644 foosball/app/src/phone/res/values/styles.xml delete mode 100644 foosball/app/src/phone/res/xml-v25/shortcuts.xml delete mode 100644 foosball/app/src/tablet/AndroidManifest.xml delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/App.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/CreateCutThroatGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/CreateGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/CreatePlayerActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/CreateTableKingGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/CreateTeamTwisterGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/CutThroatGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/EloDialogActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/GameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/LeaderboardActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/MainActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/SyncActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TableKingGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TeamTwisterGameActivity.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/FoosRankLeaderboardAdapter.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/LeaderboardAdapter.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamAdapter.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamLeaderboardAdapter.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TimeWasterLeaderboardAdapter.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/UserAdapter.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/FoosRankViewHolder.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/LeaderboardViewHolder.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TeamLeaderboardViewHolder.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TimeWasterViewHolder.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CustomTeam.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatGame.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatPlayer.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Game.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/GameStatus.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Goal.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/ITeam.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/IncomingData.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Round.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Table.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableKingGame.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableSide.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Team.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamTwisterGame.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamWithPoints.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/User.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/push/PushIntentService.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/receivers/GoalReceiver.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/services/FoosballSyncService.kt delete mode 100755 foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Commentator.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Prefs.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/QRView.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/RankingUtils.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/TabletExtensions.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CountdownCircle.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayerView.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayersLayout.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/EloGraphView.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/GameTimer.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayerView.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayersLayout.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TableRequestedDialog.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TeamLayout.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinCutThroatGameDialog.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinGameDialog.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinRoundDialog.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTableKingGameDialog.kt delete mode 100644 foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTeamTwisterGameDialog.kt delete mode 100644 foosball/app/src/tablet/res/drawable-hdpi/ic_check_blue_48dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-hdpi/ic_stars_amber_400_36dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-hdpi/ic_undo_black_24dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-mdpi/ic_check_blue_48dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-mdpi/ic_stars_amber_400_36dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-mdpi/ic_undo_black_24dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xhdpi/ic_check_blue_48dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xhdpi/ic_stars_amber_400_36dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xhdpi/ic_undo_black_24dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xxhdpi/ic_check_blue_48dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xxhdpi/ic_stars_amber_400_36dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xxhdpi/ic_undo_black_24dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xxxhdpi/ic_check_blue_48dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xxxhdpi/ic_stars_amber_400_36dp.png delete mode 100644 foosball/app/src/tablet/res/drawable-xxxhdpi/ic_undo_black_24dp.png delete mode 100644 foosball/app/src/tablet/res/drawable/bg_serving_indicator.xml delete mode 100644 foosball/app/src/tablet/res/drawable/circle_outline_blue_medium.xml delete mode 100644 foosball/app/src/tablet/res/drawable/circle_outline_medium_white.xml delete mode 100644 foosball/app/src/tablet/res/drawable/circle_outline_red_medium.xml delete mode 100644 foosball/app/src/tablet/res/drawable/circle_outline_thin.xml delete mode 100644 foosball/app/src/tablet/res/drawable/circle_white.xml delete mode 100644 foosball/app/src/tablet/res/drawable/vd_person_add_black.xml delete mode 100644 foosball/app/src/tablet/res/drawable/vd_person_add_white_24dp.xml delete mode 100644 foosball/app/src/tablet/res/drawable/vd_star_amber_a400_48dp.xml delete mode 100644 foosball/app/src/tablet/res/drawable/vd_swap_horiz_accent_48dp.xml delete mode 100644 foosball/app/src/tablet/res/drawable/vd_trophy.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_create_cut_throat_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_create_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_create_player.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_create_table_king_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_create_team_twister_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_elo_layout.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_foos_rank_leaderboard.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_game_cut_throat.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_leaderboard.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_main.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_sync.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_table_king_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/activity_team_twister_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/adapter_leaderboard.xml delete mode 100644 foosball/app/src/tablet/res/layout/adapter_team_dialog.xml delete mode 100644 foosball/app/src/tablet/res/layout/adapter_team_leaderboard.xml delete mode 100644 foosball/app/src/tablet/res/layout/adapter_user_dialog.xml delete mode 100644 foosball/app/src/tablet/res/layout/dialog_table_requested.xml delete mode 100644 foosball/app/src/tablet/res/layout/dialog_win_game.xml delete mode 100644 foosball/app/src/tablet/res/layout/dialog_win_game_cut_throat.xml delete mode 100644 foosball/app/src/tablet/res/layout/dialog_win_round.xml delete mode 100644 foosball/app/src/tablet/res/layout/dialog_win_table_king.xml delete mode 100644 foosball/app/src/tablet/res/layout/dialog_win_team_twister.xml delete mode 100644 foosball/app/src/tablet/res/layout/elo_dialog_layout.xml delete mode 100644 foosball/app/src/tablet/res/layout/layout_cut_throat_players.xml delete mode 100644 foosball/app/src/tablet/res/layout/layout_players.xml delete mode 100644 foosball/app/src/tablet/res/layout/view_cut_throat_player.xml delete mode 100644 foosball/app/src/tablet/res/layout/view_player.xml delete mode 100644 foosball/app/src/tablet/res/layout/view_team_layout.xml delete mode 100644 foosball/app/src/tablet/res/layout/view_team_layout_vertical.xml delete mode 100644 foosball/app/src/tablet/res/values-w820dp/dimens.xml delete mode 100644 foosball/app/src/tablet/res/values/attrs.xml delete mode 100644 foosball/app/src/tablet/res/values/dimens.xml delete mode 100644 foosball/app/src/tablet/res/values/strings.xml delete mode 100644 foosball/build.gradle delete mode 120000 foosball/buildSrc/.gitignore delete mode 120000 foosball/buildSrc/build.gradle.kts delete mode 120000 foosball/buildSrc/src delete mode 120000 foosball/gradle delete mode 120000 foosball/gradlew delete mode 100644 foosball/settings.gradle delete mode 100644 foosball/wear/.gitignore delete mode 100644 foosball/wear/build.gradle delete mode 100644 foosball/wear/proguard-rules.pro delete mode 100644 foosball/wear/src/main/AndroidManifest.xml delete mode 100644 foosball/wear/src/main/java/com/instructure/androidfoosball/wear/TableCardFragment.kt delete mode 100644 foosball/wear/src/main/java/com/instructure/androidfoosball/wear/WearActivity.kt delete mode 100644 foosball/wear/src/main/java/com/instructure/androidfoosball/wear/WinLossCardFragment.kt delete mode 100644 foosball/wear/src/main/res/layout/activity_wear.xml delete mode 100644 foosball/wear/src/main/res/layout/fragment_table.xml delete mode 100644 foosball/wear/src/main/res/layout/fragment_win_loss.xml delete mode 100644 foosball/wear/src/main/res/layout/rect_activity_wear.xml delete mode 100644 foosball/wear/src/main/res/layout/round_activity_wear.xml delete mode 100755 foosball/wear/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100755 foosball/wear/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100755 foosball/wear/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100755 foosball/wear/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100755 foosball/wear/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 foosball/wear/src/main/res/values/dimens.xml delete mode 100644 foosball/wear/src/main/res/values/strings.xml delete mode 100644 foosball/wear/src/main/res/values/styles.xml delete mode 100644 foosball/wearutils/.gitignore delete mode 100644 foosball/wearutils/build.gradle delete mode 100644 foosball/wearutils/proguard-rules.pro delete mode 100644 foosball/wearutils/src/androidTest/java/com/instructure/wearutils/ExampleInstrumentedTest.kt delete mode 100644 foosball/wearutils/src/main/AndroidManifest.xml delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/WearClient.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/WearConst.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/interfaces/DataReceived.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/interfaces/DataRequest.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/interfaces/WearableCallbacks.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/models/DataPage.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/models/DataRow.kt delete mode 100644 foosball/wearutils/src/main/java/com/instructure/wearutils/services/BaseWearService.kt delete mode 100755 foosball/wearutils/src/main/res/drawable-hdpi/ic_foosball_watermark.png delete mode 100755 foosball/wearutils/src/main/res/drawable-hdpi/ic_foosball_watermark_small.png delete mode 100755 foosball/wearutils/src/main/res/drawable-mdpi/ic_foosball_watermark.png delete mode 100755 foosball/wearutils/src/main/res/drawable-mdpi/ic_foosball_watermark_small.png delete mode 100755 foosball/wearutils/src/main/res/drawable-xhdpi/ic_foosball_watermark.png delete mode 100755 foosball/wearutils/src/main/res/drawable-xhdpi/ic_foosball_watermark_small.png delete mode 100755 foosball/wearutils/src/main/res/drawable-xxhdpi/ic_foosball_watermark.png delete mode 100755 foosball/wearutils/src/main/res/drawable-xxhdpi/ic_foosball_watermark_small.png delete mode 100755 foosball/wearutils/src/main/res/drawable-xxxhdpi/ic_foosball_watermark.png delete mode 100755 foosball/wearutils/src/main/res/drawable-xxxhdpi/ic_foosball_watermark_small.png delete mode 100644 foosball/wearutils/src/main/res/drawable/page_bg_1.xml delete mode 100644 foosball/wearutils/src/main/res/drawable/page_bg_2.xml delete mode 100644 foosball/wearutils/src/main/res/values/colors.xml delete mode 100644 foosball/wearutils/src/main/res/values/strings.xml delete mode 100644 foosball/wearutils/src/test/java/com/instructure/wearutils/ExampleUnitTest.kt delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ar.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ca.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_cy.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_da.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_da_instk12.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_de.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_en_AU.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_en_AU_unimelb.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_en_CA.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_en_CY.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_en_GB.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_en_GB_instukhe.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_es.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_es_ES.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_fi.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_fr.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_fr_CA.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ga.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_hi.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ht.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_id.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_is.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_it.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ja.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_mi.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ms.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_nb.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_nb_instk12.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_nl.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_pl.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_pt_BR.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_pt_PT.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_ru.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_sl.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_sv.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_sv_instk12.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_th.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_vi.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_zh.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_zh_HK.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_zh_Hans.arb delete mode 100644 libs/flutter_student_embed/lib/l10n/res/intl_zh_Hant.arb delete mode 100644 refooz_2_lose/.gitignore delete mode 100644 refooz_2_lose/.metadata delete mode 100644 refooz_2_lose/BarcodeScanPlugin/CHANGELOG.md delete mode 100644 refooz_2_lose/BarcodeScanPlugin/README.md delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/.gitignore delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/build.gradle delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/gradle.properties delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 refooz_2_lose/BarcodeScanPlugin/android/gradlew delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/gradlew.bat delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/settings.gradle delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/src/main/AndroidManifest.xml delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScanPlugin.kt delete mode 100644 refooz_2_lose/BarcodeScanPlugin/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScannerActivity.kt delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/.gitignore delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/Assets/.gitkeep delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/Classes/BarcodeScanPlugin.h delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/Classes/BarcodeScanPlugin.m delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/Classes/BarcodeScannerViewController.h delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/Classes/BarcodeScannerViewController.m delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/Classes/BarcodeScannerViewControllerDelegate.h delete mode 100644 refooz_2_lose/BarcodeScanPlugin/ios/barcode_scan.podspec delete mode 100644 refooz_2_lose/BarcodeScanPlugin/lib/barcode_scan.dart delete mode 100644 refooz_2_lose/BarcodeScanPlugin/pubspec.yaml delete mode 100644 refooz_2_lose/README.md delete mode 100644 refooz_2_lose/android/.gitignore delete mode 100644 refooz_2_lose/android/app/build.gradle delete mode 100644 refooz_2_lose/android/app/google-services.json delete mode 100644 refooz_2_lose/android/app/src/main/AndroidManifest.xml delete mode 100644 refooz_2_lose/android/app/src/main/kotlin/com/instructure/refooz2lose/MainActivity.kt delete mode 100644 refooz_2_lose/android/app/src/main/res/drawable/launch_background.xml delete mode 100755 refooz_2_lose/android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100755 refooz_2_lose/android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100755 refooz_2_lose/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100755 refooz_2_lose/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100755 refooz_2_lose/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 refooz_2_lose/android/app/src/main/res/values/styles.xml delete mode 100644 refooz_2_lose/android/build.gradle delete mode 100644 refooz_2_lose/android/debug.keystore delete mode 100644 refooz_2_lose/android/gradle.properties delete mode 100644 refooz_2_lose/android/gradle/wrapper/gradle-wrapper.jar delete mode 100644 refooz_2_lose/android/gradle/wrapper/gradle-wrapper.properties delete mode 100755 refooz_2_lose/android/gradlew delete mode 100644 refooz_2_lose/android/gradlew.bat delete mode 100644 refooz_2_lose/android/settings.gradle delete mode 100644 refooz_2_lose/images/sad_panda.png delete mode 100644 refooz_2_lose/ios/.gitignore delete mode 100644 refooz_2_lose/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 refooz_2_lose/ios/Flutter/Debug.xcconfig delete mode 100644 refooz_2_lose/ios/Flutter/Release.xcconfig delete mode 100644 refooz_2_lose/ios/Podfile delete mode 100644 refooz_2_lose/ios/Podfile.lock delete mode 100644 refooz_2_lose/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 refooz_2_lose/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 refooz_2_lose/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 refooz_2_lose/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 refooz_2_lose/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 refooz_2_lose/ios/Runner/AppDelegate.swift delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 refooz_2_lose/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 refooz_2_lose/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 refooz_2_lose/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 refooz_2_lose/ios/Runner/GoogleService-Info.plist delete mode 100644 refooz_2_lose/ios/Runner/Info.plist delete mode 100644 refooz_2_lose/ios/Runner/Runner-Bridging-Header.h delete mode 100644 refooz_2_lose/ios/Runner/Runner.entitlements delete mode 100644 refooz_2_lose/lib/main.dart delete mode 100644 refooz_2_lose/lib/models/FoozTable.dart delete mode 100644 refooz_2_lose/lib/pages/assignment_page.dart delete mode 100644 refooz_2_lose/lib/pages/login_page.dart delete mode 100644 refooz_2_lose/lib/pages/tables_page.dart delete mode 100644 refooz_2_lose/lib/pages/user_page.dart delete mode 100644 refooz_2_lose/lib/ui/ColorParser.dart delete mode 100644 refooz_2_lose/lib/ui/FoozTheme.dart delete mode 100644 refooz_2_lose/lib/widgets/TableTile.dart delete mode 100644 refooz_2_lose/lib/widgets/user_header_widget.dart delete mode 100644 refooz_2_lose/lib/widgets/user_message_widget.dart delete mode 100644 refooz_2_lose/pubspec.yaml delete mode 100644 refooz_2_lose/test/widget_test.dart delete mode 100644 training/README.md diff --git a/InstrumentationTests/.gitignore b/InstrumentationTests/.gitignore deleted file mode 100644 index b5faaad07e..0000000000 --- a/InstrumentationTests/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# built application files # -build/ -*.apk -*.ap_ - -# files for the dex VM # -*.dex - -# Java class files # -*.class - -# generated files # -bin/ -gen/ -target - -# Local configuration file # -local.properties - -# Windows thumbnail db # -Thumbs.db - -# OSX files # -.DS_Store - -# Eclipse project files # -.classpath -.project - -# Android Studio and Intellij # -.idea/ -*.iml -*.iws - -# Package Files # -*.jar -*.war -*.ear - -# Gradle Files # -.gradle -gradle.properties -release_build/.gradle - -# Project Files # -.gitconfig diff --git a/InstrumentationTests/app/.gitignore b/InstrumentationTests/app/.gitignore deleted file mode 100644 index b5faaad07e..0000000000 --- a/InstrumentationTests/app/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# built application files # -build/ -*.apk -*.ap_ - -# files for the dex VM # -*.dex - -# Java class files # -*.class - -# generated files # -bin/ -gen/ -target - -# Local configuration file # -local.properties - -# Windows thumbnail db # -Thumbs.db - -# OSX files # -.DS_Store - -# Eclipse project files # -.classpath -.project - -# Android Studio and Intellij # -.idea/ -*.iml -*.iws - -# Package Files # -*.jar -*.war -*.ear - -# Gradle Files # -.gradle -gradle.properties -release_build/.gradle - -# Project Files # -.gitconfig diff --git a/InstrumentationTests/app/build.gradle b/InstrumentationTests/app/build.gradle deleted file mode 100644 index e9c5e0ddd0..0000000000 --- a/InstrumentationTests/app/build.gradle +++ /dev/null @@ -1,80 +0,0 @@ -apply plugin: 'com.android.application' -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -repositories { - jcenter() - maven { url "https://jitpack.io" } -} - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath "com.android.tools.build:gradle:$GLOBAL_GRADLE_TOOLS_VERSION" - } -} - -android { - compileSdkVersion rootProject.ext.compileSdkVersion - buildToolsVersion rootProject.ext.buildToolsVersion - defaultConfig { - applicationId "instructure.instrumentationtests" - minSdkVersion rootProject.ext.minSdkVersion - targetSdkVersion rootProject.ext.targetSdkVersion - versionCode rootProject.ext.versionCode - versionName rootProject.ext.versionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - lintOptions { - abortOnError false - } - - dexOptions { - preDexLibraries = false - javaMaxHeapSize '2g' - } - -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - compile rootProject.ext.supportDependencies.appCompat - - testCompile "org.robolectric:robolectric:3.2.2" - testCompile "org.robolectric:shadows-play-services:3.0" - testCompile "org.robolectric:shadows-support-v4:3.0" - - compile project(':canvas-api-2') - compile project(':pandautils') - compile project(':recyclerview') - compile project(':blueprint') - releaseCompile project(path: ':login-api-2', configuration: 'release') - debugCompile project(path: ':login-api-2', configuration: 'debug') - - testCompile 'junit:junit:4.12' -} diff --git a/InstrumentationTests/app/proguard-rules.pro b/InstrumentationTests/app/proguard-rules.pro deleted file mode 100644 index 6e40fe674e..0000000000 --- a/InstrumentationTests/app/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/{user}/AndroidSDK/sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# 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 *; -#} diff --git a/InstrumentationTests/app/src/androidTest/java/instructure/instrumentationtests/ExampleInstrumentedTest.java b/InstrumentationTests/app/src/androidTest/java/instructure/instrumentationtests/ExampleInstrumentedTest.java deleted file mode 100644 index 8e57e6e3b9..0000000000 --- a/InstrumentationTests/app/src/androidTest/java/instructure/instrumentationtests/ExampleInstrumentedTest.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package instructure.instrumentationtests; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("instructure.instrumentationtests", appContext.getPackageName()); - } -} diff --git a/InstrumentationTests/app/src/main/AndroidManifest.xml b/InstrumentationTests/app/src/main/AndroidManifest.xml deleted file mode 100644 index 2a4e5d3414..0000000000 --- a/InstrumentationTests/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - diff --git a/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java b/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java deleted file mode 100644 index 4b98307eec..0000000000 --- a/InstrumentationTests/app/src/main/java/instructure/instrumentationtests/AppManager.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package instructure.instrumentationtests; - -import android.app.Application; - -public class AppManager extends Application { - -} diff --git a/InstrumentationTests/app/src/main/res/mipmap-hdpi/ic_launcher.png b/InstrumentationTests/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index cde69bcccec65160d92116f20ffce4fce0b5245c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3418 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 diff --git a/InstrumentationTests/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/InstrumentationTests/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bfa42f0e7b91d006d22352c9ff2f134e504e3c1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4842 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 diff --git a/InstrumentationTests/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/InstrumentationTests/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 324e72cdd7480cb983fa1bcc7ce686e51ef87fe7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7718 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 diff --git a/InstrumentationTests/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/InstrumentationTests/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index aee44e138434630332d88b1680f33c4b24c70ab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10486 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 - - - - #3F51B5 - #303F9F - #FF4081 - diff --git a/InstrumentationTests/app/src/main/res/values/strings.xml b/InstrumentationTests/app/src/main/res/values/strings.xml deleted file mode 100644 index 8449b18c9e..0000000000 --- a/InstrumentationTests/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - InstrumentationTests - diff --git a/InstrumentationTests/app/src/main/res/values/styles.xml b/InstrumentationTests/app/src/main/res/values/styles.xml deleted file mode 100644 index 47ce9a26ce..0000000000 --- a/InstrumentationTests/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - diff --git a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/SampleTest.java b/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/SampleTest.java deleted file mode 100644 index 7a0d21bd33..0000000000 --- a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/SampleTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package instructure.instrumentationtests; - -import com.instructure.canvasapi2.utils.DateHelper; - -import org.junit.Test; - -import java.util.Calendar; -import java.util.GregorianCalendar; - -import instructure.instrumentationtests.robo.RoboTestCase; - -public class SampleTest extends RoboTestCase { - - @Test - public void dateTest() { - GregorianCalendar now = new GregorianCalendar(); - GregorianCalendar later = new GregorianCalendar(); - later.add(Calendar.DAY_OF_WEEK, 1); - - assertTrue(DateHelper.compareDays(now, later) == -1); - - assertTrue(DateHelper.compareDays(now, now) == 0); - - assertTrue(DateHelper.compareDays(later, now) == 1); - } - - @Test - public void resourceTest() { - String logIn = context().getResources().getString(R.string.login); - assertEquals(logIn, "Login"); - } -} diff --git a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboAppManager.java b/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboAppManager.java deleted file mode 100644 index 0a1d6570eb..0000000000 --- a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboAppManager.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package instructure.instrumentationtests.robo; - -import org.robolectric.shadows.gms.ShadowGooglePlayServicesUtil; - -import instructure.instrumentationtests.AppManager; - -public class RoboAppManager extends AppManager { - - @Override - public void onCreate() { - // See issue: https://github.com/robolectric/robolectric/issues/1995 - // For now we just return that Play Services is disabled. - ShadowGooglePlayServicesUtil.setIsGooglePlayServicesAvailable(3);//3 == Disabled - super.onCreate(); - } -} diff --git a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java b/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java deleted file mode 100644 index 169dbe7b4b..0000000000 --- a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestCase.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package instructure.instrumentationtests.robo; - -import android.content.Context; -import android.support.annotation.NonNull; - -import junit.framework.TestCase; - -import org.junit.Before; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import instructure.instrumentationtests.BuildConfig; - -@RunWith(RoboTestRunner.class) -@Config(constants = BuildConfig.class, sdk = RoboTestRunner.DEFAULT_SDK) -public abstract class RoboTestCase extends TestCase { - - private RoboAppManager mApplication; - - @Override - @Before - public void setUp() throws Exception { - super.setUp(); - } - - protected @NonNull RoboAppManager application() { - if (mApplication != null) { - return mApplication; - } - mApplication = (RoboAppManager) RuntimeEnvironment.application; - return mApplication; - } - - protected @NonNull Context context() { - return application().getApplicationContext(); - } -} diff --git a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestRunner.java b/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestRunner.java deleted file mode 100644 index b0d6769968..0000000000 --- a/InstrumentationTests/app/src/test/java/instructure/instrumentationtests/robo/RoboTestRunner.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2016 Kickstarter, PBC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package instructure.instrumentationtests.robo; - -import org.junit.runners.model.InitializationError; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; -import org.robolectric.manifest.AndroidManifest; -import org.robolectric.res.FileFsFile; -import org.robolectric.util.Logger; -import org.robolectric.util.ReflectionHelpers; - -public class RoboTestRunner extends RobolectricTestRunner { - - public static final int DEFAULT_SDK = 21; - private static final String BUILD_OUTPUT = "build/intermediates"; - - public RoboTestRunner(final Class testClass) throws InitializationError { - super(testClass); - } - - @Override - protected AndroidManifest getAppManifest(final Config config) { - if (config.constants() == Void.class) { - Logger.error("Field 'constants' not specified in @Config annotation"); - Logger.error("This is required when using RobolectricGradleTestRunner!"); - throw new RuntimeException("No 'constants' field in @Config annotation!"); - } - - final String type = getType(config); - final String flavor = getFlavor(config); - final String packageName = getPackageName(config); - - final FileFsFile res; - final FileFsFile assets; - final FileFsFile manifest; - - // res/merged added in Android Gradle plugin 1.3-beta1 - if (FileFsFile.from(BUILD_OUTPUT, "res", "merged").exists()) { - res = FileFsFile.from(BUILD_OUTPUT, "res", "merged", flavor, type); - } else if (FileFsFile.from(BUILD_OUTPUT, "res").exists()) { - res = FileFsFile.from(BUILD_OUTPUT, "res", flavor, type); - } else { - res = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "res"); - } - - if (FileFsFile.from(BUILD_OUTPUT, "assets").exists()) { - assets = FileFsFile.from(BUILD_OUTPUT, "assets", flavor, type); - } else { - assets = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "assets"); - } - - if (FileFsFile.from(BUILD_OUTPUT, "manifests").exists()) { - manifest = FileFsFile.from(BUILD_OUTPUT, "manifests", "full", flavor, type, "AndroidManifest.xml"); - } else { - manifest = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "AndroidManifest.xml"); - } - - Logger.debug("Robolectric assets directory: " + assets.getPath()); - Logger.debug(" Robolectric res directory: " + res.getPath()); - Logger.debug(" Robolectric manifest path: " + manifest.getPath()); - Logger.debug(" Robolectric package name: " + packageName); - - return new AndroidManifest(manifest, res, assets) { - @Override - public String getRClassName() throws Exception { - return instructure.instrumentationtests.R.class.getName(); - } - }; - } - - private static String getType(final Config config) { - try { - return ReflectionHelpers.getStaticField(config.constants(), "BUILD_TYPE"); - } catch (Throwable e) { - return null; - } - } - - private static String getFlavor(final Config config) { - try { - return ReflectionHelpers.getStaticField(config.constants(), "FLAVOR"); - } catch (Throwable e) { - return null; - } - } - - private static String getPackageName(final Config config) { - try { - final String packageName = config.packageName(); - if (packageName != null && !packageName.isEmpty()) { - return packageName; - } else { - return ReflectionHelpers.getStaticField(config.constants(), "APPLICATION_ID"); - } - } catch (Throwable e) { - return null; - } - } -} diff --git a/InstrumentationTests/app/src/test/resources/robolectric.properties b/InstrumentationTests/app/src/test/resources/robolectric.properties deleted file mode 100644 index 0028dd332a..0000000000 --- a/InstrumentationTests/app/src/test/resources/robolectric.properties +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2017 - present Instructure, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -application=instructure.instrumentationtests.robo.RoboAppManager \ No newline at end of file diff --git a/InstrumentationTests/build.gradle b/InstrumentationTests/build.gradle deleted file mode 100644 index ffd49bb3c7..0000000000 --- a/InstrumentationTests/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -buildscript { - /* Global constants */ - apply from: '../gradle/global.gradle' - - repositories { - jcenter() - } - dependencies { - classpath "com.android.tools.build:gradle:$GLOBAL_GRADLE_TOOLS_VERSION" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$GLOBAL_KOTLIN_VERSION" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} - -ext { - compileSdkVersion = GLOBAL_COMPILE_SDK - buildToolsVersion = GLOBAL_BUILD_TOOLS_VERSION - - targetSdkVersion = GLOBAL_TARGET_SDK - minSdkVersion = 17 - - versionCode = 1 - versionName = '1.0d' - - supportLibraryVersion = GLOBAL_SUPPORT_LIBRARY_VERSION - googlePlayServicesVersion = GLOBAL_PLAY_SERVICES_VERSION - - supportDependencies = [ - design : "com.android.support:design:$supportLibraryVersion", - recyclerView : "com.android.support:recyclerview-v7:$supportLibraryVersion", - appCompat : "com.android.support:appcompat-v7:$supportLibraryVersion", - supportAnnotation: "com.android.support:support-annotations:$supportLibraryVersion", - cardView: "com.android.support:cardview-v7:$supportLibraryVersion", - gpsWearable: "com.google.android.gms:play-services-wearable:$googlePlayServicesVersion", - supportLibV13: "com.android.support:support-v13:$supportLibraryVersion", - percent: "com.android.support:percent:$supportLibraryVersion", - ] -} diff --git a/InstrumentationTests/gradle b/InstrumentationTests/gradle deleted file mode 120000 index a2df95ce1c..0000000000 --- a/InstrumentationTests/gradle +++ /dev/null @@ -1 +0,0 @@ -../gradle/gradle \ No newline at end of file diff --git a/InstrumentationTests/gradlew b/InstrumentationTests/gradlew deleted file mode 120000 index 4936b5d3b2..0000000000 --- a/InstrumentationTests/gradlew +++ /dev/null @@ -1 +0,0 @@ -../gradle/gradlew \ No newline at end of file diff --git a/InstrumentationTests/gradlew.bat b/InstrumentationTests/gradlew.bat deleted file mode 100644 index aec99730b4..0000000000 --- a/InstrumentationTests/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/InstrumentationTests/settings.gradle b/InstrumentationTests/settings.gradle deleted file mode 100644 index 3f8cda030c..0000000000 --- a/InstrumentationTests/settings.gradle +++ /dev/null @@ -1,16 +0,0 @@ -include ':app' -include ':pandautils' -include ':login-api-2' -include ':recyclerview' -include ':canvas-api-2' -include ':canvas-api' -include ':blueprint' -include ':espresso' - -project(':canvas-api').projectDir = new File(rootProject.projectDir, '/../canvas-api') -project(':pandautils').projectDir = new File(rootProject.projectDir, '/../pandautils') -project(':login-api-2').projectDir = new File(rootProject.projectDir, '/../login-api-2') -project(':recyclerview').projectDir = new File(rootProject.projectDir, '/../recyclerview') -project(':canvas-api-2').projectDir = new File(rootProject.projectDir, '/../canvas-api-2/canvasapi') -project(':blueprint').projectDir = new File(rootProject.projectDir, '/../blueprint') -project(':espresso').projectDir = new File(rootProject.projectDir, '/../espresso') diff --git a/README.md b/README.md index 0f9832fe42..9e2c4c61d3 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ The open source code provided by the Android Team at Instructure. First, install the Flutter SDK using the instructions found [here](https://flutter.dev/docs/get-started/install). -Next, run `./open_source.sh` once. You may now use Gradle to build the apps. Prior to building the Student app for the first time, navigate to `libs/flutter_student_embed` and run the command `flutter pub get`. +Next, run `./open_source.sh` once. You may now use Gradle to build the apps. -### Student and Teacher +### Student, Teacher and native Parent 1. Open `apps/build.gradle` in Android Studio ``` @@ -20,7 +20,7 @@ Android Studio > Import Project > canvas-android/apps/build.gradle 2. Select the app from the list of configurations (`student` or `teacher`) 3. Tap 'Run' (`^R`) to run the app -### Parent +### Flutter Parent 1. Open `canvas-android/apps/flutter_parent` in Android Studio. 2. Make sure the `main.dart` configuration is selected @@ -34,7 +34,7 @@ Parent | (in apps/flutter_parent) `flutter pub get; flutter build apk` | [![Par ## Running tests -To run unit tests for Student and Teacher +To run unit tests for Student, Teacher and native Parent 1. Open the Build Variants window and set the variant to `qaDebug` for the app that you wish to test. 2. You can run the tests by tapping on the play button next to the test case or the test class. @@ -58,19 +58,19 @@ App | Description Module | Description --- | --- -BluePrint | An MVP Architecture that depends on PandaRecyclerView. -Canvas-Api | *Deprecated* - Canvas for Android Api used to talk to Canvas LMS. (deprecated) -Canvas-Api-2 | Canvas for Android Api used to talk to the Canvas LMS and is testable. -dataseedingapi| gRPC wrapper for Canvas that enables creating data to test the apps -Espresso | The UI testing library built on Espresso. -SoSeedyCLI | CLI for using data seeding API manually -SoSeedyGRPC | gRPC server for using data seeding with iOS from Xcode -Foosball | A Foosball Application created and used interally to boost fun by over 120%. -Login-Api | *Deprecated* - The Library used to making logging in and getting a token relatively easy. (deprecated) -Login-Api-2 | The libarary used to make logging in and getting a token relative easy and is testable. -PandaUtils | The core library for new features in the Student and Teacher apps. -PandaRecyclerView | A fancy RecyclerView library that supports expanding and collapsing, pagination, and stuff like that. -Rceditor | A wrapper for rich content editing used in Canvas Teacher. +annotations | A wrapper for the PSPDFKit library and logic for annotation handling and converting in PDF documents. +blueprint | An MVP Architecture that depends on PandaRecyclerView. (deprecated) +buildSrc | Library for common gradle dependencies and gradle transformers that are used by the project. +canvas-api-2 | Canvas for Android Api used to talk to the Canvas LMS and is testable. +dataseedingapi | gRPC wrapper for Canvas that enables creating data to test the apps. +DocumentScanner | A wrapper for document scanning features. +espresso | The UI testing library built on Espresso. +interactions | Interactions for navigation used in the apps. +login-api-2 | The libarary used to make logging in and getting a token relative easy and is testable. +pandares | Collection of resources used in our apps. +pandautils | The core library for the apps. All the common code is implemented here that is reused by the 3 apps. +rceditor | A wrapper for rich content editing used in our apps. +recyclerview | A fancy RecyclerView library that supports expanding and collapsing, pagination, and stuff like that. (deprecated) #### Our applications are licensed under the GPLv3 License. diff --git a/android-vault b/android-vault index e9ea50424a..15fababdb6 160000 --- a/android-vault +++ b/android-vault @@ -1 +1 @@ -Subproject commit e9ea50424a27d20bf744ccd5235750c0bdec9c2c +Subproject commit 15fababdb67c36b68ad528108af12e7583724bf2 diff --git a/apps/student/build.gradle b/apps/student/build.gradle index b3df9a528b..217d48b892 100644 --- a/apps/student/build.gradle +++ b/apps/student/build.gradle @@ -112,12 +112,6 @@ android { buildConfigField "String", "HEAP_APP_ID", "\"$heapStagingId\"" - buildConfigField "String", "PRONOUN_STUDENT_TEST_USER", "\"$pronounTestStudent\"" - buildConfigField "String", "PRONOUN_STUDENT_TEST_PASSWORD", "\"$pronounTestStudentPassword\"" - - buildConfigField "String", "PUSH_NOTIFICATIONS_STUDENT_TEST_USER", "\"$pushNotificationsTestStudent\"" - buildConfigField "String", "PUSH_NOTIFICATIONS_STUDENT_TEST_PASSWORD", "\"$pushNotificationsTestStudentPassword\"" - ext { heapEnabled = true } @@ -162,6 +156,11 @@ android { qa { buildConfigField "boolean", "IS_TESTING", "true" + buildConfigField "String", "PRONOUN_STUDENT_TEST_USER", "\"$pronounTestStudent\"" + buildConfigField "String", "PRONOUN_STUDENT_TEST_PASSWORD", "\"$pronounTestStudentPassword\"" + + buildConfigField "String", "PUSH_NOTIFICATIONS_STUDENT_TEST_USER", "\"$pushNotificationsTestStudent\"" + buildConfigField "String", "PUSH_NOTIFICATIONS_STUDENT_TEST_PASSWORD", "\"$pushNotificationsTestStudentPassword\"" dimension 'default' } diff --git a/apps/teacher/build.gradle b/apps/teacher/build.gradle index 8a300f1144..41e3d18e66 100644 --- a/apps/teacher/build.gradle +++ b/apps/teacher/build.gradle @@ -87,6 +87,11 @@ android { qa { dimension "icecream" buildConfigField "boolean", "IS_TESTING", "true" + buildConfigField "String", "PRONOUN_TEACHER_TEST_USER", "\"$pronounTestTeacher\"" + buildConfigField "String", "PRONOUN_TEACHER_TEST_PASSWORD", "\"$pronounTestTeacherPassword\"" + + buildConfigField "String", "PUSH_NOTIFICATIONS_TEACHER_TEST_USER", "\"$pushNotificationsTestTeacher\"" + buildConfigField "String", "PUSH_NOTIFICATIONS_TEACHER_TEST_PASSWORD", "\"$pushNotificationsTestTeacherPassword\"" } } @@ -106,12 +111,6 @@ android { buildConfigField "String", "HEAP_APP_ID", "\"$heapStagingId\"" - buildConfigField "String", "PRONOUN_TEACHER_TEST_USER", "\"$pronounTestTeacher\"" - buildConfigField "String", "PRONOUN_TEACHER_TEST_PASSWORD", "\"$pronounTestTeacherPassword\"" - - buildConfigField "String", "PUSH_NOTIFICATIONS_TEACHER_TEST_USER", "\"$pushNotificationsTestTeacher\"" - buildConfigField "String", "PUSH_NOTIFICATIONS_TEACHER_TEST_PASSWORD", "\"$pushNotificationsTestTeacherPassword\"" - ext { heapEnabled = true } diff --git a/docs/git-workflow/README.md b/docs/git-workflow/README.md index 5871b7efc8..60e847081c 100644 --- a/docs/git-workflow/README.md +++ b/docs/git-workflow/README.md @@ -8,26 +8,11 @@ 1. Create a new branch from master. Use the naming convention specified below. 2. Create and commit changes. Try to keep one commit per feature/change to reduce clutter during code reviews. 3. When ready to merge, create a Pull Request with master as the base branch. - 4. Code must be reviewed and approved by at least one non-author. When applicable, the reviewer should manually test the changes and/or verify that adequate tests are in place. + 4. Code must be reviewed and approved by at least one or two non-author and should be manually tested at least by one person. For further PR rules check the related Confluence page. 6. Once approved, proceed to merge the changes. The preferred merging method, if available, is *Squash and merge*. This cuts down on the number of merge commits and reduce noise in the git history compared to a regular merge. 7. Delete the branch. - -3. **Release branches** - Releases are achieved using release branches: - 1. Initiate the release process by creating a new release branch from master. Use the naming convention specified below. - 2. Push and protect this branch. There should be no commits directly to this branch until the release is in production. This must happen before the remaining steps to ensure that other developers can access the branch. - 3. For any changes (version bump, update translations, bug fix, etc), create a new topic branch from this release branch, using the naming convention specified below. - 4. When changes are complete, this topic branch should be merged back into the source release branch via Pull Request, after proper Code Review, and then deleted. - 5. When a release is ready for final testing, use the appropriate workflow in the CI service to generate a release candidate APK from the head of the release branch and test appropriately. - 6. When ready to deploy to production, use the appropriate workflow in the CI service to generate and upload a release APK to the internal Google Play test track. This will add the APK to the artifact library and will deploy the release to internal users who require early access to the release (e.g. the documentation team). - 7. A developer should then manually initiate a new release in the Google Play console, using the APK uploaded in during the prior step, and begin rollout to a small subset of users (5-10%). - 8. If no blocking issues are discovered during the rollout, the rollout percentage may be incrementally increased. - 9. If issues are discovered during rollout, repeat the previous steps as necessary while bumping the version code (not the version name) for each new release. - 10. Once rollout reaches 100% and the release is considered complete, create a git tag and GitHub release based on the head of the release branch. Follow the naming convention specified in the next section. - 11. The release branch can now be merged back into master via Pull Request. If many changes have occurred on master since the release branch was created, it may be necessary to unprotect the branch, merge in master, and resolve any merge conflicts first. - 12. Once merged, unprotect and delete the release branch. -4. **Branch Naming Conventions** +3. **Branch Naming Conventions** - **Normal branches** - It is suggested that normal branch names include the associated project name and ticket number, where applicable, and optionally a few words describing the purpose of the branch. *Examples:* `parent/MBL-1234`, `MBL-1234-update-rating-dialog`, `fix-teacher-release-crash` @@ -41,7 +26,7 @@ *{project}-{version_name}-{version_code}* *Example:* `parent-1.1.0-5` -5. **Pull Request message tags** +4. **Pull Request message tags** Example: `[project][MBL-0000] This is my PR message` Adding tags to your Pull Request messages helps provide information that will be useful for both reviewers and for future developers (including yourself). Tags take the form of one or two short words surrounded by square brackets, and should be added at the beginning of the first line of the PR message. These are the primary tags you'll be using: @@ -57,10 +42,7 @@ - **Skip CI**: Often when your code is a work in progress you don't need to trigger Continuous Integration builds for your changes. If you want to skip these builds for your WIP PR and free up CI resources for other active PRs, add the [skip ci] tag. Like the [WIP] tag, make sure to remove this tag when your changes are complete. *Example:* `[WIP][skip ci] Testing out some changes` - - **Release Target**: If the pull request will be merged into a release branch, it is suggested that you add a tag for the project name (see above) as well as a release target tag that specifies the release version, in the form of [R-#.#.#] - *Example:* `[Teacher][R-1.8.1] Fix dashboard regression` - -6. **Misc** +5. **Misc** To maintain SOC 2 compliance, no code should ever be committed directly to the master branch. All changes must be pushed to topic branches and merged via Pull Request after proper Code Review and QA. This also applies to release branches where possible, particularly for commits made prior to 100% deployment. Generally, a topic branch should only belong to the developer who created it. In cases where multiple developers must commit to the same branch, ensure that you do not rebase pushed commits. Things will get messy. diff --git a/foosball/.gitignore b/foosball/.gitignore deleted file mode 100644 index a9cd6060b4..0000000000 --- a/foosball/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -# Private data -debug.keystore -debug.properties -private.properties -app/fabric.properties -google-services.json -app/src/tablet/res/raw/bagel_song.mp3 -app/src/tablet/res/raw/ding.mp3 -app/src/tablet/res/raw/ding_ding.mp3 -app/src/tablet/res/raw/ding_reverse.mp3 -app/src/tablet/res/raw/dominating.mp3 -app/src/tablet/res/raw/doublekill.mp3 -app/src/tablet/res/raw/firstblood.mp3 -app/src/tablet/res/raw/killingspree.mp3 -app/src/tablet/res/raw/massacre.mp3 -app/src/tablet/res/raw/multikill.mp3 -app/src/tablet/res/raw/murca.mp3 -app/src/tablet/res/raw/rotate_ding.mp3 -app/src/tablet/res/raw/unstoppable.mp3 -app/src/tablet/res/raw/motivation.mp3 -app/src/tablet/res/raw/leeroy_jenkins.mp3 -app/src/tablet/res/raw/illuminati_confirmed.mp3 -app/src/tablet/res/raw/mlg_horn.mp3 -app/src/tablet/res/raw/legitness.mp3 -app/src/tablet/res/raw/profamity.mp3 -app/src/tablet/res/raw/police_siren.mp3 - -# built application files # -*.apk -*.ap_ - -# files for the dex VM # -*.dex - -# Java class files # -*.class - -# generated files # -bin -gen -target - -# Local configuration file (sdk path, etc) # -local.properties - -# Windows thumbnail db # -Thumbs.db - -# OSX files -.DS_Store - -# Eclipse project files # -.classpath -.project - -# Android Studio # -.idea -*.iml -build -*.iws - -# Package Files # -*.jar -*.war -*.ear - -# Project Files # -.gitconfig - -# Gradle Files # -gradle.properties -.gradle -total 1304 diff --git a/foosball/adb_foos.py b/foosball/adb_foos.py deleted file mode 100644 index c2009853d9..0000000000 --- a/foosball/adb_foos.py +++ /dev/null @@ -1,113 +0,0 @@ -import CHIP_IO.GPIO as GPIO -import time -import os -import urllib2 -import socket -import logging -from subprocess import call - -TIMESTR = time.strftime("%Y%m%d-%H%M%S") - -logging.basicConfig(level=logging.DEBUG, filename='foos_' + TIMESTR + '.log') - -TABLE_ID = "5FLOOR" - -BTNRESET = "GPIO2" -BTN1 = "GPIO3" -BTN2 = "GPIO4" -LED1 = "GPIO5" -LED2 = "GPIO6" - -OFF = GPIO.HIGH -ON = GPIO.LOW - -FLASH_TIME = 0.2 -FLASH_COUNT = 10 - -GPIO.setup(LED1, GPIO.OUT) -GPIO.setup(LED2, GPIO.OUT) -GPIO.output(LED1, OFF) -GPIO.output(LED2, OFF) - -GPIO.setup(BTN1, GPIO.IN) -GPIO.setup(BTN2, GPIO.IN) -GPIO.setup(BTNRESET, GPIO.IN) - -def printlog(message): - print(message) - logging.info(message) - -def blink(speed, count, *leds): - while count > 0: - count -= 1 - for led in leds: - GPIO.output(led, ON) - time.sleep(speed) - for led in leds: - GPIO.output(led, OFF) - time.sleep(speed) - -def command(command): - call(command, shell=True) - -# Initialize -GPIO.output(LED1, ON) -GPIO.output(LED2, ON) - -#Init adb -printlog("Initilizing ADB") -command('adb devices') - -blink(FLASH_TIME, FLASH_COUNT, LED1, LED2) - -flashing = False - -def updateScore(side): - try: - if side == 0: - command('adb shell am broadcast -a action_goal --es scoringSide "SIDE_1"') - else: - command('adb shell am broadcast -a action_goal --es scoringSide "SIDE_2"') - return True - except: - logging.exception("Update Score failure:") - return False - -def buttoncallback(button): - global flashing - if flashing: - return - flashing = True - if button == BTN1: - printlog("TEAM 1 GOAL!") - GPIO.output(LED1, ON) - if updateScore(0): - blink(FLASH_TIME, FLASH_COUNT, LED1) - else: - GPIO.output(LED1, OFF) - else: - printlog("TEAM 2 GOAL!") - GPIO.output(LED2, ON) - if updateScore(1): - blink(FLASH_TIME, FLASH_COUNT, LED2) - else: - GPIO.output(LED2, OFF) - flashing = False - -GPIO.add_event_detect(BTN1, GPIO.FALLING, buttoncallback) -GPIO.add_event_detect(BTN2, GPIO.FALLING, buttoncallback) - -printlog ("Awaiting Button press") - -try: - GPIO.wait_for_edge(BTNRESET, GPIO.FALLING) - printlog("Reset button pressed") - blink(0.1, 20, LED1, LED2) - os.system("reboot") -except: - logging.exception("Exiting reset button loop:") - GPIO.cleanup() - -printlog("Cleaning up") - -GPIO.cleanup() diff --git a/foosball/app/.gitignore b/foosball/app/.gitignore deleted file mode 100644 index af55bfbd9f..0000000000 --- a/foosball/app/.gitignore +++ /dev/null @@ -1,51 +0,0 @@ -# Private data -debug.keystore -debug.properties -private.properties -google-services.json - -# built application files # -*.apk -*.ap_ - -# files for the dex VM # -*.dex - -# Java class files # -*.class - -# generated files # -bin -gen -target - -# Local configuration file (sdk path, etc) # -local.properties - -# Windows thumbnail db # -Thumbs.db - -# OSX files -.DS_Store - -# Eclipse project files # -.classpath -.project - -# Android Studio # -.idea -*.iml -build -*.iws - -# Package Files # -*.jar -*.war -*.ear - -# Project Files # -.gitconfig - -# Gradle Files # -gradle.properties -.gradle diff --git a/foosball/app/build.gradle b/foosball/app/build.gradle deleted file mode 100644 index ee76984e5b..0000000000 --- a/foosball/app/build.gradle +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'realm-android' -apply plugin: 'kotlin-kapt' - -android { - compileSdkVersion Versions.COMPILE_SDK - buildToolsVersion Versions.BUILD_TOOLS - - defaultConfig { - applicationId "com.instructure.androidfoosball" - minSdkVersion Versions.MIN_SDK - targetSdkVersion Versions.TARGET_SDK - versionCode rootProject.ext.versionCode - versionName rootProject.ext.versionName - vectorDrawables.useSupportLibrary = true - - buildConfigField "String", "FIREBASE_USERNAME", "\"$firebase_tab_username\"" - buildConfigField "String", "FIREBASE_PASSWORD", "\"$firebase_tab_password\"" - buildConfigField "String", "FIREBASE_SERVER_KEY", "\"$firebase_serverkey\"" - buildConfigField "String", "FIREBASE_STORAGE_BASE_URL", "\"$firebase_storage_base_url\"" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - debug { - minifyEnabled false - signingConfig signingConfigs.debug - } - } - - flavorDimensions 'default' - productFlavors { - phone { - dimension 'default' - applicationId "com.instructure.androidfoosball" - versionName "1.0-phone" - } - tablet { - dimension 'default' - applicationId "com.instructure.androidfoosball.tablet" - versionName "1.0-tablet" - } - } - - signingConfigs { - debug { - storeFile file("../debug.keystore") - storePassword "android" - keyAlias "androiddebugkey" - keyPassword "android" - } - } -} - -androidExtensions { - experimental = true -} - -kotlin { - experimental { - coroutines 'enable' - } -} - -dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - - api project(':wearutils') - wearApp project(':wear') - - testImplementation 'junit:junit:4.12' - implementation Libs.SUPPORT_APPCOMPAT - implementation Libs.SUPPORT_V4 - implementation Libs.SUPPORT_DESIGN - implementation Libs.SUPPORT_PERCENT - implementation Libs.SUPPORT_CARDVIEW - // Dependency for Google Sign-In - implementation Libs.PLAY_SERVICES_AUTH - implementation "com.google.firebase:firebase-core:${Versions.PLAY_SERVICES}" - implementation "com.google.firebase:firebase-auth:${Versions.PLAY_SERVICES}" - implementation "com.google.firebase:firebase-database:${Versions.PLAY_SERVICES}" - implementation "com.google.firebase:firebase-storage:${Versions.PLAY_SERVICES}" - implementation "com.google.firebase:firebase-messaging:${Versions.PLAY_SERVICES}" - implementation 'com.firebaseui:firebase-ui-database:0.6.1' - - implementation 'com.squareup.picasso:picasso:2.5.2' - implementation 'de.hdodenhof:circleimageview:2.0.0' - implementation 'com.afollestad.material-dialogs:core:0.8.6.2' - implementation Libs.KOTLIN_STD_LIB - implementation Libs.KOTLIN_COROUTINES_CORE - implementation Libs.KOTLIN_COROUTINES_ANDROID - implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.5.0' - implementation "org.jetbrains.anko:anko-commons:${Versions.KOTLIN_ANKO}" - implementation "org.jetbrains.anko:anko-sdk21-listeners:${Versions.KOTLIN_ANKO}" - implementation "org.jetbrains.anko:anko-sdk21:${Versions.KOTLIN_ANKO}" - implementation 'io.reactivex:rxjava:1.0.16' - implementation 'com.squareup.okhttp3:okhttp:3.4.1' - - implementation 'com.google.zxing:core:3.3.2' - implementation ("com.github.bumptech.glide:glide:4.6.1") { - exclude group: "com.android.support" - } -} - -apply plugin: 'com.google.gms.google-services' - diff --git a/foosball/app/proguard-rules.pro b/foosball/app/proguard-rules.pro deleted file mode 100644 index 599abaa6db..0000000000 --- a/foosball/app/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/{user}/android-sdks/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# 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 *; -#} diff --git a/foosball/app/src/main/AndroidManifest.xml b/foosball/app/src/main/AndroidManifest.xml deleted file mode 100644 index 74f5b45476..0000000000 --- a/foosball/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/activities/ChangeAvatarActivity.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/activities/ChangeAvatarActivity.kt deleted file mode 100644 index c4a168be52..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/activities/ChangeAvatarActivity.kt +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.activities - -import android.app.Activity -import android.app.ProgressDialog -import android.content.ActivityNotFoundException -import android.content.Context -import android.content.Intent -import android.graphics.* -import android.media.ExifInterface -import android.net.Uri -import android.os.Build -import android.os.Bundle -import android.provider.MediaStore -import android.support.v4.content.FileProvider -import android.support.v7.app.AlertDialog -import android.support.v7.app.AppCompatActivity -import android.view.View -import android.widget.Toast -import com.davemorrissey.labs.subscaleview.ImageSource -import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView -import com.google.firebase.database.FirebaseDatabase -import com.google.firebase.storage.FirebaseStorage -import com.instructure.androidfoosball.BuildConfig -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.utils.setVisible -import kotlinx.android.synthetic.main.activity_change_avatar.* -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread -import java.io.File -import java.io.FileOutputStream -import java.util.* - -/** - * I was going to add comments and documentation to this file, but then I didn't. - */ - -enum class Mode(val displayName : String) { - CAMERA("Camera"), - Gallery("Photo Library") -} - -class ChangeAvatarActivity : AppCompatActivity() { - - companion object { - val EXTRA_ACTION_MODE = "actionMode" - val EXTRA_USER_ID = "userId" - val EXTRA_AVATAR_URL = "avatarUrl" - fun createIntent(context: Context, userId: String?, mode: Mode): Intent { - return Intent(context, ChangeAvatarActivity::class.java).apply { - putExtra(EXTRA_USER_ID, userId) - putExtra(EXTRA_ACTION_MODE, mode) - } - } - } - - val USER_AVATARS_DIR = "user_avatars" - val AVATAR_TMP_FILE_NAME = "avatar_tmp" - - val REQUEST_CODE_TAKE_PICTURE = 1337 - val REQUEST_CODE_GET_GALLERY_IMAGE = 7331 - - private val userId: String? by lazy { intent.getStringExtra(EXTRA_USER_ID) } - private val mode: Mode by lazy { intent.getSerializableExtra(EXTRA_ACTION_MODE) as Mode } - private val tmpFile by lazy { File(externalCacheDir, AVATAR_TMP_FILE_NAME) } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_change_avatar) - setup() - when (mode) { - Mode.CAMERA -> takeImage() - Mode.Gallery -> pickImage() - } - } - - fun setup() { - btnBack.setOnClickListener { finish() } - btnDone.setOnClickListener { cropAndPost() } - imageView.setOnImageEventListener(object : SubsamplingScaleImageView.OnImageEventListener { - override fun onReady() { } - override fun onTileLoadError(p0: Exception?) { } - override fun onImageLoadError(p0: Exception?) { } - override fun onPreviewLoadError(p0: Exception?) { } - override fun onImageLoaded() { - btnDone.setVisible() - progressBar.setVisible(false) - } - }) - } - - fun takeImage() { - try { - val intent = Intent() - intent.action = MediaStore.ACTION_IMAGE_CAPTURE - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION - val contentUri = FileProvider.getUriForFile(this, "com.instructure.androidfoosball.fileProvider", tmpFile) - intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri) - } else { - intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFile)) - } - startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE) - } catch (anfe: ActivityNotFoundException) { - Toast.makeText(this, "No activity found to open this attachment.", Toast.LENGTH_LONG).show() - } - } - - fun pickImage() { - val intent = Intent() - intent.type = "image/*" - intent.action = Intent.ACTION_GET_CONTENT - startActivityForResult(intent, REQUEST_CODE_GET_GALLERY_IMAGE) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (resultCode != RESULT_OK) { finish(); return } - when (requestCode) { - REQUEST_CODE_TAKE_PICTURE -> setImage() - REQUEST_CODE_GET_GALLERY_IMAGE -> { - contentResolver.openInputStream(data!!.data).copyTo(FileOutputStream(tmpFile)) - setImage() - } - } - } - - fun setImage() { - root.visibility = View.VISIBLE - imageView.orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF - imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_CROP) - imageView.setImage(ImageSource.uri(tmpFile.absolutePath)) - } - - private fun cropAndPost() { - - val dialog = ProgressDialog(this).apply { - setMessage(context.getString(R.string.uploading)) - isIndeterminate = true - } - - dialog.show() - - doAsync { - val outFile = cropFile(tmpFile, getCropInfo()) - uiThread { - val uuid = UUID.randomUUID().toString() - val ref = FirebaseStorage.getInstance().getReferenceFromUrl(BuildConfig.FIREBASE_STORAGE_BASE_URL).child(USER_AVATARS_DIR).child("$uuid.jpg") - ref.putFile(Uri.fromFile(outFile)) - .addOnSuccessListener { - val avatarUrl = it.downloadUrl.toString() - if (!userId.isNullOrBlank()) { - FirebaseDatabase.getInstance().reference.child("users").child(userId).child("avatar").setValue(avatarUrl) - } - dialog.dismiss() - if (callingActivity != null) { - setResult(Activity.RESULT_OK, Intent().apply { - putExtra(EXTRA_AVATAR_URL, avatarUrl) - }) - } - finish() - } - .addOnFailureListener { - dialog.dismiss() - Toast.makeText(this@ChangeAvatarActivity, R.string.error_uploading_photo, Toast.LENGTH_SHORT).show() - } - } - } - } - - fun getCropInfo(): RectF { - val origin = imageView.viewToSourceCoord(0f, 0f) - val dimen = imageView.viewToSourceCoord(imageView.width.toFloat(), imageView.height.toFloat()) - - val (appliedWidth, appliedHeight) = when (imageView.appliedOrientation) { - 90, 270 -> Pair(imageView.sHeight, imageView.sWidth) - else -> Pair(imageView.sWidth, imageView.sHeight) - } - - return RectF( - origin.x / appliedWidth, - origin.y / appliedHeight, - dimen.x / appliedWidth, - dimen.y / appliedHeight) - } - -} - -fun showImageSourcePicker(context: Context, userId: String? = null, onSelected: (intent: Intent) -> Unit) { - AlertDialog.Builder(context) - .setItems(Mode.values().map { it.displayName }.toTypedArray()) { dialog, which -> - onSelected(ChangeAvatarActivity.createIntent(context, userId, Mode.values()[which])) - }.show() -} - -private val CROP_SIZE = 512 -private val COMPRESS_QUALITY = 70 - -private fun cropFile(srcFile: File, cropInfoInput: RectF?): File { - - val bOptions = BitmapFactory.Options() - bOptions.inJustDecodeBounds = true - BitmapFactory.decodeFile(srcFile.absolutePath, bOptions) - bOptions.inJustDecodeBounds = false - - val orientationTag = ExifInterface(srcFile.absolutePath).getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) - - val sWidth = bOptions.outWidth - val sHeight = bOptions.outHeight - - val cropInfo: RectF = if (cropInfoInput != null) cropInfoInput else { - - var aWidth = sWidth - var aHeight = sHeight - - if (orientationTag == ExifInterface.ORIENTATION_ROTATE_270 || orientationTag == ExifInterface.ORIENTATION_ROTATE_90) { - aWidth = sHeight - aHeight = sWidth - } - - val dimenX: Float = if (aHeight > aWidth) 0.5f else aHeight / 2f / aWidth - val dimenY: Float = if (aHeight > aWidth) aWidth / 2f / aHeight else 0.5f - RectF(0.5f - dimenX, 0.5f - dimenY, 0.5f + dimenX, 0.5f + dimenY) - } - - val adjustedCrop = when (orientationTag) { - ExifInterface.ORIENTATION_ROTATE_90 -> RectF(cropInfo.top, 1 - cropInfo.right, cropInfo.bottom, 1 - cropInfo.left) - ExifInterface.ORIENTATION_ROTATE_180 -> RectF(1 - cropInfo.right, 1 - cropInfo.bottom, 1 - cropInfo.left, 1 - cropInfo.top) - ExifInterface.ORIENTATION_ROTATE_270 -> RectF(1 - cropInfo.bottom, cropInfo.left, 1 - cropInfo.top, cropInfo.right) - else -> cropInfo - } - - val croppedWidth = (sWidth * adjustedCrop.width()).toInt() - val sampleScale = if (croppedWidth < CROP_SIZE) 1 else croppedWidth / CROP_SIZE * 2 - - bOptions.inSampleSize = sampleScale - - // Ignored by system in Lollipop and higher - @Suppress("DEPRECATION") - bOptions.inPurgeable = true - - val decodeRect = Rect( - (sWidth * adjustedCrop.left).toInt(), - (sHeight * adjustedCrop.top).toInt(), - (sWidth * adjustedCrop.right).toInt(), - (sHeight * adjustedCrop.bottom).toInt()) - - val input = BitmapRegionDecoder.newInstance(srcFile.absolutePath, false).decodeRegion(decodeRect, bOptions) - - val filterPaint = Paint(Paint.ANTI_ALIAS_FLAG) - filterPaint.isFilterBitmap = true - - val output = Bitmap.createBitmap(CROP_SIZE, CROP_SIZE, Bitmap.Config.RGB_565) - val cacheCanvas = Canvas(output) - - val matrix = Matrix() - val scale = CROP_SIZE.toFloat() / input.width - val center = CROP_SIZE / 2f - matrix.preScale(scale, scale) - when (orientationTag) { - ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90f, center, center) - ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180f, center, center) - ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270f, center, center) - } - - cacheCanvas.drawBitmap(input, matrix, filterPaint) - - val outFile = File(srcFile.absolutePath + "_cropped") - output.compress(Bitmap.CompressFormat.JPEG, COMPRESS_QUALITY, outFile.outputStream()) - return outFile -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/activities/EditUserActivity.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/activities/EditUserActivity.kt deleted file mode 100644 index ccba2260e7..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/activities/EditUserActivity.kt +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.activities - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import android.support.v7.app.AppCompatActivity -import android.view.View -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 com.instructure.androidfoosball.BuildConfig -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.* -import com.instructure.androidfoosball.views.ConfirmPinDialog -import kotlinx.android.synthetic.main.activity_edit_player.* -import org.jetbrains.anko.sdk21.listeners.onCheckedChange -import org.jetbrains.anko.sdk21.listeners.onClick - -class EditUserActivity : AppCompatActivity() { - - private val REQUEST_CODE_AVATAR = 2212 - - private val mUserId: String by lazy { intent.getStringExtra(Const.USER_ID) } - lateinit private var mUser: User - private val mDatabase = FirebaseDatabase.getInstance().reference - private val mCommentator = Commentator() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - mCommentator.initialize(this) - getUser() - } - - private fun getUser() { - mDatabase.child("users").child(mUserId).addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - dataSnapshot.getValue(User::class.java)?.let { user -> - user.id = dataSnapshot.key - mUser = user - setup() - } - } - - override fun onCancelled(databaseError: DatabaseError) { } - }) - } - - private fun setup() { - setContentView(R.layout.activity_edit_player) - - enablePinView.onCheckedChange { button, isChecked -> - mUser.pinDisabled = if (isChecked) "false" else "true" - btnChangePin.isEnabled = isChecked - } - - enablePinView.isChecked = mUser.pinDisabled != "true" - avatarView.setAvatar(mUser, resources.getDimension(R.dimen.avatar_size_large).toInt()) - displayNameView.text = mUser.name - assignmentTextView.text = mUser.customAssignmentPhrase - victoryTextView.text = mUser.customVictoryPhrase - - addAvatarView.onClick { - showImageSourcePicker(this, null) { startActivityForResult(it, REQUEST_CODE_AVATAR) } - } - - btnChangePin.onClick { - ConfirmPinDialog(this, mUser, true) {}.overrideOnPinHashCreated { mUser.pinHash = it }.show() - } - - btnSave.onClick { save() } - - if (BuildConfig.APPLICATION_ID.endsWith("tablet")) { - announceNameView.onClick { mCommentator.announce(displayNameView.text) } - announceAssignmentView.onClick { mCommentator.announce(assignmentTextView.text) } - announceVictoryView.onClick { mCommentator.announce(victoryTextView.text) } - } else { - announceNameView.visibility = View.GONE - announceAssignmentView.visibility = View.GONE - announceVictoryView.visibility = View.GONE - } - - } - - fun save() { - ValidatorChain() - .first(displayNameView.validate("User name must be min 3 letters") { it.length > 3 }) - .then(mUserId.validate("Invalid user ID", { !it.isNullOrBlank() }, { shortToast(it) })) - .finally { - mUser.name = displayNameView.text - mUser.customVictoryPhrase = victoryTextView.text - mUser.customAssignmentPhrase = assignmentTextView.text - mDatabase.child("users").child(mUserId).setValue(mUser) - finish() - } - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode == REQUEST_CODE_AVATAR && resultCode == Activity.RESULT_OK) { - mUser.avatar = data?.getStringExtra(ChangeAvatarActivity.EXTRA_AVATAR_URL) ?: "" - avatarView.setAvatar(mUser) - } - super.onActivityResult(requestCode, resultCode, data) - } - - override fun onDestroy() { - super.onDestroy() - mCommentator.shutUp() - } -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/utils/Const.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/utils/Const.kt deleted file mode 100644 index 5710eb1ac9..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/utils/Const.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.utils - -object Const { - val USER_ID = "userId" - val USER = "user" - val GAME = "game" - val TABLE = "table" - val TEAM = "team" - val SAVED_TABLE_ID = "saved_table_id" - val PREFERRED_TABLE_ID = "preferred_table_id" -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/utils/Extensions.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/utils/Extensions.kt deleted file mode 100644 index f030c5c49a..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/utils/Extensions.kt +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -@file:Suppress("unused") - -package com.instructure.androidfoosball.utils - -import android.app.Activity -import android.app.Dialog -import android.content.Context -import android.graphics.Color -import android.support.design.widget.TextInputLayout -import android.support.v4.view.GestureDetectorCompat -import android.text.Editable -import android.text.TextWatcher -import android.util.TypedValue -import android.view.GestureDetector -import android.view.MotionEvent -import android.view.View -import android.view.ViewGroup -import android.widget.EditText -import android.widget.ImageView -import android.widget.Toast -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.views.UserInitialsDrawable -import com.squareup.picasso.Picasso -import org.jetbrains.anko.displayMetrics -import org.jetbrains.anko.sdk21.listeners.onTouch -import java.util.* -import java.util.regex.Pattern -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty - - -fun ImageView.setAvatar(user: User?, avatarSize: Int = 0) { - val picasso = Picasso.with(context).apply { cancelRequest(this@setAvatar) } - when { - user == null -> setImageResource(R.drawable.sadpanda) - user.avatar.isBlank() -> setImageDrawable(UserInitialsDrawable(user, avatarSize)) - else -> picasso.load(user.avatar).placeholder(R.drawable.sadpanda).error(R.drawable.sadpanda).into(this) - } -} - -fun ImageView.setAvatarUrl(url: String?) { - val picasso = Picasso.with(context).apply { cancelRequest(this@setAvatarUrl) } - when { - url.isNullOrBlank() -> setImageResource(R.drawable.sadpanda) - else -> picasso.load(url).placeholder(R.drawable.sadpanda).error(R.drawable.sadpanda).into(this) - } -} - -fun String?.elseIfBlank(alt: String): String = if (isNullOrBlank()) alt else this!! - -fun Activity.shortToast(message: String) = Toast.makeText(this, message, Toast.LENGTH_SHORT).show() -fun Activity.shortToast(messageId: Int) = Toast.makeText(this, messageId, Toast.LENGTH_SHORT).show() -fun Activity.longToast(message: String) = Toast.makeText(this, message, Toast.LENGTH_LONG).show() -fun Activity.longToast(messageId: Int) = Toast.makeText(this, messageId, Toast.LENGTH_LONG).show() - -fun TextInputLayout.validate(validator: (String) -> Boolean, errorMessage: String, afterValidation: (isValid: Boolean) -> Unit): Boolean { - return if (validator(editText?.text.toString())) { - error = "" - afterValidation(true) - true - } else { - error = errorMessage - afterValidation(false) - false - } -} - -fun TextInputLayout.onTextChanged(onChanged: (newText: String) -> Unit) { - editText?.addTextChangedListener(object : TextWatcher { - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } - override fun afterTextChanged(s: Editable?) { onChanged(s.toString()) } - }) -} - -fun EditText.onTextChanged(onChanged: (newText: String) -> Unit) { - addTextChangedListener(object : TextWatcher { - override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } - override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } - override fun afterTextChanged(s: Editable?) { onChanged(s.toString()) } - }) -} - -fun TextInputLayout.validateOnTextChanged(validator: (String) -> Boolean, errorMessage: String, afterValidation: (newText: String, isValid: Boolean) -> Unit) { - onTextChanged { newText -> validate(validator, errorMessage, { afterValidation(newText, it) }) } -} - -var TextInputLayout.text: String - get() = editText?.text.toString() - set(value) { - editText?.setText(value) - } - -fun T.setVisible(isVisible: Boolean = true): T = apply { - visibility = if (isVisible) View.VISIBLE else View.GONE -} - -fun String.matches(pattern: Pattern) = pattern.matcher(this).matches() - -/** - * Calculates this user's win rate. - * @param minGamesRequired The minimum number of games this user must have played to warrant a proper win rate - * * - * @return A float between 0 and 100, or -1 if the user has not played enough games to warrant a win rate - */ -fun User.getWinRate(minGamesRequired: Int) = when { - wins + losses < minGamesRequired -> -1f - wins == 0 -> 0f - losses == 0 -> 100f - else -> 100f * wins / (wins + losses) -} - -fun List.sortByWinRatio(minGamesRequired: Int) - = sortedWith(compareBy({ -it.getWinRate(minGamesRequired) }, { -it.wins }, { it.losses } )) - -fun List.sortByFoosRanking() = sortedBy { -it.foosRanking } - -/** - * Clamps a color's brightness - * @property maxBrightness A float between 0 and 1, where 1 is maximum possible brightness - */ -fun Int.clampToBrightness(maxBrightness: Float): Int { - val hsv = FloatArray(3) - Color.colorToHSV(this, hsv) - hsv[2] = hsv[2].coerceAtMost(maxBrightness) - return Color.HSVToColor(hsv) -} - -/** A color generated from the user's name */ -val User.avatarColor: Int - get() = name.hashCode() or 0xFF000000.toInt() - -/** The user's initials, or entire name if it's only one word */ -val User.initials: String - get() { - if (name.isBlank()) return "?" - val names = name.split(' ', limit = 3).filter { it.isNotBlank() } - return if (names.size == 1) { - names[0] - } else { - names.fold("") { initials, nextName -> initials + nextName[0].toUpperCase() } - } - } - -class Unless(val value: T, private val condition: (T) -> Boolean) { - infix fun then(alternateValue: T) = if (condition(value)) alternateValue else value -} - -infix fun T.unless(condition: (T) -> Boolean) = Unless(this, condition) - -class ValidatorChain(private val validators: MutableList> = ArrayList()) { - infix fun first(validator: Validator<*>) = then(validator) - - infix fun then(validator: Validator<*>): ValidatorChain { - validators.add(validator) - return this - } - - infix fun finally(block: () -> Unit) { - if (validators.all { it.validate() }) block() - } -} - -data class Validator(val field: T, private val errorText: String, private val condition: (T) -> Boolean, private val onFail: (String) -> Unit) { - fun validate() = condition(field).apply { if (!this) onFail(errorText) } -} - -fun TextInputLayout.validate(errorText: String, condition: (String) -> Boolean) = Validator(this, errorText, { condition(text) }, { error = errorText; requestFocus() }) - -fun T.validate(errorText: String, condition: (T) -> Boolean, onFail: (String) -> Unit) = Validator(this, errorText, { condition(this) }, onFail) - -fun validationBlock(block: ValidatorChain.() -> Unit) { ValidatorChain().block() } - -/** Returns a list of all children (direct descendants) in this ViewGroup */ -val ViewGroup.children: List get() = (0 until childCount).map { getChildAt(it) } - -/** Returns a list of all children of a specific type in this ViewGroup */ -@Suppress("UNCHECKED_CAST") -inline fun ViewGroup.children() = children.filter { it is T } as List - -/** Returns a list of all descendants in this ViewGroup */ -val ViewGroup.descendants: List get() = children + children().flatMap { it.descendants } - -/** Returns a list of all descendants of a specific type in this ViewGroup */ -@Suppress("UNCHECKED_CAST") -inline fun ViewGroup.descendants() = descendants.filter { it is T } as List - -/** Performs the provided function on all of this ViewGroup's descendants of a specific type */ -inline fun ViewGroup.modifyDescendants(mod: (T) -> Unit) = descendants().forEach { mod(it) } - -/** View binding, for scopes not covered by Kotlin's Android Extensions */ -fun Dialog.bind(id: Int): Binder = Binder { it.findViewById(id) } - -fun ViewGroup.bind(id: Int): Binder = Binder { it.findViewById(id) } - -@Suppress("UNCHECKED_CAST") -class Binder(private val finder: (T) -> View?) : ReadOnlyProperty { - private var cachedView: V? = null - override fun getValue(thisRef: T, property: KProperty<*>): V { - if (cachedView == null) { - val v = finder(thisRef) ?: throw RuntimeException("Unable to bind ${property.name}; findViewById returned null.") - cachedView = v as V - } - return cachedView!! - } -} - -fun Int.toDp(context: Context) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), context.displayMetrics) -fun Float.toDp(context: Context) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, context.displayMetrics) - -fun View.onDoubleTap(listener: () -> Unit) { - val detector = GestureDetectorCompat(context, object : GestureDetector.OnGestureListener { - override fun onShowPress(p0: MotionEvent?) = Unit - override fun onSingleTapUp(p0: MotionEvent?): Boolean = true - override fun onDown(p0: MotionEvent?): Boolean = true - override fun onFling(p0: MotionEvent?, p1: MotionEvent?, p2: Float, p3: Float): Boolean = true - override fun onScroll(p0: MotionEvent?, p1: MotionEvent?, p2: Float, p3: Float): Boolean = true - override fun onLongPress(p0: MotionEvent?) = Unit - }) - - detector.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener { - override fun onDoubleTapEvent(p0: MotionEvent?) = true - override fun onSingleTapConfirmed(p0: MotionEvent?) = true - override fun onDoubleTap(p0: MotionEvent?): Boolean { - listener() - return true - } - }) - - this.onTouch { _, event -> detector.onTouchEvent(event) } -} - -fun Iterable.disjunctiveUnion(other: Iterable): Set = (this - other).union(other - this) diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/utils/PrefUtils.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/utils/PrefUtils.kt deleted file mode 100644 index c82e5e3a34..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/utils/PrefUtils.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.utils - -import android.content.Context -import android.content.SharedPreferences -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty - -open class PrefManager(val context: Context, val prefsFileName: String = "prefs") { - val prefs: SharedPreferences by lazy { context.getSharedPreferences(prefsFileName, Context.MODE_PRIVATE) } - val editor: SharedPreferences.Editor by lazy { prefs.edit() } -} - -class Pref(val defaultValue: T, val keyName: String? = null) : ReadWriteProperty { - - @Suppress("UNCHECKED_CAST", "IMPLICIT_CAST_TO_ANY") - override fun getValue(thisRef: PrefManager, property: KProperty<*>): T { - val prefs = thisRef.prefs - val key = keyName ?: property.name - return when (defaultValue) { - is Boolean -> prefs.getBoolean(key, defaultValue) - is Float -> prefs.getFloat(key, defaultValue) - is Int -> prefs.getInt(key, defaultValue) - is Long -> prefs.getLong(key, defaultValue) - is String -> prefs.getString(key, defaultValue) - else -> throw UnsupportedOperationException("Unsupported preference type ${property.javaClass} on property ${property.name}") - } as T - } - - override fun setValue(thisRef: PrefManager, property: KProperty<*>, value: T) { - val editor = thisRef.editor - val key = keyName ?: property.name - when (value) { - is Boolean -> editor.putBoolean(key, value) - is Float -> editor.putFloat(key, value) - is Int -> editor.putInt(key, value) - is Long -> editor.putLong(key, value) - is String -> editor.putString(key, value) - else -> throw UnsupportedOperationException("Unsupported preference type ${property.javaClass} on property ${property.name}") - } - editor.commit() - } - -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/views/ConfirmPinDialog.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/views/ConfirmPinDialog.kt deleted file mode 100644 index a48a932223..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/views/ConfirmPinDialog.kt +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.views - -import android.app.AlertDialog -import android.app.Dialog -import android.content.Context -import android.graphics.Color -import android.os.Bundle -import android.support.v4.content.ContextCompat -import android.view.View -import android.widget.TextView -import android.widget.Toast -import com.google.firebase.database.FirebaseDatabase -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.bind -import org.jetbrains.anko.backgroundColor -import org.jetbrains.anko.sdk21.listeners.onClick - -class ConfirmPinDialog( - context: Context, - val user: User, - var createNewPin: Boolean = false, - var onConfirmed: (User) -> Unit -) : Dialog(context) { - - private enum class State { - NEW_PIN, - CONFIRM_NEW, - CONFIRM_EXISTING - } - - private var mNewPinHash = "" - private var mPin = "" - private var mState = State.CONFIRM_EXISTING - - private val mMessage by bind(R.id.pin_message) - private val mPinDisplay by bind(R.id.pin_display) - private val mPinPad by bind(R.id.pin_pad) - private val mBackspace by bind(R.id.backspace) - private val mUserName by bind(R.id.userName) - - private var onPinHashCreated: (String) -> Unit = { updateUserPinHash(it) } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.dialog_confirm_pin) - setupListeners() - mUserName.text = user.name - if (createNewPin) createPin() else confirmPin() - } - - private fun setupListeners() { - mPinPad.onButtonTapped = onButtonTapped - mBackspace.onClick { updatePin(mPin.dropLast(1)) } - } - - private val onButtonTapped = { number: String -> - updatePin(mPin + number) - if (mPin.length == 4) { - val hash = mPin.hashCode().toString() - when (mState) { - ConfirmPinDialog.State.NEW_PIN -> { - mNewPinHash = hash - setMessage(R.string.confirm_pin, R.color.confirm_blue) - mState = State.CONFIRM_NEW - } - ConfirmPinDialog.State.CONFIRM_NEW -> { - if (hash != mNewPinHash) { - setMessage(R.string.pin_mismatch, R.color.error_red) - mNewPinHash = "" - mState = State.NEW_PIN - } else { - onPinHashCreated(hash) - } - } - ConfirmPinDialog.State.CONFIRM_EXISTING -> { - if (hash != user.pinHash) { - setMessage(R.string.incorrect_pin, R.color.error_red) - } else { - dismiss() - onConfirmed(user) - } - } - } - updatePin("") - } - } - - private fun updatePin(newPin: String) { - mPin = newPin - mPinDisplay.text = "•".repeat(mPin.length) - } - - fun overrideOnPinHashCreated(block: (String) -> Unit): ConfirmPinDialog { - onPinHashCreated = { - block(it) - dismiss() - } - return this - } - - override fun show() { - if ("true" == user.pinDisabled) { - onConfirmed(user) - } else if (user.pinHash.isNullOrBlank()) { - showInfoDialog() - } else { - super.show() - } - } - - private fun showInfoDialog() { - AlertDialog.Builder(context) - .setTitle(R.string.create_pin) - .setMessage(R.string.pin_dialog_info_message) - .setPositiveButton(R.string.create_pin) { dialog, which -> - createNewPin = true - super.show() - } - .setNegativeButton(R.string.maybe_later) { dialog, which -> - onConfirmed(user) - } - .setNeutralButton(R.string.disable_pin) { dialog, which -> - showConfirmDisablePinDialog() - } - .show() - } - - private fun showConfirmDisablePinDialog() { - AlertDialog.Builder(context) - .setMessage(R.string.disable_pin_confirmation_message) - .setPositiveButton(android.R.string.yes) { dialog, which -> - FirebaseDatabase.getInstance().reference.child("users").child(user.id).child("pinDisabled").setValue("true") - Toast.makeText(context, R.string.pin_has_been_disabled, Toast.LENGTH_SHORT).show() - onConfirmed(user) - } - .setNegativeButton(android.R.string.no) { dialog, which -> - showInfoDialog() - } - .show() - } - - private fun createPin() { - mState = State.NEW_PIN - setMessage(R.string.enter_pin) - } - - private fun confirmPin() { - mState = State.CONFIRM_EXISTING - setMessage(R.string.confirm_pin) - } - - private fun setMessage(messageResId: Int, colorResId: Int? = null) { - mMessage.setText(messageResId) - if (colorResId == null) { - mMessage.setTextColor(ContextCompat.getColor(context, android.R.color.darker_gray)) - mMessage.setBackgroundColor(Color.TRANSPARENT) - } else { - mMessage.setTextColor(Color.WHITE) - mMessage.backgroundColor = ContextCompat.getColor(context, colorResId) - } - } - - private fun updateUserPinHash(pinHash: String) { - FirebaseDatabase.getInstance().reference.child("users").child(user.id).child("pinHash").setValue(pinHash) - Toast.makeText(context, R.string.pin_saved, Toast.LENGTH_SHORT).show() - dismiss() - onConfirmed(user) - } -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/views/CropOverlay.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/views/CropOverlay.kt deleted file mode 100644 index 3db8b614b8..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/views/CropOverlay.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.views - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.Path -import android.graphics.Region -import android.util.AttributeSet -import android.view.View -import android.view.ViewGroup -import com.instructure.androidfoosball.R - - -class CropOverlay @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : View(context, attrs, defStyleRes) { - - /** Resource ID of the source view */ - private var mCutoutSourceId: Int = 0 - - /** Reference to the source view. Bound in onSizeChanged() */ - private var mCutoutSourceView: View? = null - - /** Color of the primary overlay */ - private var mMaskColor = 0xAAFFFFFF.toInt() - - /** Frame path */ - private var mFramePath = Path() - - /** Frame backgroundPaint */ - private var mFramePaint = Paint(Paint.ANTI_ALIAS_FLAG) - - init { setup(attrs) } - - private fun setup(attrs: AttributeSet? = null) { - mFramePaint.style = Paint.Style.STROKE - if (attrs != null) { - val a = context.obtainStyledAttributes(attrs, R.styleable.CropOverlay) - - // Get source view ID - mCutoutSourceId = a.getResourceId(R.styleable.CropOverlay_cutoutViewId, 0) - - // Get primary overlay color - mMaskColor = a.getColor(R.styleable.CropOverlay_maskColor, mMaskColor) - - // Get frame stroke width - mFramePaint.strokeWidth = a.getDimension(R.styleable.CropOverlay_frameWidth, 10f) - - // Get frame color - mFramePaint.color = a.getColor(R.styleable.CropOverlay_frameColor, 0xFF888888.toInt()) - a.recycle() - } - } - - override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) { - super.onSizeChanged(width, height, oldWidth, oldHeight) - if (mCutoutSourceId > 0) { - mCutoutSourceView = (parent as ViewGroup).findViewById(mCutoutSourceId) - mFramePath.rewind() - - val x = mCutoutSourceView!!.left.toFloat() - val y = mCutoutSourceView!!.top.toFloat() - - val w = mCutoutSourceView!!.width.toFloat() - val h = mCutoutSourceView!!.height.toFloat() - - val centerX = x + w / 2f - val centerY = y + h / 2f - val radius = Math.min(w, h) / 2f - - mFramePath.addCircle(centerX, centerY, radius, Path.Direction.CW) - } - } - - override fun onDraw(canvas: Canvas) { - // Skip drawing if there is no source view - if (mCutoutSourceView == null) return - - // Draw primary overlay - canvas.save() - canvas.clipPath(mFramePath, Region.Op.DIFFERENCE) - canvas.drawColor(mMaskColor) - canvas.restore() - - // Draw frame stroke - canvas.drawPath(mFramePath, mFramePaint) - } -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/views/PinButton.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/views/PinButton.kt deleted file mode 100644 index 821f91c485..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/views/PinButton.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.views - -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.content.Context -import android.util.AttributeSet -import android.util.TypedValue -import android.view.Gravity -import android.view.MotionEvent -import android.view.View -import android.widget.TextView - -class PinButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : TextView(context, attrs, defStyleAttr) { - - private val animator = AnimatorSet().apply { - playTogether(ObjectAnimator.ofFloat(this@PinButton, "scaleX", TOUCH_ZOOM, 1f), - ObjectAnimator.ofFloat(this@PinButton, "scaleY", TOUCH_ZOOM, 1f)) - duration = 150 - } - - var onTap: (String) -> Unit = {} - - init { - gravity = Gravity.CENTER - setOnClickListener { if (!text.isNullOrBlank()) onTap(text.toString()) } - } - - override fun onTouchEvent(event: MotionEvent): Boolean { - when (event.action) { - MotionEvent.ACTION_DOWN -> { - animator.cancel() - scaleX = TOUCH_ZOOM - scaleY = TOUCH_ZOOM - } - MotionEvent.ACTION_UP, - MotionEvent.ACTION_CANCEL -> animator.start() - } - return super.onTouchEvent(event) - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.EXACTLY) { - val height = View.MeasureSpec.getSize(heightMeasureSpec).toFloat() - setTextSize(TypedValue.COMPLEX_UNIT_PX, height * NUMBER_SIZE) - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - } - - companion object { - private val NUMBER_SIZE = 0.5f - private val TOUCH_ZOOM = 1.3f - } -} \ No newline at end of file diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/views/PinPad.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/views/PinPad.kt deleted file mode 100644 index 197e03dfc6..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/views/PinPad.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.views - -import android.content.Context -import android.util.AttributeSet -import android.view.View -import android.widget.FrameLayout -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.utils.modifyDescendants - -class PinPad @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = 0 -) : FrameLayout(context, attrs, defStyleAttr) { - - var onButtonTapped: (String) -> Unit = {} - - init { - View.inflate(context, R.layout.view_pin_pad, this) - if (!isInEditMode) modifyDescendants { it.onTap = { number -> onButtonTapped(number) } } - } -} diff --git a/foosball/app/src/main/java/com/instructure/androidfoosball/views/UserInitialsDrawable.kt b/foosball/app/src/main/java/com/instructure/androidfoosball/views/UserInitialsDrawable.kt deleted file mode 100644 index 6d244222ae..0000000000 --- a/foosball/app/src/main/java/com/instructure/androidfoosball/views/UserInitialsDrawable.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.views - -import android.graphics.* -import android.graphics.drawable.Drawable -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.avatarColor -import com.instructure.androidfoosball.utils.clampToBrightness -import com.instructure.androidfoosball.utils.initials -import com.instructure.androidfoosball.utils.unless - -class UserInitialsDrawable(val user: User, val size: Int = 0) : Drawable() { - - private val MAX_BG_BRIGHTNESS = 0.6f - private val MAX_TEXT_WIDTH_PERCENTAGE = 0.9f - - private val mPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { - color = Color.WHITE - textAlign = Paint.Align.CENTER - typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) - } - - override fun draw(canvas: Canvas) { - canvas.drawColor(user.avatarColor.clampToBrightness(MAX_BG_BRIGHTNESS)) - val initials = user.initials - val srcHyp = Math.sqrt( - Math.pow(mPaint.measureText(initials).toDouble(), 2.0) - + Math.pow(-mPaint.fontMetrics.ascent.toDouble(), 2.0) - ).toFloat() - mPaint.textSize = MAX_TEXT_WIDTH_PERCENTAGE * (mPaint.textSize * canvas.width / srcHyp) - canvas.drawText( - initials, - canvas.width / 2f, - (canvas.height - mPaint.fontMetrics.ascent - mPaint.fontMetrics.descent) / 2f, - mPaint - ) - } - - override fun getOpacity() = PixelFormat.TRANSLUCENT - override fun setAlpha(alpha: Int) { } - override fun setColorFilter(colorFilter: ColorFilter?) { } - override fun getIntrinsicWidth() = bounds.width() unless {it == 0} then size - override fun getIntrinsicHeight() = bounds.height() unless {it == 0} then size -} diff --git a/foosball/app/src/main/res/drawable-hdpi/ic_arrow_back_grey_700_36dp.png b/foosball/app/src/main/res/drawable-hdpi/ic_arrow_back_grey_700_36dp.png deleted file mode 100644 index b873bdfa110610f8d331189dd79be7c23d0c266a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 267 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL1|)l2v+e?^OP(%{Ar-gY-aIJSWFXM`Q08l! zY-E$}65(IY)*IP*jb-+<1V(I{{k*<{wZ>U3=iah8#X&wyY&;SM2?rW#rxtdKxx_+DAnQ1E2Z6CH(=XxU}Gsso_dl>g!a;{y&<{1j~ O9fPNI!wh=E|46gd!i5Q#*7YMAf%_dgctU;<5x z+|(2$FV7-NSU?w!;UswyX+v@L9K}g;1i@Jl`EVTQ9s)FQ97pC;7iYHtIDgT>nQuU8 zfq<@>f};bp(iBz$#7F#-h12u>c*EJ0~uA{oQU13ELb2-86_ijxJj zVR)sgg5`K8SBA zPK3Nw0%}%63vn>FO29xSN)6I@8b!(*z_%2~I8xC7p`|!FTO}kw6s5L`yzox;DmeDhT@@E0b)W}`DvL1eQX6IxC8aLRnVK=D>{=Hmq$ zdbL`7A7sK`3%IR1_o+Wsp)P|`3%IR2D*ySlv2BcUWanM)DAH&)SWnr^N4Yw zPG(Bv+CiK}%uBr!BKsn@B42f#kmZ~s%PPIwz*oQd-aG>_5Cbs~12GT-aWeA@!Ok7j T{gajA00000NkvXXu0mjfL((15 diff --git a/foosball/app/src/main/res/drawable-hdpi/ic_close_white_48dp.png b/foosball/app/src/main/res/drawable-hdpi/ic_close_white_48dp.png deleted file mode 100644 index 717c7b59190385c7c55c515beb1f45439eee6d19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2V4Ujd;uunK>+P+Bd4~*mjurad zJya|Ev~7y-*f|&&Sp*!w1Pg@9W~-Y2 z$l$2LoeQ@`j%#ka*^oA;`|mn^!Am{Ham70-6e}Ok;K=Mu=3X*a>V=q}$tB%6s+Zz8 zza;iwFHc_LZc+bw0gKc+4z49ab6%~#p&ZB>#L@R$Q>;^@?Qt#tEMcp^lYgu<`WP@r z%>3mvkB1g(y?Vtwgyu}!IzxRD&+^iZuNqa3cCL8V-o)EiZl-a(Gpl@0(-bE4P4ZuO zf~4lWXp7Vgl9F+C-}vOUNAu#Wo%^~}GLL9RFHSC#DZRW;#IucAz~1oR63b`TOU_Kc zHzCwEPxFHD)58-uHKqO9GCef{d>_ta($w~QqTs;v4uu9V!2zMFy5$om-}hO)V5KH7o)|n`{an^LB{Ts5sZG74 diff --git a/foosball/app/src/main/res/drawable-hdpi/sadpanda.png b/foosball/app/src/main/res/drawable-hdpi/sadpanda.png deleted file mode 100644 index 7bfd91bb89b11b93237950f264b411e6f6213b14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27917 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�dF9vmE~ybQf;3App)k8$~qJP|~D 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�Jr+Z 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 G@c#fB8KD;d diff --git a/foosball/app/src/main/res/drawable-mdpi/ic_arrow_back_grey_700_36dp.png b/foosball/app/src/main/res/drawable-mdpi/ic_arrow_back_grey_700_36dp.png deleted file mode 100644 index 362fe334509668a623e7e39b713c9d5f20236bd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBW_!9ghE&{od)=3-K|!D`ap8jE zD&g|j74v6r)nyeo>R9p9_|*1_@BEUFHI__i3T9GhVED8=N5_Hf)2)#F3EhTwcP$k^ z(SEb4Rb zicbBjWyTpV4&HboH~Udh>dv|iF&CUxhmViFjEhk)Qk?seg- z0O48II`Bu3&p-vXv6hauz$j$+zXaH-^AWSaitxY8cr&VgfYAMP1+8vR^r?PJZ8rxHFGx} z;H^oh1XwA(5(GxXWm2`-Ri+1;A@M*{5ZCy&L}_}U5t;XJq^xWmDOvW2r4-b)%0=t~ zKAJt}0xsKaF9NO(Jl-yMMHT@HEHMIXReB5vo?Uwmu&-Hp^2CxGti$Q;Z^2qD!Xpyz3;wxcLE3?fB*sr@K1nC z*e>jz5XOc*Z)Z>d@xeF$SSuJ|w`az+!X}>Cv)%zD zqB#87TPTGXYKJemMu!3fEPQDlID>$OM-;LYVyqD!Rf)$p5R~x9R^kXj3yvk`%46&{AjIcz3X)jh<-8f+~U23w9b*s3vFoS36UO{WDAKmY** b5CFaJELQUamZcBV00000NkvXXu0mjf$2@;u diff --git a/foosball/app/src/main/res/drawable-mdpi/sadpanda.png b/foosball/app/src/main/res/drawable-mdpi/sadpanda.png deleted file mode 100644 index 536e4e7768935e0a346d8932b54647d8042f94b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22255 zcmV(#LFB%PP)-Q`_)tIO5A+qXO4&Ns8Ovx39n08tb{DY7d<8Skm}dVQ=z

5V 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 diff --git a/foosball/app/src/main/res/drawable-xhdpi/ic_close_white_48dp.png b/foosball/app/src/main/res/drawable-xhdpi/ic_close_white_48dp.png deleted file mode 100644 index 9ef2d8f9fbe5914285f0776e412c4d1be25d17aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 601 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U{dgOaSW-r_4ZC+UbBIS%f%dp zw?z$e53|kETYi>JV@2nbevLzo>E~~VXZ|}qXB+3Y!^v<76Oj13%SGvlPQ2{H$e#~6cAgG*tq85ta5{3<=kvDL;Vg;XKfh-eF}%ooYNfDb ziu|W=>C$9Aj-#jh|A{T>Q3$N-d(Pm>GV@chEvL4k$JF`7x*DPj^B4ZP(_L8W$a3`yKlehY9-ozqI*i9SVs4$z`47%+TcfQ!9FsyHdo|^;^_y zSejygX3hRoEueEcd`?#d`@wBBS2s?X;d`RHW&PO55cgztX3> zd(`%ICm3=(GtsJ8yS9db;X%BB{2_)9rc>Ar8OqjX?doy7rE_fQy0<0gINm+A=3_aX zcj8U#)h#Y7mexeK%sRE*WyRW>rI8_-4KlYo_A)!YUC(+_dCP~W2_{b3?^8}HZTaFC z_C#luNyDW(=N7bGxWZl7#j$p(e*1-_pFtdJr|CBf6b3K8sTX=m|I7=94RSAw3~wvl zY1%MvUTN7+o{H876$!x}KQG>Inx|+X7bzA746p{#gMTmVyD(YUa@(d)$=aN_;*enh fFd`M6eq#S;eQNDygJ~+j2xjnf^>bP0l+XkKX6gf2 diff --git a/foosball/app/src/main/res/drawable-xhdpi/sadpanda.png b/foosball/app/src/main/res/drawable-xhdpi/sadpanda.png deleted file mode 100644 index 924f7eb8ee892f3910c4e0f336eafb21dce0f072..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47026 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 diff --git a/foosball/app/src/main/res/drawable-xxhdpi/ic_backspace_grey_500_48dp.png b/foosball/app/src/main/res/drawable-xxhdpi/ic_backspace_grey_500_48dp.png deleted file mode 100644 index 200b5f8be90f0669757039ed1074e8da86494cd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1358 zcmZ{k>sQhT9L9ejh+-(3Qr-Y%DLN}9Gb^*-7}rdRv|3)8<^7(fi!eJ#R(L5zX>P}f z1{&&8^NyD0ZKZDJh04@CS#C%0ikIBXsbhaYFTT&`&2!H4ee*o&r@ZJWq!|(b02Gr! zIjv#N|EHs^(P`R8IRL;-n3QjPIAik@&9Se*-R(>D&d%@X3_ejAuIwTJkj@mG2^^Zr zfna%vxB6sxw`tXM@yW}^;JY+{>IysX_{X#C+Nc4}vG<2o_HU)Qt$4RJjI6CWo884) zk9-G%q9Fo+0$6{EMyT-ns$W#)ss@!zW$=2~K=HNWfP(7%%m&Q#%=fH|F8S$30nIaI z7!pHj4eaV(>#t|o7xzDmaA8uzN+G^M+^*+kk=0*;tWk7Q%E8J!Kxtg?piwx;do*e4 zLjE**9w*Jb-hxIBFfqq7#EvaJGCSI?b!Wdr;++m$f2S4(s@T@SmFIu-a z7;`XdUxg)Fs;41ROX;My13z-FMh+yz>}`@kdt`J62aUbr&-NFdekb#gTW=n%H-*+{ z4U<})uWVfNoV`Wp^Tp21<_pSBfI)rgRUNvhf5j)fs6K4EqVo#H4qGm$b;&l)B>TL+ z5}?RfVtgw~;$mCV!>uu3kl|#nxlUG@4wfyrgbN5!r_p@0S+kzpoxTtzE?^&rY?aVK zfC>$Y?{sc&?BH%)t<)15h@b8q11!&8esge?f;VNGaQHX=xoR0ubl*R|3dz)9NGX;_kZ_HpMRqA0cDN~E!t9bsnK`l=p>GIYde4wLFqZscIOL+C! zRk2p~++=D!Cj;7oQ%xi$;WNxwh9H9QY)@T*K=MMNo3q)R%F=x|;`bYEfGUECy?6_@ zJej#5w?m;nma<-qbc@Ff57WW zABIefguZT9AQN!Ud4bPV1iV{WffI7w4&#ruxI;_NQrMHdkO>H*QuBVERtr)eSO~xgt5WzkH@E}-(B)M~U9+XHBjxcQXuP@F&67*TL6FE=YxB?^g&&Mxp z5cAaC;e~N4S8RIU_60-AF)wU*xYX9IJDT zkvh=py?XoSsp#@H{gQZ561hZ0zk25T^w<$psla)2u1Ws>UbRuqZFXqXrrk-^KyZV# z(H&VN*cfo4>Qwfj>cVjOqHEMvWyK;QBSs_)1b+~j9SMZS+uhnkif>c)VZJohCm`jjq#25g1D_i-gn`urcTAtbocu5mn(+md{+cxFl7^ z6T!yuXx`_ScVOK_#l-&PurP+kJrPioyxR;N7ILJ(sq#KFoVlWV+J(mITHj&p1oQnD*QG;i4G=EMk9xvHb)HZ#$`-w0eNj2kF{L~i;gjyZ>N zBR==i-u(S3t+g|HztPyN+g<%d;~b3}di6m9qg4n5m~HcTb7m;S}c*6bv} Mq3eu-I7$jH!b$-=z5|4Tj{RhQTCi`upOm!0nEPbz=Sx)mB&CNKy&2sto$ zFmNhxDln=51;9c~9$+D$07wX~W&z_~xm$8o-xPK0`QG~3GyYPX*Z=f$1-E;N%jdeN z?(bb4T8|?S3C2E(T&1+CPhIq4c!ihJEJlB+MejevC{;1OcwP}C@R!A3)5ZAV%f1&< zHqRd?n=HEdp~Urzw2i7jZ_JjvMYlh0=Uf#1VNQRp(t_v0O(`zf4{xa@ z_^FnTU?8{6)OXCPidoIeZ_Rzd;DDwPGM+ZWDSA|Z*zt1D!2y_mTEp2HQM3mxCL zDP%EaJn^m<@a0=^NP6*HwO8(ptG?{|s3s|B^Eb_m$wYEqhRX*B5yp&Vg4%%{4;ojP zE|}SF?W)kkzGzy5Rqs^mx*xx#|4*w81**Ej72s~OR`4KmAh!c&MU)ay%}PeqN13f0 zavjT9w{RcdthQ*aae&%9(`%3Ze)+wRx%JV`RNb~mD~m+G6&*cPDj!zByXaws)?Ich zrC%J!i+L9bRjj((`HwH~){7nQ1*RSh{up^9ydy|`L0#(#k$J29AIIwpxSmh=#~)~E zGxa<3-g)nGRUYqj*|NGLy-j!RCiN%=PhgrwBv5#Y1t(&LNx(DljzJYD@<);T3K0RYd%SJnUk diff --git a/foosball/app/src/main/res/drawable-xxhdpi/sadpanda.png b/foosball/app/src/main/res/drawable-xxhdpi/sadpanda.png deleted file mode 100644 index a6028541e191b1c4a85263fcb5ca24c9f8ac51ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76943 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�tRJ&J9O2)qfhd4ouy->vq1q? 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 O_^B#sDAveZM*JTZY@BWY diff --git a/foosball/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_grey_700_36dp.png b/foosball/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_grey_700_36dp.png deleted file mode 100644 index a1e1b1a153e04ff9446e88ba5e9e863d66cab39a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 537 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$farf$@Q-i(^Q|t+#hK@-`a?I0UjK zOXfRHYCG%cykyG7xvU%Ci`FxKPH`|x%Ur7)WYVnAz%qeB$U(?~$%BDYfm4A|1t}7RJvlOf3Fe&hoJE+b|qt7Jv{R z7+ClnJ}{WD&SO_GWrPc_V&IT#c)$oE0$CkwKiDv?;Dn0svLG|^j(#p`%w}q0SEyiU za%W~lVl0UM_+tAqX0Z7swjg=-1+PI?I56yNWqhI-756wcph1D@L=c;USg`K0Tjv-B z9RwIzCg!YaKap+=WC6J+A99_2$kkWg$f3}|(B#2)vjxlm5+=+G;yV81EHwa0Km?V5 zrg1=s4u)5q8O%%dut_djAJ(AI_2}kV2L@Ncx5s!FXed=Ma47?wXMoN?33UcZ7H}jm pOajIWFbX_@@dAm22@ID^_A)Byzmvv4FO#npWoiYFb diff --git a/foosball/app/src/main/res/drawable-xxxhdpi/ic_backspace_grey_500_48dp.png b/foosball/app/src/main/res/drawable-xxxhdpi/ic_backspace_grey_500_48dp.png deleted file mode 100644 index 31a11d94e804996fb29e60f01373215bf4dde8df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1796 zcmbVNYgAKL7C!fKgCv3tH#|a72#}D7hzOR2Ji;YB1f&>f5CzI(5ODh7r8Fo3E|El7 zh+t(zi%0-VQ;^8RSu(9QAqX;qPO&2`;v-}Pv1lb-l#;?V%+)=KQtkUq0K2+1f#L03h&x7|p3|Xeqk4#u?3J zRB%m|6T}7ovqpX)yDwyCH(T@jt?`;8RZswNrX;wq^eE)?Lh>))qf^hX4sWaJxrYq0 z`^NCh@bZ{D5!N$5+=`deviiRm^p%3EJ7doaq`SX|gYMGXur1RI@pua3g(aO*3v*-(W z7VZH>E&jS zlFuiTk+39E)7^v{9H|EOkW-4Z#cD5RtV6~o=Qp>hl3{H=4@`cQM(_iq*q0EQTo)4hqfSa2jaqk#Oq1<16O77+AK6AwwO-s3XsEbpNG>V5GV5V`aimi&JMueizt{Yug4 z!j7xq-$i76sok-4s8^<-{VYq5liszHdWghEu^5Ag>-v;}WqHNTEo+;fdLUzo&+WCT z*~V|z?NBDI;TVo3Ihs1z2R^W4E%^boE;-BsweMJ$f1WxrF0a>8j@A7?akxOVM zbiYejW%hG}q8I#))`ONOF0!PeNHs1sD{^$vGj{B}i}NjDG|ldJ+aVJ*;nR)I=D2km_VvOq6i#Ng#(^z$o7a zweN4c^Y^W6L;tV$ccFtc^_L*Nd*U)$^04^R&jZt6Y4f*ZDuLSkT!#B$BlnCZ+t@=H zdr2jpPVvwZUH%ap>Laepb$8mJ%HkPRsXtQ{nmTqdlfVYcwGw-cJbid=-G7#73i?eN*-V8J6*fdBk92NEr2 zDWrm)!(?0WS##L5OCw9Bj7i3D&H2eMD1)axkkKpmJ+Wu;azyU=qZjtf&7AC3%PbP; z>EAl_EEIIn5A-$;%tera&CS;r2JbeLjCdn$d8#0);r#V@lPys2L? z0*^1v#^c*tHZsj=Pvz^UO+m+O6ytj>ZAX>Cf#!2#1K>g_8seM5EV@1~%%87!$J`gk z*Z&mw?A{gcKk8HWK2B*Fu4Z9P@S|YQ+RiWze5Qkt$}O` z%t12SKdiG*kaW-$;aZ!0eM z%ZYrw^X?s6hSSpj6Mt3MItQ5jyMEcQPMY;##^d=48uI^38Xqt=JnfZl`t^~&IpNAj z=K%YEiUK`0bsVpb*LNl`ANX{P-|_E{Xk`xxdzP<{^Sc#N{|H>^|NqCT#A$*FNY#Bl z$6G%XSIF0Ev&j0LD_d3R7-0VI^J~tA*VcVsmcC%w+oHTeroKDhAl6TW<(T|`JpmwD zFU!F6xPQM8Pvghq_qka>Brg|`wC864k%DX>QWzv#ujOLewDn_uIrqtq_a#e|4gP)L zKj!6@@Q2}ul0h9qlAwe=!$yuC`GyFVWBd*}Opna1Z3W?$znb73_v>w;f55T8yFb+j2Y@!i}o;naNm&3->}_rE;B<6hcH84 zs{lh@8<1`nW030*WRU9=VQ_rh&d?C{xZaMHkzwNF{nnvB?N2K(By4?Hj z!f>Qto{8bnaehXIk08ZAJ~}fv{Q05CpiuWmfI+~%4ya82f4yP^bHX3*{r}T=85vgM zREKVyf=t85dRwvIi;_3Wb2fhLH?QM3!~l%wjSM~VO%V*hsMle5+^!(j@X=X-`@j#y z4%UP}0!Nq(>Nt`Zfyyp2lpVV-c95^(b@hyD<9}uLsr}F2$Td7wH27D=qI>NA+t>xs z3LtjwvHKsb4m{&xITqi);OdXvah(6SnI5lqzmWH5?t4}%B@2oFNdjAB>eCta1EcIK z$F08o)(!IoB - - - - - - \ No newline at end of file diff --git a/foosball/app/src/main/res/drawable/vd_add_black_24dp.xml b/foosball/app/src/main/res/drawable/vd_add_black_24dp.xml deleted file mode 100644 index f06436f079..0000000000 --- a/foosball/app/src/main/res/drawable/vd_add_black_24dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/foosball/app/src/main/res/drawable/vd_group_add_white_48dp.xml b/foosball/app/src/main/res/drawable/vd_group_add_white_48dp.xml deleted file mode 100644 index e85f005609..0000000000 --- a/foosball/app/src/main/res/drawable/vd_group_add_white_48dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/foosball/app/src/main/res/drawable/vd_search_black_24dp.xml b/foosball/app/src/main/res/drawable/vd_search_black_24dp.xml deleted file mode 100644 index 56e0927aa8..0000000000 --- a/foosball/app/src/main/res/drawable/vd_search_black_24dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/foosball/app/src/main/res/drawable/vd_volume_up_grey_500_18dp.xml b/foosball/app/src/main/res/drawable/vd_volume_up_grey_500_18dp.xml deleted file mode 100644 index 661fec29dd..0000000000 --- a/foosball/app/src/main/res/drawable/vd_volume_up_grey_500_18dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/foosball/app/src/main/res/layout/activity_change_avatar.xml b/foosball/app/src/main/res/layout/activity_change_avatar.xml deleted file mode 100644 index ebf35e8983..0000000000 --- a/foosball/app/src/main/res/layout/activity_change_avatar.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/layout/activity_edit_player.xml b/foosball/app/src/main/res/layout/activity_edit_player.xml deleted file mode 100644 index 8e9a16abf4..0000000000 --- a/foosball/app/src/main/res/layout/activity_edit_player.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/layout/adapter_foos_rank.xml b/foosball/app/src/main/res/layout/adapter_foos_rank.xml deleted file mode 100644 index 3c83578237..0000000000 --- a/foosball/app/src/main/res/layout/adapter_foos_rank.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/main/res/layout/adapter_time_waster.xml b/foosball/app/src/main/res/layout/adapter_time_waster.xml deleted file mode 100644 index 2d03657211..0000000000 --- a/foosball/app/src/main/res/layout/adapter_time_waster.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/layout/dialog_confirm_pin.xml b/foosball/app/src/main/res/layout/dialog_confirm_pin.xml deleted file mode 100644 index e149ccbe58..0000000000 --- a/foosball/app/src/main/res/layout/dialog_confirm_pin.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/layout/dialog_team_picker.xml b/foosball/app/src/main/res/layout/dialog_team_picker.xml deleted file mode 100644 index 62bf040ff8..0000000000 --- a/foosball/app/src/main/res/layout/dialog_team_picker.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/layout/dialog_user_picker.xml b/foosball/app/src/main/res/layout/dialog_user_picker.xml deleted file mode 100644 index 4b40512a71..0000000000 --- a/foosball/app/src/main/res/layout/dialog_user_picker.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/layout/view_pin_pad.xml b/foosball/app/src/main/res/layout/view_pin_pad.xml deleted file mode 100644 index 843748e25d..0000000000 --- a/foosball/app/src/main/res/layout/view_pin_pad.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/main/res/mipmap-hdpi/ic_launcher.png b/foosball/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100755 index 3cd7753f361354f81bd90adb725b6c4f271c58cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4942 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 M07*qoM6N<$f+lrz+yDRo diff --git a/foosball/app/src/main/res/mipmap-mdpi/ic_launcher.png b/foosball/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100755 index b2872af092dfb97d515baca28da0b38afafd4294..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3031 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 Z{{dzCmdu2o0%-sM002ovPDHLkV1hJ_yY&D7 diff --git a/foosball/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/foosball/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100755 index 16802cb60a4721eec529c3f5304b0538aa44314b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6979 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 Vi}x)W`lSE>002ovPDHLkV1i`BVm|-? diff --git a/foosball/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/foosball/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100755 index a9e0158ee41753e1f239866e410371bfc32aecdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10988 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 BDtrI{ diff --git a/foosball/app/src/main/res/values-w820dp/dimens.xml b/foosball/app/src/main/res/values-w820dp/dimens.xml deleted file mode 100644 index 8746fd7ce6..0000000000 --- a/foosball/app/src/main/res/values-w820dp/dimens.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - 64dp - diff --git a/foosball/app/src/main/res/values/attrs.xml b/foosball/app/src/main/res/values/attrs.xml deleted file mode 100644 index 0e604f998f..0000000000 --- a/foosball/app/src/main/res/values/attrs.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/values/colors.xml b/foosball/app/src/main/res/values/colors.xml deleted file mode 100644 index ea6139431a..0000000000 --- a/foosball/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - #383838 - #232323 - #00ACEC - #00ACEC - #DC3C00 - #00AC4C - #DDD - #fdcd20 - diff --git a/foosball/app/src/main/res/values/dimens.xml b/foosball/app/src/main/res/values/dimens.xml deleted file mode 100644 index 7f13e1bb14..0000000000 --- a/foosball/app/src/main/res/values/dimens.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - 16dp - 16dp - 40dp - 70dp - 140dp - diff --git a/foosball/app/src/main/res/values/strings.xml b/foosball/app/src/main/res/values/strings.xml deleted file mode 100644 index 6520f975d5..0000000000 --- a/foosball/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - Foosball - Loading - Wins - Losses - Pick a table - Pick a user - Pick a team - Start Game - Okay - Winner Winner! - %s won! - All Done - Swap sides - Quit Game - %d wins - %d losses - Leaderboard - FoosRank - Team - Individual - FoosRank Over Time - Add Player - Add Team - Create Player - Reset Teams - Change Avatar - Error uploading photo. Try again. - Uploading… - Pinch-zoom and drag to adjust your photo. - Cancel - Done - Create New Player - Display Name - Email - Confirm Email - +\nAdd Avatar - Please assign teams - Assigning team… - ASSIGNED TO - Something broke, and it\'s probably your fault. - Win Rate - Foos Rank - N/A - %.1f%% - Create Pin - Maybe Later - Disable for my account - Are you sure you wish to disable PIN protection? - PIN protection has been disabled for your account - Your player account can now be protected with a 4-digit PIN. This will help prevent evil coworkers from changing your avatar or \'accidentally\' assigning you to a team when you\'re not around or \'accidentally\' making you lose several times. - Enter a 4-digit PIN - Confirm PIN - PINs do not match. Do it again. - Incorrect PIN - Contact an Android engineer to reset your PIN - PIN successfully saved - Syncing Table Info - New Game - Cut-Throat - Resume Game - Players need at least %d games to rank - Players need to suck less to do better - Player rankings based on the ELO system - Enter team name - Best of - rounds - points per round - Uneven Teams - The teams have an uneven number of players. Do you still wish to start this game? - Avg. Win Rate: %.1f%% - Pause Game - Game Paused - Are you sure you wish to quit this game? You will NOT be able to resume it later. - Starting next round in… - Undo last goal - Swap\nNow - round - of - points to win - %s wins this round! - %s wins the game! - Best of %d - End Game - Guest accounts cannot be edited - Goal Timer - SERVING - Round Timer - Game Timer - Jordan Marshall and Brady Larson welcome your Motivosity love.]]> - 3 players minimum - Force rotation after - points - New Cut Throat Game - NOTE: Results are not recorded for cut-throat games at this time. Player win rates will not be affected. - Edit Player - Custom Team Assignment Phrase - Custom Victory Phrase - Save Changes - Enable PIN protection - Change PIN - Search - Time Wasters - Most rounds played - Rounds - %.2f hours wasted - 4 Players Required - Team Twister - Which players make the best team?\nTwo players swap sides after each goal to cover all possible team combinations. First team to 4 points wins.\nUnranked. - New Team Twister Game - King of the Table - Who will be King of the Table?\nPlayers change teams after every round, 3 rounds per set. The player with the most goals at the end of the game will be crowned King!\nUnranked. - New King of the Table Game - set(s) - %d rounds total - Duration: %1$d to %2$d goals - Duration: %s goals minimum - Warning! The table has been requested by another group. - Table requested by %1$s on %2$s - Table requested - Another group wants to use the foosball table when you\'re done.\nPlease be mindful by quickening your pace and accepting the final score. - Alternatively, if you are an unfriendly group of people, please consider taking some of the following actions to demonstrate your special qualities: - • Play slower. There\'s no rush. Your time is the only time that matters.\n• Keep adding rounds; never accept defeat. It\'s a matter of pride, after all!\n• Generate lots of heat. Breath through your mouth so the next group doesn\'t have to play in the cold.\n• Don\'t wear deodorant. Intimidate your opponents with chemical warfare.\n• Eat a large meal right before playing. Ensure everyone enjoys the smell of company lunch a second time.\n• Eliminate any ventilation. Who knows when a stray draft might shift the ball and cost you the game?\n• Be as loud as possible. Surely you can level up your game through sheer volume.\n• Use brute strength instead of skill. Break some equipment and tell nobody. - diff --git a/foosball/app/src/main/res/values/styles.xml b/foosball/app/src/main/res/values/styles.xml deleted file mode 100644 index 476ce214ec..0000000000 --- a/foosball/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - diff --git a/foosball/app/src/main/res/xml/file_paths.xml b/foosball/app/src/main/res/xml/file_paths.xml deleted file mode 100644 index 3e34f4832a..0000000000 --- a/foosball/app/src/main/res/xml/file_paths.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/phone/AndroidManifest.xml b/foosball/app/src/phone/AndroidManifest.xml deleted file mode 100644 index bd10f5860b..0000000000 --- a/foosball/app/src/phone/AndroidManifest.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/BaseFireBaseActivity.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/BaseFireBaseActivity.kt deleted file mode 100644 index 51505af9fc..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/BaseFireBaseActivity.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.activities - -import android.support.v7.app.AppCompatActivity -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.database.DatabaseReference -import com.google.firebase.database.FirebaseDatabase -import com.instructure.androidfoosball.interfaces.FragmentCallbacks -import com.instructure.androidfoosball.models.User - -abstract class BaseFireBaseActivity : AppCompatActivity(), FragmentCallbacks { - - override var mUser: User? = null - override var mAuth: FirebaseAuth? = null - override var mDatabase: DatabaseReference? = null - - protected abstract fun onAuthStateChange(firebaseAuth: FirebaseAuth) - - protected fun initFireBase() { - mAuth = FirebaseAuth.getInstance() - mDatabase = FirebaseDatabase.getInstance().reference - } - - private val mAuthStateListener = FirebaseAuth.AuthStateListener { firebaseAuth -> onAuthStateChange(firebaseAuth) } - - override fun onStop() { - super.onStop() - mAuth?.removeAuthStateListener(mAuthStateListener) - } - - override fun onStart() { - super.onStart() - mAuth?.addAuthStateListener(mAuthStateListener) - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/NfcReadActivity.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/NfcReadActivity.kt deleted file mode 100644 index 1a6af5ce5a..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/NfcReadActivity.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.activities - -import android.annotation.SuppressLint -import android.graphics.Color -import android.nfc.NdefMessage -import android.nfc.NfcAdapter -import android.os.Bundle -import android.os.Handler -import android.support.v7.app.AppCompatActivity -import android.util.Log -import android.view.View -import android.widget.Toast -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.auth.FirebaseUser -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 com.instructure.androidfoosball.R -import com.instructure.androidfoosball.models.Table -import com.instructure.androidfoosball.utils.Prefs -import kotlinx.android.synthetic.phone.activity_nfc_read.* -import org.jetbrains.anko.startActivity -import org.jetbrains.anko.vibrator - - -class NfcReadActivity : AppCompatActivity() { - - private val TAG = "FoosNFC" - - private val mAuth = FirebaseAuth.getInstance() - internal lateinit var mUser: FirebaseUser - private val mAuthListener = FirebaseAuth.AuthStateListener { firebaseAuth -> - val user = firebaseAuth.currentUser - if (user != null) { - mUser = user - parseNfc() - } else { - startActivity() - finish() - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - vibrator.vibrate(200) // Provide haptic feedback as soon as possible - setContentView(R.layout.activity_nfc_read) - } - - private fun parseNfc() { - try { - val rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES) - val foosRecord = (rawMsgs[0] as NdefMessage).records[0] - - val uri = foosRecord.toUri() - val segments = uri.pathSegments - - Log.i(TAG, "Read NFC Tag for table " + segments[0] + ", side " + segments[1]) - - assignTeam(segments[0], segments[1].toIntOrNull() ?: 0) - } catch (e: Throwable) { - try { - val segments = intent.data.pathSegments - Log.i(TAG, "Read URI for table " + segments[0] + ", side " + segments[1]) - assignTeam(segments[0], segments[1].toIntOrNull() ?: 0) - } catch (e: Throwable) { - fail(e.message ?: "Unknown error parsing NFC data") - } - } - } - - private fun assignTeam(tableId: String, side: Int) { - - val db = FirebaseDatabase.getInstance().reference - db.child("tables").child(tableId).addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - val table = dataSnapshot.getValue(Table::class.java)!! - - val colorString: String - val teamColor: Int - - colorString = if (side == 0) table.sideOneColor else table.sideTwoColor - teamColor = Color.parseColor(colorString) - val teamName = if (side == 0) table.sideOneName else table.sideTwoName - val userId = Prefs(this@NfcReadActivity).userId - Log.v(TAG, "Assigning Team " + side) - db.child("incoming").child(tableId).child(if (side == 0) "sideOne" else "sideTwo").setValue(userId) - - success(table.name, teamName, teamColor) - } - - override fun onCancelled(databaseError: DatabaseError) { - fail(databaseError.message) - } - }) - } - - @SuppressLint("SetTextI18n") - private fun success(tableName: String, teamName: String, teamColor: Int) { - successView.setCardBackgroundColor(teamColor) - tableLabel.text = tableName - teamLabel.text = teamName - loadingView.visibility = View.GONE - successView.visibility = View.VISIBLE - errorView.visibility = View.GONE - finishAfterDelay() - } - - - private fun fail(message: String) { - Toast.makeText(this, message, Toast.LENGTH_LONG).show() - loadingView.visibility = View.GONE - successView.visibility = View.GONE - errorView.visibility = View.VISIBLE - finishAfterDelay() - } - - private fun finishAfterDelay() { - Handler().postDelayed({ finish() }, 3000) - } - - override fun onBackPressed() { - // Do nothing. TRAP THE USER!!!! - } - - override fun onStop() { - super.onStop() - mAuth.removeAuthStateListener(mAuthListener) - } - - override fun onStart() { - super.onStart() - mAuth.addAuthStateListener(mAuthListener) - } - -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/PrimaryActivity.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/PrimaryActivity.kt deleted file mode 100644 index 1ea41a5f39..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/PrimaryActivity.kt +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.activities - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v4.app.FragmentManager -import android.support.v4.app.FragmentPagerAdapter -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.view.inputmethod.InputMethodManager -import com.google.firebase.auth.FirebaseAuth -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.fragments.TableFragment -import com.instructure.androidfoosball.fragments.UserFragment -import com.instructure.androidfoosball.interfaces.TextEditCallback -import com.instructure.androidfoosball.models.User -import com.instructure.androidfoosball.utils.AnimUtils -import com.instructure.androidfoosball.utils.Const -import com.instructure.androidfoosball.utils.FireUtils -import com.instructure.androidfoosball.utils.Prefs -import kotlinx.android.synthetic.phone.activity_primary.* -import org.jetbrains.anko.startActivity -import java.util.* - -class PrimaryActivity : BaseFireBaseActivity(), TextEditCallback { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_primary) - setSupportActionBar(toolbar) - initFireBase() - setupUser() - - pager.offscreenPageLimit = 2 - pager.adapter = TabsPagerAdapter(supportFragmentManager) - tabs.setupWithViewPager(pager) - - if (SignInActivity.ACTION_SHORTCUT_TABLES == intent.action) - pager.currentItem = PAGE_TABLES - - phraseDone.setOnClickListener(mPhraseDoneClickListener) - } - - private fun setupUser() { - val user = intent.extras.getParcelable(Const.USER) - if (user == null) { - startActivity() - finish() - } else { - mUser = user - } - } - - override fun onAuthStateChange(firebaseAuth: FirebaseAuth) { - if (firebaseAuth.currentUser == null) { - Prefs(this).userId = "" - startActivity() - finish() - } - } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu_logout, menu) - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.logout) { - mAuth?.signOut() - return true - } - return super.onOptionsItemSelected(item) - } - - inner class TabsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) { - - override fun getItem(position: Int): Fragment { - when (position) { - PAGE_USER -> return UserFragment.newInstance() - else -> return TableFragment.newInstance() - } - } - - override fun getCount(): Int { - return 2 - } - - override fun getPageTitle(position: Int): CharSequence { - when (position) { - PAGE_USER -> return mUser?.name?.toUpperCase() ?: "" - else -> return getString(R.string.tables).toUpperCase(Locale.getDefault()) - } - } - } - - //region TextEditCallbacks - - override fun requestTextEdit(resId_requester: Int, text: String) { - phraseDone.tag = resId_requester - phraseEditText.setText(text) - phraseEditText.setSelection(phraseEditText.text.length) - if (phraseEditWrapper.visibility != View.VISIBLE) { - showKeyboard() - } - AnimUtils.fadeIn(360, phraseEditWrapper) - } - - private val mPhraseDoneClickListener = View.OnClickListener { v -> - val resId_requester = v.tag as Int - val fragment = supportFragmentManager.findFragmentByTag("android:switcher:" + R.id.pager + ":" + 0) - when (resId_requester) { - R.id.startupPhrase -> { - FireUtils.setStartupPhrase(mUser!!.id, mDatabase!!, phraseEditText.text.toString()) - if (fragment is UserFragment) { - fragment.updateStartupPhraseText(phraseEditText.text.toString()) - } - } - R.id.victoryPhrase -> { - FireUtils.setVictoryPhrase(mUser!!.id, mDatabase!!, phraseEditText.text.toString()) - if (fragment is UserFragment) { - fragment.updateVictoryPhraseText(phraseEditText.text.toString()) - } - } - } - hideKeyboard() - AnimUtils.fadeOut(360, phraseEditWrapper) - } - - //endregion - - override fun onBackPressed() { - if (phraseEditWrapper.visibility == View.VISIBLE) { - AnimUtils.fadeOut(360, phraseEditWrapper) - return - } - super.onBackPressed() - } - - private fun showKeyboard() { - val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0) - } - - private fun hideKeyboard() { - val view = this.currentFocus - if (view != null) { - val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.hideSoftInputFromWindow(view.windowToken, 0) - } - } - - companion object { - - val PAGE_USER = 0 - val PAGE_TABLES = 1 - - fun createIntent(context: Context, user: User): Intent { - val intent = Intent(context, PrimaryActivity::class.java) - val bundle = Bundle() - bundle.putParcelable(Const.USER, user) - intent.putExtras(bundle) - return intent - } - - /** - * Creates an intent with the data provided - * @param context Where we are coming from - * * - * @param user User's info - * * - * @param action The action - * * - * @return A fully armed and operational intent - */ - fun createIntent(context: Context, user: User, action: String): Intent { - val intent = Intent(context, PrimaryActivity::class.java) - intent.action = action - val bundle = Bundle() - bundle.putParcelable(Const.USER, user) - intent.putExtras(bundle) - return intent - } - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/SignInActivity.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/SignInActivity.kt deleted file mode 100644 index da13da0ad5..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/activities/SignInActivity.kt +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.activities - -import android.app.ProgressDialog -import android.content.Intent -import android.os.Bundle -import android.util.Log -import android.widget.Toast -import com.google.android.gms.auth.api.Auth -import com.google.android.gms.auth.api.signin.GoogleSignInAccount -import com.google.android.gms.auth.api.signin.GoogleSignInOptions -import com.google.android.gms.auth.api.signin.GoogleSignInResult -import com.google.android.gms.common.ConnectionResult -import com.google.android.gms.common.api.GoogleApiClient -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.auth.GoogleAuthProvider -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseError -import com.google.firebase.database.ValueEventListener -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.models.User -import com.instructure.androidfoosball.utils.Prefs -import kotlinx.android.synthetic.phone.activity_sign_in.* -import org.jetbrains.anko.sdk21.listeners.onClick - - -class SignInActivity : BaseFireBaseActivity(), GoogleApiClient.OnConnectionFailedListener { - - private var mGoogleApiClient: GoogleApiClient? = null - private var mProgressDialog: ProgressDialog? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_sign_in) - setupListeners() - - // Configure sign-in to request the user's ID, email address, and basic - // profile. ID and basic profile are included in DEFAULT_SIGN_IN. - val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestIdToken(getString(R.string.default_web_client_id)).requestEmail().build() - - // Build a GoogleApiClient with access to the Google Sign-In API and the - // options specified by gso. - mGoogleApiClient = GoogleApiClient.Builder(this).enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */).addApi(Auth.GOOGLE_SIGN_IN_API, gso).build() - - initFireBase() - } - - override fun onAuthStateChange(firebaseAuth: FirebaseAuth) { - val firebaseUser = firebaseAuth.currentUser - if (firebaseUser != null) { - // User is signed in - Log.d(TAG, "onAuthStateChanged:signed_in:" + firebaseUser.uid) - finish() - overridePendingTransition(0, 0) - - val user = User( - id = Prefs(this).userId, - name = firebaseUser.displayName ?: "", - email = firebaseUser.email ?: "", - avatar = firebaseUser.photoUrl?.toString() ?: "" - ) - - startActivity(PrimaryActivity.createIntent(this@SignInActivity, user, intent.action)) - } else { - // User is signed out - Log.d(TAG, "onAuthStateChanged:signed_out") - } - } - - - public override fun onStop() { - super.onStop() - hideProgressDialog() - } - - private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount, user: User) { - Log.d(TAG, "firebaseAuthWithGoogle:" + acct.id!!) - showProgressDialog() - - val credential = GoogleAuthProvider.getCredential(acct.idToken, null) - mAuth?.signInWithCredential(credential)?.addOnCompleteListener(this) { task -> - Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful) - - // If sign in fails, display a message to the user. If sign in succeeds - // the auth state listener will be notified and logic to handle the - // signed in user can be handled in the listener. - if (!task.isSuccessful) { - Log.w(TAG, "signInWithCredential", task.exception) - Toast.makeText(this@SignInActivity, "Authentication failed.", - Toast.LENGTH_SHORT).show() - } else { - postUser(acct, user) - } - hideProgressDialog() - } - } - - private fun postUser(acct: GoogleSignInAccount, user: User) { - mDatabase!!.child("users").orderByChild("email").equalTo(user.email).limitToFirst(1).addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - var acctId = acct.id ?: "" - if (dataSnapshot.childrenCount == 0L) { - mDatabase!!.child("users").child(acctId).setValue(user) - } else { - acctId = dataSnapshot.children.iterator().next().getValue(User::class.java)!!.id - user.id = acctId - } - Prefs(this@SignInActivity).userId = acctId - finish() - overridePendingTransition(0, 0) - startActivity(PrimaryActivity.createIntent(this@SignInActivity, user)) - } - - override fun onCancelled(databaseError: DatabaseError) { - } - - }) - } - - fun showProgressDialog() { - if (mProgressDialog == null) { - mProgressDialog = ProgressDialog(this) - mProgressDialog!!.setMessage(getString(R.string.loading)) - mProgressDialog!!.isIndeterminate = true - } - - mProgressDialog!!.show() - } - - fun hideProgressDialog() { - if (mProgressDialog != null && mProgressDialog!!.isShowing) { - mProgressDialog!!.dismiss() - } - } - - override fun onConnectionFailed(connectionResult: ConnectionResult) { - Toast.makeText(this, "Connection failed: " + connectionResult.errorMessage!!, Toast.LENGTH_LONG).show() - } - - - private fun setupListeners() { - sign_in_button.onClick { signIn() } - } - - private fun signIn() { - val signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient) - startActivityForResult(signInIntent, RC_SIGN_IN) - } - - private fun handleSignInResult(result: GoogleSignInResult, user: User) { - Log.d("abcde", "handleSignInResult:" + result.isSuccess) - if (result.isSuccess) { - // Signed in successfully, show authenticated UI. - val acct = result.signInAccount - Toast.makeText(this@SignInActivity, "Signed in " + acct!!.displayName + " " + acct.photoUrl, Toast.LENGTH_SHORT).show() - firebaseAuthWithGoogle(acct, user) - - //updateUI(true); - } else { - // Signed out, show unauthenticated UI. - //updateUI(false); - } - } - - public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { - super.onActivityResult(requestCode, resultCode, data) - - // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...); - if (requestCode == RC_SIGN_IN) { - val result = Auth.GoogleSignInApi.getSignInResultFromIntent(data) - //add the user to the database - val user = User() - result.signInAccount?.let { acct -> - user.id = acct.id ?: "" - user.name = acct.displayName ?: "" - user.email = acct.email ?: "" - user.avatar = acct.photoUrl?.toString() ?: "" - } - handleSignInResult(result, user) - } - } - - companion object { - - private val TAG = "SignInActivity" - - val ACTION_SHORTCUT_TABLES = "com.instructure.androidfoosball.SHORTCUT_TABLES" - private val RC_SIGN_IN = 9001 - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/adapters/TableFireRecyclerAdapter.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/adapters/TableFireRecyclerAdapter.kt deleted file mode 100644 index 1be9d7d360..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/adapters/TableFireRecyclerAdapter.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.adapters - -import android.content.Context -import com.firebase.ui.database.FirebaseRecyclerAdapter -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseReference -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.holders.TableViewHolder -import com.instructure.androidfoosball.models.Table -import java.lang.ref.WeakReference - - -class TableFireRecyclerAdapter(context: Context, ref: DatabaseReference) : FirebaseRecyclerAdapter(Table::class.java, R.layout.adapter_table, TableViewHolder::class.java, ref) { - - var currentPreferredTable: Int = -1 - var mContext: WeakReference = WeakReference(context) - - override fun parseSnapshot(snapshot: DataSnapshot?): Table { - return super.parseSnapshot(snapshot).apply { id = snapshot?.key.orEmpty() } - } - - override fun populateViewHolder(holder: TableViewHolder, table: Table, position: Int) { - holder.bind(mContext.get(), table, adapterCallback = { pos -> - notifyItemChanged(pos) - if (currentPreferredTable != -1) - notifyItemChanged(currentPreferredTable) - currentPreferredTable = pos - }) - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/decorators/SpacesItemDecoration.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/decorators/SpacesItemDecoration.kt deleted file mode 100644 index f1a99d8354..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/decorators/SpacesItemDecoration.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.decorators - -import android.content.Context -import android.graphics.Rect -import android.support.annotation.DimenRes -import android.support.v7.widget.RecyclerView -import android.view.View - -class SpacesItemDecoration(context: Context, @DimenRes spaceResId: Int) : RecyclerView.ItemDecoration() { - - private val space: Int - - init { - this.space = context.resources.getDimensionPixelOffset(spaceResId) - } - - override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) { - outRect.left = space - outRect.right = space - outRect.bottom = space - - if (parent.getChildAdapterPosition(view) == 0) - outRect.top = space - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/TableFragment.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/TableFragment.kt deleted file mode 100644 index 1e9bcca865..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/TableFragment.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.fragments - -import android.content.Context -import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v7.widget.LinearLayoutManager -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.adapters.TableFireRecyclerAdapter -import com.instructure.androidfoosball.decorators.SpacesItemDecoration -import com.instructure.androidfoosball.interfaces.FragmentCallbacks -import kotlinx.android.synthetic.phone.fragment_tables.* - - -class TableFragment : Fragment() { - - lateinit private var mCallbacks: FragmentCallbacks - private var mAdapter: TableFireRecyclerAdapter? = null - - override fun onAttach(context: Context) { - super.onAttach(context) - mCallbacks = context as FragmentCallbacks - } - - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater!!.inflate(R.layout.fragment_tables, container, false) - return rootView - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - recyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) - recyclerView.addItemDecoration(SpacesItemDecoration(context, R.dimen.card_spacing)) - mAdapter = TableFireRecyclerAdapter(context, mCallbacks.mDatabase!!.child("tables")) - recyclerView.adapter = mAdapter - } - - override fun onDestroy() { - super.onDestroy() - mAdapter?.cleanup() - } - - companion object { - fun newInstance(): TableFragment { - return TableFragment() - } - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/UserFragment.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/UserFragment.kt deleted file mode 100644 index f0e3d4259c..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/fragments/UserFragment.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.fragments - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v4.widget.SwipeRefreshLayout -import android.text.TextUtils -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseError -import com.google.firebase.database.ValueEventListener -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.activities.ChangeAvatarActivity -import com.instructure.androidfoosball.activities.Mode -import com.instructure.androidfoosball.interfaces.FragmentCallbacks -import com.instructure.androidfoosball.interfaces.TextEditCallback -import com.instructure.androidfoosball.models.User -import com.instructure.androidfoosball.utils.AnimUtils -import com.instructure.androidfoosball.utils.FireUtils -import kotlinx.android.synthetic.phone.fragment_user.* -import com.squareup.picasso.Picasso - - -class UserFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { - - private var mCallbacks: FragmentCallbacks? = null - private var mTextEditCallbacks: TextEditCallback? = null - - override fun onAttach(context: Context?) { - super.onAttach(context) - mCallbacks = context as FragmentCallbacks? - mTextEditCallbacks = context as TextEditCallback? - } - - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater!!.inflate(R.layout.fragment_user, container, false) - return rootView - } - - override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { - swipeRefreshLayout.setOnRefreshListener(this) - } - - override fun onActivityCreated(savedInstanceState: Bundle?) { - super.onActivityCreated(savedInstanceState) - loadData() - } - - private fun loadData() { - winProgress.visibility = View.VISIBLE - lossProgress.visibility = View.VISIBLE - - val user = mCallbacks?.mUser - if (user != null) { - userEmail.text = user.email - setupAvatar(user) - setupWinLossCount(user) - setupPhrase(user) - } - } - - private fun setupAvatar(user: User) { - val ref = mCallbacks!!.mDatabase!!.child("users").child(user.id).child("avatar") - ref.keepSynced(false) - ref.addValueEventListener(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - val url = dataSnapshot.getValue(String::class.java) - Picasso.with(context).load(url).error(R.drawable.sadpanda).into(avatar) - } - - override fun onCancelled(databaseError: DatabaseError) { - Picasso.with(context).load(R.drawable.sadpanda).into(avatar) - } - }) - if (!TextUtils.isEmpty(user.avatar)) { - Picasso.with(context).load(user.avatar).placeholder(R.drawable.sadpanda).error(R.drawable.sadpanda).into(avatar) - } else { - Picasso.with(context).load(R.drawable.sadpanda).into(avatar) - } - - avatar.setOnClickListener { - mCallbacks?.mUser?.let { u -> - startActivityForResult(Intent(ChangeAvatarActivity.createIntent(activity, u.id, Mode.CAMERA)), REQUEST_CODE_TAKE_PICTURE) - } - } - } - - private fun setupWinLossCount(user: User) { - FireUtils.getWinCount(user.id, mCallbacks!!.mDatabase!!) { value -> - win.text = value.toString() - winProgress!!.visibility = View.INVISIBLE - } - - FireUtils.getLossCount(user.id, mCallbacks!!.mDatabase!!) { value -> - loss.text = value.toString() - lossProgress!!.visibility = View.INVISIBLE - } - } - - private fun setupPhrase(user: User) { - FireUtils.getVictoryPhrase(user.id, mCallbacks!!.mDatabase!!) { value -> - victoryPhrase.text = value - swipeRefreshLayout.isRefreshing = false - AnimUtils.fadeIn(320, victoryPhraseCard) - } - - FireUtils.getStartupPhrase(user.id, mCallbacks!!.mDatabase!!) { value -> - startupPhrase!!.text = value - AnimUtils.fadeIn(320, startupPhraseCard) - } - - victoryEdit.setOnClickListener { mTextEditCallbacks!!.requestTextEdit(victoryPhrase.id, victoryPhrase.text.toString()) } - startupEdit.setOnClickListener { mTextEditCallbacks!!.requestTextEdit(startupPhrase.id, startupPhrase.text.toString()) } - } - - fun updateStartupPhraseText(text: String) { - startupPhrase.text = text - } - - fun updateVictoryPhraseText(text: String) { - victoryPhrase.text = text - } - - override fun onRefresh() { - swipeRefreshLayout.isRefreshing = true - loadData() - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - - if (requestCode == REQUEST_CODE_TAKE_PICTURE && resultCode == Activity.RESULT_OK && data != null) { - val avatarUrl = data.getStringExtra(ChangeAvatarActivity.EXTRA_AVATAR_URL) - if (!TextUtils.isEmpty(avatarUrl)) { - Picasso.with(context).load(avatarUrl).placeholder(R.drawable.sadpanda).error(R.drawable.sadpanda).into(avatar) - } - } - } - - companion object { - - fun newInstance(): UserFragment { - return UserFragment() - } - - private val REQUEST_CODE_TAKE_PICTURE = 1337 - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/holders/TableViewHolder.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/holders/TableViewHolder.kt deleted file mode 100644 index 721c3fdf4c..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/holders/TableViewHolder.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.holders - - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.util.Log -import android.view.View -import com.google.firebase.database.FirebaseDatabase -import com.google.firebase.messaging.FirebaseMessaging -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.interfaces.FragmentCallbacks -import com.instructure.androidfoosball.models.Table -import com.instructure.androidfoosball.models.User -import com.instructure.androidfoosball.utils.Prefs -import com.squareup.picasso.Picasso -import de.hdodenhof.circleimageview.CircleImageView -import kotlinx.android.synthetic.phone.adapter_table.view.* - - -class TableViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - - fun bind(context: Context?, table: Table, adapterCallback: (Int) -> Unit) { - - itemView.tableLabel.text = table.name - val currentGame = table.currentGame - - if (context != null) { - when (currentGame) { - "FREE" -> { - //Table not busy - itemView.tableStatusResult.text = context.getString(R.string.status_free) - itemView.cardGameState.visibility = View.GONE - } - "TABLE_KING" -> { - itemView.tableStatusResult.text = context.getString(R.string.tableKing) - itemView.cardGameState.visibility = View.GONE - } - "TEAM_TWISTER" -> { - itemView.tableStatusResult.text = context.getString(R.string.teamTwister) - itemView.cardGameState.visibility = View.GONE - } - "BUSY" -> { - //Table busy - itemView.tableStatusResult.text = context.getString(R.string.status_busy) - itemView.cardGameState.visibility = View.VISIBLE - itemView.bestOfCount.text = table.currentBestOf - itemView.roundCount.text = table.currentRound - itemView.pointsCount.text = table.currentPointsToWin - itemView.teamOneScore.text = table.currentScoreTeamOne - itemView.teamTwoScore.text = table.currentScoreTeamTwo - - // Reset avatar views - with(itemView) { listOf(playerOne, playerTwo, playerThree, playerFour).forEach { it.visibility = View.INVISIBLE }} - - safeLet(table.teamOne, table.teamTwo) { teamOne, teamTwo -> - fun setTeamAvatars(users: List, vararg views: CircleImageView) { - for ( (user, view) in users.zip(views)) { - view.visibility = View.VISIBLE - if (user.avatar.isNullOrBlank()) { - view.setImageResource(R.drawable.sadpanda) - } else { - Picasso.with(view.context).load(user.avatar).error(R.drawable.sadpanda).into(view) - } - } - } - setTeamAvatars(teamOne.users.reversed(), itemView.playerTwo, itemView.playerOne) - setTeamAvatars(teamTwo.users, itemView.playerThree, itemView.playerFour) - } - - itemView.buttonNotifyWhenDone.setOnClickListener { - if (!table.pushId.isBlank()) { - FirebaseMessaging.getInstance().subscribeToTopic(table.pushId) - } else { - Log.e("push", "Table PushId was null cannot subscribe to topic") - } - (context as? FragmentCallbacks)?.mUser?.let { user -> - val ref = FirebaseDatabase.getInstance().reference.child("incoming").child(table.id) - ref.updateChildren( - mapOf( - "tableRequestUserId" to user.id, - "tableRequestTime" to System.currentTimeMillis().toString() - ) - ) - } - } - - } - else -> { - itemView.tableStatusResult.text = context.getString(R.string.status_unknown) - itemView.cardGameState.visibility = View.GONE - } - } - - if (Prefs(context).preferredTableId == table.pushId) - itemView.preferredTable.visibility = View.VISIBLE - else itemView.preferredTable.visibility = View.GONE - - itemView.rootView.setOnLongClickListener { - Prefs(context).preferredTableId = table.pushId - itemView.preferredTable.visibility = View.VISIBLE - adapterCallback(adapterPosition) - true - } - } - } - - fun safeLet(p1: T1?, p2: T2?, block: (T1, T2)-> Unit): Boolean { - if (p1 != null && p2 != null) { - block(p1, p2) - return true - } - return false - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/FragmentCallbacks.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/FragmentCallbacks.kt deleted file mode 100644 index 00307faa60..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/FragmentCallbacks.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.interfaces - -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.database.DatabaseReference -import com.instructure.androidfoosball.models.User - -interface FragmentCallbacks { - var mUser: User? - var mAuth: FirebaseAuth? - var mDatabase: DatabaseReference? -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/TextEditCallback.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/TextEditCallback.kt deleted file mode 100644 index 2afe3f352a..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/interfaces/TextEditCallback.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.interfaces - - -interface TextEditCallback { - fun requestTextEdit(resId_requester: Int, text: String) -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/ktmodels/User.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/ktmodels/User.kt deleted file mode 100644 index 8c8c714d46..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/ktmodels/User.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.ktmodels - - -class User( - var id: String = "", - var name: String = "", - var email: String = "", - var avatar: String = "", - var pinHash: String = "", - var pinDisabled: String = "", - var guest: Boolean = false, - var customAssignmentPhrase: String = "", - var customVictoryPhrase: String = "", - var foosRanking: Int = 0, - var wins: Int = 0, - var losses: Int = 0 -) diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Game.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Game.kt deleted file mode 100644 index 86241b9e3c..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Game.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.models - -import android.os.Parcelable -import kotlinx.android.parcel.Parcelize - -@Parcelize -class Game( - var teamList: List = arrayListOf(), - var table: String = "" -) : Parcelable diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Table.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Table.kt deleted file mode 100644 index a4bc075e45..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Table.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.models - -import android.os.Parcelable -import kotlinx.android.parcel.Parcelize - -@Parcelize -class Table ( - var id: String = "", - var currentBestOf: String = "", - var currentGame: String = "", - var currentPointsToWin: String = "", - var currentRound: String = "", - var currentScoreTeamOne: String = "", - var currentScoreTeamTwo: String = "", - var name: String = "", - var sideOneColor: String = "", - var sideOneName: String = "", - var sideTwoColor: String = "", - var sideTwoName: String = "", - var pushId: String = "", - var teamOne: TableTeam? = null, - var teamTwo: TableTeam? = null -) : Parcelable diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/TableTeam.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/models/TableTeam.kt deleted file mode 100644 index 5f1de0c4ae..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/TableTeam.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.models - -import android.os.Parcelable -import kotlinx.android.parcel.Parcelize - -@Parcelize -class TableTeam( - var averageWinRate: Float = 0f, - var customName: String = "", - var users: List = listOf() -) : Parcelable diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Team.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Team.kt deleted file mode 100644 index 3da2f071f8..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/Team.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.models - -import android.os.Parcelable -import kotlinx.android.parcel.Parcelize - -@Parcelize -class Team( - var id: String = "", - var users: List = arrayListOf(), - var score: Int = 0, - var side: String = "" -) : Parcelable diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/User.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/models/User.kt deleted file mode 100644 index 7b8f1f696b..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/models/User.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.models - -import android.os.Parcelable -import kotlinx.android.parcel.Parcelize - -@Parcelize -class User( - var id: String = "", - var name: String = "", - var email: String = "", - var avatar: String = "", - var wins: Int = 0, - var losses: Int = 0 -) : Parcelable diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/services/FireBasePushNotificationService.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/services/FireBasePushNotificationService.kt deleted file mode 100644 index fa8ea29499..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/services/FireBasePushNotificationService.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.services - -import android.app.NotificationManager -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import android.support.v7.app.NotificationCompat -import android.util.Log - -import com.google.firebase.messaging.FirebaseMessaging -import com.google.firebase.messaging.FirebaseMessagingService -import com.google.firebase.messaging.RemoteMessage -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.activities.SignInActivity - - -class FireBasePushNotificationService : FirebaseMessagingService() { - - override fun onMessageReceived(remoteMessage: RemoteMessage?) { - super.onMessageReceived(remoteMessage) - - Log.d("abcde", "From: " + remoteMessage!!.from) - //Get the channel the users subscribed too - val pushId = remoteMessage.from.replace("/topics/", "") - //Unsubscribe - FirebaseMessaging.getInstance().unsubscribeFromTopic(pushId) - - val notificationIntent = Intent(applicationContext, SignInActivity::class.java) - notificationIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP - val intent = PendingIntent.getActivity(applicationContext, 0, notificationIntent, 0) - - //post notification - val builder = NotificationCompat.Builder(applicationContext) - builder.setSmallIcon(R.drawable.ic_status_notification) - builder.setContentTitle(getString(R.string.app_name)) - builder.setContentIntent(intent) - builder.setAutoCancel(true) - val tableName = remoteMessage.data["message"] - val contentText = String.format(getString(R.string.push_text), tableName) - builder.setContentText(contentText) - - val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - manager.notify(NOTIFICATION_ID, builder.build()) - - if (remoteMessage.data.size > 0) { - Log.d("abcde", "Message data payload: " + remoteMessage.data) - } - - if (remoteMessage.notification != null) { - Log.d("abcde", "Message Notification Body: " + remoteMessage.notification.body) - } - } - - override fun onDeletedMessages() { - super.onDeletedMessages() - Log.d("abcde", "Push Message Deleted") - } - - override fun onMessageSent(s: String?) { - super.onMessageSent(s) - Log.d("abcde", "Push Message Sent: " + s!!) - } - - override fun onSendError(s: String?, e: Exception?) { - super.onSendError(s, e) - Log.d("abcde", "Push Message Error: " + s!!) - } - - companion object { - - private val NOTIFICATION_ID = 444930 - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/AnimUtils.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/AnimUtils.kt deleted file mode 100644 index e14e9933e9..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/AnimUtils.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.utils - -import android.view.View -import android.view.animation.AlphaAnimation -import android.view.animation.Animation - - -object AnimUtils { - - fun fadeIn(duration: Long, view: View) { - if (view.visibility == View.VISIBLE) return - - val anim = AlphaAnimation(0.0f, 1.0f) - anim.duration = duration - anim.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationStart(animation: Animation) { - } - - override fun onAnimationEnd(animation: Animation) { - view.visibility = View.VISIBLE - } - - override fun onAnimationRepeat(animation: Animation) { - } - }) - view.startAnimation(anim) - } - - fun fadeOut(duration: Long, view: View) { - if (view.visibility != View.VISIBLE) return - - val anim = AlphaAnimation(1.0f, 0.0f) - anim.duration = duration - anim.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationStart(animation: Animation) { - } - - override fun onAnimationEnd(animation: Animation) { - view.visibility = View.INVISIBLE - } - - override fun onAnimationRepeat(animation: Animation) { - } - }) - view.startAnimation(anim) - } - -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Commentator.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Commentator.kt deleted file mode 100755 index 0c9d584717..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Commentator.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.utils - -import android.content.Context -import android.speech.tts.TextToSpeech -import com.instructure.androidfoosball.BuildConfig -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.models.* -import java.util.* - -@Suppress("UNUSED_PARAMETER") -class Commentator { - fun initialize(context: Context) { } - fun shutUp() { } - fun announce(text: String, flush: Boolean = true) {} -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/FireUtils.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/FireUtils.kt deleted file mode 100644 index 4cef420f3d..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/FireUtils.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.utils - -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseError -import com.google.firebase.database.DatabaseReference -import com.google.firebase.database.ValueEventListener -import com.instructure.androidfoosball.models.Table - - -object FireUtils { - - fun getTables(database: DatabaseReference, onFinish: (tables: List) -> Unit) { - database.keepSynced(false) - database.child("tables").addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - onFinish(dataSnapshot.children.map { it.getValue(Table::class.java)!!.apply { id = it.key } }) - } - - override fun onCancelled(databaseError: DatabaseError) { - onFinish(emptyList()) - } - }) - } - - fun setStartupPhrase(id: String, database: DatabaseReference, phrase: String) { - database.child("users").child(id).child("customAssignmentPhrase").setValue(phrase) - } - - fun setVictoryPhrase(id: String, database: DatabaseReference, phrase: String) { - database.child("users").child(id).child("customVictoryPhrase").setValue(phrase) - } - - fun getWinCount(id: String, database: DatabaseReference, callback: (value: Int) -> Unit) { - database.child("users").child(id).child("wins").addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - callback(dataSnapshot.getValue(Int::class.java) ?: 0) - } - - override fun onCancelled(databaseError: DatabaseError) { - callback(0) - } - }) - } - - fun getLossCount(id: String, database: DatabaseReference, callback: (value: Int) -> Unit) { - database.child("users").child(id).child("losses").addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - callback(dataSnapshot.getValue(Int::class.java) ?: 0) - } - - override fun onCancelled(databaseError: DatabaseError) { - callback(0) - } - }) - } - - fun getStartupPhrase(id: String, database: DatabaseReference, callback: (value: String) -> Unit) { - database.child("users").child(id).child("customAssignmentPhrase").addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - callback(dataSnapshot.getValue(String::class.java) ?: "") - } - - override fun onCancelled(databaseError: DatabaseError) { - callback("") - } - }) - } - - fun getVictoryPhrase(id: String, database: DatabaseReference, callback: (value: String) -> Unit) { - database.child("users").child(id).child("customVictoryPhrase").addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - callback(dataSnapshot.getValue(String::class.java) ?: "") - } - - override fun onCancelled(databaseError: DatabaseError) { - callback("") - } - }) - } -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Prefs.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Prefs.kt deleted file mode 100644 index fdbd1b4470..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/utils/Prefs.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.utils - -import android.content.Context - -class Prefs(context: Context) : PrefManager(context, "prefs") { - var userId by Pref("", Const.USER_ID) - var preferredTableId by Pref("\\", Const.PREFERRED_TABLE_ID) -} diff --git a/foosball/app/src/phone/java/com/instructure/androidfoosball/wear/WearService.kt b/foosball/app/src/phone/java/com/instructure/androidfoosball/wear/WearService.kt deleted file mode 100644 index 565a617a61..0000000000 --- a/foosball/app/src/phone/java/com/instructure/androidfoosball/wear/WearService.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2016 - present Instructure, Inc. - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.instructure.androidfoosball.wear - -import android.os.Handler -import android.util.Log -import com.google.android.gms.wearable.DataMap -import com.google.firebase.database.FirebaseDatabase -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken -import com.instructure.androidfoosball.utils.FireUtils -import com.instructure.androidfoosball.utils.Prefs -import com.instructure.wearutils.WearConst -import com.instructure.wearutils.interfaces.WearableCallbacks -import com.instructure.wearutils.models.DataPage -import com.instructure.wearutils.services.BaseWearService -import java.util.* - - -class WearService : BaseWearService(), WearableCallbacks { - - override fun onCreate() { - super.onCreate() - Log.d("wear", "Wear Service Created") - setCallbacks(this) - } - - override fun OnSyncDataItemTask(dataMap: DataMap) { - Log.d("wear", "OnSyncDataItemTask()") - Handler().post { /* Action requests from wear device */ } - } - - override fun OnGetMessageTask(messagePath: String) { - Log.d("wear", "OnGetMessageTask()") - Handler().post { - //Data request from wear device - if (WearConst.WEAR_DATA_REQUEST == messagePath) { - - val userId = Prefs(applicationContext).userId - val database = FirebaseDatabase.getInstance().reference - - FireUtils.getWinCount(userId, database) { value -> - Log.d("wear", "Sending win count data: " + value) - syncString(WearConst.DATA_ITEM_WIN_COUNT, value.toString()) - } - - FireUtils.getLossCount(userId, database) { value -> - Log.d("wear", "Sending loss count data: " + value) - syncString(WearConst.DATA_ITEM_LOSS_COUNT, value.toString()) - } - - FireUtils.getTables(database) { values -> - Log.d("wear", "Sending table data") - - val type = object : TypeToken>() { - - }.type - val pages = ArrayList(values.size) - - for (table in values) { - pages.add(DataPage(table.name, table.currentGame, 0, DataPage.TABLE)) - } - - val json = Gson().toJson(pages, type) - syncString(WearConst.DATA_ITEM_TABLES, json) - } - } - } - } -} diff --git a/foosball/app/src/phone/res/drawable-hdpi/ic_check_white_48dp.png b/foosball/app/src/phone/res/drawable-hdpi/ic_check_white_48dp.png deleted file mode 100644 index 699d0b2c466bb9d4013fcf3542d66369d41267d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 426 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U@Y`>aSW-r_4ZbD)?o*p)`x2p zv@<3 z7m%Ht^dV}A;PYF;=O(%P^i0@wB=Xm!dCgn;8-hR2yzcZ$YWcSX5#3*|S@#|Dtm1k( z%TcN@Z|~!bwNgtx@(N7KH}3RUSFmOJRZAeHv+bv*O1MQ>X}in8jc=M&nEFZ+)$SEW znRGppTps#VE3PoA?9wB_<)xYW_X>VomV*Wf15*bBB$xsY{9#hbR`fcseK!j*4j4RL L{an^LB{Ts5tiGuT diff --git a/foosball/app/src/phone/res/drawable-hdpi/ic_close_white_48dp.png b/foosball/app/src/phone/res/drawable-hdpi/ic_close_white_48dp.png deleted file mode 100644 index 717c7b59190385c7c55c515beb1f45439eee6d19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2V4Ujd;uunK>+P+Bd4~*mjurad zJya|Ev~7y-*f|&&Sp*!w1Pg@9W~-Y2 z$l$2LoeQ@`j%#ka*^oA;`|mn^!Am{Ham70-6e}Ok;K=Mu=3X*a>V=q}$tB%6s+Zz8 zza;iwFHc_LZc+bw0gKc+4z49ab6%~#p&ZB>#L@R$Q>;^@?Qt#tEMcp^lYgu<`WP@r z%>3mvkB1g(y?Vtwgyu}!IzxRD&+^iZuNqa3cCL8V-o)EiZl-a(Gpl@0(-bE4P4ZuO zf~4lWXp7Vgl9F+C-}vOUNAu#Wo%^~}GLL9RFHSC#DZRW;#IucAz~1oR63b`TOU_Kc zHzCwEPxFHD)58-uHKqO9GCef{d>_ta($w~QqTs;v4uu9V!2zMFy5$om-}hO)V5KH7o)|n`{an^LB{Ts5sZG74 diff --git a/foosball/app/src/phone/res/drawable-hdpi/ic_shortcut_tables.png b/foosball/app/src/phone/res/drawable-hdpi/ic_shortcut_tables.png deleted file mode 100644 index adedd5272c1a57f4f2d1b2b63cf8c75fa4fd8abe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1720 zcmV;p21ogcP)ta#iS4y6Tyrvyg*no zI*Br~8LrD<>SW>oWpPRaxM}7xf8V1=N_)LNcfF%`wBO`X=+QrX^8Nju-}AfYImYtJ zD=!0OTh0$#Th(NL?x{-m)vMQ>oxLYF(o=RioH)0^wT=Z|^|G>i*07oWZx@eiv-1L- zj?!_Q4*VQ`ER%+sv8 z>b|7c5*#*r;j88gfQ8x#kwu9O`Ei6jsu6wOcAg2N^916op~X`OU#VRsqFa6Ou+EsITpH z(J9b@uCK{C|A^s~4UKMV6y{Hj_%m^nEdw|RrS8~Jy(FA!w>%_{Oxe~CJKm&GFoKex zh9HHtyhnkS7ybClw2xdeAP1*x{TkUJJBz}19Qf|8O}=FTbp85uU#X)wgiwkH0XRW& zO;^i8onu0Uv_P_{3@aaj2%(O_uq};FBj={Xu+n>U(j#G`6u3;aQ=I&2N&#*_Z@u5? z?Ku|d1`tVb(5HL+rkzKju>6Cn@3;zFl7}}Z**Kl!tg0v-*t+QfI|@BGCh(fqtf7>c zq~%UUV~_;B01aa(M^${_J^$h`Zg%}Ud68XgJ47xzDplL@5(tnh<0M`2%x+Z2P8556 zZB3SeBjupt`mOB2(}(0vJ1J=gGI9_?>qO^HxMx|aV7+zzjlE+2DXJ__6>5-6Dby4J zU7DF2xXoVZwsOM@VRm76Yy9j#QRpvuREJp4F~MhbIM7Wc#cb8Rii3$;sXn?f)rqq8 zYj;^44xDpCQK6E1B;kK;=LU4}$dLE$lG`0thJ)ObV)T-egIwg5Yr4sX*x>g+HCWv} zsGvFFNNV89K{RqX{*2CBKKCFws}ypPgU3N$mb>!u0IC}r9?Mlgb&7y+-HOF^2dyH^ z*3rDzL8z|nN)B>c5zbkfl&Va~in&M$kfq!MC_2MQVvq=EV~)dt%9Q}wtpe!WOTolW zpYNd>6dC#cH;&7LaG*x)2MW2+P6^mh#FgFGKae00RK`ule1h>HRAJ O0000eDAYMGF zE6S|PHHM{C-_^G5vxndP%G(4mYt&4^MEY?_5$q_jDG?)0$U}0E9yK=KNZZ(9OfV} zBgM#VV6LPGl>{3OoB;Z#IQ6K_k#w$-U_%4gpcJPK0qjC0!P@$p=Z`AI>2+Yfq=yv) zb4O-26W9lIN^txRSO@HuWR(VM1#AYE11%!X-vWDp?UG)V6UuF6mWvQIkJbcWFwhb3 zNZkZ3OZrf5sN7(G!f}?(#E6;M08eP3WtM^1^^KCeeEhbQ0-F-bgtwz2QYGn4kw28u zm6mBSGFeU;v9%%C$V2wq&S6+$)y}JKk1*7*r zVg&<6-M?Edl5WM!Mug_v8mIz%E=wx5KDFKfo&`JAlHL~$Pm+GAh&2bidHZ$mk0&Fw zE^5ac`6BO`;m3w@O&OU@+|2p{J_IHWi;u#Pc%vLqirUBn<`vu{GBUyWy#RLqZ-6=c zr7-ry{a+1WjX72}zRZZZCo?+>OiS>3K7jd-Sysslb~KDZapy-Q`QDjJ%&Z?U4(JR# z2Chr0%l%fy70t|Ne&597vRBfwEGjeeQd1qqb1y|cqWj!-%l8G~w4^VEl0Q7k9l)vt zfK8Itr-7N7mz@>Bnh>eD`U{{&(y69^`7ywT1c23&9J-{K*;wEh&?807p?qonv1#Sa zF~8d_35J(S^2eM8Ruj%X($xHzVUncRjY@gJe0B3&h>EwPd6K*bdkvd8y!aMo@r4DM+BZn zNnqW=`Pw|7S%S(}V7;WDQss|>IY_8qwZN=cy)|00000 LNkvXXu0mjfPtKSy diff --git a/foosball/app/src/phone/res/drawable-hdpi/sadpanda.png b/foosball/app/src/phone/res/drawable-hdpi/sadpanda.png deleted file mode 100644 index 7bfd91bb89b11b93237950f264b411e6f6213b14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27917 zcmX7wV|ZmvvxZ|E6DJef_KxjLl8J5Gwl%TsOl*5%+qSK<-|t-ON`CD0>fNimS9R50 zPbET8UIGyg7Y+mj1W`&-R2c*WR1x@N1_K5BJECr51ocFG{^4s z`ZW3*RssrgY?V^V5ek+@NlJhmHuO0&oFpiJMvvf$pq0$NlB?6T*ow-n*#60eYpq|6BWgPg$*beMR8o=Vt_Z> zZ?MN-vF;@=Bzwf}Xa%>hNAz1>zLD_8tW{cJp$jG*sIrA^T9AOPr;`0+f^e>Mj{Z4A6W_T|EzGD2^sESkhQcDc(S`P5-=y+Kd$ zujsqE)IQ>!N^i3_11n1g6g-RQ#D09okz{LP_VXqx4<`S~;p>7;CJZ z2e5c?aHiETq>qP2DCv7+(Y1M(ci6+;#w&incLqL~haFJSLB|>x7{rrGAdRMzmfA;0 zM+VQ#DCXVG#4GOdadYGBq3;n32oUb=?SbHcZnV3=f4v^(0+d>Vh+4#&fjdFkiuW(G zGI$vxcR`iX=8cWjw`j&Oog;DZwGK^9tnZ=wI>v{4)re~olWtpRsRnO7GuRN5T61C9 z$;qft)({Iy$7C^J8TnR%587`~Z#V7*?MdRkFdd7Rho>FRcB?ZM26cYo8kyhF$SB|a zc2BWUQi)0v;rm9TND_54o0rpgDr+^DBE;-!s|y~BK^x_3N{FzepI8$0NR)XSniObR*lBm+?QWE}zkH&sAcy zdJU06WW!HuT>FjAPj7m?-{nr4h z*HtdO7UH5jUx8?AV|8PTX5yR%x-h3t%_f?=8N^1suilR!ZY|n3ihXSHL41bGgSRrR3XHp<#_rg6ybW&Y!jYAdGLSpB;c_zzEtI&JG@F(oBU zejhKlIEOrodJ542U%X~7BrW1bm#@+%S>7IU=G<|DOC`kmuOMz8sl@2nC*$|JOOuvO z;*a7M4Mefqg|62q&Na}#HUnW>K=l}(LmSoMN~2o#lWFqlavi!+=Bfsne!Ii%ns6eE8@)t66OPk%=lNT)g*fMKGdDNM5UmI!hChUFt_AXBOrBQS2c5H+XrPsMdZW2(v^!JVr ztDV4&-{^tqp6WFIa!X*ah2jfDf*AdCMWXZ8iDeoJkOt-5& zP6xZe)6$ZrN}~;oLOu(|>-ow>P*QuXG{8nt*?UerH8SNStqjsUE%dB_^8Un8uOap2 z>T^uUke#iktNb_FFTlhE0-IGM`xzAr{Lp0bL5A6a!Y9_FN>Zme@}o`Q@1u#5Yg@xV6bQ`?N zk4?I<`>P=x_l(3jb3sdQKaGc{8xfM76w-19 zh4K?OzD4^ioBFlvx*$K_AHyzI8={sBLU5?m^s(v5LGr=$ic;=DiJei>Dl{b3svn=i^105-0rNzhjFZ6 z4~O?0d$Jd}r1ma0J2(+=xnLZRCa8bK{PD^Ix!j7w=SEYj(Wd^5jzc}1KHHq5gXR&2 z#}#YL)?7RBkgpJKC=P`iA@khesoT!mIjtb?K^SB})*Xq}=ztnI_t-&&>=SAfJ*9{R z-#;*ruRg7NbG73}tZ>C=_)8<52qUlf)9bqD__xHF#QK_N@b(X)R1GaHuJWK5wMo}N zaYRFgQ4O-<`aBo>iBRq<4}?}FY;e1c*l?I{%+%=GeQdEwL(LXjMED~{khNcNb!Udx zbZN;+O_$!UcS0>Sn|YG6Bmjm&jEljvUQ9T6MBZSAIYq?+PE$=aTL9*T^IgmDlQ;E2KHbcCQ< zt+rSlk>t1nQAe4x9o+7QP++4A!#+OaFw)laJIySI&qMzzt4*<5lf6N)d>jsJuwLR+;@KIkpAlT=PP;lSv{Txb}NTiu?B6OLJHZo(qI<% zJG3&w!FIb&2i=`227(23{_yU|`ezr=`yy?h&1nFO>wE&>SU_QeO zJ14+U5m6Ska#iwP=(C9#maXhya;9~JD<3C^NgVX6+mIN_5zmONJEs2zfsHJf^>TUE z3BqMt_lKHR23WFJj^lhLW`PZAiS{rau&XVcc@{<1@4P>z#wDdqK~-AK5tB0h&zx znFfW79s@t@KekkjT)>L_S5Kp%9!n-5jhvw}5Zz!LFzs|lQ{-4)OFSabf)mW9O{KqX zlN0$4+&v9)SVdT8!oy)ydKQ!0gYF2KVFVy2zVd~&tW|fNAmwY7YV5`IZKO(a&t9x-;7zNoVX+NX&G+pt=NUGm z6|u_~5AxE|ESuMpD+p|ZPjMAJRG7TeIsCk7pU~B8uj@_hYR%SyCnMNpM56N-q$zAs zrxXhUIJG@bJo+{6@8rBRfPjzJ`+;%BOx6+HwLS`x2o;Q<4JGYN?Nfnwz1zzeLzsY2 z+0(ZVaD`E`$UYu~xfvOE{8DQ283CU+ zrlZrFL|PBcHb)cljTN@jmN}_$hfeB66Y*34F%QKVYJ2)n(R5>_gT}I}~LZvi8CVT&*-suk&pdvY))l}Hryi6LKYO{J0qlZzJ{$r*7fQSHDVja6rY(qETI|pB z&SDe%ppeX694fR}M@?&(AE1l2Eq*;;O!~bbO|$x+9r?Y%*Ob`r;3IuBoCBN>^sG#Z zAb34%;SDS0MwHm>mdU7Lre(|_!NI-L4Zfjgi!nGGAquQV*W;O~GjzO2+y&K2%l1L! zb9eg3NAm{IW|uTwkBh+cWKQR$T5kd9i<8<7g^I7$^qGe~f5yJhR7m zEaRh5ftaf8A7PuojSbsBO*i1&FRTVD`=2jXs)=;9KRSoDv9*_de}Gn`?=Ra7s=w!XqLAhN7@UGC6GK#veQbwB{1PJ?xGS8 z(DQwTghIdvi6atJt5QhkX-6kY1+*)uK%v&n�dF9vmE~ybQf;3App)k8$~qJP|~D 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�Jr+Z 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 G@c#fB8KD;d diff --git a/foosball/app/src/phone/res/drawable-mdpi/ic_check_white_48dp.png b/foosball/app/src/phone/res/drawable-mdpi/ic_check_white_48dp.png deleted file mode 100644 index 1f4846cbea8e43242ff2a943aae5135e93e2d8d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt51uZLAr-gY-tgu-q#)9on8p{| zcfQwh_w6EfJ@?zJ3NF4@3#J`!Wj?96^YOpddH(8|nbv{h z=f7=EF*#s#FHg~}L!NDd%za@6?S0}0RL%FXI|SND1<3TXtT?imA?qVYL;w6OkD{5c zJWgh;HZM1CzxODa!S3J3+8f5gfx30v8={Z=zoso1XlnP2*WOS~~PCJDoe8eOwyO>3BT*PAiM#`qG)g oA$y+Xh6sH8W9|iY?u$z1Z6D^=D{sBM0O)rHPgg&ebxsLQ01d)<6951J diff --git a/foosball/app/src/phone/res/drawable-mdpi/ic_close_white_48dp.png b/foosball/app/src/phone/res/drawable-mdpi/ic_close_white_48dp.png deleted file mode 100644 index 0b00a33a728a56902219f949ade2a25821dc9276..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 329 zcmV-P0k-~$P)-Hp^2CxGti$Q;Z^2qD!Xpyz3;wxcLE3?fB*sr@K1nC z*e>jz5XOc*Z)Z>d@xeF$SSuJ|w`az+!X}>Cv)%zD zqB#87TPTGXYKJemMu!3fEPQDlID>$OM-;LYVyqD!Rf)$p5R~x9R^kXj3yvk`%46&{AjIcz3X)jh<-8f+~U23w9b*s3vFoS36UO{WDAKmY** b5CFaJELQUamZcBV00000NkvXXu0mjf$2@;u diff --git a/foosball/app/src/phone/res/drawable-mdpi/ic_shortcut_tables.png b/foosball/app/src/phone/res/drawable-mdpi/ic_shortcut_tables.png deleted file mode 100644 index 123cb3f303b760b164056abc71153dd9cfca7afb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1187 zcmV;U1YG-xP)Fz*^gTFqm)nt30-ATP)?~IA%sOYsOBtCA#F-O3Jo*}LhHv=QoGRBMI+{F zGcAiQXPX&;vEKJ^7W4F-v$MX-Oi~1dh=Ub_ zsd1!px2`73mZXru4_{dUQh{QIuQe0qUKcaw8>x&%h$>3*S#YrdY4rjKjYb%CMAPL% z?1;~tF+Ju`z!3ADHs#+4BEI{4{7DOvKdn1T=_u&g`iN?c)n=7R9niS~| z;CpJ*@j3_G7KWbnx`s%%)6FI*nhY?52nU!t-ceWgdp|mGRIWC*2iNAD4qm#}8uSH5 zgL2}@ifr^kP>KlA9N3tD-r*kjq{BolH5o~UE-fjw9jnxvqZdOzIw7(3Q43g=Rc_1Q zk->%yRu-YMCJr4&EgFON*4A>vE{60aeLgtlAQxzkRSak6ynYCpd|8b~+ z3VQ%YA1-gXKUM_4{3FDBs)hu5p7Ha5>V{5QTim3x$Fq|cv`Egvs1+ro>fClsedIP;eBaibNOiY>J3Evdv_ko69*L!L6 zcJKh^Md`Vlyjou)CwWArSR=Cnv8XmzlRO1SZuNo!AdDEk!U={-DZ3I@PU%Dg!*LUz z3vpgB;eEHmJ&^>MXlDo1sf0?UYJoL!J%0y4L0D~ B9*Y0~ diff --git a/foosball/app/src/phone/res/drawable-mdpi/ic_status_notification.png b/foosball/app/src/phone/res/drawable-mdpi/ic_status_notification.png deleted file mode 100755 index 49b076c5ceefd60f3a6da5b8fbc1be419f54ef23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 576 zcmV-G0>AxP000>X1^@s6#OZ}&00069NklUE80brh ztpjHyy(31Oz7csN#z!6|K@LAGowc_RYO^G+NdY}W?RzYxC z()((FGP4uFPT*Ux<`uA`f{5EV3LMP|`sI*ipcNQ*&w)IU55ROz$m;(E=>_%xZoyhk zyS(Le=d^1*{kocf0boCHG9|JCJO>sf<;_P)BCB_u1D>TIvy!@Ue*LDfEJz#hCMEbl z()A)ChX60QWW5Ya>Ms(~2)qRv5~2f=hGGyi^Iqpx?gc&qbCP~W+e&%U%ytF4S`wnY zlJ2J=W_BPH=HYPmCk(tBk~S(O-h0vC?K{ZhXEPz83wywYaM`Eg zSxGM<5P!}+5gYp@`CQ6;!Xv=tP^2X$@CmphX+9}vW@Et32;_>S$CV)d#it?{|H+G) z9Sb=)7~*}X%>f?!y%0#Sb|280cwGyUd|a1SRxv&Tjz|9FwxlQ3*2-T3BEx#W!*U(~ O0000-Q`_)tIO5A+qXO4&Ns8Ovx39n08tb{DY7d<8Skm}dVQ=z

5V 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 diff --git a/foosball/app/src/phone/res/drawable-xhdpi/ic_shortcut_tables.png b/foosball/app/src/phone/res/drawable-xhdpi/ic_shortcut_tables.png deleted file mode 100644 index 30f1d16391cb14a3d240ff71e1021780cc896b46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2231 zcmV;o2uSydP)MHrr=D1x;t;zyMt zS0QSE*lPko43#!PDoWBLT2g)r7@^FHr8v$L}Z2?z)X z2)GrVO#NY_imJW%;G?YoH;F!mBbr(`7KIl3(S&hNqAN{5_P0B|*JJqQ2ySp}r;j63 ze*YmV1W+a%i1p((y>R?f#ounL^7dS~jKXzI==;_V)O-CFdEe;Vhf#H4CMusbIqBzs z2$#NTLcNE712N)X0s&fZJBV8Y79{3+0f6+`B?bPfc{9om9P04zKJW|b#-szuZM#<8 z^WN(9J5e5fenEK=%E=ze^!YcBokBzM9!HUB^Ag1XG~l+^YB4+(+DjE~mDPb#33{{) z==J4Gwvxxt%S($U5}VPBzkB{5(E*}RtCC*=^6PQiWQ9$6EFgY05HCLmy?H_TOK9$_ zNu-C%B7pTA?L3P@OZ;f6Z!GuU0sEXvKoA-i6=f8z*5omP{H3(lOG@vcrxW99^Up2+{uK)tWlJ7|$giZ9BgK0?kSycq$#W>Qxq&>E>-kK@ z#V_~AqAP2`lIk;F08Bm*zckrvvc1U3)-Je)#}vmamczqZEJ83N1)zy`k8C+g_-tK( zl$SOX0MWtR99{`}5RVVJd-txi>b=>`xQZ!Os&Ihx#vRLSMSc>%|FQX}F)vFQ5dlCx z{2)3{gQm`1M@F-W;~Ri(l+Zd^#7mSKgJze!cx_*KN}yfO>v^&xa}|=b@qfRn6$! z5&hMV696I{ulSHmW$=sy%{gFpNx>eOe7US_J93H;K0NyYa&!v$FprdEc2$Ot79Zv% z;YqKrt$D_qTfF2XWAIi|K|?eB)bFm2$=TfCriHyFRD4( zdCt*xlWrU^43iI*lp+FT1X*WMnFN5r)_2YAr*Y*YA(w)|eiE%HpQSWq5}^G=cir>P z=2apAA^;?02GnB#0=jbm?)_fxsF8wv^{B+9sh39*UhS4DN6CI53Cl}fRA99(3);A& z(TmH>({As|XVz{d{;v`FN@b~H1YEmuyGoF+i+n(pCJTbewi8|FUGM!m$tSr$YYy=L zcju0T1oT3}$+%LB0A+$ZZYWbFfV@z)=lm5x9Uu5pox)5N0kBGWz^O&2gJFcLO9V9n zOm|xsh5DXD!d1d_H3Ag7jeHnr8H{2k0qC5+SCG#g-egk~$s)k#wkZY^;S&PHkq@gJ zOa_wx1#ThV;Hn3)aGOj3$B%v)PpTL)Di#(*1+WMMxE-8MCAeP83F~~I$9KH?J{ppj z%d))0(g?T*-50Jnf_(7&z7=lmnKCkF6Tm6tYw7hjk97$FtRmkmq!pm&{AEGDl>!9U z?ECNJWKMl5*X>9Fq6!``t!ZiY5koL~1 zI?}APDd?>>AfGt`RA(=Uf*0nlBN1UXfOv!K!U(i;wV=dA4JB)N)fO^;WES}*pHMNy zf+Bjp0j`vsIX_HxL=og`5a4WUIEwlHLl4@>M}TK{VMS-Bbgy79QUS zitp80#K|GJZeT-?$Qb%qQJP`&l&-MATsbwSzF|!)5woe&JY&?XhkHfNQL#VZsNzh zFw5id!2UNa@z3?R>>@r!w5Zu}eXyEO4%amWX1qB5NLJP$2{zt#c>S)`dIDAh9U}tsJ6PTJ7=VB3ph|@_M2l>9HZSD1} zj-G>bohxu5i2L`Kt2}%5=3xA zVs7C@zUpxRiwH_L@o`A0$@L~a+^-R%C29cKc$s^O5$+t`|D}OnixvH}^FBGF2=BOk3n5d!5vQ-<^7LuW+yPv|+calrdvQ5Nj)V1m^E@y@@Ya|$s)gtF42iT;`u75Chc1IRb< zT3>QYb0cohX)6KZgpf+6JXg77-i)`OcyzeWvvVKsOOK+oqJdS)mflA`BLzsbsE;mo zc_-Yy;iDEMZ~0ivXekkTY^RSSR@jSxfPjF2fD--}U;ql%6+anNL|Fg;002ovPDHLk FV1o7j5zYVr diff --git a/foosball/app/src/phone/res/drawable-xhdpi/ic_status_notification.png b/foosball/app/src/phone/res/drawable-xhdpi/ic_status_notification.png deleted file mode 100755 index 537ab9408b65e65f8bdc7669dfa922851880d06f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1060 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 diff --git a/foosball/app/src/phone/res/drawable-xxhdpi/ic_close_white_48dp.png b/foosball/app/src/phone/res/drawable-xxhdpi/ic_close_white_48dp.png deleted file mode 100644 index 5a99107d646936e817f9a2f14775d6ed484d0b2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 865 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$farfmy@T#WAGf*4sOQeoBraZGquR zi+|r|&N<>3eu-I7$jH!b$-=z5|4Tj{RhQTCi`upOm!0nEPbz=Sx)mB&CNKy&2sto$ zFmNhxDln=51;9c~9$+D$07wX~W&z_~xm$8o-xPK0`QG~3GyYPX*Z=f$1-E;N%jdeN z?(bb4T8|?S3C2E(T&1+CPhIq4c!ihJEJlB+MejevC{;1OcwP}C@R!A3)5ZAV%f1&< zHqRd?n=HEdp~Urzw2i7jZ_JjvMYlh0=Uf#1VNQRp(t_v0O(`zf4{xa@ z_^FnTU?8{6)OXCPidoIeZ_Rzd;DDwPGM+ZWDSA|Z*zt1D!2y_mTEp2HQM3mxCL zDP%EaJn^m<@a0=^NP6*HwO8(ptG?{|s3s|B^Eb_m$wYEqhRX*B5yp&Vg4%%{4;ojP zE|}SF?W)kkzGzy5Rqs^mx*xx#|4*w81**Ej72s~OR`4KmAh!c&MU)ay%}PeqN13f0 zavjT9w{RcdthQ*aae&%9(`%3Ze)+wRx%JV`RNb~mD~m+G6&*cPDj!zByXaws)?Ich zrC%J!i+L9bRjj((`HwH~){7nQ1*RSh{up^9ydy|`L0#(#k$J29AIIwpxSmh=#~)~E zGxa<3-g)nGRUYqj*|NGLy-j!RCiN%=PhgrwBv5#Y1t(&LNx(DljzJYD@<);T3K0RYd%SJnUk diff --git a/foosball/app/src/phone/res/drawable-xxhdpi/ic_shortcut_tables.png b/foosball/app/src/phone/res/drawable-xxhdpi/ic_shortcut_tables.png deleted file mode 100644 index 0b8aaa5ef778617fdc405592ae50b0c14d995dc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3383 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 diff --git a/foosball/app/src/phone/res/drawable-xxhdpi/sadpanda.png b/foosball/app/src/phone/res/drawable-xxhdpi/sadpanda.png deleted file mode 100644 index a6028541e191b1c4a85263fcb5ca24c9f8ac51ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76943 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�tRJ&J9O2)qfhd4ouy->vq1q? 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 O_^B#sDAveZM*JTZY@BWY diff --git a/foosball/app/src/phone/res/drawable-xxxhdpi/ic_check_white_48dp.png b/foosball/app/src/phone/res/drawable-xxxhdpi/ic_check_white_48dp.png deleted file mode 100644 index 7c722eedc16b547e606d8db6bc2c335e5fcec84f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 860 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zf+;U{>~YaSW-r_4d|9&%+54Z5Piy zSR1YJ%46NdgL4iBu8}?>CbCCk(bn95Pb^#08|&UTvTT~UEK@o3vpNR@Ck-I)9bJZ1 z-?qH3y)VWPdi?*_+e`~y{b+Z5U@wKSQcTA$uXxPvaE!m9N1j2_p24V&A>|Lli64v; zJ~Ar+CB$DBo&{1bKQb@)@`Ev;>JNj4Z5_iDIeP}LetCwa$N3vBJ!U`f<1!V91X)`N zdxm5Ae;6e8e`HSh19a0zX%vC|1`OuEN diff --git a/foosball/app/src/phone/res/drawable-xxxhdpi/ic_close_white_48dp.png b/foosball/app/src/phone/res/drawable-xxxhdpi/ic_close_white_48dp.png deleted file mode 100644 index fa87f2514f88cc53f7b87f36264e78503ccba1f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1026 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 diff --git a/foosball/app/src/phone/res/drawable-xxxhdpi/ic_status_notification.png b/foosball/app/src/phone/res/drawable-xxxhdpi/ic_status_notification.png deleted file mode 100755 index 404df03f7ce83c864cb2c88b2bdcd532099f9794..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2788 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 - - - diff --git a/foosball/app/src/phone/res/drawable/vd_done.xml b/foosball/app/src/phone/res/drawable/vd_done.xml deleted file mode 100644 index 7dcd09249b..0000000000 --- a/foosball/app/src/phone/res/drawable/vd_done.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/foosball/app/src/phone/res/drawable/vd_edit.xml b/foosball/app/src/phone/res/drawable/vd_edit.xml deleted file mode 100644 index 3d2da0b22a..0000000000 --- a/foosball/app/src/phone/res/drawable/vd_edit.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/foosball/app/src/phone/res/drawable/vd_person_add_black.xml b/foosball/app/src/phone/res/drawable/vd_person_add_black.xml deleted file mode 100644 index 61a9ffc0e5..0000000000 --- a/foosball/app/src/phone/res/drawable/vd_person_add_black.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/foosball/app/src/phone/res/layout/activity_leaderboard_tablet.xml b/foosball/app/src/phone/res/layout/activity_leaderboard_tablet.xml deleted file mode 100644 index 5797ce42b3..0000000000 --- a/foosball/app/src/phone/res/layout/activity_leaderboard_tablet.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/phone/res/layout/activity_main_tablet.xml b/foosball/app/src/phone/res/layout/activity_main_tablet.xml deleted file mode 100644 index 25f9e858cb..0000000000 --- a/foosball/app/src/phone/res/layout/activity_main_tablet.xml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - -

) { - statusTextView.text = "Select a table" - MaterialDialog.Builder(this@SyncActivity) - .cancelable(false) - .title(R.string.pick_a_table) - .items(tables.map { it.name }) - .itemsCallback { dialog, view, which, text -> - Toast.makeText(this@SyncActivity, "Selected table: ${tables[which].name}", Toast.LENGTH_SHORT).show() - Prefs.tableId = tables[which].id - dialog.dismiss() - startMainActivity() - } - .show() - } - - private fun startMainActivity() { - statusTextView.text = "Done" - startActivity(Intent(this@SyncActivity, MainActivity::class.java)) - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TableKingGameActivity.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TableKingGameActivity.kt deleted file mode 100644 index ffa13a278a..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TableKingGameActivity.kt +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.activities - -import android.app.AlarmManager -import android.app.PendingIntent -import android.content.Context -import android.graphics.Color -import android.media.AudioManager -import android.os.Bundle -import android.support.v7.app.AppCompatActivity -import com.afollestad.materialdialogs.MaterialDialog -import com.google.firebase.database.DatabaseReference -import com.google.firebase.database.FirebaseDatabase -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.GameStatus -import com.instructure.androidfoosball.ktmodels.Table -import com.instructure.androidfoosball.ktmodels.TableKingGame -import com.instructure.androidfoosball.ktmodels.TableSide -import com.instructure.androidfoosball.push.PushIntentService -import com.instructure.androidfoosball.receivers.GoalReceiver -import com.instructure.androidfoosball.utils.* -import com.instructure.androidfoosball.utils.Commentator.Sfx -import com.instructure.androidfoosball.views.WinTableKingGameDialog -import kotlinx.android.synthetic.tablet.activity_table_king_game.* -import org.jetbrains.anko.sdk21.listeners.onClick -import org.jetbrains.anko.textColor -import java.util.* - -class TableKingGameActivity : AppCompatActivity() { - - companion object { - val EXTRA_GAME_ID = "gameId" - } - - private val mGameId by lazy { intent.getStringExtra(EXTRA_GAME_ID) ?: "" } - private val mGame by lazy { App.realm.where(TableKingGame::class.java).equalTo("id", mGameId).findFirst()!! } - private val mDatabase: DatabaseReference = FirebaseDatabase.getInstance().reference - private val mTable = Table.getSelectedTable() - private val mHistory = Stack() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_table_king_game) - volumeControlStream = AudioManager.STREAM_MUSIC - setupViews() - updateState() - GoalReceiver.register(this, goalReceiver, 100) - updateGameStatusBusy() - } - - private fun setupViews() { - - // Get table colors - val sideOneColor = Color.parseColor(mTable.sideOneColor) - val sideTwoColor = Color.parseColor(mTable.sideTwoColor) - - // Set team name colors - teamOneName.textColor = sideOneColor - teamTwoName.textColor = sideTwoColor - - // Set TeamLayout colors - teamOneLayout.setTeamColor(sideOneColor) - teamTwoLayout.setTeamColor(sideTwoColor) - - // Pause game - pauseGameButton.onClick { - shortToast(R.string.game_paused) - updateGameStatusFree() - finish() - } - - // Quit game - quitGameButton.onClick { - MaterialDialog.Builder(this) - .title(R.string.quit_game) - .content(R.string.confirm_quit_game) - .negativeText(android.R.string.cancel) - .positiveText(R.string.quit_game) - .onPositive { _, _ -> - mGame.edit { status = GameStatus.CANCELED.name } - updateGameStatusFree() - finish() - } - .show() - } - - // Undo last goal - undoView.onClick { undoGoal() } - - // Tap team to count a goal - teamOneLayout.onClick { goalReceiver.onGoal(TableSide.SIDE_1) } - teamTwoLayout.onClick { goalReceiver.onGoal(TableSide.SIDE_2) } - - mCommentator.announceGameStart() - } - - private fun undoGoal() { - if (mHistory.isNotEmpty()) { - val snapshot = mHistory.pop() - App.realm.inTransaction { it.copyToRealmOrUpdate(snapshot) } - mCommentator.announce("Oops") - } - updateState() - } - - private val goalReceiver: GoalReceiver = GoalReceiver { side -> - if (mGame.isGameComplete) return@GoalReceiver - mHistory += App.realm.copyFromRealm(mGame) - val (willWinRound, willEndGame) = mGame.getGoalOutcome(side) - if (!willEndGame) { - if (willWinRound) { - val announcement = "${Sfx.DING} ${Sfx.ROTATE_DING} ${mGame.getNextSwappedPlayers().joinToString("and") { it.name }} - swap now" - mCommentator.announce(announcement, true) - } else { - val (team1, team2) = mGame.currentTeams - val (scoringTeam, opposingTeam) = if (side.isSide1) team1 to team2 else team2 to team1 - val (scoringName, opposingName) = with(mTable) { - if (side.isSide1) sideOneName to sideTwoName else sideTwoName to sideOneName - } - mCommentator.announceGoal(scoringTeam.teamName.elseIfBlank(scoringName), - opposingTeam.teamName.elseIfBlank(opposingName), scoringTeam.points + 1, opposingTeam.points) - } - } - mGame.recordGoal(side) - updateState() - } - - private fun updateState() { - val (team1, team2) = mGame.currentTeams - - teamOneName.text = team1.teamName.elseIfBlank(mTable.sideOneName) - teamTwoName.text = team2.teamName.elseIfBlank(mTable.sideTwoName) - - teamOneLayout.team = team1 - teamTwoLayout.team = team2 - - pointsToWinView.text = mGame.pointsToWin.toString() - - gameTimerView.setStartTime(mGame.startTime) - - teamOneScore.text = team1.points.toString() - teamTwoScore.text = team2.points.toString() - - undoView.setVisible(mHistory.isNotEmpty()) - - val sideOneServing = mGame.getServingSide() == TableSide.SIDE_1 - teamOneServingIndicator.setVisible(sideOneServing) - teamTwoServingIndicator.setVisible(!sideOneServing) - - if (mGame.isGameComplete) { - mCommentator.announce(Sfx.WINNING_GOAL.name) - WinTableKingGameDialog(this, mGame, { this.undoGoal() }, { this.endGame() }).show() - } - } - - private fun endGame() { - mGame.edit { - status = GameStatus.FINISHED.name - endTime = System.currentTimeMillis() - } - updateGameStatusFree() - finish() - } - - override fun onStart() { - super.onStart() - val am = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val pi = PendingIntent.getService(this, 0, PushIntentService.getIntent(this, mTable.pushId, mTable.name), PendingIntent.FLAG_CANCEL_CURRENT) - am.cancel(pi) - } - - override fun onStop() { - super.onStop() - val am = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val pi = PendingIntent.getService(this, 0, PushIntentService.getIntent(this, mTable.pushId, mTable.name), PendingIntent.FLAG_CANCEL_CURRENT) - am.set(AlarmManager.RTC_WAKEUP, 90000, pi) - } - - override fun onDestroy() { - super.onDestroy() - GoalReceiver.unregister(this, goalReceiver) - } - - private fun updateGameStatusBusy() { - mDatabase.child("tables") - .child(mTable.id) - .child("currentGame").setValue("TABLE_KING") - } - - private fun updateGameStatusFree() { - mDatabase.child("tables").child(mTable.id).apply { - child("currentGame").setValue("FREE") - child("currentScoreTeamOne").setValue("") - child("currentScoreTeamTwo").setValue("") - child("currentBestOf").setValue("") - child("currentPointsToWin").setValue("") - child("currentRound").setValue("") - child("teamOne").setValue(null) - child("teamTwo").setValue(null) - } - } - - override fun onBackPressed() { - // Do nothing - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TeamTwisterGameActivity.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TeamTwisterGameActivity.kt deleted file mode 100644 index 4258738825..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/activities/TeamTwisterGameActivity.kt +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.activities - -import android.app.AlarmManager -import android.app.PendingIntent -import android.content.Context -import android.graphics.Color -import android.media.AudioManager -import android.os.Bundle -import android.support.v7.app.AppCompatActivity -import com.afollestad.materialdialogs.MaterialDialog -import com.google.firebase.database.DatabaseReference -import com.google.firebase.database.FirebaseDatabase -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.GameStatus -import com.instructure.androidfoosball.ktmodels.Table -import com.instructure.androidfoosball.ktmodels.TableSide -import com.instructure.androidfoosball.ktmodels.TeamTwisterGame -import com.instructure.androidfoosball.push.PushIntentService -import com.instructure.androidfoosball.receivers.GoalReceiver -import com.instructure.androidfoosball.utils.* -import com.instructure.androidfoosball.utils.Commentator.Sfx -import com.instructure.androidfoosball.views.WinTeamTwisterGameDialog -import kotlinx.android.synthetic.tablet.activity_team_twister_game.* -import org.jetbrains.anko.sdk21.listeners.onClick -import org.jetbrains.anko.textColor -import java.util.* - -class TeamTwisterGameActivity : AppCompatActivity() { - - companion object { - val EXTRA_GAME_ID = "gameId" - } - - private val mGameId by lazy { intent.getStringExtra(EXTRA_GAME_ID) ?: "" } - private val mGame by lazy { App.realm.where(TeamTwisterGame::class.java).equalTo("id", mGameId).findFirst()!! } - private val mDatabase: DatabaseReference = FirebaseDatabase.getInstance().reference - private val mTable = Table.getSelectedTable() - private val mHistory = Stack() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_team_twister_game) - volumeControlStream = AudioManager.STREAM_MUSIC - setupViews() - updateState() - GoalReceiver.register(this, goalReceiver, 100) - updateGameStatusBusy() - } - - private fun setupViews() { - - // Get table colors - val sideOneColor = Color.parseColor(mTable.sideOneColor) - val sideTwoColor = Color.parseColor(mTable.sideTwoColor) - - // Set team name colors - teamOneName.textColor = sideOneColor - teamTwoName.textColor = sideTwoColor - - // Set TeamLayout colors - teamOneLayout.setTeamColor(sideOneColor) - teamTwoLayout.setTeamColor(sideTwoColor) - - // Pause game - pauseGameButton.onClick { - shortToast(R.string.game_paused) - updateGameStatusFree() - finish() - } - - // Quit game - quitGameButton.onClick { - MaterialDialog.Builder(this) - .title(R.string.quit_game) - .content(R.string.confirm_quit_game) - .negativeText(android.R.string.cancel) - .positiveText(R.string.quit_game) - .onPositive { _, _ -> - mGame.edit { status = GameStatus.CANCELED.name } - updateGameStatusFree() - finish() - } - .show() - } - - // Undo last goal - undoView.onClick { undoGoal() } - - // Tap team to count a goal - teamOneLayout.onClick { goalReceiver.onGoal(TableSide.SIDE_1) } - teamTwoLayout.onClick { goalReceiver.onGoal(TableSide.SIDE_2) } - - mCommentator.announceGameStart() - } - - private fun undoGoal() { - if (mHistory.isNotEmpty()) { - val snapshot = mHistory.pop() - App.realm.inTransaction { it.copyToRealmOrUpdate(snapshot) } - mCommentator.announce("Oops") - } - updateState() - } - - private val goalReceiver: GoalReceiver = GoalReceiver { side -> - if (mGame.hasWinner) return@GoalReceiver - val announcement = "${Sfx.ROTATE_DING} ${mGame.getNextSwappedPlayers().joinToString(" and ") { it.name }} - swap now" - mHistory += App.realm.copyFromRealm(mGame) - mGame.recordGoal(side) - if (!mGame.hasWinner) mCommentator.announce(announcement, true) - updateState() - } - - private fun updateState() { - val (team1, team2) = mGame.currentTeams - - teamOneName.text = team1.teamName.elseIfBlank(mTable.sideOneName) - teamTwoName.text = team2.teamName.elseIfBlank(mTable.sideTwoName) - - teamOneLayout.team = team1 - teamTwoLayout.team = team2 - - pointsToWinView.text = mGame.pointsToWin.toString() - - gameTimerView.setStartTime(mGame.startTime) - - teamOneScore.text = team1.points.toString() - teamTwoScore.text = team2.points.toString() - - undoView.setVisible(mHistory.isNotEmpty()) - - val sideOneServing = mGame.getServingSide().isSide1 - teamOneServingIndicator.setVisible(sideOneServing) - teamTwoServingIndicator.setVisible(!sideOneServing) - - if (mGame.hasWinner) { - mCommentator.announce(Sfx.WINNING_GOAL.name) - WinTeamTwisterGameDialog(this, mGame, { undoGoal() }, { endGame() }).show() - } - } - - private fun endGame() { - mGame.edit { - status = GameStatus.FINISHED.name - endTime = System.currentTimeMillis() - } - updateGameStatusFree() - finish() - } - - override fun onStart() { - super.onStart() - val am = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val pi = PendingIntent.getService(this, 0, PushIntentService.getIntent(this, mTable.pushId, mTable.name), PendingIntent.FLAG_CANCEL_CURRENT) - am.cancel(pi) - } - - override fun onStop() { - super.onStop() - val am = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager - val pi = PendingIntent.getService(this, 0, PushIntentService.getIntent(this, mTable.pushId, mTable.name), PendingIntent.FLAG_CANCEL_CURRENT) - am.set(AlarmManager.RTC_WAKEUP, 90000, pi) - } - - override fun onDestroy() { - super.onDestroy() - GoalReceiver.unregister(this, goalReceiver) - } - - private fun updateGameStatusBusy() { - mDatabase.child("tables") - .child(mTable.id) - .child("currentGame").setValue("TEAM_TWISTER") - } - - private fun updateGameStatusFree() { - mDatabase.child("tables").child(mTable.id).apply { - child("currentGame").setValue("FREE") - child("currentScoreTeamOne").setValue("") - child("currentScoreTeamTwo").setValue("") - child("currentBestOf").setValue("") - child("currentPointsToWin").setValue("") - child("currentRound").setValue("") - child("teamOne").setValue(null) - child("teamTwo").setValue(null) - } - } - - override fun onBackPressed() { - // Do nothing - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/FoosRankLeaderboardAdapter.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/FoosRankLeaderboardAdapter.kt deleted file mode 100644 index 85bc22a153..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/FoosRankLeaderboardAdapter.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.adapters - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.LayoutInflater -import android.view.ViewGroup -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.holders.FoosRankViewHolder -import com.instructure.androidfoosball.ktmodels.User - - -class FoosRankLeaderboardAdapter (private val mContext: Context, private val mUsers: List, val foosRankCallback: (User) -> Unit) : RecyclerView.Adapter() { - - override fun getItemCount(): Int { - return mUsers.size - } - - override fun onBindViewHolder(holder: FoosRankViewHolder, position: Int) { - holder.bind(mContext, mUsers[position], position, foosRankCallback) - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoosRankViewHolder { - val view = LayoutInflater.from(parent.context).inflate(R.layout.adapter_foos_rank, parent, false) - return FoosRankViewHolder(view) - } - - - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/LeaderboardAdapter.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/LeaderboardAdapter.kt deleted file mode 100644 index 4de7191c74..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/LeaderboardAdapter.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.adapters - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.LayoutInflater -import android.view.ViewGroup -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.holders.LeaderboardViewHolder -import com.instructure.androidfoosball.ktmodels.User - - -class LeaderboardAdapter (private val mContext: Context, private val mUsers: List) : RecyclerView.Adapter() { - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LeaderboardViewHolder { - val v = LayoutInflater.from(parent.context).inflate(R.layout.adapter_leaderboard, parent, false) - return LeaderboardViewHolder(v) - } - - override fun onBindViewHolder(holder: LeaderboardViewHolder, position: Int) { - holder.bind(mContext, mUsers[position], position) - } - - override fun getItemCount() = mUsers.size -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamAdapter.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamAdapter.kt deleted file mode 100644 index a61122a73f..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamAdapter.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.instructure.androidfoosball.adapters - -import android.annotation.SuppressLint -import android.content.Context -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter -import android.widget.TextView -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.CustomTeam -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setAvatar -import de.hdodenhof.circleimageview.CircleImageView - -class TeamAdapter(private val mContext: Context, private val mRawTeams: List, private val userMap: Map) : BaseAdapter() { - private val mAvatarSize = mContext.resources.getDimension(R.dimen.avatar_size_small).toInt() - - private var mTeams = mRawTeams - - override fun getCount() = mTeams.size - - override fun getItem(position: Int) = mTeams[position] - - override fun getItemId(position: Int) = position.toLong() - - override fun hasStableIds() = true - - var searchQuery = "" - set(value) { - field = value - mTeams = if (value.isBlank()) { - mRawTeams - } else { - mRawTeams.filter { it.teamName.contains(searchQuery, true) } - } - notifyDataSetChanged() - } - - @SuppressLint("ViewHolder") - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - var view = convertView - val holder: TeamHolder - if (view == null) { - view = View.inflate(mContext, R.layout.adapter_team_dialog, null) - holder = TeamHolder() - holder.teamName = view.findViewById(R.id.teamName) - holder.avatar1 = view.findViewById(R.id.avatar1) - holder.avatar2 = view.findViewById(R.id.avatar2) - view.tag = holder - } else { - holder = view.tag as TeamHolder - } - val team = mTeams[position] - holder.teamName?.text = team.teamName - holder.avatar1?.setAvatar(userMap[team.users[0]], mAvatarSize) - holder.avatar2?.setAvatar(userMap[team.users[1]], mAvatarSize) - return view!! - } - - internal class TeamHolder { - var teamName: TextView? = null - var avatar1: CircleImageView? = null - var avatar2: CircleImageView? = null - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamLeaderboardAdapter.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamLeaderboardAdapter.kt deleted file mode 100644 index fb247d1706..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TeamLeaderboardAdapter.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.adapters - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.LayoutInflater -import android.view.ViewGroup -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.holders.TeamLeaderboardViewHolder -import com.instructure.androidfoosball.ktmodels.CustomTeam -import com.instructure.androidfoosball.ktmodels.User - - -class TeamLeaderboardAdapter (private val mContext: Context, private val mTeams: List, private val mUsers: Map) : RecyclerView.Adapter() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TeamLeaderboardViewHolder { - val v = LayoutInflater.from(parent.context).inflate(R.layout.adapter_team_leaderboard, parent, false) - return TeamLeaderboardViewHolder(v) - } - - override fun onBindViewHolder(holder: TeamLeaderboardViewHolder, position: Int) { - holder.bind(mContext, mTeams[position], mUsers, position) - } - - override fun getItemCount() = mTeams.size -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TimeWasterLeaderboardAdapter.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TimeWasterLeaderboardAdapter.kt deleted file mode 100644 index c018e0c998..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/TimeWasterLeaderboardAdapter.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.adapters - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.LayoutInflater -import android.view.ViewGroup -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.holders.TimeWasterViewHolder -import com.instructure.androidfoosball.ktmodels.Game -import com.instructure.androidfoosball.ktmodels.GameStatus -import com.instructure.androidfoosball.ktmodels.User - -class TimeWasterLeaderboardAdapter(private val mContext: Context, private val mUsers: List) : RecyclerView.Adapter() { - - private val averageRoundTime by lazy { - val games = App.realm.where(Game::class.java).equalTo("status", GameStatus.FINISHED.name).findAll().toList() - val rounds = games.flatMap { it.rounds }.filter { it.startTime > 0 && it.endTime > 0 } - val totalTime = rounds.sumBy { ((it.endTime - it.startTime) / 1000).toInt() } - totalTime / games.size.toDouble() / 3600 - } - - override fun getItemCount(): Int = mUsers.size - - override fun onBindViewHolder(holder: TimeWasterViewHolder, position: Int) { - holder.bind(mContext, mUsers[position], position, averageRoundTime) - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TimeWasterViewHolder { - val view = LayoutInflater.from(parent.context).inflate(R.layout.adapter_time_waster, parent, false) - return TimeWasterViewHolder(view) - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/UserAdapter.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/UserAdapter.kt deleted file mode 100644 index 381809305d..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/adapters/UserAdapter.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.adapters - -import android.annotation.SuppressLint -import android.content.Context -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter -import android.widget.TextView -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setAvatar -import de.hdodenhof.circleimageview.CircleImageView - -class UserAdapter(private val mContext: Context, private val mRawUsers: List) : BaseAdapter() { - private val mAvatarSize = mContext.resources.getDimension(R.dimen.avatar_size_small).toInt() - - private var mUsers = mRawUsers - - override fun getCount() = mUsers.size - - override fun getItem(position: Int) = mUsers[position] - - override fun getItemId(position: Int) = position.toLong() - - override fun hasStableIds() = true - - var searchQuery = "" - set(value) { - field = value - mUsers = if (value.isBlank()) { - mRawUsers - } else { - mRawUsers.filter { it.name.contains(searchQuery, true) } - } - notifyDataSetChanged() - } - - @SuppressLint("ViewHolder") - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - var view = convertView - val holder: UserHolder - if (view == null) { - view = View.inflate(mContext, R.layout.adapter_user_dialog, null) - holder = UserHolder() - holder.userName = view.findViewById(R.id.userName) - holder.avatar = view.findViewById(R.id.avatar) - view.tag = holder - - } else { - holder = view.tag as UserHolder - } - holder.avatar?.setAvatar(mUsers[position], mAvatarSize) - holder.userName?.text = mUsers[position].name - return view!! - } - - internal class UserHolder { - var userName: TextView? = null - var avatar: CircleImageView? = null - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/FoosRankViewHolder.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/FoosRankViewHolder.kt deleted file mode 100644 index 29467f9a3f..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/FoosRankViewHolder.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.holders - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.View -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setAvatar -import kotlinx.android.synthetic.main.adapter_foos_rank.view.* -import org.jetbrains.anko.sdk21.listeners.onClick - - -class FoosRankViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bind(context: Context, user: User, position: Int, foosRankCallback: (User) -> Unit) { - itemView.foosRank.text = when { - user.rankedGamesPlayed > 0 -> user.foosRanking.toString() - else -> context.getString(R.string.no_ranking) - } - itemView.position.text = "${position + 1}" - itemView.name.text = user.name - itemView.avatar.setAvatar(user, context.resources.getDimension(R.dimen.avatar_size_medium).toInt()) - itemView.onClick { foosRankCallback(user) } - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/LeaderboardViewHolder.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/LeaderboardViewHolder.kt deleted file mode 100644 index 66e726c0d9..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/LeaderboardViewHolder.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.holders - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.View -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.activities.LeaderboardActivity -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.getWinRate -import com.instructure.androidfoosball.utils.setAvatar -import kotlinx.android.synthetic.tablet.adapter_leaderboard.view.* - - -class LeaderboardViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bind(context: Context, user: User, position: Int) { - val winRate = user.getWinRate(LeaderboardActivity.MIN_GAMES_FOR_RANKING) - itemView.winRate.text = when { - winRate >= 0 -> context.getString(R.string.win_rate_format).format(winRate) - else -> context.getString(R.string.no_ranking) - } - itemView.position.text = "${position + 1}" - itemView.name.text = user.name - itemView.wins.text = context.getString(R.string.leaderboard_wins).format(user.wins) - itemView.losses.text = context.getString(R.string.leaderboard_losses).format(user.losses) - itemView.avatar.setAvatar(user, context.resources.getDimension(R.dimen.avatar_size_medium).toInt()) - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TeamLeaderboardViewHolder.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TeamLeaderboardViewHolder.kt deleted file mode 100644 index c9ec57a6f7..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TeamLeaderboardViewHolder.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.holders - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.View -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.activities.LeaderboardActivity -import com.instructure.androidfoosball.ktmodels.CustomTeam -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.getWinRate -import com.instructure.androidfoosball.utils.setAvatar -import com.instructure.androidfoosball.utils.setVisible -import kotlinx.android.synthetic.tablet.adapter_team_leaderboard.view.* - - -class TeamLeaderboardViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bind(context: Context, team: CustomTeam, users: Map, position: Int) { - val playerOne: User? = users[team.users.getOrNull(0) ?: ""] - val playerTwo: User? = users[team.users.getOrNull(1) ?: ""] - if (playerOne == null || playerTwo == null) { - return - } - val winRate = team.getWinRate(LeaderboardActivity.MIN_GAMES_FOR_TEAM_RANKING) - itemView.team_winRate.text = when { - winRate >= 0 -> context.getString(R.string.win_rate_format).format(winRate) - else -> context.getString(R.string.no_ranking) - } - itemView.team_position.text = (position + 1).toString() - itemView.team_name.setVisible(!team.teamName.isBlank()) - itemView.team_name.text = team.teamName - itemView.wins.text = context.getString(R.string.leaderboard_wins).format(team.teamWins) - itemView.losses.text = context.getString(R.string.leaderboard_losses).format(team.teamLosses) - itemView.avatar_player_one.setAvatar(playerOne, context.resources.getDimension(R.dimen.avatar_size_medium).toInt()) - itemView.avatar_player_two.setAvatar(playerTwo, context.resources.getDimension(R.dimen.avatar_size_medium).toInt()) - - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TimeWasterViewHolder.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TimeWasterViewHolder.kt deleted file mode 100644 index 94981bec5d..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/holders/TimeWasterViewHolder.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.holders - -import android.content.Context -import android.support.v7.widget.RecyclerView -import android.view.View -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setAvatar -import kotlinx.android.synthetic.main.adapter_time_waster.view.* - -class TimeWasterViewHolder(view: View) : RecyclerView.ViewHolder(view) { - fun bind(context: Context, user: User, position: Int, averageRoundTime: Double) { - val rounds = user.wins + user.losses - itemView.roundsPlayedView.text = when { - rounds > 0 -> rounds.toString() - else -> context.getString(R.string.no_ranking) - } - itemView.position.text = "${position + 1}" - itemView.name.text = user.name - itemView.avatar.setAvatar(user, context.resources.getDimension(R.dimen.avatar_size_medium).toInt()) - itemView.timeWastedView.text = context.getString(R.string.hoursWastedFormatted, averageRoundTime * rounds) - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CustomTeam.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CustomTeam.kt deleted file mode 100644 index b4ad6aba22..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CustomTeam.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.util.* - - -data class CustomTeam( - var id: String = "", - var teamName: String = "", - var teamWins: Long = 0, - var teamLosses: Long = 0, - var users: List = ArrayList() -) { - fun toRealmTeam() = RealmTeam(id, teamName, teamWins, teamLosses).apply { userList = users } -} - -open class RealmTeam( - @PrimaryKey - var id: String = "", - var teamName: String = "", - var teamWins: Long = 0, - var teamLosses: Long = 0, - var usersString: String = "" -) : RealmObject() { - - var userList: List - get() = usersString.split("|") - set(value) { - usersString = value.joinToString("|") - } - - fun toCustomTeam() = CustomTeam(id, teamName, teamWins, teamLosses, userList) -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatGame.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatGame.kt deleted file mode 100644 index 90911bd3a6..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatGame.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmList -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.util.* - - -open class CutThroatGame( - @PrimaryKey - var id: String = UUID.randomUUID().toString(), - var status: String = GameStatus.ONGOING.name, - var pointsToWin: Int = 0, - var rotateAfter: Int = 0, - var singleIdx: Int = 0, - var pointsSinceRotation: Int = 0, - var players: RealmList = RealmList(), - var startTime: Long = -1L, - var endTime: Long = -1L -) : RealmObject() { - fun getSingle() = players[singleIdx] - fun hasWinner(): Boolean = getWinner() != null - fun getWinner(): User? = players.firstOrNull { it.score >= pointsToWin }?.user -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatPlayer.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatPlayer.kt deleted file mode 100644 index c16c94829c..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/CutThroatPlayer.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmObject - -open class CutThroatPlayer( - var user: User? = null, - var score: Int = 0 -) : RealmObject() diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Game.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Game.kt deleted file mode 100644 index 88c1eb6e16..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Game.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmList -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.util.* - - -@Suppress("unused") -open class Game( - @PrimaryKey - var id: String = UUID.randomUUID().toString(), - var status: String = GameStatus.ONGOING.name, - var bestOf: Int = 3, - var rounds: RealmList = RealmList(), - var teamOne: Team? = null, - var teamTwo: Team? = null, - var startTime: Long = -1L, - var endTime: Long = -1L -) : RealmObject() { - - fun currentRound(): Round = rounds.last() - - fun hasWinner(): Boolean = getWinningTeam() != null - - fun getWinningTeam(): Team? { - - val (winCountTeamOne, winCountTeamTwo) = rounds.fold(0 to 0) { (first, second), round -> - val winner = round.getWinningTeam() - when (winner) { - teamOne -> (first + 1) to second - teamTwo -> first to (second + 1) - else -> first to second - } - } - - val roundsToWin = 1 + (bestOf / 2) - return when { - winCountTeamOne >= roundsToWin -> teamOne - winCountTeamTwo >= roundsToWin -> teamTwo - else -> null - } - } - - fun getLosingTeam(): Team? = when (getWinningTeam()) { - teamOne -> teamTwo - teamTwo -> teamOne - else -> null - } - - fun getTeamWinCount(team: Team) = rounds.count { it.getWinningTeam() == team } - - /** - * Returns the [TableSide] that should serve the ball, based on which [Team] scored last. - */ - fun getServingSide() = if (getLastScoringTeam() == currentRound().sideOneTeam) TableSide.SIDE_2 else TableSide.SIDE_1 - - /** - * Returns the [Team] that last scored during this game. If no team has scored yet, this function - * returns the team with the higher FoosRank - */ - private fun getLastScoringTeam() = when { - // If current round has goal history, return the team of the last goal - currentRound().goalHistory.isNotEmpty() -> currentRound().goalHistory.last().team - - // If not, and there was a previous round, return the team of that round's last goal - rounds.size > 1 -> rounds[rounds.size - 2].goalHistory.last().team - - // Otherwise, return the team with the better average win rate - else -> listOf(teamOne, teamTwo).maxBy { it?.getCompositeFoosRank() ?: 0.0 }!! - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/GameStatus.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/GameStatus.kt deleted file mode 100644 index c9f7429b87..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/GameStatus.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -enum class GameStatus { - ONGOING, - CANCELED, - FINISHED -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Goal.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Goal.kt deleted file mode 100644 index 0a7c6c87a0..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Goal.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmObject - -open class Goal ( - var team: Team? = null, - var time: Long = System.currentTimeMillis() -) : RealmObject() diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/ITeam.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/ITeam.kt deleted file mode 100644 index caf7ac3b81..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/ITeam.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.utils.getTeamHash -import io.realm.RealmList - -interface ITeam { - - var users: RealmList - - fun getTeamHash() = users.map(User::id).getTeamHash() - - val teamName: String? get() = App.realm.where(RealmTeam::class.java).equalTo("id", getTeamHash()).findFirst()?.teamName - - fun getAverageWinRate(): Float { - val (wins, losses) = users.fold(Pair(0, 0)) { pair, user -> - Pair(pair.first + user.wins, pair.second + user.losses) - } - if (wins == 0) return 0f - if (losses == 0) return 100f - return wins * 100f / (wins + losses) - } - - fun getCompositeFoosRank() = users.map { it.foosRanking }.average() - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/IncomingData.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/IncomingData.kt deleted file mode 100644 index 0c3adc3d19..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/IncomingData.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -data class IncomingData( - val sideOne: String = "", - val sideTwo: String = "", - val tableRequestUserId: String = "", - val tableRequestTime: String = "" -) diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Round.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Round.kt deleted file mode 100644 index bbfa3ab69a..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Round.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import com.instructure.androidfoosball.utils.edit -import com.instructure.androidfoosball.utils.elseIfBlank -import io.realm.RealmList -import io.realm.RealmObject - -@Suppress("unused") -open class Round( - var pointsToWin: Int = 5, - var sideOneTeam: Team? = null, - var sideTwoTeam: Team? = null, - var goalHistory: RealmList = RealmList(), - var startTime: Long = -1L, - var endTime: Long = -1L -) : RealmObject() { - fun getScore(team: Team) = goalHistory.count { it.team == team } - - fun getTeamName(side: TableSide, table: Table) = when (side) { - TableSide.SIDE_1 -> sideOneTeam?.teamName.elseIfBlank(table.sideOneName) - TableSide.SIDE_2 -> sideTwoTeam?.teamName.elseIfBlank(table.sideTwoName) - } - fun getTeamName(team: Team, table: Table) = when (team) { - sideOneTeam -> sideOneTeam?.teamName.elseIfBlank(table.sideOneName) - sideTwoTeam -> sideTwoTeam?.teamName.elseIfBlank(table.sideTwoName) - else -> "" - } - - fun recordGoal(side: TableSide) { - edit { - val goal = Goal(if (side == TableSide.SIDE_1) sideOneTeam else sideTwoTeam) - goalHistory.add(goal) - } - } - - fun hasWinner() = getWinningTeam() != null - - fun getWinningTeam(): Team? = when { - getScore(sideOneTeam!!) >= pointsToWin -> sideOneTeam - getScore(sideTwoTeam!!) >= pointsToWin -> sideTwoTeam - else -> null - } - - fun getLosingTeam(): Team? = when { - getScore(sideOneTeam!!) >= pointsToWin -> sideTwoTeam - getScore(sideTwoTeam!!) >= pointsToWin -> sideOneTeam - else -> null - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Table.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Table.kt deleted file mode 100644 index e624fa89aa..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Table.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.instructure.androidfoosball.ktmodels - -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.utils.Prefs -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey - - -@Suppress("unused") -open class Table( - @PrimaryKey - var id: String = "", - var name: String = "", - var sideOneColor: String = "", - var sideTwoColor: String = "", - var sideOneName: String = "", - var sideTwoName: String = "", - var currentGame: String = "", - var currentGameInfo: String = "", - var pushId: String = "" -) : RealmObject() { - companion object { - - /** - * Returns the selected [Table], specified by `tableId` in [Prefs] - */ - fun getSelectedTable(): Table - = App.realm.where(Table::class.java).equalTo("id", Prefs.tableId).findFirst() - ?: throw IllegalStateException("Table cannot be request before initial sync") - - /** - * Returns `true` if there are any ongoing games - */ - fun hasOngoingGames() = App.realm.where(Game::class.java).equalTo("status", GameStatus.ONGOING.name).count() > 0 - || App.realm.where(CutThroatGame::class.java).equalTo("status", GameStatus.ONGOING.name).count() > 0 - || App.realm.where(TeamTwisterGame::class.java).equalTo("status", GameStatus.ONGOING.name).count() > 0 - || App.realm.where(TableKingGame::class.java).equalTo("status", GameStatus.ONGOING.name).count() > 0 - - /** - * Returns a [List] of ongoing [Game]s - */ - fun getOngoingGames(): List - = App.realm.where(Game::class.java).equalTo("status", GameStatus.ONGOING.name).findAll().toList() + - App.realm.where(CutThroatGame::class.java).equalTo("status", GameStatus.ONGOING.name).findAll().toList() + - App.realm.where(TeamTwisterGame::class.java).equalTo("status", GameStatus.ONGOING.name).findAll().toList() + - App.realm.where(TableKingGame::class.java).equalTo("status", GameStatus.ONGOING.name).findAll().toList() - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableKingGame.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableKingGame.kt deleted file mode 100644 index a5dfad2532..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableKingGame.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import com.instructure.androidfoosball.utils.disjunctiveUnion -import com.instructure.androidfoosball.utils.edit -import com.instructure.androidfoosball.utils.swappedIf -import io.realm.RealmList -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.util.* - -@Suppress("unused") -open class TableKingGame( - @PrimaryKey - var id: String = UUID.randomUUID().toString(), - var status: String = GameStatus.ONGOING.name, - var pointsToWin: Int = 0, - var completedRounds: Int = 0, - var teams: RealmList = RealmList(), - var startTime: Long = -1L, - var endTime: Long = -1L -) : RealmObject() { - - private val hasRoundWinner: Boolean get() = with(currentTeams) { first.points == pointsToWin || second.points == pointsToWin } - - private val teamConfigIdx get() = TEAM_CONFIGS[completedRounds % TEAM_CONFIGS.size] - - private val nextTeams: Pair - get() { - val nextConfig = TEAM_CONFIGS[(completedRounds + 1) % TEAM_CONFIGS.size] - return teams[nextConfig] to teams[5 - nextConfig] - } - - val currentTeams get() = teams[teamConfigIdx] to teams[5 - teamConfigIdx] - - val isGameComplete: Boolean get() = completedRounds >= 3 - - fun getServingSide() = with(currentTeams) { - if (first.serveValue > second.serveValue) TableSide.SIDE_1 else TableSide.SIDE_2 - } - - fun recordGoal(side: TableSide) = edit { - val (scoringTeam, otherTeam) = currentTeams.swappedIf(side.isSide2) - scoringTeam.points++ - scoringTeam.madeLastGoal = true - otherTeam.madeLastGoal = false - if (hasRoundWinner) completedRounds++ - } - - fun getGoalOutcome(side: TableSide): Pair { - val scoringTeam = when (side) { - TableSide.SIDE_1 -> currentTeams.first - TableSide.SIDE_2 -> currentTeams.second - } - val willWinRound = (scoringTeam.points + 1) >= pointsToWin - val willEndGame = willWinRound && (completedRounds + 1) >= 3 - return willWinRound to willEndGame - } - - fun getNextSwappedPlayers() = currentTeams.first.users.disjunctiveUnion(nextTeams.first.users) - - companion object { - private val TEAM_CONFIGS = listOf(0, 3, 1) - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableSide.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableSide.kt deleted file mode 100644 index 86bdd73d97..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TableSide.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -enum class TableSide { - SIDE_1, - SIDE_2; - - val isSide1 get() = this == SIDE_1 - val isSide2 get() = this == SIDE_2 -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Team.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Team.kt deleted file mode 100644 index a3b2d889a8..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/Team.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmList -import io.realm.RealmObject - - -open class Team( - override var users: RealmList = RealmList() -) : RealmObject(), ITeam diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamTwisterGame.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamTwisterGame.kt deleted file mode 100644 index 0f7b503754..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamTwisterGame.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import com.instructure.androidfoosball.utils.disjunctiveUnion -import com.instructure.androidfoosball.utils.edit -import com.instructure.androidfoosball.utils.swappedIf -import io.realm.RealmList -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.util.* - -@Suppress("unused") -open class TeamTwisterGame( - @PrimaryKey - var id: String = UUID.randomUUID().toString(), - var status: String = GameStatus.ONGOING.name, - var pointsToWin: Int = 0, - var goalCount: Int = 0, - var teams: RealmList = RealmList(), - var startTime: Long = -1L, - var endTime: Long = -1L -) : RealmObject() { - - private val winningTeam: TeamWithPoints? get() = teams.firstOrNull { it.points >= pointsToWin } - - private val losingTeams: List get() = teams - winningTeam - - private val teamConfigIdx get() = TEAM_CONFIGS[goalCount % TEAM_CONFIGS.size] - - private val nextTeams: Pair - get() { - val nextConfigIdx = TEAM_CONFIGS[(goalCount + 1) % TEAM_CONFIGS.size] - return teams[nextConfigIdx] to teams[5 - nextConfigIdx] - } - - val hasWinner: Boolean get() = winningTeam != null - - val currentTeams get() = teams[teamConfigIdx] to teams[5 - teamConfigIdx] - - fun getServingSide() = with(currentTeams) { - if (first.serveValue > second.serveValue) TableSide.SIDE_1 else TableSide.SIDE_2 - } - - fun recordGoal(side: TableSide) { - edit { - val (scoringTeam, otherTeam) = currentTeams.swappedIf(side.isSide2) - scoringTeam.points++ - scoringTeam.madeLastGoal = true - otherTeam.madeLastGoal = false - goalCount++ - } - } - - fun getNextSwappedPlayers() = currentTeams.first.users.disjunctiveUnion(nextTeams.first.users) - - companion object { - private val TEAM_CONFIGS = listOf(0, 3, 1, 5, 3, 4, 5, 2, 4, 0, 2, 1) - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamWithPoints.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamWithPoints.kt deleted file mode 100644 index c75b22303b..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/TeamWithPoints.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmList -import io.realm.RealmObject - -open class TeamWithPoints( - var points: Int = 0, - override var users: RealmList = RealmList(), - var madeLastGoal: Boolean = false -) : RealmObject(), ITeam { - val serveValue get() = if (madeLastGoal) -Double.MAX_VALUE else (points * -10000) - getCompositeFoosRank() -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/User.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/User.kt deleted file mode 100644 index 9fa7607133..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/ktmodels/User.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.ktmodels - -import io.realm.RealmObject -import io.realm.annotations.Ignore -import io.realm.annotations.PrimaryKey -import java.util.* - - -open class User( - @PrimaryKey - var id: String = "", - var name: String = "", - var email: String = "", - var avatar: String = "", - var pinHash: String = "", - var pinDisabled: String = "", - var guest: Boolean = false, - var customAssignmentPhrase: String = "", - var customVictoryPhrase: String = "", - var foosRanking: Int = 0, - var rankedGamesPlayed: Int = 0, - @Ignore - var foosRankMap: HashMap = HashMap(), - var wins: Int = 0, - var losses: Int = 0 -) : RealmObject() diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/push/PushIntentService.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/push/PushIntentService.kt deleted file mode 100644 index cd0a506529..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/push/PushIntentService.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.push - -import android.app.IntentService -import android.content.Context -import android.content.Intent -import android.util.Log -import com.instructure.androidfoosball.BuildConfig -import okhttp3.MediaType -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.RequestBody -import org.json.JSONObject - - -class PushIntentService: IntentService("PushIntentService") { - - private val JSON = MediaType.parse("application/json; charset=utf-8") - private val FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send" - private val mClient = OkHttpClient() - - companion object { - - val PUSH_ID = "push_id" - val TABLE_NAME = "table_name" - - fun getIntent(context: Context, pushId: String, tableName: String) = Intent(context, PushIntentService::class.java).apply { - putExtra(PUSH_ID, pushId) - putExtra(TABLE_NAME, tableName) - } - } - - override fun onHandleIntent(intent: Intent?) { - try { - - val pushId = intent?.getStringExtra(PUSH_ID) - val tableName = intent?.getStringExtra(TABLE_NAME) - - val bodyString = JSONObject( - "{\"to\": \"/topics/"+ pushId + "\", \"data\": {\"message\": \"" + tableName + "\" }}" - ) - - Log.d("push", "json: " + bodyString.toString()) - - val body = RequestBody.create(JSON, bodyString.toString()) - val request = Request.Builder().url(FCM_MESSAGE_URL).post(body) - .addHeader("Authorization", "key=" + BuildConfig.FIREBASE_SERVER_KEY).build() - val response = mClient.newCall(request).execute() - val resultJson = JSONObject(response.body().string()) - - val success = resultJson.getInt("success") - val failure = resultJson.getInt("failure") - - Log.d("push", "Success: " + success) - Log.d("push", "Failure: " + failure) - } catch (e: Exception) { - Log.d("push", "Error: " + e) - } - - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/receivers/GoalReceiver.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/receivers/GoalReceiver.kt deleted file mode 100644 index 18c455d9cd..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/receivers/GoalReceiver.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.receivers - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import com.instructure.androidfoosball.ktmodels.TableSide - -class GoalReceiver(val onGoal: (TableSide) -> Unit) : BroadcastReceiver() { - - companion object { - val GOAL_ACTION = "action_goal" - val EXTRA_SIDE = "scoringSide" - - fun getGoalIntent(side: TableSide) = Intent(GOAL_ACTION).apply { - putExtra(EXTRA_SIDE, side.name) - } - - fun sendGoal(context: Context, side: TableSide) { - context.sendOrderedBroadcast(getGoalIntent(side), null) - } - - fun register(context: Context, receiver: GoalReceiver, priority: Int = 0) { - val filter = IntentFilter(GOAL_ACTION) - filter.priority = priority - context.registerReceiver(receiver, filter) - } - - fun unregister(context: Context, receiver: GoalReceiver) { - context.unregisterReceiver(receiver) - } - } - - override fun onReceive(context: Context, intent: Intent) { - if (intent.action == GOAL_ACTION) { - val sideString = intent.getStringExtra(EXTRA_SIDE) - onGoal(TableSide.valueOf(sideString)) - abortBroadcast() - } - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/services/FoosballSyncService.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/services/FoosballSyncService.kt deleted file mode 100644 index 8781dcb388..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/services/FoosballSyncService.kt +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.services - -import android.app.Service -import android.content.Intent -import android.os.Binder -import android.support.v4.app.NotificationCompat -import com.google.firebase.auth.FirebaseAuth -import com.google.firebase.database.* -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.BuildConfig -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.CustomTeam -import com.instructure.androidfoosball.ktmodels.Table -import com.instructure.androidfoosball.ktmodels.User -import java.util.* - -class FoosballSyncService : Service() { - - private val SERVICE_ID = 12321 - - inner class FoosballSyncServiceBinder : Binder() { - fun getService() = this@FoosballSyncService - } - - lateinit private var mAuth: FirebaseAuth - lateinit private var mDatabase: DatabaseReference - - private val mBinder = FoosballSyncServiceBinder() - private val mPendingSyncs = ArrayList<(Boolean) -> Unit>() - private var mIsFirebaseReady = false - private var mIsFirebaseFailed = false - private var mIsSyncing = false - private var mIsListeningForUserChanges = false - private var mIsListeningForTeamChanges = false - private var mSyncStep = 0 - - override fun onBind(intent: Intent?) = mBinder - - override fun onCreate() { - super.onCreate() - startForeground(SERVICE_ID, NotificationCompat.Builder(this, "Refoos to lose") - .setSmallIcon(R.mipmap.ic_launcher) - .setContentText("Foosball Service Running") - .build()) - - mAuth = FirebaseAuth.getInstance() - - mAuth.signInWithEmailAndPassword(BuildConfig.FIREBASE_USERNAME, BuildConfig.FIREBASE_PASSWORD).addOnCompleteListener { task -> - if (!task.isSuccessful) { - mIsFirebaseFailed = true - finishSync(false) - } else { - mIsFirebaseReady = true - if (mPendingSyncs.isNotEmpty()) startSync() - } - } - - mDatabase = FirebaseDatabase.getInstance().reference - } - - fun requestSync(onFinish: (Boolean) -> Unit) { - if (mIsFirebaseFailed) { - onFinish(false) - } else { - mPendingSyncs.add(onFinish) - startSync() - } - } - - private fun startSync() { - if (!mIsFirebaseReady || mIsSyncing) return - performNextSyncStep() - } - - private fun performNextSyncStep() { - mIsSyncing = true - mSyncStep++ - when (mSyncStep) { - 1 -> syncTables() - 2 -> syncUsers() - 3 -> syncTeams() - 4 -> finishSync(true) - } - } - - private fun syncTables() { - mDatabase.child("tables").addListenerForSingleValueEvent(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - val tables = ArrayList
() - val tableNames = ArrayList() - for (child in dataSnapshot.children) { - val table = child.getValue(Table::class.java) ?: continue - table.id = child.key - tables.add(table) - tableNames.add(table.name) - } - - App.realm.beginTransaction() - App.realm.copyToRealmOrUpdate(tables) - App.realm.commitTransaction() - - performNextSyncStep() - } - - override fun onCancelled(databaseError: DatabaseError) { - finishSync(false) - } - }) - } - - private fun syncUsers() { - if (mIsListeningForUserChanges) { - performNextSyncStep() - } else { - mDatabase.child("users").addValueEventListener(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - val users = ArrayList() - for (child in dataSnapshot.children) { - val user = child.getValue(User::class.java) ?: continue - user.id = child.key - users.add(user) - } - - App.realm.beginTransaction() - App.realm.copyToRealmOrUpdate(users) - App.realm.commitTransaction() - - if (!mIsListeningForUserChanges) { - mIsListeningForUserChanges = true - performNextSyncStep() - } - } - - override fun onCancelled(databaseError: DatabaseError) { - if (!mIsListeningForUserChanges) finishSync(false) - } - }) - } - } - - private fun syncTeams() { - if (mIsListeningForTeamChanges) { - performNextSyncStep() - } else { - mDatabase.child("customTeams").addValueEventListener(object : ValueEventListener { - override fun onDataChange(dataSnapshot: DataSnapshot) { - val teams = mutableListOf() - for (child in dataSnapshot.children) { - val team = child.getValue(CustomTeam::class.java) ?: continue - team.id = child.key - teams += team - } - - App.realm.beginTransaction() - App.realm.copyToRealmOrUpdate(teams.map { it.toRealmTeam() }) - App.realm.commitTransaction() - - if (!mIsListeningForTeamChanges) { - mIsListeningForTeamChanges = true - performNextSyncStep() - } - } - - override fun onCancelled(databaseError: DatabaseError) { - if (!mIsListeningForTeamChanges) finishSync(false) - } - }) - } - } - - private fun finishSync(success: Boolean) { - mIsSyncing = false - mSyncStep = 0 - mPendingSyncs.forEach { it(success) } - mPendingSyncs.clear() - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Commentator.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Commentator.kt deleted file mode 100755 index 9082135c4f..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Commentator.kt +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.utils - -import android.content.Context -import android.speech.tts.TextToSpeech -import com.instructure.androidfoosball.BuildConfig -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.* -import java.util.* - -class Commentator { - - enum class Sfx(val resId: Int) { - DING(R.raw.ding), - REVERSE_DING(R.raw.ding_reverse), - ROTATE_DING(R.raw.rotate_ding), - WINNING_GOAL(R.raw.ding_ding), - FIRST_BLOOD(R.raw.firstblood), - DOMINATING(R.raw.dominating), - MASSACRE(R.raw.massacre), - MURCA(R.raw.murca), - BAGEL_SONG(R.raw.bagel_song), - DOUBLE_KILL(R.raw.doublekill), - MULTI_KILL(R.raw.multikill), - KILLING_SPREE(R.raw.killingspree), - UNSTOPPABLE(R.raw.unstoppable), - LEEROY_JENKINS(R.raw.leeroy_jenkins), - MOTIVATION(R.raw.motivation), - ILLUMINATI_CONFIRMED(R.raw.illuminati_confirmed), - MLG_HORN(R.raw.mlg_horn), - LEGITNESS(R.raw.legitness), - PROFAMITY(R.raw.profamity), - POLICE_SIREN(R.raw.police_siren) - } - - private val mSfxNames = Sfx.values().map { it.name } - private val mQueuedText = ArrayList() - private var mIsReady = false - private val mRandy = Random() - lateinit private var mTts: TextToSpeech - private var rotatingCommentIndices: HashMap> = HashMap() - private var mInitialized = false - - fun initialize(context: Context) { - if (mInitialized) return - mTts = TextToSpeech(context) { mIsReady = true; mQueuedText.forEach { speak(it) } } - Sfx.values().forEach { mTts.addSpeech(it.name, BuildConfig.APPLICATION_ID, it.resId) } - mInitialized = true - } - - fun shutUp() { - mTts.stop() - mTts.shutdown() - } - - @Suppress("DEPRECATION") - private fun speak(text: String, flush: Boolean = true) { - when (mIsReady) { - true -> segmentify(text).forEachIndexed { idx, it -> - mTts.speak(it, if (idx == 0 && flush) TextToSpeech.QUEUE_FLUSH else TextToSpeech.QUEUE_ADD, null) - } - false -> mQueuedText.add(text) - } - } - - private fun segmentify(text: String, start: Int = 0, list: ArrayList = ArrayList()): List { - return when { - start >= text.length -> list - else -> { - val match = text.findAnyOf(mSfxNames, start) - when (match) { - null -> list.add(text.substring(start)) - else -> { - list.addIfValid(text.substring(start, match.first)) - list.add(match.second) - segmentify(text, match.first + match.second.length, list) - } - } - list - } - } - } - - private fun rotate(id: Int, vararg comments: String): String { - if (comments.isEmpty()) return "No comment" - val validIndices = rotatingCommentIndices.getOrPut(id) {(0 until comments.size).toMutableList()} - if (validIndices.isEmpty()) validIndices.addAll(0 until comments.size) - return comments[validIndices.removeAt(mRandy.nextInt(validIndices.size))] - } - - fun announce(text: String, flush: Boolean = true) = speak(text, flush) - - fun queueAnnounce(text: String) = announce(text, false) - - fun announceBadTouch() = speak(rotate( 12347, - Sfx.MLG_HORN.name, - "You have to start a game first. ${Sfx.MOTIVATION}", - "Don't touch that", - "I can't even.", - Sfx.MURCA.name, - "Ding. Wait, that's not right.", - "In soviet foosball, button press you.", - "I know that you believe you understand what you think I said, but I'm not sure you realize that what you heard is not what I meant.", - "Gross.", - "Do you even know what you're doing?", - "Insert coin", - "Look at me! I'm so special! I pressed a button. Hahahahaaaayugugudidididididahahahaaaaaaaaaaa.", - "That's inappropriate", - "There's no game in progress, dummy.", - "Look buddy. You can't be doing that.", - "Get your greasy fingers away from that button", - "The controls are over here dude", - "Touch that again and you're grounded", - "Do you think that's funny? Just going around pressing all the buttons you see?", - "${Sfx.DING} One point goes to nobody, because nobody is playing right now.", - "${Sfx.DING} Is this what you wanted? Free points with no effort? Fine, take all the points you want. It doesn't mean anything in the end. ${Sfx.WINNING_GOAL}", - "Is doesn't work like that. You have to start a game first.", - "Maybe you're new to this. You see, in foosball you need to score a goal to get a point. And in order to score a point you need to start a game.", - "Watch out! There's a serial button presser on the loose!", - "I don't know what you want me to do. You have to tell me.", - "Congratulations, you pressed a button. Do you want a sticker or something?" - )) - - fun announcePlayerAssignment(user: User, teamName: String) { - // Use custom assignment phrase if available - if (user.customAssignmentPhrase.isNotBlank()) { - announce(user.customAssignmentPhrase) - return - } - - // Otherwise, use the normal assignment set - val playerName = user.name - speak(rotate(87394, - "$playerName is assigned to $teamName", - "$playerName will be playing for $teamName", - "$teamName grudgingly accepts $playerName", - "$teamName pulls $playerName from the bench", - "$teamName must be desperate if they're putting $playerName into play", - "$playerName joins $teamName", - "$playerName is ready to fight for $teamName", - "$teamName adds $playerName to its ranks", - "$playerName rips his shirt off before realizing this isn't shirts versus skins.", - "$teamName takes on $playerName. How charitable.", - "$playerName risks joining $teamName", - "$teamName risks bringing on $playerName", - "$teamName regrets to inform your that it is contractually obligated to allow $playerName on the field.", - "$playerName takes one for $teamName", - "$playerName asks $teamName to make his tombstone the biggest.", - "Grant one ticket to $playerName for a ride on the $teamName train.", - "$teamName takes $playerName away.", - "Isn't $playerName a bit too skilled for $teamName?", - "Where oh where has my little $playerName gone? $teamName, that's where.", - "$playerName pulls out his com and says Beam me up $teamName", - "$playerName. $teamName. Now.", - "In a classic move, $playerName chooses $teamName", - "Do you, $playerName, take $teamName to be your lawfully wedded team?", - "$teamName, I'm home. I brought $playerName with me.", - "One small step for $playerName, one giant mistake for $teamName", - "$teamName could only afford $playerName", - "$playerName needs to start somewhere, so $teamName has to do for now." - )) - } - - fun announceGameStart(text: String = rotate( 832, - Sfx.LEEROY_JENKINS.name, - Sfx.MLG_HORN.name, - "Let's get this party started", - "Let's make this a clean fight", - "Go go go! Move move move move!", - "Game start. Go!", - "The goal is to get the thing into the other team's thing", - "This isn't going to take as long as last time, is it?", - "Let's make this fast. I totally didn't place any bets. Totally.", - "If you don't finish this in 5 minutes, I will self destruct.", - "This again? Do you people never learn?", - "3. 2. 1. Stop. Go. Wait. Yeah, go. Go now. For reals.", - "Just do it! Don't let your dreams be dreams!" - )) = speak("${Sfx.DING.name} $text") - - fun announceGoal(scoringSide: TableSide, round: Round, table: Table) { - val (scoringTeam, opposingTeam) = when (scoringSide) { - TableSide.SIDE_1 -> round.sideOneTeam!! to round.sideTwoTeam!! - TableSide.SIDE_2 -> round.sideTwoTeam!! to round.sideOneTeam!! - } - announceGoal(round.getTeamName(scoringTeam, table), round.getTeamName(opposingTeam, table), round.getScore(scoringTeam), round.getScore(opposingTeam)) - } - - fun announceUndoGoal(shameTeam: Team, opposingTeam: Team, round: Round, table: Table) { - announceUndoGoal(round.getTeamName(shameTeam, table), round.getTeamName(opposingTeam, table), round.getScore(shameTeam), round.getScore(opposingTeam)) - } - - private fun announceUndoGoal(shameTeamName: String, opponentTeamName: String, scoringTeamScore: Int, opponentTeamScore: Int) { - speak(Sfx.REVERSE_DING.name + rotate(3321, - "One less point for $shameTeamName. ${Sfx.PROFAMITY}", - "Shame on you $shameTeamName. You should feel bad. One less point for you.", - "Maybe we'll take the point away from $shameTeamName and give it to $opponentTeamName", - "Look at how far you got $shameTeamName. A whole $scoringTeamScore points. Then you went and threw it all away.", - "First you want the point, then you don't want the point. Make up your mind, will you?", - "W T F. Moving all of these points around is hard work. I just placed that point there and now you want me to move it again?", - "It seems $shameTeamName was a bit trigger happy. How embarrassing.", - "$shameTeamName made an honest mistake. Surely this is cause for ridicule." - )) - } - - fun announceGoal(scoringTeamName: String, opponentTeamName: String, scoringTeamScore: Int, opponentTeamScore: Int) { - speak((if (scoringTeamScore >= 5) Sfx.WINNING_GOAL.name else Sfx.DING.name) + when { - - /* Random chance to spawn patriotism */ - mRandy.nextFloat() < 0.01 -> Sfx.MURCA.name - - /* Winning Goal */ - scoringTeamScore >= 5 -> when (opponentTeamScore) { - - /* BAGEL! */ - 0 -> rotate(1, - "${Sfx.LEGITNESS} Absolutely beautiful. I couldn't have done it better myself.", - "Give me a B. Give me an A. Give me a G. Give me an E. Give me an L. B. A. G. E. L. What does it spell? ${Sfx.MASSACRE}", - "Get the cream cheese ready because this bagel is hot hot hot.", - "Roll out the bagel carpet because $opponentTeamName is about to take the walk of shame.", - Sfx.BAGEL_SONG.name, - "$opponentTeamName has bagel on their face. How embarrassing.", - "Well, that was easy. Bagels on the house." - ) - - /* Little competition */ - in 1..2 -> rotate(2, - "$opponentTeamName didn't put up much of a fight.", - "Was $opponentTeamName even trying?", - "$opponentTeamName must be a bunch of interns.", - "Piece of cake. Slice of pie. Like taking candy from an intern.", - "Let's hope $opponentTeamName is better at their job than at foosball.", - "This isn't ping pong $opponentTeamName. Get your head in the game.", - "Clearly $opponentTeamName had their mind on other things." - ) - - /* Eh */ - 3 -> rotate(3, - "It looks like $opponentTeamName needs a bit more practice.", - "$opponentTeamName wins the match! Oh, wait. No they didn't.", - "$opponentTeamName forgot to drink their Ovaltine." - ) - - /* A close game */ - 4 -> rotate(4, - "Good game $opponentTeamName. If only you had sucked a little less.", - "It was a close match but the better team came out on top." - ) - - else -> "This shouldn't happen. You shouldn't be here. ${Sfx.MURCA}" - - } + " $scoringTeamName wins the match!" - - /* Opponent hasn't scored */ - opponentTeamScore == 0 -> when (scoringTeamScore) { - - /* First goal of the game */ - 1 -> rotate(5, - "$scoringTeamName drew ${Sfx.FIRST_BLOOD}", - "$scoringTeamName is off to a good start.", - "It's okay $opponentTeamName, there's plenty of time to waste $scoringTeamName", - "First point goes to $scoringTeamName", - "Don't worry; we're just getting started.", - "One down, four to go." - ) - - /* Not first goal */ - 2 -> rotate(6, - Sfx.DOUBLE_KILL.name, - "Two zero. 1 2 3. Double oh 7. One billion. Numbers are meaningless.", - "Wow. Just wow.", - "If $scoringTeamName scores and $opponentTeamName isn't there to watch it, does it still count?", - "Huh." - ) - 3 -> rotate(7, - "Three to zero, illuminati confirmed ${Sfx.ILLUMINATI_CONFIRMED}", - Sfx.MULTI_KILL.name, - "I'm seeing a trend here", - "I see where this is going", - "$opponentTeamName is just rolling over and taking it.", - "I've got the phone if you want to order some bagels." - ) - 4 -> rotate(8, Sfx.KILLING_SPREE.name, Sfx.UNSTOPPABLE.name) - else -> "Trlololololololo" - } - - else -> when (scoringTeamScore - opponentTeamScore) { - - -3 -> rotate(9, - "$scoringTeamName is making a comeback. Well, probably not.", - "$scoringTeamName might have a chance after all", - "Don't get overconfident. $opponentTeamName is still 3 points ahead is thoroughly destroying you.", - "$scoringTeamName is making some progress. Finally", - "Bagel successfully avoided." - ) - - -2 -> rotate(10, - "$scoringTeamName is closing the gap", - "Just two more points and you might have a shot at winning this $scoringTeamName", - "Look into your collective hearts and find the power to win", - "Look at $scoringTeamName trying so hard to win. It would almost be cute if it weren't so pathetic.", - "$scoringTeamName is now losing a little less than before." - ) - - -1 -> rotate(11, - "$scoringTeamName is only one point behind.", - "You win some; you lose some. But you really lose most of them.", - "$scoringTeamName is basically winning. Except they're not.", - "$scoringTeamName got a goal. Fascinating.", - "This game might actually get interesting if $scoringTeamName keeps up the pace." - ) - - 0 -> when (scoringTeamScore) { - 1 -> rotate(12, - "Snake eyes! Place your bets now!", - "One to one. Brother to brother. Dust to dust. Mano a mano.", - "Just keep that up and maybe you'll make it to big league someday $scoringTeamName" - ) - 2, 3 -> rotate(13, - "Tie game! Only one can be victorious. Will $scoringTeamName take the lead or will $opponentTeamName come out on top?", - "$scoringTeamName has leveled the playing field. Not that it was unleveled before. If it was, you should probably get that fixed.", - "A tie game only means that $opponentTeamName sucks just as much as $scoringTeamName", - "Only one team can win, but everyone gets a participation trophy.", - "There are no winners here. I would know. I looked at the roster", - "Papa used to tell me that foosball would get me far in life. That was before he died when a foosball table fell on top of him." - ) - 4 -> rotate(14, - "I don't care who wins, would somebody just hurry up and score?", - "Both teams are neck and neck at 4 points. Next point wins the match!", - "No matter who scores the next goal, remember that I will love both teams equally. But I will love the winner more.", - "Now is a good time for a break, don't you think?" - ) - else -> "WAT" - } - - 1 -> rotate(15, - "$scoringTeamName takes the lead. Barely.", - "$scoringTeamName is one step ahead, but that's not saying much.", - "$scoringTeamName and $opponentTeamName sitting in a tree. F. O. O. S. I. N. G.", - "$scoringTeamName got lucky.", - "Let's keep this match clean, shall we?", - "$opponentTeamName let one get by. Typical.", - "Good. Now do it again." - ) - - 2 -> rotate(16, - "$opponentTeamName just needs some motivation. ${Sfx.MOTIVATION}", - "$scoringTeamName is on a roll", - "$opponentTeamName is lagging behind.", - "I'm pretty sure $scoringTeamName just cheated", - "$scoringTeamName should take it easy. They might hurt the feelings of $opponentTeamName", - "If I had a dollar for every goal $scoringTeamName made, I would have $scoringTeamScore dollars." - ) - - 3 -> rotate(17, - "$scoringTeamName is ${Sfx.DOMINATING}", - "$scoringTeamName is ${Sfx.UNSTOPPABLE}", - "Now I'm confident $scoringTeamName is cheating", - "It's not that $scoringTeamName is any good; it's that $opponentTeamName just sucks. A lot.", - "Go $opponentTeamName, I believe in you! But I'm still betting everything on $scoringTeamName" - ) - - else -> "Is there a bug in the app? Probably. You shouldn't be hearing this. Did you hear this? You did? Oh great, now I'll have to kill you." - } - }) - } -} - -fun ArrayList.addIfValid(text: String) { - if (text.isNotBlank()) add(text) -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Prefs.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Prefs.kt deleted file mode 100644 index d7eb21d1ad..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/Prefs.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.utils - -import com.instructure.androidfoosball.App - - -object Prefs : PrefManager(App.context, "com.instructure.androidfoosball") { - var userId: String by Pref("") - var tableId: String by Pref("") -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/QRView.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/QRView.kt deleted file mode 100644 index 35012d7ca4..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/QRView.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2018 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.instructure.androidfoosball.utils - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.Color -import android.util.AttributeSet -import android.widget.ImageView -import com.google.zxing.BarcodeFormat -import com.google.zxing.EncodeHintType -import com.google.zxing.qrcode.QRCodeWriter -import com.instructure.androidfoosball.ktmodels.Table -import com.instructure.androidfoosball.ktmodels.TableSide - -class QRView @JvmOverloads constructor( - context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 -) : ImageView(context, attrs, defStyleAttr) { - - private var contents: String? = null - private var rendered = false - - init { - if (isInEditMode) contents = "Testing...TESTING...1...2...3" - minimumWidth = 32f.dp(context).toInt() - minimumHeight = 32f.dp(context).toInt() - } - - fun setQRContents(contents: String) { - this.contents = contents - rendered = false - renderContents() - } - - fun setTableSide(table: Table, side: TableSide) { - setQRContents("foos://com.instructure.foos/${table.id}/${if (side.isSide1) 0 else 1}") - } - - private fun renderContents() { - if (contents != null && measuredWidth > 0 && measuredHeight > 0 && !rendered) { - val hints = mapOf(EncodeHintType.MARGIN to "0") - val bm = QRCodeWriter().encode(contents, BarcodeFormat.QR_CODE, measuredWidth, measuredHeight, hints) - val bitmap = Bitmap.createBitmap(bm.width, bm.height, Bitmap.Config.RGB_565) - for (i in 0 until (bm.width * bm.height)) { - val x = i % bm.width - val y = i / bm.width - bitmap.setPixel(x, y, if (bm[x, y]) Color.BLACK else Color.WHITE) - } - rendered = true - setImageBitmap(bitmap) - } - } - - override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - renderContents() - } - -} - diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/RankingUtils.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/RankingUtils.kt deleted file mode 100644 index c1a13dbe51..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/RankingUtils.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.utils - -import com.instructure.androidfoosball.ktmodels.User -import java.util.* - -object RankingUtils { - - - const val DEFAULT_FOOS_RANK = 1500 - const val FOOS_RANK_FLOOR = 1000 - const val FOOS_RANK_CEILING = 3000 - - fun updateFoosRankings(winners: List, losers: List) { - // NOTE: Any number of users on either team could be guest users (user.guest == true) - if ((winners + losers).any { it.guest }) return - //Check for non-initialized foosranks - - for (user in (winners + losers)) { - if(user.foosRanking < FOOS_RANK_FLOOR){ - user.foosRanking = DEFAULT_FOOS_RANK - } - } - - val winnersFoosRank = winners.sumBy { it.foosRanking } / winners.size - val losersFoosRank = losers.sumBy { it.foosRanking } / losers.size - - //If not, we must calculate the FoosRank changes for each player starting with the winners - //each player is compared to the composite score of the opposing team - - for(user in winners) { - var foosRank = user.foosRanking + (32*(1 - (1 / (1 + Math.pow(10.0, (losersFoosRank - user.foosRanking.toDouble()) / 400))))).toInt() - //Prevent the player from breaking through the foosrank ceiling - if(foosRank > FOOS_RANK_CEILING) { - foosRank = FOOS_RANK_CEILING - user.foosRanking = foosRank - } else { - user.foosRanking = foosRank - } - user.rankedGamesPlayed++ - //Update rank map with today's date - user.foosRankMap.put(Date().time.toString(), user.foosRanking) - } - - for(user in losers) { - var foosRank = user.foosRanking + (32*(0 - (1 / (1 + Math.pow(10.0, (winnersFoosRank - user.foosRanking.toDouble()) / 400))))).toInt() - //Prevent the player from dropping below the foosrank floor - if(foosRank < FOOS_RANK_FLOOR) { - foosRank = FOOS_RANK_FLOOR - user.foosRanking = foosRank - } else { - user.foosRanking = foosRank - } - user.rankedGamesPlayed++ - //Update rank map with today's date - user.foosRankMap.put(Date().time.toString(), user.foosRanking) - } - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/TabletExtensions.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/TabletExtensions.kt deleted file mode 100644 index 4a55e8af72..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/utils/TabletExtensions.kt +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -@file:Suppress("unused") - -package com.instructure.androidfoosball.utils - -import android.annotation.SuppressLint -import android.app.Activity -import android.content.Context -import android.text.Editable -import android.text.TextWatcher -import android.util.TypedValue -import android.view.LayoutInflater -import android.view.View -import android.view.WindowManager -import android.view.inputmethod.InputMethodManager -import com.afollestad.materialdialogs.MaterialDialog -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.adapters.TeamAdapter -import com.instructure.androidfoosball.adapters.UserAdapter -import com.instructure.androidfoosball.ktmodels.CustomTeam -import com.instructure.androidfoosball.ktmodels.RealmTeam -import com.instructure.androidfoosball.ktmodels.User -import io.realm.Realm -import io.realm.RealmList -import io.realm.RealmObject -import kotlinx.android.synthetic.main.dialog_team_picker.view.* -import kotlinx.android.synthetic.main.dialog_user_picker.view.* -import org.jetbrains.anko.displayMetrics -import org.jetbrains.anko.sdk21.listeners.onClick -import org.jetbrains.anko.sdk21.listeners.onItemClick -import java.util.* -import kotlinx.android.synthetic.main.dialog_user_picker.view.clearButton as teamClearButton - -inline fun T.edit(block: T.(realm: Realm) -> Unit) = App.realm.inTransaction { block(this) } - -inline fun > T.edit(block: T.(realm: Realm) -> Unit) = App.realm.inTransaction { block(this) } - -inline fun Realm.inTransaction(block: Realm.(realm: Realm) -> Unit) { - beginTransaction() - block(this) - commitTransaction() -} - -fun T.copyToRealmOrUpdate() = edit { it.copyToRealmOrUpdate(this) } - -val Activity.mCommentator: Commentator get() = App.commentator - -fun Float.dp() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, App.context.displayMetrics) -fun Float.dp(context: Context) = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, context.displayMetrics) - -fun List.shift(offset: Int): List = if (offset == 0) this else subList(offset, size) + subList(0, offset) - -fun List.split(vararg splitSizes: Int): List> { - if (splitSizes.sum() > size) throw IndexOutOfBoundsException("Sum of requested split sizes is larger than source list size") - val list = ArrayList>() - var idx = 0 - splitSizes.forEach { - list.add(subList(idx, idx + it)) - idx += it - } - list.add(subList(idx, size)) - return list -} - - -fun CustomTeam.getWinRate(minGamesRequired: Int) = when { - teamWins + teamLosses < minGamesRequired -> -1f - teamWins == 0L -> 0f - teamLosses == 0L -> 100f - else -> 100f * teamWins / (teamWins + teamLosses) -} - -fun List.getTeamHash(): String = sorted().joinToString("") - -fun CustomTeam.getTeamHash() : String = users.getTeamHash() - -fun List.sortCustomTeamByWinRatio(minGamesRequired: Int) - = sortedWith(compareBy({ -it.getWinRate(minGamesRequired) }, { -it.teamWins }, { it.teamLosses } )) - -@SuppressLint("InflateParams") -fun showUserPicker(context: Context, onUserSelected: (User) -> Unit) { - val users: List = App.realm.where(User::class.java).findAllSorted("name").toList() - var dialog: MaterialDialog? = null - val adapter = UserAdapter(context, users) - - val view = LayoutInflater.from(context).inflate(R.layout.dialog_user_picker, null) - view.userSearchInput.addTextChangedListener(object: TextWatcher { - override fun afterTextChanged(p0: Editable?) {} - - override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} - - override fun onTextChanged(text: CharSequence, p1: Int, p2: Int, p3: Int) { - adapter.searchQuery = text.toString() - view.clearButton.visibility = if (text.isBlank()) View.INVISIBLE else View.VISIBLE - } - - }) - view.userListView.adapter = adapter - view.userListView.onItemClick { _, _, position, _ -> - dialog?.dismiss() - onUserSelected(adapter.getItem(position)) - } - view.clearButton.onClick { view.userSearchInput.setText("") } - - dialog = MaterialDialog.Builder(context).title(R.string.pick_a_user).customView(view, false).show() - dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) - dialog?.setOnDismissListener { - val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - inputMethodManager.hideSoftInputFromWindow(view.userSearchInput.windowToken, 0) - } -} - -@SuppressLint("InflateParams") -fun showTeamPicker(context: Context, onUserSelected: (User) -> Unit) { - val userMap = App.realm.where(User::class.java).findAllSorted("name").toList().associateBy(User::id) - val teams = App.realm.where(RealmTeam::class.java).isNotEmpty("teamName").findAllSorted("teamName").map { it.toCustomTeam() } - var dialog: MaterialDialog? = null - val adapter = TeamAdapter(context, teams.filter { it.users.size == 2 }, userMap) - - val view = LayoutInflater.from(context).inflate(R.layout.dialog_team_picker, null) - view.teamSearchInput.addTextChangedListener(object: TextWatcher { - override fun afterTextChanged(p0: Editable?) {} - - override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} - - override fun onTextChanged(text: CharSequence, p1: Int, p2: Int, p3: Int) { - adapter.searchQuery = text.toString() - view.teamClearButton.visibility = if (text.isBlank()) View.INVISIBLE else View.VISIBLE - } - - }) - view.teamListView.adapter = adapter - view.teamListView.onItemClick { _, _, position, _ -> - dialog?.dismiss() - val selectedTeam = adapter.getItem(position) - selectedTeam.users.map { userMap[it]!! }.forEach { onUserSelected(it) } - } - view.teamClearButton.onClick { view.teamSearchInput.setText("") } - - dialog = MaterialDialog.Builder(context).title(R.string.pick_a_team).customView(view, false).show() - dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) - dialog?.setOnDismissListener { - val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - inputMethodManager.hideSoftInputFromWindow(view.teamSearchInput.windowToken, 0) - } -} - -fun Pair.swappedIf(condition: Boolean): Pair = if (condition) second to first else this diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CountdownCircle.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CountdownCircle.kt deleted file mode 100644 index 9b083e2a0a..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CountdownCircle.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.RectF -import android.support.v4.content.ContextCompat -import android.util.AttributeSet -import android.view.View -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.utils.dp - -class CountdownCircle @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) { - - private val rect = RectF() - private var strokeSize = 6f - private var onCountdown: (Int) -> Unit = {} - private var startTime = 0L - private var endTime = 0L - private var timerLength = 0 - private var running = false - private var currentSecond = 0 - - init { - if (!isInEditMode) strokeSize = strokeSize.dp() - } - - fun startCountdown(seconds: Int, onCountdown: (Int) -> Unit) { - this.onCountdown = onCountdown - currentSecond = seconds - onCountdown(seconds) - startTime = System.currentTimeMillis() - timerLength = seconds * 1000 - endTime = System.currentTimeMillis() + timerLength - running = true - invalidate() - } - - fun stopCountdown() { - running = false - } - - private val paint by lazy { - Paint(Paint.ANTI_ALIAS_FLAG).apply { - color = ContextCompat.getColor(context, R.color.colorAccent) - style = Paint.Style.STROKE - strokeWidth = strokeSize - } - } - - override fun onDraw(canvas: Canvas) { - if (!running) return - val progress = 1 - ((System.currentTimeMillis() - startTime) / timerLength.toFloat()).coerceIn(0f, 1f) - canvas.drawArc(rect, 270f, -360f * progress, false, paint) - - val second = ((999 + progress * timerLength) / 1000).toInt() - if (second != currentSecond) { - currentSecond = second - onCountdown(currentSecond) - } - - if (progress > 0) { - invalidate() - } else { - running = false - } - } - - override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - super.onSizeChanged(w, h, oldw, oldh) - val inset = strokeSize / 2 + 0.5f - rect.set(inset, inset, w - inset, h - inset) - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayerView.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayerView.kt deleted file mode 100644 index 2643b0efcf..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayerView.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.util.AttributeSet -import android.view.View -import android.widget.FrameLayout -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.CutThroatPlayer -import com.instructure.androidfoosball.utils.setAvatar -import kotlinx.android.synthetic.tablet.view_cut_throat_player.view.* -import org.jetbrains.anko.sdk21.listeners.onClick - -class CutThroatPlayerView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyleRes) { - - init { - View.inflate(context, R.layout.view_cut_throat_player, this) - } - - fun setEditablePlayer(player: CutThroatPlayer, onClear: (CutThroatPlayer) -> Unit) { - scoreView.visibility = View.GONE - avatarView.setAvatar(player.user, context.resources.getDimension(R.dimen.avatar_size_large).toInt()) - removeButton.onClick { onClear(player) } - } - - fun setPlayer(player: CutThroatPlayer) { - removeButton.visibility = View.GONE - scoreView.text = player.score.toString() - avatarView.setAvatar(player.user, context.resources.getDimension(R.dimen.avatar_size_large).toInt()) - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayersLayout.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayersLayout.kt deleted file mode 100644 index f7b2edf724..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/CutThroatPlayersLayout.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.content.res.TypedArray -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.RectF -import android.util.AttributeSet -import android.view.View -import android.widget.LinearLayout -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.CutThroatPlayer -import com.instructure.androidfoosball.ktmodels.User -import kotlinx.android.synthetic.tablet.view_team_layout.view.* -import org.jetbrains.anko.sdk21.listeners.onClick -import java.util.* - -class CutThroatPlayersLayout @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : LinearLayout(context, attrs, defStyleRes) { - - var players: MutableList = ArrayList() - set(value) { - field = value - refresh() - onPlayersChanged() - } - - private var canEdit: Boolean = true - private val rect = RectF() - private var radius = 0f - - var onAddPlayerClicked: () -> Unit = {} - var onPlayersChanged: () -> Unit = {} - - private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.GRAY } - - init { - orientation = LinearLayout.HORIZONTAL - setWillNotDraw(false) - if (attrs != null) { - val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.CutThroatPlayersLayout) - canEdit = a.getBoolean(R.styleable.CutThroatPlayersLayout_ctpl_canEdit, canEdit) - backgroundPaint.color = a.getColor(R.styleable.CutThroatPlayersLayout_ctpl_bgColor, Color.GRAY) - a.recycle() - } - View.inflate(context, R.layout.layout_cut_throat_players, this) - addPlayerButton.onClick { onAddPlayerClicked() } - refresh() - } - - override fun onDraw(canvas: Canvas) { - canvas.drawRoundRect(rect, radius, radius, backgroundPaint) - super.onDraw(canvas) - } - - fun addUser(user: User) = addPlayer(CutThroatPlayer(user)) - - fun addPlayer(player: CutThroatPlayer) { - removePlayer(player) - players.add(player) - addPlayerView(player) - onPlayersChanged() - } - - fun removePlayer(player: CutThroatPlayer) { - val idx = players.indexOfFirst { it.user == player.user } - if (idx < 0) return - players.removeAt(idx) - root.removeViewAt(idx) - onPlayersChanged() - } - - @Suppress("unused") - fun setCanEdit(value: Boolean) { - canEdit = value - refresh() - } - - fun setBgColor(color: Int) { - backgroundPaint.color = color - invalidate() - } - - fun refresh() { - addPlayerButton.visibility = if (canEdit && players.size < 2) View.VISIBLE else View.GONE - kotlin.repeat(root.childCount - 1) { root.removeViewAt(0) } - players.forEach { addPlayerView(it) } - } - - private fun addPlayerView(player: CutThroatPlayer) { - val view = CutThroatPlayerView(context) - if (canEdit) { - view.setEditablePlayer(player) { removePlayer(it) } - } else { - view.setPlayer(player) - } - root.addView(view, root.childCount - 1) - } - - override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - super.onSizeChanged(w, h, oldw, oldh) - rect.left = 1f - rect.top = 1f - rect.right = w.toFloat() - 1 - rect.bottom = h.toFloat() - 1 - radius = Math.min(w, h) / 2f - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/EloGraphView.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/EloGraphView.kt deleted file mode 100644 index e0dcbb0d49..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/EloGraphView.kt +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.graphics.* -import android.text.format.DateUtils -import android.util.AttributeSet -import android.view.View -import com.instructure.androidfoosball.utils.RankingUtils -import com.instructure.androidfoosball.utils.toDp -import java.text.SimpleDateFormat -import java.util.* - - -class EloGraphView @JvmOverloads constructor(context: Context, - attrs: AttributeSet? = null -) : View(context, attrs) { - - private val LINE_COLOR = 0xFF00ACEC.toInt() - private var timeFrame = DateUtils.DAY_IN_MILLIS * 20 - private var startTime: Long = 0 - private var maxY: Int = RankingUtils.FOOS_RANK_CEILING - private var minY: Int = RankingUtils.FOOS_RANK_FLOOR - private var data: List> = listOf() - private var cal: Calendar = GregorianCalendar.getInstance() - var backgroundPaint: Paint = Paint() - var labelDate: Date = Date() - val gridPaint by lazy { - Paint().apply { - color = Color.DKGRAY - strokeWidth = 0.5f.toDp(context) - isAntiAlias = true - } - } - val pointPaint by lazy { - Paint().apply { - isAntiAlias = true - color = LINE_COLOR - } - } - val linePaint by lazy { - Paint().apply { - color = 0x6600ACEC.toInt() - strokeWidth = 4.toDp(context) - style = Paint.Style.STROKE - isAntiAlias = true - } - } - val axisPaint by lazy { - Paint().apply { - color = Color.DKGRAY - strokeWidth = 2.toDp(context) - style = Paint.Style.STROKE - isAntiAlias = true - } - } - val yAxisLabelPaint by lazy { - Paint().apply { - color = Color.DKGRAY - textSize = 18.toDp(context) - textAlign = Paint.Align.RIGHT - typeface = Typeface.DEFAULT_BOLD - isAntiAlias = true - } - } - val xAxisLabelPaint by lazy { - Paint().apply { - color = Color.DKGRAY - textSize = 18.toDp(context) - textAlign = Paint.Align.CENTER - typeface = Typeface.DEFAULT_BOLD - isAntiAlias = true - } - } - val pointRadius by lazy { 5.toDp(context) } - val linePath = Path() - val dateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d") - - init { - if(isInEditMode){ - setDummyData() - } - } - - fun setData(dataSet: HashMap) { - if(dataSet.isEmpty()) return - val today = getBeginningOfDay(Date()) - startTime = getBeginningOfDay(Date(today.time - timeFrame)).time - - data = dataSet - .map { Pair(it.key.toLong(), it.value) } - .filter { it.first >= startTime } - .sortedBy { it.first } - - if(data.isEmpty()) return - - invalidate() - } - - override fun onDraw(canvas: Canvas) { - if(data.isEmpty()) return - - //Draw data - val yLabelWidth = yAxisLabelPaint.measureText("3000 ") - val xLabelHeight = (xAxisLabelPaint.fontMetrics.bottom - xAxisLabelPaint.fontMetrics.top) * 1.5f - val yLabelOffset = (yAxisLabelPaint.fontMetrics.ascent + yAxisLabelPaint.fontMetrics.descent) / -2 - val rect = RectF(yLabelWidth, xLabelHeight, width.toFloat(), height.toFloat() - xLabelHeight) - val dayWidth = rect.width() / 21f - val eloWidth = rect.height() / 4f - var gridStart = rect.left - - canvas.save() - canvas.clipRect(rect) - val bgRect = RectF() - for(i in 0..20) { - bgRect.set(gridStart, rect.top, gridStart + dayWidth, rect.bottom + dayWidth) - if (i % 2 == 0) canvas.drawRoundRect(bgRect, dayWidth / 2, dayWidth / 2, backgroundPaint.apply { color = 0xFFEEEEEE.toInt() }) - gridStart += dayWidth - } - canvas.restore() - - canvas.drawText("${dateFormat.format(Date(startTime))} - ${dateFormat.format(Date())}", rect.centerX(), rect.bottom + xLabelHeight - xAxisLabelPaint.fontMetrics.bottom, xAxisLabelPaint) - - var eloGridStart = rect.top - for(i in 0..4) { - if(i in 1..3) { - canvas.drawLine(rect.left, eloGridStart, rect.right, eloGridStart, gridPaint) - } - when (i) { - 0 -> canvas.drawText("${3000 - i * 500} ", rect.left, eloGridStart + yLabelOffset * 2, yAxisLabelPaint) - 4 -> canvas.drawText("${3000 - i * 500} ", rect.left, eloGridStart, yAxisLabelPaint) - else -> canvas.drawText("${3000 - i * 500} ", rect.left, eloGridStart + yLabelOffset, yAxisLabelPaint) - } - eloGridStart += eloWidth - } - var pointX: Float - var pointY: Float - data.forEachIndexed { i, it -> - pointX = (it.first - startTime).toFloat() / timeFrame - pointX *= rect.width() - pointX += rect.left - pointY = (it.second - minY).toFloat() / (maxY - minY) - pointY *= rect.height() - pointY = rect.height() - pointY - if(i == data.lastIndex) { - canvas.drawCircle(pointX, pointY, pointRadius * 1.5f, pointPaint) - } - canvas.drawCircle(pointX, pointY, pointRadius, pointPaint) - if(i == 0) { - linePath.moveTo(rect.left, pointY) - } - linePath.lineTo(pointX, pointY) - } - canvas.drawPath(linePath, linePaint) - - //Draw X - axis - canvas.drawLine(rect.left, rect.bottom, rect.right, rect.bottom, axisPaint) - //Draw Y - axis - canvas.drawLine(rect.left, rect.bottom, rect.left, rect.top, axisPaint) - - super.onDraw(canvas) - } - - - fun getBeginningOfDay(date: Date) : Date { - cal.time = date - - cal.set(GregorianCalendar.HOUR_OF_DAY, 0) - cal.set(GregorianCalendar.SECOND, 0) - cal.set(GregorianCalendar.MILLISECOND, 0) - - return cal.time!! - } - - fun setDummyData() { - val today = getBeginningOfDay(Date()) - val weeksAgo = getBeginningOfDay(Date(today.time - timeFrame)).time - val rand = Random() - val mapThing = HashMap() - kotlin.repeat(15) { - mapThing.put((weeksAgo + rand.nextInt(timeFrame.toInt())).toString(), minY + rand.nextInt(300) + 500) - } - setData(mapThing) - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/GameTimer.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/GameTimer.kt deleted file mode 100644 index 0543d9244e..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/GameTimer.kt +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.os.SystemClock -import android.util.AttributeSet -import android.widget.TextView - -class GameTimer @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : TextView(context, attrs, defStyleRes) { - - private var mStartTime = 0L - private var mIsAttached = false - - private val mTicker: Runnable = object : Runnable { - override fun run() { - onTimeChanged() - val now = SystemClock.uptimeMillis() - val nowSystem = System.currentTimeMillis() - val nextSystem = nowSystem + (1000 - (nowSystem - mStartTime) % 1000) - val next = now + nextSystem - nowSystem - handler.postAtTime(this, next) - } - } - - fun setStartTime(startTime: Long) { - mStartTime = startTime - start() - } - - private fun onTimeChanged() { - val time = (System.currentTimeMillis() - mStartTime) / 1000 - text = if (isInEditMode) "1:23" else "%d:%02d".format(time / 60, time % 60) - } - - private fun start() { - if (mIsAttached) { - stop() - mTicker.run() - } - } - - private fun stop() { - handler.removeCallbacks(mTicker) - } - - override fun onAttachedToWindow() { - super.onAttachedToWindow() - mIsAttached = true - mTicker.run() - } - - override fun onDetachedFromWindow() { - stop() - mIsAttached = false - super.onDetachedFromWindow() - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayerView.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayerView.kt deleted file mode 100644 index 7fdb6452dc..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayerView.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.util.AttributeSet -import android.view.View -import android.widget.FrameLayout -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setAvatar -import com.instructure.androidfoosball.utils.setVisible -import kotlinx.android.synthetic.tablet.view_player.view.* -import org.jetbrains.anko.sdk21.listeners.onClick - -class PlayerView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyleRes) { - - init { - View.inflate(context, R.layout.view_player, this) - } - - fun setEditablePlayer(player: User, onClear: (User) -> Unit) { - scoreView.visibility = View.GONE - avatarView.setAvatar(player, context.resources.getDimension(R.dimen.avatar_size_large).toInt()) - removeButton.onClick { onClear(player) } - } - - fun setPlayer(player: User, score: Int? = null) { - removeButton.visibility = View.GONE - avatarView.setAvatar(player, context.resources.getDimension(R.dimen.avatar_size_large).toInt()) - scoreView.setVisible(score != null) - score?.let { scoreView.text = it.toString() } - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayersLayout.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayersLayout.kt deleted file mode 100644 index 14e327f19f..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/PlayersLayout.kt +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.content.res.TypedArray -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.RectF -import android.util.AttributeSet -import android.view.View -import android.widget.LinearLayout -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setVisible -import kotlinx.android.synthetic.tablet.layout_players.view.* -import org.jetbrains.anko.sdk21.listeners.onClick - -class PlayersLayout @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : LinearLayout(context, attrs, defStyleRes) { - - var players: MutableList = mutableListOf() - set(value) { - field = value - refresh() - onPlayersChanged() - } - - private var canEdit: Boolean = true - private val rect = RectF() - private var radius = 0f - - private var maxPlayerCount = 16 - - var onAddPlayerClicked: () -> Unit = {} - var onPlayersChanged: () -> Unit = {} - - private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.GRAY } - - init { - orientation = HORIZONTAL - setWillNotDraw(false) - if (attrs != null) { - val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.PlayersLayout) - canEdit = a.getBoolean(R.styleable.PlayersLayout_pl_canEdit, canEdit) - backgroundPaint.color = a.getColor(R.styleable.PlayersLayout_pl_bgColor, Color.GRAY) - maxPlayerCount = a.getInt(R.styleable.PlayersLayout_pl_maxPlayers, maxPlayerCount) - a.recycle() - } - View.inflate(context, R.layout.layout_players, this) - addPlayerButton.onClick { onAddPlayerClicked() } - refresh() - } - - override fun onDraw(canvas: Canvas) { - canvas.drawRoundRect(rect, radius, radius, backgroundPaint) - super.onDraw(canvas) - } - - fun addUser(user: User) = addPlayer(user) - - fun addPlayer(player: User) { - removePlayer(player) - players.add(player) - addPlayerView(player) - addPlayerButton.setVisible(canEdit && players.size < maxPlayerCount) - onPlayersChanged() - } - - fun removePlayer(player: User) { - val idx = players.indexOf(player) - if (idx < 0) return - players.removeAt(idx) - root.removeViewAt(idx) - addPlayerButton.setVisible(canEdit && players.size < maxPlayerCount) - onPlayersChanged() - } - - @Suppress("unused") - fun setCanEdit(value: Boolean) { - canEdit = value - refresh() - } - - fun setBgColor(color: Int) { - backgroundPaint.color = color - invalidate() - } - - fun refresh() { - addPlayerButton.setVisible(canEdit && players.size < maxPlayerCount) - kotlin.repeat(root.childCount - 1) { root.removeViewAt(0) } - players.forEach { addPlayerView(it) } - } - - private fun addPlayerView(player: User) { - val view = PlayerView(context) - if (canEdit) { - view.setEditablePlayer(player) { removePlayer(it) } - } else { - view.setPlayer(player) - } - root.addView(view, root.childCount - 1) - } - - override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - super.onSizeChanged(w, h, oldw, oldh) - rect.left = 1f - rect.top = 1f - rect.right = w.toFloat() - 1 - rect.bottom = h.toFloat() - 1 - radius = Math.min(w, h) / 2f - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TableRequestedDialog.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TableRequestedDialog.kt deleted file mode 100644 index 3934a05009..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TableRequestedDialog.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2018 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.instructure.androidfoosball.views - -import android.os.Bundle -import android.support.v4.app.DialogFragment -import android.support.v4.app.FragmentManager -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.bumptech.glide.Glide -import com.google.firebase.database.DataSnapshot -import com.google.firebase.database.DatabaseReference -import com.instructure.androidfoosball.App -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.IncomingData -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.Commentator -import com.instructure.androidfoosball.utils.dp -import com.instructure.androidfoosball.utils.setAvatar -import kotlinx.android.synthetic.tablet.dialog_table_requested.* -import org.jetbrains.anko.sdk21.listeners.onClick -import java.text.SimpleDateFormat -import java.util.* - -class TableRequestedDialog : DialogFragment() { - - private val dateFormat = SimpleDateFormat("MMMM d 'at' h:mmaa", Locale.getDefault()) - - lateinit var user: User - lateinit var date: Date - - override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater?.inflate(R.layout.dialog_table_requested, container, false) - } - - override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { - Glide.with(context).load("https://upload.wikimedia.org/wikipedia/commons/8/8c/Blaulicht.gif").apply { - into(sirenOne) - into(sirenTwo) - } - okayButton.onClick { dismiss() } - userAvatar.setAvatar(user, context.resources.getDimension(R.dimen.avatar_size_small).toInt()) - userInfo.text = getString(R.string.tableRequestUserInfo, user.name, dateFormat.format(date)) - } - - override fun onResume() { - super.onResume() - dialog?.apply { window.setLayout(920f.dp().toInt(), ViewGroup.LayoutParams.WRAP_CONTENT) } - App.commentator.announce(Commentator.Sfx.POLICE_SIREN.name + getString(R.string.tableRequestAnnouncement)) - } - - companion object { - - fun showIfNecessary(dataRef: DatabaseReference, snapshot: DataSnapshot?, fm: FragmentManager) { - with (snapshot?.getValue(IncomingData::class.java) ?: return) { - if (tableRequestUserId.isEmpty() || tableRequestTime.isEmpty()) return - val realmUser = App.realm.where(User::class.java).equalTo("id", tableRequestUserId).findFirst() - ?: User(name = "Unknown User") - val time = tableRequestTime.toLongOrNull() ?: return - val dialog = TableRequestedDialog().apply { - user = realmUser - date = Date(time) - } - if (fm.findFragmentByTag(TableRequestedDialog::class.java.simpleName) == null) { - dialog.show(fm, TableRequestedDialog::class.java.simpleName) - } - dataRef.setValue(IncomingData()) - } - } - - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TeamLayout.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TeamLayout.kt deleted file mode 100644 index d9642f9dda..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/TeamLayout.kt +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.content.Context -import android.content.res.TypedArray -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.RectF -import android.util.AttributeSet -import android.view.View -import android.widget.FrameLayout -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.ITeam -import com.instructure.androidfoosball.ktmodels.Team -import com.instructure.androidfoosball.ktmodels.User -import com.instructure.androidfoosball.utils.setAvatar -import com.instructure.androidfoosball.utils.setVisible -import de.hdodenhof.circleimageview.CircleImageView -import kotlinx.android.synthetic.tablet.view_team_layout.view.* -import org.jetbrains.anko.sdk21.listeners.onClick - -class TeamLayout @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyleRes) { - - var team: ITeam = Team() - set(value) { - field = value; refresh() - } - - private var canEdit: Boolean = true - private val rect = RectF() - private var radius = 0f - private var isVertical = false - - var onAddPlayerClicked: () -> Unit = {} - var onAddTeamClicked: () -> Unit = {} - var onTeamChanged: () -> Unit = {} - - private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.GRAY } - - init { - setWillNotDraw(false) - if (attrs != null) { - val a: TypedArray = context.obtainStyledAttributes(attrs, R.styleable.TeamLayout) - canEdit = a.getBoolean(R.styleable.TeamLayout_canEdit, canEdit) - backgroundPaint.color = a.getColor(R.styleable.TeamLayout_teamColor, Color.GRAY) - isVertical = a.getBoolean(R.styleable.TeamLayout_isVertical, false) - a.recycle() - } - View.inflate(context, if (isVertical) R.layout.view_team_layout_vertical else R.layout.view_team_layout, this) - addPlayerButton.onClick { onAddPlayerClicked() } - addTeamButton.onClick { onAddTeamClicked() } - refresh() - if (isInEditMode) { - avatar1.visibility = View.VISIBLE - avatar2.visibility = View.VISIBLE - avatar1.setImageResource(R.drawable.sadpanda) - avatar2.setImageResource(R.drawable.sadpanda) - } - } - - override fun onDraw(canvas: Canvas) { - canvas.drawRoundRect(rect, radius, radius, backgroundPaint) - super.onDraw(canvas) - } - - fun addUser(user: User): Boolean { - if (team.users.contains(user) || team.users.size >= 2) return false - team.users.add(user) - refresh() - onTeamChanged() - return true - } - - fun removeUser(user: User): Boolean { - if (!team.users.contains(user)) return false - team.users.remove(user) - refresh() - onTeamChanged() - return true - } - - fun hasUsers() = team.users.isNotEmpty() - - fun setCanEdit(value: Boolean) { - canEdit = value - refresh() - } - - fun setTeamColor(color: Int) { - backgroundPaint.color = color - invalidate() - } - - private fun refresh() { - addTeamButton.setVisible(canEdit && team.users.isEmpty()) - addPlayerButton.visibility = if (canEdit && team.users.size < 2) View.VISIBLE else View.GONE - attemptPlayerAssignment(0, avatar1, removeAvatar1) - attemptPlayerAssignment(1, avatar2, removeAvatar2) - } - - private fun attemptPlayerAssignment(idx: Int, avatar: CircleImageView, removeView: View) { - if (team.users.size > idx) { - avatar.visibility = View.VISIBLE - avatar.setAvatar(team.users[idx], resources.getDimension(R.dimen.avatar_size_large).toInt()) - if (canEdit) { - removeView.visibility = View.VISIBLE - removeView.setOnClickListener { - team.users.remove(team.users[idx]) - refresh() - onTeamChanged() - } - } - } else { - avatar.visibility = View.GONE - removeView.visibility = View.GONE - } - } - - override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - super.onSizeChanged(w, h, oldw, oldh) - rect.left = 1f - rect.top = 1f - rect.right = w.toFloat() - 1 - rect.bottom = h.toFloat() - 1 - radius = Math.min(w, h) / 2f - } - -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinCutThroatGameDialog.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinCutThroatGameDialog.kt deleted file mode 100644 index 68f4fe0943..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinCutThroatGameDialog.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.animation.OvershootInterpolator -import android.widget.ImageView -import android.widget.TextView -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.CutThroatGame -import com.instructure.androidfoosball.utils.bind -import org.jetbrains.anko.sdk21.listeners.onClick - -class WinCutThroatGameDialog( - context: Context, - val game: CutThroatGame, - private val onEndGame: () -> Unit, - private val onUndoGoal: () -> Unit -) : Dialog(context, R.style.AppTheme) { - - private val COUNTDOWN_SECONDS = 15 - - private val playerLayout: TeamLayout by bind(R.id.playerLayout) - private val victoryTrophy: ImageView by bind(R.id.victoryTrophy) - private val playerNameView: TextView by bind(R.id.playerNameView) - private val countdownView: CountdownCircle by bind(R.id.countdownView) - private val undoView: TextView by bind(R.id.undoView) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setCancelable(false) - setCanceledOnTouchOutside(false) - setContentView(R.layout.dialog_win_game_cut_throat) - setupViews() - setupListeners() - animateTrophy() - } - - private fun setupViews() { - game.getWinner()?.let { user -> - playerLayout.addUser(user) - playerNameView.text = context.getString(R.string.team_win_game).format(user.name) - } - } - - private fun animateTrophy() { - // Set initial scale - victoryTrophy.scaleX = 0f - victoryTrophy.scaleY = 0f - - // Start scale animation - AnimatorSet().apply { - playTogether( - ObjectAnimator.ofFloat(victoryTrophy, "scaleX", 0f, 1f), - ObjectAnimator.ofFloat(victoryTrophy, "scaleY", 0f, 1f) - ) - duration = 600 - startDelay = 200 - interpolator = OvershootInterpolator() - }.start() - - // Start ongoing rotation animation - ObjectAnimator.ofFloat(victoryTrophy, "rotation", -6f, 6f).apply { - repeatCount = ObjectAnimator.INFINITE - repeatMode = ObjectAnimator.REVERSE - duration = 3000 - }.start() - } - - private fun setupListeners() { - - countdownView.startCountdown(COUNTDOWN_SECONDS) { seconds -> - if (seconds > 0) { - //countdownSeconds.text = seconds.toString() - } else { - onEndGame() - dismiss() - } - } - - countdownView.onClick { - onEndGame() - dismiss() - } - - undoView.onClick { - onUndoGoal() - dismiss() - } - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinGameDialog.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinGameDialog.kt deleted file mode 100644 index ebbb11c622..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinGameDialog.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.View -import android.view.animation.OvershootInterpolator -import android.widget.ImageView -import android.widget.TextView -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.Game -import com.instructure.androidfoosball.ktmodels.Table -import com.instructure.androidfoosball.utils.bind -import org.jetbrains.anko.sdk21.listeners.onClick - -class WinGameDialog( - context: Context, - val game: Game, - val onIncrementBestOf: () -> Unit, - val onUndoGoal: () -> Unit, - val onEndGame: () -> Unit -) : Dialog(context, R.style.AppTheme) { - - private val COUNTDOWN_SECONDS = 15 - - private val teamLayout: TeamLayout by bind(R.id.teamLayout) - private val victoryTrophy: ImageView by bind(R.id.victoryTrophy) - private val undoView: View by bind(R.id.undoView) - private val teamNameView: TextView by bind(R.id.winningTeamNameView) - private val bestOfView: TextView by bind(R.id.bestOfView) - private val countdownView: CountdownCircle by bind(R.id.countdownView) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setCancelable(false) - setCanceledOnTouchOutside(false) - setContentView(R.layout.dialog_win_game) - setupViews() - setupListeners() - animateTrophy() - } - - private fun setupViews() { - game.currentRound().getWinningTeam()?.let { team -> - teamLayout.team = team - teamNameView.text = context.getString(R.string.team_win_game).format(game.currentRound().getTeamName(team, Table.getSelectedTable())) - } - bestOfView.text = context.getString(R.string.best_of_increment).format(game.bestOf + 2) - } - - private fun animateTrophy() { - // Set initial scale - victoryTrophy.scaleX = 0f - victoryTrophy.scaleY = 0f - - // Start scale animation - AnimatorSet().apply { - playTogether( - ObjectAnimator.ofFloat(victoryTrophy, "scaleX", 0f, 1f), - ObjectAnimator.ofFloat(victoryTrophy, "scaleY", 0f, 1f) - ) - duration = 600 - startDelay = 200 - interpolator = OvershootInterpolator() - }.start() - - // Start ongoing rotation animation - ObjectAnimator.ofFloat(victoryTrophy, "rotation", -6f, 6f).apply { - repeatCount = ObjectAnimator.INFINITE - repeatMode = ObjectAnimator.REVERSE - duration = 3000 - }.start() - } - - private fun setupListeners() { - - // Change best of - bestOfView.onClick { - onIncrementBestOf() - dismiss() - } - - countdownView.startCountdown(COUNTDOWN_SECONDS) { seconds -> - if (seconds > 0) { - //countdownSeconds.text = seconds.toString() - } else { - onEndGame() - dismiss() - } - } - - countdownView.onClick { - countdownView.stopCountdown() - onEndGame() - dismiss() - } - - // Undo goal - undoView.onClick { - onUndoGoal() - dismiss() - } - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinRoundDialog.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinRoundDialog.kt deleted file mode 100644 index 3b17d2567e..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinRoundDialog.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.View -import android.view.animation.OvershootInterpolator -import android.widget.ImageView -import android.widget.TextView -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.Game -import com.instructure.androidfoosball.ktmodels.Table -import com.instructure.androidfoosball.utils.bind -import org.jetbrains.anko.sdk21.listeners.onClick - -class WinRoundDialog(context: Context, val game: Game, val onNextRound: () -> Unit, val onUndoGoal: () -> Unit) : Dialog(context) { - - private val COUNTDOWN_SECONDS = 8 - - private val countdownView: CountdownCircle by bind(R.id.countdownView) - private val countdownSeconds: TextView by bind(R.id.countdownSeconds) - private val teamLayout: TeamLayout by bind(R.id.teamLayout) - private val victoryStar: ImageView by bind(R.id.victoryStar) - private val undoView: View by bind(R.id.undoView) - private val teamNameView: TextView by bind(R.id.winningTeamNameView) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setCancelable(false) - setCanceledOnTouchOutside(false) - setContentView(R.layout.dialog_win_round) - setupViews() - setupListeners() - animateStar() - } - - private fun setupViews() { - game.currentRound().getWinningTeam()?.let { team -> - teamLayout.team = team - teamNameView.text = context.getString(R.string.team_win_round).format(game.currentRound().getTeamName(team, Table.getSelectedTable())) - } - } - - private fun animateStar() { - // Set initial scale - victoryStar.scaleX = 0f - victoryStar.scaleY = 0f - - // Start scale animation - AnimatorSet().apply { - playTogether( - ObjectAnimator.ofFloat(victoryStar, "scaleX", 0f, 1f), - ObjectAnimator.ofFloat(victoryStar, "scaleY", 0f, 1f) - ) - duration = 600 - startDelay = 200 - interpolator = OvershootInterpolator() - }.start() - - // Start ongoing rotation animation - ObjectAnimator.ofFloat(victoryStar, "rotation", 0f, 360f).apply { - repeatCount = ObjectAnimator.INFINITE - duration = 10000 - }.start() - } - - private fun setupListeners() { - // Countdown timer - countdownView.startCountdown(COUNTDOWN_SECONDS) { seconds -> - if (seconds > 0) { - countdownSeconds.text = seconds.toString() - } else { - onNextRound() - dismiss() - } - } - - // Undo goal - undoView.onClick { - onUndoGoal() - dismiss() - } - - // Next round (Swap now) - countdownView.onClick { - onNextRound() - dismiss() - } - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTableKingGameDialog.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTableKingGameDialog.kt deleted file mode 100644 index 6b2204a5e9..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTableKingGameDialog.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.animation.OvershootInterpolator -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.TableKingGame -import kotlinx.android.synthetic.tablet.dialog_win_table_king.* -import org.jetbrains.anko.sdk21.listeners.onClick - -class WinTableKingGameDialog( - context: Context, - private val game: TableKingGame, - private val onUndoGoal: () -> Unit, - private val onEndGame: () -> Unit -) : Dialog(context, R.style.AppTheme) { - - private val COUNTDOWN_SECONDS = 30 - - private val playerViews by lazy { listOf(playerLayout1, playerLayout2, playerLayout3, playerLayout4) } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setCancelable(false) - setCanceledOnTouchOutside(false) - setContentView(R.layout.dialog_win_table_king) - setupViews() - setupListeners() - animateTrophy() - } - - private fun setupViews() { - game.teams.flatMap { it.users }.distinct() - .map { user -> - user to game.teams.filter { user in it.users }.sumBy { it.points } - } - .sortedByDescending { it.second } - .forEachIndexed { i, (user, score) -> - playerViews[i].setPlayer(user, score) - } - } - - private fun setupListeners() { - countdownView.startCountdown(COUNTDOWN_SECONDS) { seconds -> - if (seconds == 0) { - onEndGame() - dismiss() - } - } - - countdownView.onClick { - countdownView.stopCountdown() - onEndGame() - dismiss() - } - - // Undo goal - undoView.onClick { - onUndoGoal() - dismiss() - } - } - - private fun animateTrophy() { - // Set initial scale - victoryTrophy.scaleX = 0f - victoryTrophy.scaleY = 0f - - // Start scale animation - AnimatorSet().apply { - playTogether( - ObjectAnimator.ofFloat(victoryTrophy, "scaleX", 0f, 1f), - ObjectAnimator.ofFloat(victoryTrophy, "scaleY", 0f, 1f) - ) - duration = 600 - startDelay = 200 - interpolator = OvershootInterpolator() - }.start() - - // Start ongoing rotation animation - ObjectAnimator.ofFloat(victoryTrophy, "rotation", -6f, 6f).apply { - repeatCount = ObjectAnimator.INFINITE - repeatMode = ObjectAnimator.REVERSE - duration = 3000 - }.start() - } -} diff --git a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTeamTwisterGameDialog.kt b/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTeamTwisterGameDialog.kt deleted file mode 100644 index cd90257e50..0000000000 --- a/foosball/app/src/tablet/java/com/instructure/androidfoosball/views/WinTeamTwisterGameDialog.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2017 - present Instructure, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package com.instructure.androidfoosball.views - -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import com.instructure.androidfoosball.R -import com.instructure.androidfoosball.ktmodels.TeamTwisterGame -import kotlinx.android.synthetic.tablet.dialog_win_team_twister.* -import org.jetbrains.anko.sdk21.listeners.onClick - -class WinTeamTwisterGameDialog( - context: Context, - private val game: TeamTwisterGame, - private val onUndoGoal: () -> Unit, - private val onEndGame: () -> Unit -) : Dialog(context, R.style.AppTheme) { - - private val COUNTDOWN_SECONDS = 45 - - private val teamLayouts by lazy { listOf(teamLayout1, teamLayout2, teamLayout3, teamLayout4, teamLayout5, teamLayout6) } - private val scoreViews by lazy { listOf(scoreView1, scoreView2, scoreView3, scoreView4, scoreView5, scoreView6)} - private val playerViews by lazy { listOf(playerLayout1, playerLayout2, playerLayout3, playerLayout4) } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setCancelable(false) - setCanceledOnTouchOutside(false) - setContentView(R.layout.dialog_win_team_twister) - setupViews() - setupListeners() - } - - private fun setupViews() { - game.teams.sortedByDescending { it.points }.forEachIndexed { i, team -> - teamLayouts[i].team = team - scoreViews[i].text = team.points.toString() - } - game.teams.flatMap { it.users }.distinct() - .map { user -> - user to game.teams.filter { user in it.users }.sumBy { it.points } - } - .sortedByDescending { it.second } - .forEachIndexed { i, (user, score) -> - playerViews[i].setPlayer(user, score) - } - } - - private fun setupListeners() { - - countdownView.startCountdown(COUNTDOWN_SECONDS) { seconds -> - if (seconds == 0) { - onEndGame() - dismiss() - } - } - - countdownView.onClick { - countdownView.stopCountdown() - onEndGame() - dismiss() - } - - // Undo goal - undoView.onClick { - onUndoGoal() - dismiss() - } - } -} diff --git a/foosball/app/src/tablet/res/drawable-hdpi/ic_check_blue_48dp.png b/foosball/app/src/tablet/res/drawable-hdpi/ic_check_blue_48dp.png deleted file mode 100644 index 8e499c259f6ff95d43c37ffc303ec23a61cec863..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 429 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U@Y-;aSW-r_4d|5-@^_9t%>0d ztP>O(7kzPO4i<0?;P9NFWO0#sjq3afV%2+%U(Y>RU-A8;`ptWlw-PJ<%AK%hWK?Ki zVB!D~9Skf24h)PyBCeP{!0x-|drhVQx##I!3{#G4x^wk>o^Vjpc~{_^*=&~%b8;-{ z7Usz~V!84W3)7~9oJ=Y0!VD+Gj$2+hCv)5|Kw4(G!`lKGrmaT{*-ReInf=Iu=@#2@ z&I@H0d=1--wp6@t!q$j-OhSH=I4M`16qADr*&mdKI;Vst0B*6Sd;kCd diff --git a/foosball/app/src/tablet/res/drawable-hdpi/ic_stars_amber_400_36dp.png b/foosball/app/src/tablet/res/drawable-hdpi/ic_stars_amber_400_36dp.png deleted file mode 100644 index 88bb0c1d07c8c765f5effff230b2527d9c512490..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 907 zcmV;619bd}P)9h26vqc;p`A3+`i#T|DH=LT$Y3F{Xf&yk=;*hG#A4Kz>Bho0v9Yle)WU*9B0&@E zB-M$Ah=mGGKU6Fb2}+T1UUDXRd3hh_+j2($o4fF7h9Xa;J5vSKl28My!q0)K&A0Dpiia0aOP-;B)x4g#+TMuK<& zbOI%XHr51;3K(+o7T8q?V+(+L1`Ij515|`%Y%4Gkf~h=Xz$Vki8iC0WP38Fx>@;Pp z5mzzQhZ{ju@BarJ@TQIe8G$#qS<2W#;DhD^P2wU@3H%h8a}^TC?hDM3E4J~j z39Xh|#`X$L{)BDJ4MJl!s2ZECIob0(aT&W`XcI3{F?K-cpWWv&cAL=H9V*5oV!sJ| z^KS9wN1@n~WlU-w9QXO-P6}zP;}|Z7z6(T#xVzb09*$y z0_}vYq!X|01^RG|aU7GXKR`7W_el~zVMd$;RsiJ&Gw^cM*n*4AXP;!XlwvGseq}Kl z39EjwnD7N9D8^a{uYVX=9fGN9Vj`QO80#i}+h2g~22Je%z7n4$O)=KPTsYbdnCik+ zmHHeRX=9ZAipvQF{fy+N=;W$Ll)*wqRE}iy*^_#W77HFBcsl9ld1V!C4=r_iX3toV-@ho<=TfpmCN;qnVM~?#hhV= z$Qs+drI@Tv1tg+p9V=Q5L+=eROSSyAhbUs@X)|mkJI-7gMIGzjnT)`c<8}b+H^0voi7Z7|o}#l5`Azr!X#@ h8y)M5j77$ZlYjX_@UDs(a}@vp002ovPDHLkV1jMEonQa} diff --git a/foosball/app/src/tablet/res/drawable-hdpi/ic_undo_black_24dp.png b/foosball/app/src/tablet/res/drawable-hdpi/ic_undo_black_24dp.png deleted file mode 100644 index b3af0c02c3ad7ccfeb047c167119c9a761918d55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 322 zcmV-I0lof-P);%M2 zlsX8Xqs)PL0}%g3QcDOw0pfBX=BC6!=#CNr;-w@w0vmn?#KDv}2n`$5^&gbAZ8`kLAdZ+AnpcYQy^x>Vh$)oV}N)s4*gqzn4KC9`VGV#K+H=* zs9Qrr5Z$a*K+H&~gJQ_cENnnL2a9=Slsbsga%uvad7xrKgVHoaiK7^y=?B@o&D2QL zlsHNph(Dm2r$?!SD0Ngdnpthsa1bSq5(46zK->$&mc-%hAr-gY-q_81$Uvkuv3yF8 zuv}!%JH8`KIR^|x1lTyXu>^6o|0sN$?7iHg^q+snjV{CM?JuiX1RNL`!Nk4ZvgvV* zdjE3GZ+qr9r2g5{`9fizv_nmebHkP&ZVb<#{9t3K{FvZSXCtscn4jszQDz3cx}fg$ zJQw=;S>C+OD|0UX$jBgG|KIM-%nl9l{fswsAJtd8DxEsU{)g#NWrfD05F5J>_8ZzP z4m?)A=VaJX^>O0*i>5~e#pW0A{c*n1?{9OWrh`*xexcBBfv=B^*9$TAhwtF#G>Lm@ vq`slz=T1^>bP0l+XkK8!mSE diff --git a/foosball/app/src/tablet/res/drawable-mdpi/ic_stars_amber_400_36dp.png b/foosball/app/src/tablet/res/drawable-mdpi/ic_stars_amber_400_36dp.png deleted file mode 100644 index 9013eaaff628bc982f7be8d1b8f982daeb82cbb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624 zcmV-$0+0QPP)$=w zA(t5cQ;)jc?mhQ;?%XNK;#bq0d;aHt&w0*yo^u0pcaHuX(%6zf+vt*qRbA0u-}H-Nj%|^I}r85PzG2`!ibewknYux>bTAv=!M`s zyQ(v#GqfOh^J#i}?(;FJp*Df|7bpV}`pxYZPT?aLM3HTB&S26~udXjmAiwWhxH z!oCA;hSZ_=C=k2=K~sPA`$~9Dg>;6bZ`flq!@WX{8l55QPWb?rlp?mk5*P#BpcUlW z7*hW=gHBrhc{)D!!8vJ~$C%O?IG`uXC85NjC3^T>dBOopbY9}HLL*+~@ZBWlJ z4>QhksZH?A(3{j5s$&Rj3SwxRp;zseI@~J5UQ3@GFivD!+WK6y?x_gWCf6YskqXnZ zP2k4Vb`2U$?UgQC{hVwcrpUJwc%@k^rLx0mpdC;`=a%8{%&lGOaa#MRgUBi6GJ_Et zZ(szRIkY!QOW2r?#eG7TP$fnFS_;f8TWToLHAtD7^Lb{1eq0n=G=a|H)+uI^xk~5J zks!Ij#%XKkrt)J$hzfgk7dxau4cb+AR2iytP-Q*z{=X0XNkiYrA^6?zIX{j70000< KMNUMnLSTYNmm%N) diff --git a/foosball/app/src/tablet/res/drawable-mdpi/ic_undo_black_24dp.png b/foosball/app/src/tablet/res/drawable-mdpi/ic_undo_black_24dp.png deleted file mode 100644 index 1a256aa2da04764e0d3ec33c31d8ff08dac8877f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gj%RF5iLn>}1CrGd^PVi`Ci;Dgr z->$mM!A7v-Jo86!g@5cv<~RJ%5%|uy(NI%NA$k$tk=+xIe0(VDu*Pc*tHK_hj{Qm> z|1*44RG7zbq&Glbwyo>%m4+H|k2S0Yf5bbMGj25DvsL)08Bl7_&N3nCAeU0}b>>&h z6XuU_9sP;uunK>+S8^zRZq1ZVz=E zyxBvXEJYqQRV-&%cl3iBxMDe0SXx38BjmJwuNXkcVu zU}j(dn#jYzAi=<30Jh@*R6^mB-t9bw58eMSZQIVtQ1`K1lw}d$QF(WTHwAwTSstxA zVlUfxAnPMzgq|J4xsQwmef$Tu$Idv$e!vpOZz%rrh~eKyZssE$@gfR-f0`IJJ`!i{ z5Z^E0aOQ_A!=q#R3{pe(3HKJ#_0MJHxtvg8z&8CktHbxBtO6p-+5$ z?*!$2hteC^4+;L)bgfyM@3@!a`H}1YWfK}F=k!I2agUp^F~uOYT{Fwc75i=Unjy7{Lslu6{1-oD!M<(qq$s diff --git a/foosball/app/src/tablet/res/drawable-xhdpi/ic_stars_amber_400_36dp.png b/foosball/app/src/tablet/res/drawable-xhdpi/ic_stars_amber_400_36dp.png deleted file mode 100644 index ad4a96bcefbca1e8a7d90317c2ea1acf1e7d8861..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1217 zcmV;y1U~zTP)L7{F_z^hX+USw1vA6h8RE8j+&1X2Y`PPxxlmjHLOKKf}h%kd0wu$ns}orpY2h zMNu}y#wV$XAs6$vx^zA7_OxAh-Fwe@-{(2!+;%?vHXoexKIeDOdC&7c&wC1SHzkGG z_{NrC3$g{-f^0#yp#O*lvVpBY8PEu{0ZyPB=)!-u0uO*vpcu#mBKxbLQNVhj9&iC} zNrb#wpa6*L4}xX^RlpwwDZUV*D}d?2C@2#j54SXw?(POw89iY;#q%cVL81#0)`tcNZdKi3>PDk z#wI37(MAax#Q0b(1C}$L`gG10I#$UC(kMS-uj#ox4D1-S`+}AoP&4e+f1#vDsoBfRYjB(sr zDnaSYzvK!(W3OZ$dm4qH>x=<@4p1eG!bz2D{0db;Bbka_z3kWU1C=n2?+R3z3>4ft z#^C+}V>AdF3-mC?u|`GEJ;uN)b)*=ak9m!(peXDzPz2F~or;%O9u+yx6di(+v07M- z6@+($v2_9wGJ%GJ+oJe3o}uL`*2A z4|-y6kP*}>G2w~3ZlH;BA|w~NEi!_fl5d4OK&%OJ;uO}59WsJcUZXF71Ow$H02wNgMRsE9bWQ(Q|8Jxn4LluR7kMj1g_gaP~@Ua*Q}^cP`#88U(*2}=sM z87Ao(v&$VJSi7MJVkd(js_yGum5O2^Q4m=Sg0hKXTdg9h3^$hqMGzsTjm#4P#93np4DWKVHLe&lO|4O3@dap%}zrKj#*A)&U^p-fB3$-Oo9ea!t;91*x>3<<#{o3A(uih zjNaTMS7$H>ft!q7(JI_`sOOk@+?zO$2EpEFe?J)eF4r(D%mwIm68Qm?g&Ik6V@OokRIKRJcVa?h=YFFJ<{5S0Yd1K;$`dt@=r( zNG8vlB&G*<38UxEAiVa2nQ=IKI0OYq~2sxAIx`4+}W3d|Rj3 zD*lak%PN(x2(2i{yIUe^)Wx`}7F$+c1D{Y{C-%xkJGdU3dK-Y5_%WaT$4#t+Ex{IK f3$g{-f-KBG`eozYDDU6l00000NkvXXu0mjfW>O!C diff --git a/foosball/app/src/tablet/res/drawable-xhdpi/ic_undo_black_24dp.png b/foosball/app/src/tablet/res/drawable-xhdpi/ic_undo_black_24dp.png deleted file mode 100644 index f3f4d9a0c071b98906f84393bfed7f4cd477234c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 395 zcmV;60d)R}P)e+g9&un7JD&V&WH}tT9mkxP=BNhSah)&$_OCyQw7p`JQ z?0{;-Af6h$c-mteh#la3sd3$H+8vzrORNW5u?>51++W+SW6#|C`=bVgyumr_$}z_+ z#TmS;vB^u80q?l@$2HrIWqb|HxWj&nfM@>`8jDf93d}mnb7tiE24bJseRvX>Rk7Lw z77^DOb3Sm$Y7@tf7{j-WIlEQ?77+^>Gu+`hY!whYq8M08YnB1ABj!_|eTz%h0Wl-G p@f_E25?l0tQwSl15JCu13jdeZ&{nEY`z1b&SI|Z{ zj$Nwp1?#+9;fvDUS^S%-6E`b0sb9SNSR6XtNj98Q=M=5WG}#xXz{Py;LiUI5+)z5@0DzXOMm z-+Ij9-C9V2~5GzW5}diTJ)`iv74? zIUy5;>H9-1uHaP2*bY=>lCUD6Erg=F^A>P=)P>Cex*{Me&R*b#C<^Nbtc;MT?&wE> zK2Z@?2z(r2S#fl>B|q%KN`N0SKvtYB!0@mN8_k@hkirh2G;G2~0l!$Bw0(%J@84re znyJg6?O)aspjp5#ZMbw{g#zwbhjF5ch1}Efr3&jOWHtC^!kFF`FrE*vh9^##l;^B# z62>$^$e5mxCTxbFWp!c^GD}FQMp0!%sB(i+(oJ;A5g3DLE* z{z=9-0DC)>u=}eOVKW6ius+$tIF}0==QLZwbn$VQpotjS!&uK3G|p{7il9M+JtAll z+B}T+JwfB0&n>J_SXqCPhcQnP)^0F}Q&_X0;5$7wgy!JoNXobyxr7Z6*4;EGjj`7Y z>&D9C5O$ZKp#Mno(lQu0C}{k3riJM&!Z(5fUghH-?s-Au??|`9INe~!3o90m@geLI zVKH24QrJ_10^Jbck>nFWaXfBHShldn&*}&ytK%CmdYcd?=~A*2I5uGIPExOk4Q>6&!_O|q@2bUT zyJj3qD~@d^j@85*tf3ax$7hM+3*aTJxHbT{0h58tfpf6mAuB{%RVQ3Z6&WC_5;sTqou{dk!WI%N6sAU4 zRyDx_W*((5s&vkr2+E>LD6gUvMp^t@u0nV|Mv8^lv&=ecOF%;4(QTjd5p1>O7x;56)ysP1<2ARm{*ufMq-!s zUiMVwTa>%t!>ZoL93-$8z_ZU zSqkDl3&I*K#Y$RUv9(>N(t@xnEya4SgcgAy=$7i^EC@T1;UPKMGZ<-$KuqzUak#tk_n=A@zVUG2F6T-@wgSghBuK>fXg+6!7NPp?6ZJ(EYzj+TZ4U?@^J!|*0b5zy6G1AEZ& zhH<^0Z2?{qClY<;&lGzJsPb+#1OXk!P3YeX+1Vd&0;(nYtVtAeO_?lRA!wqdv6O0_ zDTVdLDzOvvU)CwYcZ*S%BnlYI5@A5Uy?r3%9Gg1&V3(8i&&y4VsOQ&I@$Uk|iBsw5 z1a^suxiwj_Ez8hf+ICa2Obd%&9=B%LJ*&v%oO1L=6lBQiv7LH>VM~}spKbU|gk?1= zrn5)5JCSM#(^wMF>89&A=g>y`*f5J*dMJ4fIE{P$Z1w!5r8F diff --git a/foosball/app/src/tablet/res/drawable-xxhdpi/ic_undo_black_24dp.png b/foosball/app/src/tablet/res/drawable-xxhdpi/ic_undo_black_24dp.png deleted file mode 100644 index 9850a89df28cdc995ec0ee3c42625d03e6ecd9a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 566 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2VEpUp;uunK>+Q_5+Ae`IZRsW| zIxSZtZfL5CY&`BFc52e3wXOC^BHUh@JvD1@1a?Je1gm&O&YHw}(&>}vrUPdx^5-5k zIeX^soS$>Q*nQP`zc+o}%R9yI_S(rSwg@A4Ka8v;1lD|G*`8K-GdP`s&9h)=x@7tTJu4KiD4r`Su5!`PHANN;#jH1PRA9 z&(~X=^4WRr{=jyJG9}Z)cWqoxE-}h!OLy&GeywjQb!JXTR6p?P6jih$kiABUMPHJ(e1Z8YERSdmp&v-wh^T8rGo9^K=+ zjv9XR^fz1?u3FdqdsB6UX6@u@JzEkJYl^MbBqbhvS(awBP5#D$!*(88K^G3a+P3tx zTcFmZ39aS~Uw7GLdAN4X>d{_wdGidHC1TvOZw19NdAi;@Z8%T-#=2mIPLG9KUQ5UO zh9$0_T<&(VUScIj+=}o`iu2Xx_akBh!kYMuKj#`_-0ELf9{|$>gQu&X%Q~loCII>* B`T_s| diff --git a/foosball/app/src/tablet/res/drawable-xxxhdpi/ic_check_blue_48dp.png b/foosball/app/src/tablet/res/drawable-xxxhdpi/ic_check_blue_48dp.png deleted file mode 100644 index 4cb8b60bfd1e9b8c023f1d39885c49ef222b112c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 864 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 WqryMs6>vL&1Uy~+T-G@yGywpL5J-9e diff --git a/foosball/app/src/tablet/res/drawable/bg_serving_indicator.xml b/foosball/app/src/tablet/res/drawable/bg_serving_indicator.xml deleted file mode 100644 index facdd1bb07..0000000000 --- a/foosball/app/src/tablet/res/drawable/bg_serving_indicator.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/tablet/res/drawable/circle_outline_blue_medium.xml b/foosball/app/src/tablet/res/drawable/circle_outline_blue_medium.xml deleted file mode 100644 index 2f8ee9bd77..0000000000 --- a/foosball/app/src/tablet/res/drawable/circle_outline_blue_medium.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/tablet/res/drawable/circle_outline_medium_white.xml b/foosball/app/src/tablet/res/drawable/circle_outline_medium_white.xml deleted file mode 100644 index 8ceda6f588..0000000000 --- a/foosball/app/src/tablet/res/drawable/circle_outline_medium_white.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/tablet/res/drawable/circle_outline_red_medium.xml b/foosball/app/src/tablet/res/drawable/circle_outline_red_medium.xml deleted file mode 100644 index fe5da36356..0000000000 --- a/foosball/app/src/tablet/res/drawable/circle_outline_red_medium.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/tablet/res/drawable/circle_outline_thin.xml b/foosball/app/src/tablet/res/drawable/circle_outline_thin.xml deleted file mode 100644 index 6c0aaddc71..0000000000 --- a/foosball/app/src/tablet/res/drawable/circle_outline_thin.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - diff --git a/foosball/app/src/tablet/res/drawable/circle_white.xml b/foosball/app/src/tablet/res/drawable/circle_white.xml deleted file mode 100644 index ef5b97c312..0000000000 --- a/foosball/app/src/tablet/res/drawable/circle_white.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/foosball/app/src/tablet/res/drawable/vd_person_add_black.xml b/foosball/app/src/tablet/res/drawable/vd_person_add_black.xml deleted file mode 100644 index 61a9ffc0e5..0000000000 --- a/foosball/app/src/tablet/res/drawable/vd_person_add_black.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/foosball/app/src/tablet/res/drawable/vd_person_add_white_24dp.xml b/foosball/app/src/tablet/res/drawable/vd_person_add_white_24dp.xml deleted file mode 100644 index a849ae35a7..0000000000 --- a/foosball/app/src/tablet/res/drawable/vd_person_add_white_24dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/foosball/app/src/tablet/res/drawable/vd_star_amber_a400_48dp.xml b/foosball/app/src/tablet/res/drawable/vd_star_amber_a400_48dp.xml deleted file mode 100644 index e4301d675f..0000000000 --- a/foosball/app/src/tablet/res/drawable/vd_star_amber_a400_48dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/foosball/app/src/tablet/res/drawable/vd_swap_horiz_accent_48dp.xml b/foosball/app/src/tablet/res/drawable/vd_swap_horiz_accent_48dp.xml deleted file mode 100644 index 3b33aa3676..0000000000 --- a/foosball/app/src/tablet/res/drawable/vd_swap_horiz_accent_48dp.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/foosball/app/src/tablet/res/drawable/vd_trophy.xml b/foosball/app/src/tablet/res/drawable/vd_trophy.xml deleted file mode 100644 index 7ad6ac8946..0000000000 --- a/foosball/app/src/tablet/res/drawable/vd_trophy.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - \ No newline at end of file diff --git a/foosball/app/src/tablet/res/layout/activity_create_cut_throat_game.xml b/foosball/app/src/tablet/res/layout/activity_create_cut_throat_game.xml deleted file mode 100644 index 2884cc3d0c..0000000000 --- a/foosball/app/src/tablet/res/layout/activity_create_cut_throat_game.xml +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -