├── app ├── .gitignore ├── src │ ├── test │ │ ├── resources │ │ │ ├── images │ │ │ │ └── empty.png │ │ │ └── seeds │ │ │ │ └── sample_userlist_response.json │ │ └── java │ │ │ └── com │ │ │ └── codemate │ │ │ └── koffeemate │ │ │ ├── testutils │ │ │ ├── RegexMatcher.kt │ │ │ └── CommonTestUtils.kt │ │ │ ├── views │ │ │ ├── TimeAgoTextViewTest.kt │ │ │ └── TimeAgoTextFormatterTest.kt │ │ │ ├── usecases │ │ │ ├── SendCoffeeAnnouncementUseCaseTest.kt │ │ │ ├── PostAccidentUseCaseTest.kt │ │ │ └── LoadUsersUseCaseTest.kt │ │ │ ├── ui │ │ │ └── userselector │ │ │ │ └── UserSelectorPresenterTest.kt │ │ │ └── common │ │ │ └── BrewingProgressUpdaterTest.kt │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── codemate │ │ │ │ └── koffeemate │ │ │ │ ├── ui │ │ │ │ ├── base │ │ │ │ │ ├── MvpView.kt │ │ │ │ │ ├── Presenter.kt │ │ │ │ │ └── BasePresenter.kt │ │ │ │ ├── userselector │ │ │ │ │ ├── UserSelectorView.kt │ │ │ │ │ ├── UserSelectorPresenter.kt │ │ │ │ │ ├── UserSelectListener.kt │ │ │ │ │ ├── UserItemAnimator.kt │ │ │ │ │ ├── adapter │ │ │ │ │ │ ├── UserQuickDialAdapter.kt │ │ │ │ │ │ └── UserSelectorAdapter.kt │ │ │ │ │ └── views │ │ │ │ │ │ ├── UserQuickDialView.kt │ │ │ │ │ │ └── UserSelectorOverlay.kt │ │ │ │ ├── main │ │ │ │ │ ├── MainView.kt │ │ │ │ │ ├── MainPresenter.kt │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── settings │ │ │ │ │ └── SettingsActivity.kt │ │ │ │ ├── extensions │ │ │ │ ├── String.ext.kt │ │ │ │ ├── Glide.ext.kt │ │ │ │ └── Bitmap.ext.kt │ │ │ │ ├── data │ │ │ │ ├── models │ │ │ │ │ ├── CoffeeBrewingEvent.kt │ │ │ │ │ ├── Profile.kt │ │ │ │ │ └── User.kt │ │ │ │ ├── local │ │ │ │ │ ├── UserRepository.kt │ │ │ │ │ ├── CoffeePreferences.kt │ │ │ │ │ ├── CoffeeEventRepository.kt │ │ │ │ │ └── Migration.kt │ │ │ │ └── network │ │ │ │ │ └── SlackApi.kt │ │ │ │ ├── di │ │ │ │ ├── scopes │ │ │ │ │ └── PerActivity.kt │ │ │ │ ├── modules │ │ │ │ │ ├── NetModule.kt │ │ │ │ │ ├── ActivityModule.kt │ │ │ │ │ ├── ThreadingModule.kt │ │ │ │ │ ├── PersistenceModule.kt │ │ │ │ │ └── AppModule.kt │ │ │ │ └── components │ │ │ │ │ ├── ActivityComponent.kt │ │ │ │ │ └── AppComponent.kt │ │ │ │ ├── KoffeemateApp.kt │ │ │ │ ├── usecases │ │ │ │ ├── SendCoffeeAnnouncementUseCase.kt │ │ │ │ ├── PostAccidentUseCase.kt │ │ │ │ └── LoadUsersUseCase.kt │ │ │ │ ├── views │ │ │ │ ├── CoffeeProgressView.kt │ │ │ │ ├── UserSetterButton.kt │ │ │ │ ├── TimeAgoTextFormatter.kt │ │ │ │ └── TimeAgoTextView.kt │ │ │ │ └── common │ │ │ │ ├── BrewingProgressUpdater.kt │ │ │ │ ├── AwardBadgeCreator.kt │ │ │ │ └── ScreenSaver.kt │ │ ├── res │ │ │ ├── drawable-hdpi │ │ │ │ ├── ic_more.png │ │ │ │ ├── coffee_pan.png │ │ │ │ ├── ic_add_user.png │ │ │ │ ├── ic_settings.png │ │ │ │ ├── ic_thumb_down.png │ │ │ │ └── ic_user_unknown.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── ic_more.png │ │ │ │ ├── coffee_pan.png │ │ │ │ ├── ic_add_user.png │ │ │ │ ├── ic_settings.png │ │ │ │ ├── ic_thumb_down.png │ │ │ │ └── ic_user_unknown.png │ │ │ ├── drawable-nodpi │ │ │ │ ├── award.png │ │ │ │ └── empty.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── ic_more.png │ │ │ │ ├── coffee_pan.png │ │ │ │ ├── ic_add_user.png │ │ │ │ ├── ic_settings.png │ │ │ │ ├── ic_thumb_down.png │ │ │ │ └── ic_user_unknown.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── ic_more.png │ │ │ │ ├── coffee_pan.png │ │ │ │ ├── ic_add_user.png │ │ │ │ ├── ic_settings.png │ │ │ │ ├── ic_thumb_down.png │ │ │ │ └── ic_user_unknown.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── ic_more.png │ │ │ │ ├── coffee_pan.png │ │ │ │ ├── ic_add_user.png │ │ │ │ ├── ic_settings.png │ │ │ │ ├── ic_thumb_down.png │ │ │ │ └── ic_user_unknown.png │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values │ │ │ │ ├── attrs.xml │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── styles.xml │ │ │ │ └── strings.xml │ │ │ ├── drawable │ │ │ │ └── background_shadow.xml │ │ │ ├── values-v21 │ │ │ │ └── styles.xml │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ ├── layout │ │ │ │ ├── view_user_quick_dial.xml │ │ │ │ ├── view_screen_saver_overlay.xml │ │ │ │ ├── recycler_item_user.xml │ │ │ │ ├── view_coffee_progress.xml │ │ │ │ ├── view_user_selector.xml │ │ │ │ └── activity_main.xml │ │ │ └── xml │ │ │ │ └── koffeemate_preferences.xml │ │ └── AndroidManifest.xml │ └── androidTest │ │ ├── assets │ │ └── sample-db-schema-v0.realm │ │ └── java │ │ └── com │ │ └── codemate │ │ └── koffeemate │ │ └── data │ │ └── local │ │ ├── RealmTestRule.kt │ │ ├── UserRepositoryTest.kt │ │ ├── CoffeePreferencesTest.kt │ │ ├── MigrationTest.kt │ │ └── CoffeeEventRepositoryTest.kt ├── proguard-rules.pro ├── build.gradle ├── app-config.gradle └── dependencies.gradle ├── settings.gradle ├── art ├── koffeemate_logo.png ├── coffee_incoming_animation.gif └── screenshot_coffee_incoming.png ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── copyright │ ├── profiles_settings.xml │ └── Apache_2_0.xml ├── encodings.xml ├── vcs.xml ├── modules.xml ├── runConfigurations.xml ├── gradle.xml ├── compiler.xml └── misc.xml ├── .travis.yml ├── .gitignore ├── gradle.properties ├── gradlew.bat ├── README.md └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /art/koffeemate_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/art/koffeemate_logo.png -------------------------------------------------------------------------------- /art/coffee_incoming_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/art/coffee_incoming_animation.gif -------------------------------------------------------------------------------- /art/screenshot_coffee_incoming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/art/screenshot_coffee_incoming.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/test/resources/images/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/test/resources/images/empty.png -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/base/MvpView.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.ui.base 2 | 3 | interface MvpView { 4 | 5 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-hdpi/ic_more.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-mdpi/ic_more.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/award.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-nodpi/award.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-nodpi/empty.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/coffee_pan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-hdpi/coffee_pan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/coffee_pan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-mdpi/coffee_pan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xhdpi/ic_more.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxhdpi/ic_more.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxxhdpi/ic_more.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_add_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-hdpi/ic_add_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-hdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_add_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-mdpi/ic_add_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-mdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/coffee_pan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xhdpi/coffee_pan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_add_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xhdpi/ic_add_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/coffee_pan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxhdpi/coffee_pan.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_thumb_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-hdpi/ic_thumb_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_user_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-hdpi/ic_user_unknown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_thumb_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-mdpi/ic_thumb_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_user_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-mdpi/ic_user_unknown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_thumb_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xhdpi/ic_thumb_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_add_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxhdpi/ic_add_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_thumb_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxhdpi/ic_thumb_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/coffee_pan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxxhdpi/coffee_pan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_add_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxxhdpi/ic_add_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxxhdpi/ic_settings.png -------------------------------------------------------------------------------- /app/src/androidTest/assets/sample-db-schema-v0.realm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/androidTest/assets/sample-db-schema-v0.realm -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_user_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xhdpi/ic_user_unknown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_user_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxhdpi/ic_user_unknown.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_thumb_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxxhdpi/ic_thumb_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_user_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodemateLtd/Koffeemate/HEAD/app/src/main/res/drawable-xxxhdpi/ic_user_unknown.png -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/base/Presenter.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.ui.base 2 | 3 | interface Presenter { 4 | fun attachView(mvpView: V) 5 | fun detachView() 6 | } -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #03A9F4 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_shadow.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/extensions/String.ext.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.extensions 2 | 3 | import okhttp3.MediaType 4 | import okhttp3.RequestBody 5 | 6 | fun String.toRequestBody() : RequestBody { 7 | return RequestBody.create(MediaType.parse("text/plain"), this) 8 | } -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/userselector/UserSelectorView.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.ui.userselector 2 | 3 | import com.codemate.koffeemate.data.models.User 4 | import com.codemate.koffeemate.ui.base.MvpView 5 | 6 | interface UserSelectorView : MvpView { 7 | fun showProgress() 8 | fun hideProgress() 9 | fun showError() 10 | fun showUsers(users: List) 11 | } -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_user_quick_dial.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/data/models/CoffeeBrewingEvent.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.data.models 2 | 3 | import io.realm.RealmObject 4 | import io.realm.annotations.PrimaryKey 5 | 6 | open class CoffeeBrewingEvent( 7 | @PrimaryKey 8 | open var id: String = "", 9 | open var time: Long = 0, 10 | open var isSuccessful: Boolean = false, 11 | open var user: User? = null 12 | ) : RealmObject() -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | android: 4 | components: 5 | - tools 6 | - platform-tools 7 | - build-tools-25.0.0 8 | - android-25 9 | - extra-android-m2repository 10 | 11 | jdk: 12 | oraclejdk8 13 | 14 | before_script: 15 | - echo no | android create avd --force -n test -t android-18 --abi armeabi-v7a 16 | - emulator -avd test -no-audio -no-window & 17 | - android-wait-for-emulator 18 | - adb shell input keyevent 82 & 19 | 20 | script: 21 | - ./gradlew test connectedAndroidTest -------------------------------------------------------------------------------- /app/src/main/res/layout/view_screen_saver_overlay.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | app/koffeemate.properties 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # Intellij 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/libraries 40 | 41 | # Keystore files 42 | *.jks -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/ironman/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/extensions/Glide.ext.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.extensions 2 | 3 | import android.graphics.Bitmap 4 | import com.bumptech.glide.RequestManager 5 | import com.bumptech.glide.request.animation.GlideAnimation 6 | import com.bumptech.glide.request.target.SimpleTarget 7 | import com.codemate.koffeemate.R 8 | 9 | fun RequestManager.loadBitmap(url: String, completeListener: (Bitmap) -> Unit) { 10 | load(url).asBitmap() 11 | .error(R.drawable.ic_user_unknown) 12 | .into(object : SimpleTarget(512, 512) { 13 | override fun onResourceReady(resource: Bitmap, glideAnimation: GlideAnimation?) { 14 | completeListener(resource) 15 | } 16 | }) 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /.idea/copyright/Apache_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/base/BasePresenter.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.ui.base 2 | 3 | open class BasePresenter : Presenter { 4 | private var mvpView: T? = null 5 | 6 | override fun attachView(mvpView: T) { 7 | this.mvpView = mvpView 8 | } 9 | 10 | override fun detachView() { 11 | mvpView = null 12 | } 13 | 14 | fun getView(): T? { 15 | return mvpView 16 | } 17 | 18 | fun ensureViewIsAttached() { 19 | if (!isViewAttached()) { 20 | throw ViewNotAttachedException() 21 | } 22 | } 23 | 24 | fun isViewAttached(): Boolean { 25 | return mvpView != null 26 | } 27 | 28 | class ViewNotAttachedException : RuntimeException("View not attached! Please call attachView() first.") 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/scopes/PerActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.scopes 18 | 19 | import javax.inject.Scope 20 | 21 | @Scope 22 | @Retention 23 | annotation class PerActivity -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/userselector/UserSelectorPresenter.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.ui.userselector 2 | 3 | import com.codemate.koffeemate.ui.base.BasePresenter 4 | import com.codemate.koffeemate.usecases.LoadUsersUseCase 5 | import javax.inject.Inject 6 | 7 | class UserSelectorPresenter @Inject constructor( 8 | val loadUsersUseCase: LoadUsersUseCase 9 | ) : BasePresenter() { 10 | fun loadUsers() { 11 | ensureViewIsAttached() 12 | getView()?.showProgress() 13 | 14 | loadUsersUseCase.execute() 15 | .subscribe( 16 | { users -> 17 | getView()?.showUsers(users) 18 | getView()?.hideProgress() 19 | }, 20 | { getView()?.showError() } 21 | ) 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/test/resources/seeds/sample_userlist_response.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": true, 3 | "members": [{ 4 | "id": "abc123", 5 | "name": "bobby", 6 | "is_bot": false, 7 | "profile": { 8 | "first_name": "Bobby", 9 | "last_name": "Tables", 10 | "real_name": "Bobby Tables" 11 | } 12 | }, { 13 | "id": "123abc", 14 | "name": "john", 15 | "is_bot": false, 16 | "profile": { 17 | "first_name": "John", 18 | "last_name": "Smith", 19 | "real_name": "John Smith" 20 | } 21 | }, { 22 | "id": "a1b2c3", 23 | "name": "slackbot", 24 | "is_bot": true, 25 | "profile": { 26 | "first_name": "Slack", 27 | "last_name": "Bot", 28 | "real_name": "Slackbot" 29 | } 30 | }, { 31 | "id": "c3b2a1", 32 | "name": "kevin", 33 | "is_bot": false, 34 | "deleted": true, 35 | "profile": { 36 | "first_name": "Kevin", 37 | "last_name": "Smith", 38 | "real_name": "Kevin Smith" 39 | } 40 | }], 41 | "cache_ts": 123456789 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/main/MainView.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.ui.main 2 | 3 | import com.codemate.koffeemate.data.models.CoffeeBrewingEvent 4 | import com.codemate.koffeemate.data.models.User 5 | import com.codemate.koffeemate.ui.base.MvpView 6 | 7 | interface MainView : MvpView { 8 | fun showNewCoffeeIsComing() 9 | fun showCancelCoffeeProgressPrompt() 10 | 11 | fun displayUserSelectorQuickDial(users: List) 12 | fun displayFullscreenUserSelector(requestCode: Int) 13 | fun clearCoffeeBrewingPerson() 14 | 15 | fun displayUserSetterButton() 16 | fun hideUserSetterButton() 17 | 18 | fun updateLastBrewingEvent(event: CoffeeBrewingEvent) 19 | fun updateCoffeeProgress(newProgress: Int) 20 | fun resetCoffeeViewStatus() 21 | 22 | fun showNoAnnouncementChannelSetError() 23 | fun showNoAccidentChannelSetError() 24 | 25 | fun showPostAccidentAnnouncementPrompt(user: User) 26 | fun showAccidentPostedSuccessfullyMessage() 27 | fun showErrorPostingAccidentMessage() 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/ui/userselector/UserSelectListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.ui.userselector 18 | 19 | import com.codemate.koffeemate.data.models.User 20 | 21 | interface UserSelectListener { 22 | companion object { 23 | val REQUEST_WHOS_BREWING = 1 24 | val REQUEST_WHO_FAILED_BREWING = 2 25 | } 26 | 27 | fun onUserSelected(user: User, requestCode: Int) 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/modules/NetModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.modules 18 | 19 | import com.codemate.koffeemate.data.network.SlackApi 20 | import dagger.Module 21 | import dagger.Provides 22 | import okhttp3.HttpUrl 23 | import javax.inject.Singleton 24 | 25 | @Module 26 | class NetModule(val baseUrl: HttpUrl) { 27 | @Provides 28 | @Singleton 29 | fun provideApi() = SlackApi.create(baseUrl) 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/components/ActivityComponent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.components 18 | 19 | import com.codemate.koffeemate.di.modules.ActivityModule 20 | import com.codemate.koffeemate.di.scopes.PerActivity 21 | import com.codemate.koffeemate.ui.main.MainActivity 22 | import dagger.Subcomponent 23 | 24 | @PerActivity 25 | @Subcomponent(modules = arrayOf(ActivityModule::class)) 26 | interface ActivityComponent { 27 | fun inject(mainActivity: MainActivity) 28 | } -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'realm-android' 5 | 6 | apply from: 'dependencies.gradle' 7 | apply from: 'app-config.gradle' 8 | 9 | android { 10 | compileSdkVersion 25 11 | buildToolsVersion "25.0.0" 12 | defaultConfig { 13 | applicationId "com.codemate.koffeemate" 14 | minSdkVersion 16 15 | targetSdkVersion 25 16 | versionCode 1 17 | versionName "0.3" 18 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 19 | 20 | buildConfigField "String", "SLACK_AUTH_TOKEN", SLACK_AUTH_TOKEN 21 | } 22 | buildTypes { 23 | debug { 24 | testCoverageEnabled true 25 | } 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | } 35 | 36 | kapt { 37 | generateStubs = true 38 | } 39 | 40 | repositories { 41 | mavenCentral() 42 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/recycler_item_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/modules/ActivityModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.modules 18 | 19 | import android.app.Activity 20 | import com.codemate.koffeemate.common.AndroidScreenSaver 21 | import com.codemate.koffeemate.common.ScreenSaver 22 | import com.codemate.koffeemate.di.scopes.PerActivity 23 | import dagger.Module 24 | import dagger.Provides 25 | 26 | @Module 27 | class ActivityModule(private val activity: Activity) { 28 | @Provides 29 | @PerActivity 30 | fun provideScreenSaver(): ScreenSaver = AndroidScreenSaver(activity) 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/modules/ThreadingModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.modules 18 | 19 | import dagger.Module 20 | import dagger.Provides 21 | import rx.Scheduler 22 | import rx.android.schedulers.AndroidSchedulers 23 | import rx.schedulers.Schedulers 24 | import javax.inject.Named 25 | 26 | @Module 27 | class ThreadingModule { 28 | @Provides 29 | @Named("subscriber") 30 | fun provideSubscriber(): Scheduler = Schedulers.newThread() 31 | 32 | @Provides 33 | @Named("observer") 34 | fun provideObserver(): Scheduler = AndroidSchedulers.mainThread() 35 | } -------------------------------------------------------------------------------- /app/src/test/java/com/codemate/koffeemate/testutils/RegexMatcher.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.testutils 18 | 19 | import org.hamcrest.BaseMatcher 20 | import org.hamcrest.Description 21 | 22 | class RegexMatcher(private val regex: String) : BaseMatcher() { 23 | override fun matches(o: Any) = regex.toRegex(RegexOption.DOT_MATCHES_ALL).matches(o as String) 24 | 25 | override fun describeTo(description: Description) { 26 | description.appendText("matches regex $regex") 27 | } 28 | 29 | companion object { 30 | fun matchesPattern(regex: String) = RegexMatcher(regex) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/KoffeemateApp.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate 2 | 3 | import android.app.Application 4 | import com.codemate.koffeemate.data.local.Migration 5 | import com.codemate.koffeemate.data.network.SlackApi 6 | import com.codemate.koffeemate.di.components.AppComponent 7 | import com.codemate.koffeemate.di.components.DaggerAppComponent 8 | import com.codemate.koffeemate.di.modules.AppModule 9 | import com.codemate.koffeemate.di.modules.NetModule 10 | import io.realm.Realm 11 | import io.realm.RealmConfiguration 12 | 13 | class KoffeemateApp : Application() { 14 | companion object { 15 | lateinit var appComponent: AppComponent 16 | } 17 | 18 | override fun onCreate() { 19 | super.onCreate() 20 | 21 | initializeRealm() 22 | 23 | appComponent = DaggerAppComponent.builder() 24 | .appModule(AppModule(this)) 25 | .netModule(NetModule(SlackApi.BASE_URL)) 26 | .build() 27 | } 28 | 29 | private fun initializeRealm() { 30 | Realm.init(this) 31 | 32 | val configuration = RealmConfiguration.Builder() 33 | .migration(Migration()) 34 | .schemaVersion(1) 35 | .build() 36 | Realm.setDefaultConfiguration(configuration) 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/components/AppComponent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.components 18 | 19 | import com.codemate.koffeemate.di.modules.* 20 | import com.codemate.koffeemate.ui.userselector.views.UserSelectorOverlay 21 | import dagger.Component 22 | import javax.inject.Singleton 23 | 24 | @Singleton 25 | @Component(modules = arrayOf( 26 | AppModule::class, 27 | PersistenceModule::class, 28 | NetModule::class, 29 | ThreadingModule::class) 30 | ) 31 | interface AppComponent { 32 | fun inject(userSelectorOverlay: UserSelectorOverlay) 33 | 34 | fun plus(activityModule: ActivityModule): ActivityComponent 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/data/models/Profile.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.data.models 18 | 19 | import io.realm.RealmObject 20 | 21 | open class Profile( 22 | open var first_name: String = "", 23 | open var last_name: String = "", 24 | open var real_name: String = "", 25 | open var image_72: String? = null, 26 | open var image_192: String? = null, 27 | open var image_512: String? = null 28 | ) : RealmObject() { 29 | val largestAvailableImage: String 30 | get() = image_512 ?: image_192 ?: image_72 ?: "" 31 | 32 | val smallestAvailableImage: String 33 | get() = image_72 ?: image_192 ?: image_512 ?: "" 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/di/modules/PersistenceModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.di.modules 18 | 19 | import android.content.Context 20 | import com.codemate.koffeemate.data.local.* 21 | import dagger.Module 22 | import dagger.Provides 23 | import javax.inject.Singleton 24 | 25 | @Module 26 | class PersistenceModule { 27 | @Provides 28 | @Singleton 29 | fun provideCoffeePreferences(ctx: Context) = CoffeePreferences(ctx) 30 | 31 | @Provides 32 | @Singleton 33 | fun provideCoffeeEventRepository(): CoffeeEventRepository = RealmCoffeeEventRepository() 34 | 35 | @Provides 36 | @Singleton 37 | fun provideUserRepository(): UserRepository = RealmUserRepository() 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/extensions/Bitmap.ext.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.extensions 18 | 19 | import android.content.Context 20 | import android.graphics.Bitmap 21 | import java.io.File 22 | import java.io.FileOutputStream 23 | 24 | fun Bitmap.saveToFile(ctx: Context, filename: String): File { 25 | val extStorageDirectory = ctx.filesDir 26 | val file = File(extStorageDirectory, filename) 27 | 28 | try { 29 | val outStream = FileOutputStream(file) 30 | compress(Bitmap.CompressFormat.PNG, 100, outStream) 31 | 32 | outStream.flush() 33 | outStream.close() 34 | } catch (e: Exception) { 35 | e.printStackTrace() 36 | } 37 | 38 | return file 39 | } -------------------------------------------------------------------------------- /app/app-config.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * Beautiful Gradle script taken from: 3 | * https://github.com/futurice/freesound-android/blob/master/app/app-config.gradle 4 | */ 5 | ext { 6 | SLACK_AUTH_TOKEN = getSlackAuthToken() 7 | } 8 | 9 | def String getSlackAuthToken() { 10 | String slackAuthToken = isCiBuild() ? getApiKeyFromEnv() : getApiKeyFromFile(); 11 | if (slackAuthToken == null || slackAuthToken.isEmpty()) { 12 | throw new IllegalStateException( 13 | "Could not find Slack API key value in environment or property file") 14 | } 15 | return "\"$slackAuthToken\"" 16 | } 17 | 18 | private boolean isCiBuild() { 19 | System.getenv("CI") == "true" 20 | } 21 | 22 | private String getApiKeyFromFile() { 23 | Properties apiProperties = loadFileProperties("$projectDir/koffeemate.properties") 24 | return apiProperties.getProperty("SLACK_AUTH_TOKEN") 25 | } 26 | 27 | private String getApiKeyFromEnv() { 28 | System.getenv("SLACK_AUTH_TOKEN") 29 | } 30 | 31 | def Properties loadFileProperties(String fileLocation) { 32 | def Properties properties = new Properties() 33 | try { 34 | properties.load(new FileInputStream(fileLocation)) 35 | } catch (FileNotFoundException fnf) { 36 | logger.log(LogLevel.ERROR, 37 | String.format("Missing Koffeemate properties file: %s", fileLocation), 38 | fnf) 39 | throw fnf 40 | } 41 | return properties 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/data/local/UserRepository.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.data.local 18 | 19 | import com.codemate.koffeemate.data.models.User 20 | import io.realm.Realm 21 | 22 | interface UserRepository { 23 | fun addAll(users: List) 24 | fun getAll(): List 25 | } 26 | 27 | class RealmUserRepository : UserRepository { 28 | override fun addAll(users: List) { 29 | with(Realm.getDefaultInstance()) { 30 | executeTransaction { copyToRealmOrUpdate(users) } 31 | close() 32 | } 33 | } 34 | 35 | override fun getAll(): List = with(Realm.getDefaultInstance()) { 36 | val all = where(User::class.java).findAll() 37 | val copy = copyFromRealm(all) 38 | 39 | close() 40 | return@with copy 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/test/java/com/codemate/koffeemate/testutils/CommonTestUtils.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.testutils 18 | 19 | import com.codemate.koffeemate.data.models.Profile 20 | import com.codemate.koffeemate.data.models.User 21 | import java.io.File 22 | 23 | fun Any.getResourceFile(path: String): File { 24 | return File(javaClass.classLoader.getResource(path).file) 25 | } 26 | 27 | fun fakeUser() = User().apply { 28 | id = "abc123" 29 | profile = Profile() 30 | profile.first_name = "Jorma" 31 | profile.real_name = "Jorma" 32 | } 33 | 34 | fun namedUser(name: String) = User().apply { 35 | id = name 36 | this.name = name 37 | profile.real_name = name 38 | } 39 | 40 | fun namedUserWithTimestamp(name: String, lastUpdated: Long) = 41 | namedUser(name).apply { 42 | last_updated = lastUpdated 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/codemate/koffeemate/usecases/SendCoffeeAnnouncementUseCase.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Codemate Ltd 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.codemate.koffeemate.usecases 18 | 19 | import com.codemate.koffeemate.data.network.SlackApi 20 | import okhttp3.ResponseBody 21 | import retrofit2.Response 22 | import rx.Observable 23 | import rx.Scheduler 24 | import javax.inject.Inject 25 | import javax.inject.Named 26 | 27 | open class SendCoffeeAnnouncementUseCase @Inject constructor( 28 | var slackApi: SlackApi, 29 | @Named("subscriber") var subscriber: Scheduler, 30 | @Named("observer") var observer: Scheduler 31 | ) { 32 | fun execute(channel: String, newCoffeeMessage: String): Observable> { 33 | return slackApi.postMessage(channel, newCoffeeMessage) 34 | .subscribeOn(subscriber) 35 | .observeOn(observer) 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/codemate/koffeemate/data/local/RealmTestRule.kt: -------------------------------------------------------------------------------- 1 | package com.codemate.koffeemate.data.local 2 | 3 | import io.realm.Realm 4 | import io.realm.RealmConfiguration 5 | import org.junit.rules.ExternalResource 6 | import org.junit.runner.Description 7 | import org.junit.runners.model.Statement 8 | 9 | /** 10 | * A JUnit Rule that sets up a test Realm database before each test, 11 | * clears all data from it, and deletes the whole database file alltogether 12 | * after the test completes. 13 | * 14 | * Usage: 15 | * 16 | * @Rule @JvmField 17 | * val realmRule: RealmTestRule = RealmTestRule() 18 | * 19 | * The above assumes that your application logic that uses Realm always uses 20 | * the default instance. Meaning that your code calls Realm.getDefaultInstance() 21 | * and uses that for all database logic. 22 | */ 23 | class RealmTestRule : ExternalResource() { 24 | val testConfig: RealmConfiguration = RealmConfiguration.Builder() 25 | .name("test.realm") 26 | .build() 27 | 28 | override fun before() { 29 | Realm.setDefaultConfiguration(testConfig) 30 | 31 | with (Realm.getDefaultInstance()) { 32 | executeTransaction(Realm::deleteAll) 33 | close() 34 | } 35 | } 36 | 37 | override fun apply(base: Statement?, description: Description?): Statement { 38 | return super.apply(base, description) 39 | } 40 | 41 | override fun after() { 42 | Realm.deleteRealm(testConfig) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/view_coffee_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 20 | 21 | 26 | 27 | 28 | 29 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_user_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 19 | 20 | 27 | 28 | 32 | 33 |