diff --git a/README.md b/README.md index 575a7e28..8f700b99 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # The Official MHacks Android App -Get it on Google Play +Get it on Google Play # About The goal of this project is to provide a modular and open source Android client for hackathons of all sizes. Feel free to fork this project and deploy this client for your event. @@ -18,23 +18,78 @@ If you plan on building this project for release, you'll need to add a `signingC **NOTE: You may need to clean your project and sync Gradle files before your first run.** `Build > Clean project` +### Prerequisites + +To build this project, there are several requirements. + +1. `google-services.json` + + This file is needed to use Google Play Services. More specifically, for Google Maps integration, you must register on Google's [website](https://developers.google.com/maps/documentation/android-sdk/intro) to receive this key + +2. `gradle.properties` + + This file contains API keys that are used throughout the app. This is not added to the project for security reasons. Note that there are not quotation marks around MHACKS_GOOGLE_MAPS_API_KEY and there are double quotation marks around GCM_SERVER_ID. + +3. ```groovy + MHACKS_GOOGLE_MAPS_API_KEY=examplekey + GCM_SERVER_ID="example_key" + + // This is needed to transform App Compat libraries in third + // party libraries to be compat with the newer AndroidX + // packages. + android.useAndroidX = true + android.enableJetifier = true + + // Needed to use data binding for feature modules. + android.enableExperimentalFeatureDatabinding = true + ``` + +4. Android Studio 3.2 + + This project uses tools available on a recent version of Android Studio. Older versions of the IDE may not support some aspects of the development. + +# Goals + +* Demonstrate a good understanding of software architecture and tooling that are important in maintaining a modern codebase. +* Uses MVVM, in the form of Architecture Components ViewModel, as a solution for seperation of concerns and implementing [clean architecture](https://proandroiddev.com/a-guided-tour-inside-a-clean-architecture-code-base-48bb5cc9fc97). +* Conforming to Material Design standards in creating a predictable and intuitive UI. +* Sensible file and project organization. +* Demonstrate the use of common Android libraries used commonly for modern codebases. +* Use dependency injection with Dagger 2 to produce decoupled objects and services, reduces the amount of boilerplate. +* Use Data Binding to bind UI in a declarative method. + +# Screenshots + + + + + + + + + + +
Welcome Screen / TimerTicket
+ # Credits + We would like to thank the maintainers of the following for past and present version of the app: - [Square OkHTTP](http://square.github.io/okhttp/ "Square OkHTTP") - [Square Retrofit](http://square.github.io/retrofit/ "Square Retrofit") -- [MaterialDrawer](http://mikepenz.github.io/MaterialDrawer/ "Mike Penz's Material Drawer") -- [Parse Android](https://parse.com/docs/android_guide "Parse Android Developer Guide") -- [AndroidWeekView](https://github.com/alamkanak/Android-Week-View "Alam Kanak's AndroidWeekView") -- [Square Picasso](http://square.github.io/picasso/ "Square Picasso") -- [Google Guava](https://code.google.com/p/guava-libraries/ "Google Guava Libraries") -- [Firebase Android](https://www.firebase.com/docs/android/quickstart.html "Firebase Android Quick Start") -- [Floating Action Menu](https://github.com/futuresimple/android-floating-action-button "Future Simples' Android Floating Action Button Extention Library") +- [Square Moshi](https://github.com/square/moshi) +- [Dagger 2](https://google.github.io/dagger/) +- [RxJava 2](https://github.com/ReactiveX/RxJava) +- [Architecture Components](https://developer.android.com/topic/libraries/architecture/) +- [Room](https://developer.android.com/topic/libraries/architecture/room) +- [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) +- [barcodescanner](https://github.com/dm77/barcodescanner) +- [ArcLayout](https://github.com/florent37/ArcLayout) # License The MIT License (MIT) -Copyright (c) 2016 MHacks, Google Inc. +Copyright (c) 2018 MHacks Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/apk/build.gradle b/apk/build.gradle index 1714945c..fd75843b 100644 --- a/apk/build.gradle +++ b/apk/build.gradle @@ -10,7 +10,7 @@ android { applicationId 'org.mhacks.app' minSdkVersion 21 targetSdkVersion 28 - versionCode 1 + versionCode 11 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -30,6 +30,8 @@ android { } +apply plugin: "com.google.gms.google-services" + dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" diff --git a/apk/src/main/AndroidManifest.xml b/apk/src/main/AndroidManifest.xml index 429850e8..323308a1 100644 --- a/apk/src/main/AndroidManifest.xml +++ b/apk/src/main/AndroidManifest.xml @@ -39,6 +39,22 @@ + + + + + + + + + + diff --git a/base/build.gradle b/base/build.gradle index ada7b23d..2a691bab 100644 --- a/base/build.gradle +++ b/base/build.gradle @@ -5,14 +5,13 @@ apply plugin: "kotlin-android-extensions" apply plugin: "kotlin-kapt" ext { - bugsnag_key = ext.MHACKS_BUGSNAG_KEY google_maps_api_key = ext.MHACKS_GOOGLE_MAPS_API_KEY gcm_server_id = ext.GCM_SERVER_ID } android { compileSdkVersion 28 - buildToolsVersion '28.0.2' + buildToolsVersion '28.0.3' baseFeature true dexOptions { javaMaxHeapSize "4g" @@ -42,24 +41,44 @@ android { defaultConfig { minSdkVersion 21 targetSdkVersion 28 - versionName "10.0.0" + versionName "11.0.0" + + buildConfigField "String", "FIXED_START_DATE", "\"2018-10-12T00:00:00\"" + buildConfigField "String", "INSTANT_APP_URL", "\"schedule\"" + + buildConfigField "String", "WIFI_SSID", "\"MHacks11\"" + buildConfigField "String", "WIFI_PASSWORD", "\"anyonecancode\"" + + buildConfigField "String", "MHACKS_EMAIL", "\"hackathon@umich.edu\"" + + buildConfigField "String", + "SLACK_INVITE_URL", + "\"https://join.slack.com/t/mhacks11/shared_invite/enQtNDQzMDI0MDY3ODQ1LTM3YTIyMmJmNjU3NGM2NDk1MzQzZjZmMmY3ZDliZmZlNTRjOGNiMTc2OWRiZjIyODBiNzk2ZGQ4YjBmMjlkZjU\"" + + buildConfigField 'double', 'LAT', '42.2694' + buildConfigField 'double', 'LNG', '-83.7425' + resValue "string", "google_maps_api_key", google_maps_api_key + vectorDrawables.useSupportLibrary = true - multiDexEnabled true } buildTypes { release { debuggable false minifyEnabled false proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt" - multiDexEnabled true resValue "string", "google_maps_api_key", google_maps_api_key signingConfig signingConfigs.release + + buildConfigField "String", "API_URL", "\"https://mhacks.org/v1/\"" } debug { - debuggable true minifyEnabled false + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt" resValue "string", "google_maps_api_key", google_maps_api_key + + + buildConfigField "String", "API_URL", "\"https://staging.mhacks.org/v1/\"" } } @@ -67,20 +86,15 @@ android { enabled = true } - productFlavors { - - } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$rootProject.kotlin_version" -// kapt 'androidx.databinding:databinding-compiler:3.2.0' - // Play Services - implementation 'com.google.firebase:firebase-core:16.0.3' - implementation 'com.google.firebase:firebase-messaging:17.3.2' + implementation 'com.google.firebase:firebase-core:16.0.4' + implementation 'com.google.firebase:firebase-messaging:17.3.3' implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' @@ -90,8 +104,9 @@ dependencies { implementation 'com.squareup.retrofit2:converter-moshi:2.4.0' // Persistence - implementation 'androidx.room:room-runtime:2.0.0-rc01' - implementation 'androidx.room:room-rxjava2:2.0.0-rc01' + implementation 'androidx.room:room-runtime:2.0.0' + implementation 'androidx.room:room-rxjava2:2.0.0' + kapt 'androidx.room:room-compiler:2.0.0' // RxJava implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' @@ -101,8 +116,6 @@ dependencies { // Debugging implementation 'com.jakewharton.timber:timber:4.7.0' - kapt 'androidx.room:room-compiler:2.0.0-rc01' - feature project(':ui') } diff --git a/base/src/main/AndroidManifest.xml b/base/src/main/AndroidManifest.xml index 6f917aa4..b9e21c71 100644 --- a/base/src/main/AndroidManifest.xml +++ b/base/src/main/AndroidManifest.xml @@ -26,9 +26,9 @@ android:name=".MHacksApplication" android:allowBackup="true" android:fullBackupContent="false" - android:icon="@mipmap/launcher_icon" + android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:logo="@mipmap/launcher_icon" + android:logo="@mipmap/ic_launcher" android:theme="@style/SplashTheme" android:title="com.mhacks.android.MHacks" tools:ignore="GoogleAppIndexingWarning"> @@ -92,14 +92,21 @@ This is required if you want to do any message handling beyond receiving notifications on apps in the background. --> + + android:name=".data.network.fcm.FCMMessageHandler"> - + + + diff --git a/base/src/main/ic_launcher-web.png b/base/src/main/ic_launcher-web.png index 8347c1bb..b1f8f5a5 100644 Binary files a/base/src/main/ic_launcher-web.png and b/base/src/main/ic_launcher-web.png differ diff --git a/base/src/main/java/com/mhacks/app/data/Constants.kt b/base/src/main/java/com/mhacks/app/data/Constants.kt deleted file mode 100644 index bdde0b62..00000000 --- a/base/src/main/java/com/mhacks/app/data/Constants.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.mhacks.app.data - -import android.net.wifi.WifiConfiguration - -object Constants { - - const val STAGING_URL = "https://staging.mhacks.org/v1/" - - const val RELEASE_URL = "https://mhacks.org/v1/" - - const val INSTANT_APP_PATH = "/schedule" - - const val FIXED_START_DATE = "2018-05-01T00:00:00" // Using ISO Local Date and Time - - private const val WIFI_SSID = "MHacks11" - - private const val WIFI_PASSWORD = "anyonecancode" - - val WIFI_CONFIGUATION: WifiConfiguration - get() { - val wifiConfig = WifiConfiguration() - - wifiConfig.SSID = String.format("\"%s\"", WIFI_SSID); - wifiConfig.preSharedKey = String.format("\"%s\"", WIFI_PASSWORD) - - return wifiConfig - } - - const val GOOGLE_MAPS_URL = "http://maps.google.co.in/maps?q=" - - const val SLACK_INVITE_URL = "https://join.slack.com/t/mhacks11/shared_invite/enQtNDQzMDI0MDY3ODQ1LTM3YTIyMmJmNjU3NGM2NDk1MzQzZjZmMmY3ZDliZmZlNTRjOGNiMTc2OWRiZjIyODBiNzk2ZGQ4YjBmMjlkZjU" - - const val MHACKS_EMAIL = "hackathon@umich.edu" -} \ No newline at end of file diff --git a/base/src/main/java/com/mhacks/app/data/SharedPreferencesManager.kt b/base/src/main/java/com/mhacks/app/data/SharedPreferencesManager.kt index 9fd31840..a2b903c7 100644 --- a/base/src/main/java/com/mhacks/app/data/SharedPreferencesManager.kt +++ b/base/src/main/java/com/mhacks/app/data/SharedPreferencesManager.kt @@ -37,6 +37,5 @@ class SharedPreferencesManager(private val sharedPreferences: SharedPreferences) private const val FLASH_ENABLED_KEY = "FLASH_ENABLED_KEY" - private const val IS_ADMIN_KEY = "IS_ADMIN_KEY" } } \ No newline at end of file diff --git a/base/src/main/java/com/mhacks/app/data/models/common/RetrofitException.kt b/base/src/main/java/com/mhacks/app/data/models/common/RetrofitException.kt index 0d63ec69..16836b4c 100644 --- a/base/src/main/java/com/mhacks/app/data/models/common/RetrofitException.kt +++ b/base/src/main/java/com/mhacks/app/data/models/common/RetrofitException.kt @@ -9,7 +9,7 @@ class RetrofitException internal constructor( /** The request URL which produced the error. */ val url: String?, /** Response object containing status code, headers, body, etc. */ - val response: Response<*>?, + private val response: Response<*>?, /** The event kind which triggered this error. */ val kind: Kind, val exception: Throwable?) : RuntimeException(message, exception) { diff --git a/base/src/main/java/com/mhacks/app/data/network/fcm/FCMMessageHandler.kt b/base/src/main/java/com/mhacks/app/data/network/fcm/FCMMessageHandler.kt index 2d04e2b3..0e700526 100644 --- a/base/src/main/java/com/mhacks/app/data/network/fcm/FCMMessageHandler.kt +++ b/base/src/main/java/com/mhacks/app/data/network/fcm/FCMMessageHandler.kt @@ -7,6 +7,7 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage +import timber.log.Timber import com.mhacks.app.R /** @@ -25,7 +26,7 @@ class FCMMessageHandler : FirebaseMessagingService() { private fun createNotification(notification: RemoteMessage.Notification) { val builder = NotificationCompat.Builder(baseContext, mhacksGroup) .setDefaults(Notification.DEFAULT_ALL) - .setSmallIcon(R.mipmap.launcher_icon) + .setSmallIcon(R.mipmap.ic_launcher_round) .setContentTitle(notification.title) .setContentText(notification.body) .setVibrate(longArrayOf(1000, 1000, 1000, 1000, 1000)) @@ -37,6 +38,8 @@ class FCMMessageHandler : FirebaseMessagingService() { override fun onNewToken(newToken: String?) { super.onNewToken(newToken) + Timber.d("New Token is $newToken") + val intent = Intent(this, RegistrationIntentService::class.java) startService(intent) } diff --git a/base/src/main/java/com/mhacks/app/data/network/fcm/RegistrationIntentService.kt b/base/src/main/java/com/mhacks/app/data/network/fcm/RegistrationIntentService.kt index 66b8b7cb..c549d262 100644 --- a/base/src/main/java/com/mhacks/app/data/network/fcm/RegistrationIntentService.kt +++ b/base/src/main/java/com/mhacks/app/data/network/fcm/RegistrationIntentService.kt @@ -9,7 +9,8 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import timber.log.Timber import android.preference.PreferenceManager import android.content.SharedPreferences -import com.mhacks.app.data.network.services.MHacksService +import com.mhacks.app.BuildConfig +import com.mhacks.app.data.network.services.FireBaseService import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory @@ -19,12 +20,12 @@ import retrofit2.converter.moshi.MoshiConverterFactory class RegistrationIntentService : IntentService(TAG) { private val retrofit = Retrofit.Builder() - .baseUrl("https://mhacks.org/v1/") + .baseUrl(BuildConfig.API_URL) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(MoshiConverterFactory.create()) .build() - private val mhacksService = retrofit.create(MHacksService::class.java) + private val mhacksService = retrofit.create(FireBaseService::class.java) private val sharedPreferences: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(this) @@ -35,19 +36,27 @@ class RegistrationIntentService : IntentService(TAG) { .getInstance() .instanceId.addOnSuccessListener { if (it != null) { + Timber.d("Register to service") + sharedPreferences + .edit() + .putString(PUSH_TOKEN, it.token) + .apply() sendRegistrationToServer(it.token) } else { + Timber.d("Save to Shared Prefs that our value is false") sharedPreferences .edit() .putBoolean(SENT_TOKEN_TO_SERVER, false) .apply() } + }.addOnFailureListener { + Timber.e(it) } } private fun sendRegistrationToServer(token: String) { Timber.e(token) - mhacksService.postFireBaseToken(token) + mhacksService.postFireBaseToken(token, "") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( @@ -58,6 +67,8 @@ class RegistrationIntentService : IntentService(TAG) { companion object { private const val TAG = "RegIntentService" - private const val SENT_TOKEN_TO_SERVER = "sentTokenToServer" + const val SENT_TOKEN_TO_SERVER = "sentTokenToServer" + const val PUSH_TOKEN = "pushToken" + const val AUTH_TOKEN= "authToken" } } \ No newline at end of file diff --git a/base/src/main/java/com/mhacks/app/data/network/services/FireBaseService.kt b/base/src/main/java/com/mhacks/app/data/network/services/FireBaseService.kt new file mode 100644 index 00000000..47bb2764 --- /dev/null +++ b/base/src/main/java/com/mhacks/app/data/network/services/FireBaseService.kt @@ -0,0 +1,17 @@ +package com.mhacks.app.data.network.services + +import com.mhacks.app.data.models.FcmDevice +import io.reactivex.Single +import retrofit2.http.* + +/** + * Serivce for posting FireBase Token. + */ + +interface FireBaseService { + + @FormUrlEncoded + @POST("device") + fun postFireBaseToken(@Field("push_id") pushId: String, @Header("Authorization") authToken: String): Single + +} diff --git a/base/src/main/java/com/mhacks/app/data/network/services/MHacksService.kt b/base/src/main/java/com/mhacks/app/data/network/services/MHacksService.kt deleted file mode 100644 index dae4f676..00000000 --- a/base/src/main/java/com/mhacks/app/data/network/services/MHacksService.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.mhacks.app.data.network.services - -import com.mhacks.app.data.models.* -import com.mhacks.app.data.models.FcmDevice -import io.reactivex.Single -import retrofit2.http.* - -/** - * Provides definitions for interactions with the RESTful service. - */ - -interface MHacksService { - - @GET("configuration/") - fun getConfigurationResponse(): Single - - @POST("auth/login/") - @FormUrlEncoded - fun postLogin(@Field("email") email: String, - @Field("password") password: String): Single - - @GET("user/profile/") - fun getUserResponse(): Single - - @POST("user/ticket/verify") - @FormUrlEncoded - fun verifyUserTicket(@Field("email") email: String): Single - - @GET("floor") - fun getFloorResponse(): Single - - @GET("announcements") - fun getAnnouncementResponse(): Single - - @GET("event") - fun getEventResponse(): Single - - @FormUrlEncoded - @POST("device") - fun postFireBaseToken(@Field("push_id") pushId: String): Single - -} diff --git a/base/src/main/java/com/mhacks/app/data/room/dao/EventDao.kt b/base/src/main/java/com/mhacks/app/data/room/dao/EventDao.kt index 4974270c..cca04044 100644 --- a/base/src/main/java/com/mhacks/app/data/room/dao/EventDao.kt +++ b/base/src/main/java/com/mhacks/app/data/room/dao/EventDao.kt @@ -1,8 +1,5 @@ package com.mhacks.app.data.room.dao - -import android.os.Parcel -import android.os.Parcelable import androidx.room.* import com.mhacks.app.data.models.Event import io.reactivex.Single diff --git a/base/src/main/launcher_icon-web.png b/base/src/main/launcher_icon-web.png deleted file mode 100644 index f998c059..00000000 Binary files a/base/src/main/launcher_icon-web.png and /dev/null differ diff --git a/base/src/main/res/drawable/ic_launcher_foreground.xml b/base/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..5c18ed6c --- /dev/null +++ b/base/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/base/src/main/res/drawable/mh10_logo.png b/base/src/main/res/drawable/mh10_logo.png deleted file mode 100644 index 5ac63696..00000000 Binary files a/base/src/main/res/drawable/mh10_logo.png and /dev/null differ diff --git a/base/src/main/res/drawable/mhacks_wallpaper.xml b/base/src/main/res/drawable/mhacks_wallpaper.xml deleted file mode 100644 index 79c4271f..00000000 --- a/base/src/main/res/drawable/mhacks_wallpaper.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/base/src/main/res/drawable/splash.xml b/base/src/main/res/drawable/splash.xml index fe88b201..9dfb897e 100644 --- a/base/src/main/res/drawable/splash.xml +++ b/base/src/main/res/drawable/splash.xml @@ -1,10 +1,10 @@ - + + android:src="@drawable/splash_logo" /> - + \ No newline at end of file diff --git a/base/src/main/res/drawable/splash_background.xml b/base/src/main/res/drawable/splash_background.xml new file mode 100644 index 00000000..4edb09e3 --- /dev/null +++ b/base/src/main/res/drawable/splash_background.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/base/src/main/res/drawable/splash_logo.png b/base/src/main/res/drawable/splash_logo.png new file mode 100644 index 00000000..3107530d Binary files /dev/null and b/base/src/main/res/drawable/splash_logo.png differ diff --git a/base/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/base/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..6f2acb4f --- /dev/null +++ b/base/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/base/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/base/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..6f2acb4f --- /dev/null +++ b/base/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/base/src/main/res/mipmap-hdpi/ic_launcher_background.png b/base/src/main/res/mipmap-hdpi/ic_launcher_background.png new file mode 100644 index 00000000..b8c4eb98 Binary files /dev/null and b/base/src/main/res/mipmap-hdpi/ic_launcher_background.png differ diff --git a/base/src/main/res/mipmap-hdpi/ic_launcher_round.png b/base/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000..99aac379 Binary files /dev/null and b/base/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/base/src/main/res/mipmap-hdpi/launcher_icon.png b/base/src/main/res/mipmap-hdpi/launcher_icon.png deleted file mode 100644 index 3a5a53db..00000000 Binary files a/base/src/main/res/mipmap-hdpi/launcher_icon.png and /dev/null differ diff --git a/base/src/main/res/mipmap-ldpi/launcher_icon.png b/base/src/main/res/mipmap-ldpi/launcher_icon.png deleted file mode 100644 index abfae9b2..00000000 Binary files a/base/src/main/res/mipmap-ldpi/launcher_icon.png and /dev/null differ diff --git a/base/src/main/res/mipmap-mdpi/ic_launcher_background.png b/base/src/main/res/mipmap-mdpi/ic_launcher_background.png new file mode 100644 index 00000000..1b5b3bfc Binary files /dev/null and b/base/src/main/res/mipmap-mdpi/ic_launcher_background.png differ diff --git a/base/src/main/res/mipmap-mdpi/ic_launcher_round.png b/base/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000..0a63784f Binary files /dev/null and b/base/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/base/src/main/res/mipmap-mdpi/launcher_icon.png b/base/src/main/res/mipmap-mdpi/launcher_icon.png deleted file mode 100644 index 4e424eea..00000000 Binary files a/base/src/main/res/mipmap-mdpi/launcher_icon.png and /dev/null differ diff --git a/base/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/base/src/main/res/mipmap-xhdpi/ic_launcher_background.png new file mode 100644 index 00000000..15da5b49 Binary files /dev/null and b/base/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ diff --git a/base/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/base/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000..05ba081f Binary files /dev/null and b/base/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/base/src/main/res/mipmap-xhdpi/launcher_icon.png b/base/src/main/res/mipmap-xhdpi/launcher_icon.png deleted file mode 100644 index 83f027c8..00000000 Binary files a/base/src/main/res/mipmap-xhdpi/launcher_icon.png and /dev/null differ diff --git a/base/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/base/src/main/res/mipmap-xxhdpi/ic_launcher_background.png new file mode 100644 index 00000000..46364ed2 Binary files /dev/null and b/base/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ diff --git a/base/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/base/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..74f0c6d6 Binary files /dev/null and b/base/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/base/src/main/res/mipmap-xxhdpi/launcher_icon.png b/base/src/main/res/mipmap-xxhdpi/launcher_icon.png deleted file mode 100644 index 8ab7c553..00000000 Binary files a/base/src/main/res/mipmap-xxhdpi/launcher_icon.png and /dev/null differ diff --git a/base/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/base/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png new file mode 100644 index 00000000..4421b6d3 Binary files /dev/null and b/base/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ diff --git a/base/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/base/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..fe4d0435 Binary files /dev/null and b/base/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/base/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/base/src/main/res/mipmap-xxxhdpi/launcher_icon.png deleted file mode 100644 index d56241cc..00000000 Binary files a/base/src/main/res/mipmap-xxxhdpi/launcher_icon.png and /dev/null differ diff --git a/base/src/main/res/values/colors.xml b/base/src/main/res/values/colors.xml index fe4b9103..a32009ce 100644 --- a/base/src/main/res/values/colors.xml +++ b/base/src/main/res/values/colors.xml @@ -4,9 +4,10 @@ #37474F - #5D3E6E - #43374E - #F4A4A8 + #CB1458 + #13162B + #A5154B + #F09DBC #000 diff --git a/base/src/main/res/values/strings.xml b/base/src/main/res/values/strings.xml index 0b4190f5..96a2ffc2 100644 --- a/base/src/main/res/values/strings.xml +++ b/base/src/main/res/values/strings.xml @@ -32,9 +32,6 @@ Done - - Couldn\'t get configuration… - Loading announcements… Couldn\'t get announcements. @@ -44,7 +41,7 @@ Logging in… - Loading map info… + Name @@ -52,7 +49,7 @@ QR Code NO THANKS No school was selected! - Loading your ticket… + Couldn\'t fetch ticket. Username or password is incorrect. My ticket. @@ -76,4 +73,22 @@ Tap to capture. Pinch/Stretch to zoom Not a valid e-mail address. Checked in! + + + + Have Fun! + We want you to have fun, meet others, and enjoy the event. We have tons of great events throughout the weekend, check them out in the schedule! + + Trouble with your project? + Got a bug you can\'t solve? Hit a dead end with your project? Need inspiration? Need ideas? Request one of our mentors to come help you be successful with your project! Find them on the Dashboard of the MHacks website! + + Need help? + Have a problem during the event? Large or small, come talk to an organizer and we\'ll get you helped out (we\'re wearing black MHacks shirts!) + + Meet the sponsors! + We\'ve got a ton of great sponsors here to meet you and help you this weekend. Talk to them! + + + + diff --git a/build.gradle b/build.gradle index 1658bbfb..b613ba15 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0' + classpath 'com.android.tools.build:gradle:3.3.0-alpha13' classpath 'com.google.gms:google-services:3.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 10f8ec7d..cc85cb69 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Sep 30 21:55:03 PDT 2018 +#Thu Oct 04 11:52:31 EDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip diff --git a/instant/build.gradle b/instant/build.gradle index 567b2384..c71191c4 100644 --- a/instant/build.gradle +++ b/instant/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.instantapp' android { compileSdkVersion 28 - buildToolsVersion "28.0.2" + buildToolsVersion '28.0.3' } diff --git a/ui/build.gradle b/ui/build.gradle index b81f17db..b5a32637 100644 --- a/ui/build.gradle +++ b/ui/build.gradle @@ -19,7 +19,6 @@ android { versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } buildTypes { @@ -39,15 +38,8 @@ dependencies { testImplementation 'junit:junit:4.12' -// kapt 'androidx.databinding:databinding-compiler:3.2.0' - - implementation "com.google.dagger:dagger:$rootProject.dagger_version" - implementation "com.google.dagger:dagger-android-support:$rootProject.dagger_version" - kapt "com.google.dagger:dagger-compiler:$rootProject.dagger_version" - kapt "com.google.dagger:dagger-android-processor:$rootProject.dagger_version" - - implementation 'com.google.android.gms:play-services-maps:15.0.1' - implementation 'com.google.android.gms:play-services-vision:15.0.2' + implementation 'com.google.android.gms:play-services-maps:16.0.0' + implementation 'com.google.android.gms:play-services-vision:16.2.0' // Support libraries implementation 'androidx.appcompat:appcompat:1.0.0' @@ -61,7 +53,6 @@ dependencies { implementation 'com.github.kenglxn.QRGen:android:2.2.0' implementation 'com.github.vipulasri:timelineview:1.0.5' implementation 'me.dm7.barcodescanner:zxing:1.9.8' - implementation 'com.github.stanwood:BottomNavigationViewEx:41e335d' implementation 'com.github.florent37:arclayout:1.0.3' // Navigation @@ -75,8 +66,8 @@ dependencies { implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' // Persistence - implementation 'androidx.room:room-runtime:2.0.0-rc01' - implementation 'androidx.room:room-rxjava2:2.0.0-rc01' + implementation 'androidx.room:room-runtime:2.0.0' + implementation 'androidx.room:room-rxjava2:2.0.0' // RxJava implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' diff --git a/ui/src/main/java/com/mhacks/app/MHacksApplication.kt b/ui/src/main/java/com/mhacks/app/MHacksApplication.kt index 90abe8f0..87083dbf 100644 --- a/ui/src/main/java/com/mhacks/app/MHacksApplication.kt +++ b/ui/src/main/java/com/mhacks/app/MHacksApplication.kt @@ -4,23 +4,43 @@ import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context +import android.content.SharedPreferences import android.graphics.Color import android.os.Build +import android.preference.PreferenceManager import com.facebook.stetho.Stetho import com.jakewharton.threetenabp.AndroidThreeTen -import com.mhacks.app.data.Constants +import com.mhacks.app.data.network.fcm.RegistrationIntentService +import com.mhacks.app.data.network.services.FireBaseService import com.mhacks.app.di.component.* import com.mhacks.app.di.module.AuthModule import com.mhacks.app.di.module.RetrofitModule import com.mhacks.app.di.module.RoomModule import dagger.android.AndroidInjector import dagger.android.support.DaggerApplication +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers +import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.converter.moshi.MoshiConverterFactory import timber.log.Timber class MHacksApplication : DaggerApplication() { private lateinit var appComponent: AppComponent + private val retrofit = Retrofit.Builder() + .baseUrl(BuildConfig.API_URL) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addConverterFactory(MoshiConverterFactory.create()) + .build() + + private val mhacksService = retrofit.create(FireBaseService::class.java) + + private val sharedPreferences: SharedPreferences by lazy { + PreferenceManager.getDefaultSharedPreferences(this) + } + override fun onCreate() { super.onCreate() AndroidThreeTen.init(this) @@ -42,21 +62,27 @@ class MHacksApplication : DaggerApplication() { notificationManager.createNotificationChannel(notificationChannel) } + + val pushToken = sharedPreferences.getString(RegistrationIntentService.PUSH_TOKEN, "") + if (pushToken.length > 0) { + val authToken = sharedPreferences.getString(RegistrationIntentService.AUTH_TOKEN, "") + mhacksService.postFireBaseToken(pushToken, "Bearer ${authToken}") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { sharedPreferences.edit().putBoolean(RegistrationIntentService.SENT_TOKEN_TO_SERVER, true).apply() }, + { Timber.e(it) } + ) + } } override fun applicationInjector(): AndroidInjector { - val url = if (BuildConfig.DEBUG) { - Constants.STAGING_URL - } else { - Constants.RELEASE_URL - } - appComponent = DaggerAppComponent.builder() .application(this) .roomModule(RoomModule()) .authModule(AuthModule(null)) - .retrofitModule(RetrofitModule(url)) + .retrofitModule(RetrofitModule(BuildConfig.API_URL)) .build() appComponent.inject(this) return appComponent diff --git a/ui/src/main/java/com/mhacks/app/data/repository/AnnouncementRepository.kt b/ui/src/main/java/com/mhacks/app/data/repository/AnnouncementRepository.kt index bbdbd3ec..daecc5a7 100644 --- a/ui/src/main/java/com/mhacks/app/data/repository/AnnouncementRepository.kt +++ b/ui/src/main/java/com/mhacks/app/data/repository/AnnouncementRepository.kt @@ -4,11 +4,7 @@ import com.mhacks.app.data.models.Announcement import com.mhacks.app.data.models.CreateAnnouncement import com.mhacks.app.data.room.dao.AnnouncementDao import com.mhacks.app.data.service.AnnouncementService -import io.reactivex.Observable import io.reactivex.Single -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers -import java.util.concurrent.TimeUnit import javax.inject.Inject class AnnouncementRepository @Inject constructor( diff --git a/ui/src/main/java/com/mhacks/app/data/repository/UserRepository.kt b/ui/src/main/java/com/mhacks/app/data/repository/UserRepository.kt index c0cbfef7..19b9fa6a 100644 --- a/ui/src/main/java/com/mhacks/app/data/repository/UserRepository.kt +++ b/ui/src/main/java/com/mhacks/app/data/repository/UserRepository.kt @@ -1,7 +1,11 @@ package com.mhacks.app.data.repository +import android.content.Context +import android.content.SharedPreferences +import android.preference.PreferenceManager import com.mhacks.app.data.models.Login import com.mhacks.app.data.models.User +import com.mhacks.app.data.network.fcm.RegistrationIntentService import com.mhacks.app.data.room.dao.LoginDao import com.mhacks.app.data.room.dao.UserDao import com.mhacks.app.data.service.UserService @@ -11,7 +15,12 @@ import javax.inject.Inject class UserRepository @Inject constructor( private val userService: UserService, private val loginDao: LoginDao, - private val userDao: UserDao) { + private val userDao: UserDao, + private val appContext: Context) { + + private val sharedPreferences: SharedPreferences by lazy { + PreferenceManager.getDefaultSharedPreferences(appContext) + } fun getLoginCache() = loginDao.getLogin() @@ -34,6 +43,10 @@ class UserRepository @Inject constructor( fun updateLoginCache(login: Login) = Single.fromCallable { loginDao.insertLogin(login) + sharedPreferences + .edit() + .putString(RegistrationIntentService.AUTH_TOKEN, login.token) + .apply() return@fromCallable login }!! diff --git a/ui/src/main/java/com/mhacks/app/di/module/AuthModule.kt b/ui/src/main/java/com/mhacks/app/di/module/AuthModule.kt index f1aa9c2d..737a7496 100644 --- a/ui/src/main/java/com/mhacks/app/di/module/AuthModule.kt +++ b/ui/src/main/java/com/mhacks/app/di/module/AuthModule.kt @@ -13,7 +13,7 @@ import javax.inject.Singleton */ @Module -class AuthModule(internal var token: String?) { +class AuthModule(private var token: String?) { @Provides @Singleton diff --git a/ui/src/main/java/com/mhacks/app/di/module/RetrofitModule.kt b/ui/src/main/java/com/mhacks/app/di/module/RetrofitModule.kt index 3e32ac88..0396c6bd 100644 --- a/ui/src/main/java/com/mhacks/app/di/module/RetrofitModule.kt +++ b/ui/src/main/java/com/mhacks/app/di/module/RetrofitModule.kt @@ -3,7 +3,7 @@ package com.mhacks.app.di.module import android.app.Application import com.facebook.stetho.okhttp3.StethoInterceptor import com.mhacks.app.BuildConfig -import com.mhacks.app.data.network.services.MHacksService +import com.mhacks.app.data.network.services.FireBaseService import dagger.Module import dagger.Provides import okhttp3.Cache @@ -59,7 +59,7 @@ import javax.inject.Singleton @Provides @Singleton - internal fun provideMHacksService(retrofit: Retrofit): MHacksService { - return retrofit.create(MHacksService::class.java) + internal fun provideMHacksService(retrofit: Retrofit): FireBaseService { + return retrofit.create(FireBaseService::class.java) } } \ No newline at end of file diff --git a/ui/src/main/java/com/mhacks/app/ui/announcement/view/AnnouncementView.kt b/ui/src/main/java/com/mhacks/app/ui/announcement/view/AnnouncementView.kt deleted file mode 100644 index 91874726..00000000 --- a/ui/src/main/java/com/mhacks/app/ui/announcement/view/AnnouncementView.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.mhacks.app.ui.announcement.view - -import com.mhacks.app.data.models.Announcement - -/** - * Created by jeffreychang on 2/16/18. - */ - -interface AnnouncementView { - - fun onGetAnnouncementsSuccess(announcements: List) - - fun onGetAnnouncementsFailure(error: Throwable) -} diff --git a/ui/src/main/java/com/mhacks/app/ui/common/BasePresenterImpl.kt b/ui/src/main/java/com/mhacks/app/ui/common/BasePresenterImpl.kt deleted file mode 100644 index 3af64ac8..00000000 --- a/ui/src/main/java/com/mhacks/app/ui/common/BasePresenterImpl.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.mhacks.app.ui.common - -import io.reactivex.disposables.CompositeDisposable - -/** - * Created by jeffreychang on 2/17/18. - */ - -abstract class BasePresenterImpl: BasePresenter { - - var compositeDisposable: CompositeDisposable? = null - - override fun onAttach() { - compositeDisposable = CompositeDisposable() - } - - override fun onDetach() { - compositeDisposable?.dispose() - } -} \ No newline at end of file diff --git a/ui/src/main/java/com/mhacks/app/ui/common/ProgressBarAnimation.kt b/ui/src/main/java/com/mhacks/app/ui/common/ProgressBarAnimation.kt deleted file mode 100644 index c45e5c19..00000000 --- a/ui/src/main/java/com/mhacks/app/ui/common/ProgressBarAnimation.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.mhacks.app.ui.common - -import android.view.animation.Animation -import android.view.animation.Transformation -import android.widget.ProgressBar -import androidx.interpolator.view.animation.FastOutSlowInInterpolator - -/** - * @param fullDuration - time required to fill progress from 0% to 100% - */ -class ProgressBarAnimation( - private val progressBar: ProgressBar, - fullDuration: Long) : Animation() { - private var to: Int = 0 - private var from: Int = 0 - private val stepDuration: Long = fullDuration / progressBar.max - - init { - interpolator = FastOutSlowInInterpolator() - } - - fun setProgress(_progress: Int) { - var progress = _progress - if (progress < 0) { - progress = 0 - } - - if (progress > progressBar.max) { - progress = progressBar.max - } - - to = progress - - from = progressBar.progress - duration = Math.abs(to - from) * stepDuration - progressBar.startAnimation(this) - } - - override fun applyTransformation(interpolatedTime: Float, t: Transformation) { - val value = from + (to - from) * interpolatedTime - progressBar.progress = value.toInt() - } -} \ No newline at end of file diff --git a/ui/src/main/java/com/mhacks/app/ui/common/ProgressWheel.kt b/ui/src/main/java/com/mhacks/app/ui/common/ProgressWheel.kt index bdd35d3c..d70bd4c3 100644 --- a/ui/src/main/java/com/mhacks/app/ui/common/ProgressWheel.kt +++ b/ui/src/main/java/com/mhacks/app/ui/common/ProgressWheel.kt @@ -200,11 +200,6 @@ class ProgressWheel : View { invalidate() } - fun setDefText(defText: String) { - this.defText = defText - invalidate() - } - fun setPercentage(per: Int) { startAnimation(per) } diff --git a/ui/src/main/java/com/mhacks/app/ui/createannouncement/CreateAnnouncementDialogFragment.kt b/ui/src/main/java/com/mhacks/app/ui/createannouncement/CreateAnnouncementDialogFragment.kt index c642cf23..1e43b1f7 100644 --- a/ui/src/main/java/com/mhacks/app/ui/createannouncement/CreateAnnouncementDialogFragment.kt +++ b/ui/src/main/java/com/mhacks/app/ui/createannouncement/CreateAnnouncementDialogFragment.kt @@ -15,7 +15,6 @@ import com.mhacks.app.ui.common.BaseDialogFragment import kotlinx.android.synthetic.main.fragment_create_announcements.* import org.mhacks.mhacksui.R import org.mhacks.mhacksui.databinding.FragmentCreateAnnouncementsBinding -import timber.log.Timber import javax.inject.Inject /** diff --git a/ui/src/main/java/com/mhacks/app/ui/events/usecase/FavoriteEventUseCase.kt b/ui/src/main/java/com/mhacks/app/ui/events/usecase/FavoriteEventUseCase.kt index 77a0a8f6..a5ebd3f0 100644 --- a/ui/src/main/java/com/mhacks/app/ui/events/usecase/FavoriteEventUseCase.kt +++ b/ui/src/main/java/com/mhacks/app/ui/events/usecase/FavoriteEventUseCase.kt @@ -4,7 +4,6 @@ import com.mhacks.app.data.models.Event import com.mhacks.app.data.repository.EventsRepository import com.mhacks.app.mvvm.SingleUseCase import io.reactivex.Single -import java.util.concurrent.TimeUnit import javax.inject.Inject class FavoriteEventUseCase @Inject constructor( diff --git a/ui/src/main/java/com/mhacks/app/ui/info/InfoFragment.kt b/ui/src/main/java/com/mhacks/app/ui/info/InfoFragment.kt index 7ea7395a..12a5b94c 100644 --- a/ui/src/main/java/com/mhacks/app/ui/info/InfoFragment.kt +++ b/ui/src/main/java/com/mhacks/app/ui/info/InfoFragment.kt @@ -8,7 +8,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast -import com.mhacks.app.data.Constants import com.mhacks.app.ui.common.NavigationFragment import com.mhacks.app.ui.common.SpacingItemDecoration import com.mhacks.app.ui.info.model.Info @@ -19,7 +18,11 @@ import timber.log.Timber import javax.inject.Inject import android.content.Intent.ACTION_VIEW import android.net.Uri +import android.net.wifi.WifiConfiguration import androidx.recyclerview.widget.LinearLayoutManager +import com.mhacks.app.BuildConfig +import com.mhacks.app.BuildConfig.WIFI_PASSWORD +import com.mhacks.app.BuildConfig.WIFI_SSID class InfoFragment: NavigationFragment() { @@ -61,9 +64,7 @@ class InfoFragment: NavigationFragment() { context?.let { when (info.type) { Info.TYPE.WIFI -> { - val isWifiInstall = wiFiInstaller.installConferenceWifi( - Constants.WIFI_CONFIGUATION - ) + val isWifiInstall = wiFiInstaller.installConferenceWifi(WIFI_CONFIGURATION) val wifiMessage = if (isWifiInstall) { R.string.wifi_install_success } else { @@ -78,7 +79,7 @@ class InfoFragment: NavigationFragment() { it.getString(R.string.info_address) .replace(" ", "+" ) - val googleMapsUrl = Constants.GOOGLE_MAPS_URL + formattedAddress + val googleMapsUrl = GOOGLE_MAPS_URL + formattedAddress Timber.d("Opening $formattedAddress in Google Maps") @@ -97,7 +98,9 @@ class InfoFragment: NavigationFragment() { } } Info.TYPE.SLACK -> { - val i = Intent(ACTION_VIEW, Uri.parse(Constants.SLACK_INVITE_URL)) + val i = Intent(ACTION_VIEW, Uri.parse( + BuildConfig.SLACK_INVITE_URL) + ) i.action = ACTION_VIEW startActivity(i) } @@ -106,7 +109,7 @@ class InfoFragment: NavigationFragment() { Intent.ACTION_SENDTO, Uri.fromParts( "mailto", - Constants.MHACKS_EMAIL, + BuildConfig.MHACKS_EMAIL, null)) i.putExtra(Intent.EXTRA_TEXT, "Sent from Android app.") startActivity(Intent.createChooser(i, "Send Email")) @@ -114,4 +117,20 @@ class InfoFragment: NavigationFragment() { } } } + + companion object { + + const val GOOGLE_MAPS_URL = "http://maps.google.co.in/maps?q=" + + val WIFI_CONFIGURATION: WifiConfiguration + get() { + val wifiConfig = WifiConfiguration() + + wifiConfig.SSID = String.format("\"%s\"", WIFI_SSID) + wifiConfig.preSharedKey = String.format("\"%s\"", WIFI_PASSWORD) + + return wifiConfig + } + + } } \ No newline at end of file diff --git a/ui/src/main/java/com/mhacks/app/ui/info/widget/CollapsibleCard.kt b/ui/src/main/java/com/mhacks/app/ui/info/widget/CollapsibleCard.kt index ff572393..378b741c 100644 --- a/ui/src/main/java/com/mhacks/app/ui/info/widget/CollapsibleCard.kt +++ b/ui/src/main/java/com/mhacks/app/ui/info/widget/CollapsibleCard.kt @@ -35,7 +35,7 @@ class CollapsibleCard @JvmOverloads constructor( init { val arr = context.obtainStyledAttributes(attrs, R.styleable.CollapsibleCard, 0, 0) - cardTitle = arr.getString(R.styleable.CollapsibleCard_cardTitle) + cardTitle = arr.getString(R.styleable.CollapsibleCard_cardTitle)!! val cardDescription = arr.getString(R.styleable.CollapsibleCard_cardDescription) arr.recycle() root = LayoutInflater.from(context) diff --git a/ui/src/main/java/com/mhacks/app/ui/main/MainActivity.kt b/ui/src/main/java/com/mhacks/app/ui/main/MainActivity.kt index 9fb9e7f8..c805cb8e 100644 --- a/ui/src/main/java/com/mhacks/app/ui/main/MainActivity.kt +++ b/ui/src/main/java/com/mhacks/app/ui/main/MainActivity.kt @@ -7,12 +7,11 @@ import android.view.MenuItem import android.view.View import androidx.appcompat.app.AlertDialog import androidx.databinding.DataBindingUtil -import androidx.fragment.app.DialogFragment import androidx.lifecycle.Observer import androidx.navigation.Navigation import androidx.navigation.ui.NavigationUI -import com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx -import com.mhacks.app.data.Constants +import com.google.android.material.bottomnavigation.BottomNavigationView +import com.mhacks.app.BuildConfig import com.mhacks.app.ui.createannouncement.CreateAnnouncementDialogFragment import com.mhacks.app.ui.common.BaseActivity import com.mhacks.app.ui.common.NavigationColor @@ -57,7 +56,7 @@ class MainActivity : BaseActivity(), val appLinkIntent = intent val appLinkData = appLinkIntent?.data - if (appLinkData?.path == Constants.INSTANT_APP_PATH) { + if (appLinkData?.path == BuildConfig.INSTANT_APP_URL) { initActivity() return } @@ -129,6 +128,7 @@ class MainActivity : BaseActivity(), }) } + // No Android X dependency yet. override fun onSupportNavigateUp(): Boolean { return NavigationUI.navigateUp(null, Navigation.findNavController(this, R.id.main_activity_fragment_host)) @@ -145,17 +145,11 @@ class MainActivity : BaseActivity(), private fun showCreateAnnouncementDialogFragment() { val fragment = CreateAnnouncementDialogFragment.instance - fragment.setStyle(DialogFragment.STYLE_NORMAL, R.style.Theme_AppCompat_Light_Dialog) fragment.show(supportFragmentManager, null) } // Handles the click events for bottom navigation menu - private fun setupBottomNavBar(bottomNavigationView: BottomNavigationViewEx) { - - bottomNavigationView.enableAnimation(false) - bottomNavigationView.enableShiftingMode(false) - bottomNavigationView.enableItemShiftingMode(false) - + private fun setupBottomNavBar(bottomNavigationView: BottomNavigationView) { bottomNavigationView.setOnNavigationItemSelectedListener { item -> bottomNavigationView.isEnabled = false if (itemId != item.itemId) { @@ -184,10 +178,10 @@ class MainActivity : BaseActivity(), fun navigateFragment(fragmentId: Int) { + itemId = fragmentId navController.navigate(fragmentId) } - private fun showAdminOptions() { AlertDialog.Builder(this) .setTitle(getString(R.string.admin)) diff --git a/ui/src/main/java/com/mhacks/app/ui/map/widget/MapViewFragment.kt b/ui/src/main/java/com/mhacks/app/ui/map/widget/MapViewFragment.kt index 4d3f6fbd..1a86f3b3 100644 --- a/ui/src/main/java/com/mhacks/app/ui/map/widget/MapViewFragment.kt +++ b/ui/src/main/java/com/mhacks/app/ui/map/widget/MapViewFragment.kt @@ -7,7 +7,6 @@ import androidx.core.content.ContextCompat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.core.app.ActivityCompat.requestPermissions import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import com.google.android.gms.maps.CameraUpdateFactory @@ -16,6 +15,7 @@ import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.* import com.google.android.material.snackbar.Snackbar +import com.mhacks.app.BuildConfig import com.mhacks.app.data.models.common.RetrofitException import com.mhacks.app.extension.showSnackBar import com.mhacks.app.extension.viewModelProvider @@ -130,8 +130,13 @@ class MapViewFragment : val center = CameraUpdateFactory.newCameraPosition( CameraPosition.Builder() - .target(LatLng(42.292150, -83.715836)) - .zoom(16.5f) + .target( + LatLng( + BuildConfig.LAT, + BuildConfig.LNG + ) + ) + .zoom(17.5f) .bearing(0f) .tilt(0f) .build() @@ -150,6 +155,18 @@ class MapViewFragment : } else { } googleMap.animateCamera(center) + googleMap.setLatLngBoundsForCameraTarget( + LatLngBounds( + LatLng( + BuildConfig.LAT - LAT_LNG_BOUNDARY, + BuildConfig.LNG - LAT_LNG_BOUNDARY + ), + LatLng( + BuildConfig.LAT + LAT_LNG_BOUNDARY, + BuildConfig.LNG + LAT_LNG_BOUNDARY + ) + ) + ) } override fun onRequestPermissionsResult(requestCode: Int, @@ -176,7 +193,7 @@ class MapViewFragment : private fun setupMap(mapResult: MapViewModel.MapResult) { val (floorImage, mapFloor) = mapResult - val northCampusBounds = LatLngBounds( + val sportsBuildingBounds = LatLngBounds( LatLng( mapFloor.seLatitude.toDouble(), mapFloor.nwLongitude.toDouble()), // South West corner @@ -184,14 +201,17 @@ class MapViewFragment : mapFloor.nwLatitude.toDouble(), mapFloor.seLongitude.toDouble()) // North East Corner ) - val northCampusMap = GroundOverlayOptions() + val sportsBuildingMap = GroundOverlayOptions() .image(BitmapDescriptorFactory.fromBitmap(floorImage)) - .positionFromBounds(northCampusBounds) - googleMap?.addGroundOverlay(northCampusMap) + .positionFromBounds(sportsBuildingBounds) + googleMap?.addGroundOverlay(sportsBuildingMap) } companion object { val instance: MapViewFragment get() = MapViewFragment() + + // Constant of the boundaries to where the user can pan their map camera. + private const val LAT_LNG_BOUNDARY = 0.0025 } } diff --git a/ui/src/main/java/com/mhacks/app/ui/qrscan/QRScanActivity.kt b/ui/src/main/java/com/mhacks/app/ui/qrscan/QRScanActivity.kt index c44d5b36..5a7651bb 100644 --- a/ui/src/main/java/com/mhacks/app/ui/qrscan/QRScanActivity.kt +++ b/ui/src/main/java/com/mhacks/app/ui/qrscan/QRScanActivity.kt @@ -22,6 +22,7 @@ import android.view.ScaleGestureDetector import android.view.View import androidx.annotation.NonNull import androidx.appcompat.app.AlertDialog +import androidx.appcompat.widget.AlertDialogLayout import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import com.google.android.gms.common.ConnectionResult @@ -30,6 +31,8 @@ import com.google.android.gms.vision.MultiProcessor import com.google.android.gms.vision.barcode.Barcode import com.google.android.gms.vision.barcode.BarcodeDetector import com.google.android.material.snackbar.Snackbar +import com.mhacks.app.adapter.setTextMessage +import com.mhacks.app.data.models.common.TextMessage import com.mhacks.app.extension.viewModelProvider import com.mhacks.app.ui.common.BaseActivity import com.mhacks.app.ui.qrscan.widget.BarcodeGraphic @@ -107,7 +110,16 @@ class QRScanActivity: private fun subscribeUi() { qrScanViewModel?.verifyTicket?.observe(this, Observer { - showToast(R.string.checked_in) + var response = "" + for (feedback in it ) { + response += feedback.label + ": " + feedback.value + "\n" + } + + AlertDialog.Builder(this) + .setTitle("QR Response") + .setMessage(response) + .setPositiveButton("Ok") { dialog, which -> Timber.i(response) } + .show() }) qrScanViewModel?.snackBarMessage?.observe(this, Observer { @@ -142,6 +154,7 @@ class QRScanActivity: } findViewById(R.id.topLayout).setOnClickListener(listener) + Snackbar.make(graphicOverlay!!, R.string.permission_camera_rationale, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.ok, listener) diff --git a/ui/src/main/java/com/mhacks/app/ui/qrscan/usecase/VerifyTicketUseCase.kt b/ui/src/main/java/com/mhacks/app/ui/qrscan/usecase/VerifyTicketUseCase.kt index a9a47c5e..0b5d3873 100644 --- a/ui/src/main/java/com/mhacks/app/ui/qrscan/usecase/VerifyTicketUseCase.kt +++ b/ui/src/main/java/com/mhacks/app/ui/qrscan/usecase/VerifyTicketUseCase.kt @@ -1,7 +1,6 @@ package com.mhacks.app.ui.qrscan.usecase import com.mhacks.app.data.models.Feedback -import com.mhacks.app.data.models.common.RetrofitException import com.mhacks.app.data.repository.UserRepository import com.mhacks.app.di.module.AuthModule import com.mhacks.app.mvvm.SingleUseCase diff --git a/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/CameraSource.kt b/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/CameraSource.kt index 088f1e4e..8f1f32a0 100644 --- a/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/CameraSource.kt +++ b/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/CameraSource.kt @@ -861,7 +861,7 @@ private constructor() { // should guarantee that there will be an array to work with. val byteArray = ByteArray(bufferSize) val buffer = ByteBuffer.wrap(byteArray) - if (!buffer.hasArray() || !buffer.array().contentEquals(byteArray)) { + if (!buffer.hasArray() || !buffer.array()!!.contentEquals(byteArray)) { // I don't think that this will ever happen. But if it does, then we wouldn't be // passing the preview content to the underlying detector later. throw IllegalStateException("Failed to create valid buffer for camera source.") diff --git a/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/GraphicOverlay.kt b/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/GraphicOverlay.kt index 1875637f..c15c4978 100644 --- a/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/GraphicOverlay.kt +++ b/ui/src/main/java/com/mhacks/app/ui/qrscan/widget/camera/GraphicOverlay.kt @@ -80,7 +80,7 @@ class GraphicOverlay(context: Context, attrs: Attrib */ fun translateX(x: Float): Float { return if (mOverlay.mFacing == CameraSource.CAMERA_FACING_FRONT) { - mOverlay.getWidth() - scaleX(x) + mOverlay.width - scaleX(x) } else { scaleX(x) } diff --git a/ui/src/main/java/com/mhacks/app/ui/signin/SignInFragmentModule.kt b/ui/src/main/java/com/mhacks/app/ui/signin/SignInFragmentModule.kt index 60a931f0..56fb2c94 100644 --- a/ui/src/main/java/com/mhacks/app/ui/signin/SignInFragmentModule.kt +++ b/ui/src/main/java/com/mhacks/app/ui/signin/SignInFragmentModule.kt @@ -2,7 +2,6 @@ package com.mhacks.app.ui.signin import androidx.lifecycle.ViewModel import com.mhacks.app.di.ViewModelKey -import com.mhacks.app.ui.signin.SignInViewModel import dagger.Binds import dagger.Module import dagger.multibindings.IntoMap diff --git a/ui/src/main/java/com/mhacks/app/ui/signin/usecase/PostLoginUseCase.kt b/ui/src/main/java/com/mhacks/app/ui/signin/usecase/PostLoginUseCase.kt index 49b7d6ae..9ce37836 100644 --- a/ui/src/main/java/com/mhacks/app/ui/signin/usecase/PostLoginUseCase.kt +++ b/ui/src/main/java/com/mhacks/app/ui/signin/usecase/PostLoginUseCase.kt @@ -21,7 +21,7 @@ class PostLoginUseCase @Inject constructor( userRepository.updateLoginCache(it) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ + .subscribe({ _ -> Timber.d("Login Success") }, { Timber.d("Login Failure") diff --git a/ui/src/main/java/com/mhacks/app/ui/signin/usecase/SkipLoginUseCase.kt b/ui/src/main/java/com/mhacks/app/ui/signin/usecase/SkipLoginUseCase.kt index 876dda19..b6e5f6b8 100644 --- a/ui/src/main/java/com/mhacks/app/ui/signin/usecase/SkipLoginUseCase.kt +++ b/ui/src/main/java/com/mhacks/app/ui/signin/usecase/SkipLoginUseCase.kt @@ -23,7 +23,7 @@ class SkipLoginUseCase @Inject constructor( .updateLoginCache(it) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ + .subscribe({ _ -> Timber.d("Login Success") }, { Timber.d("Login Failure") diff --git a/ui/src/main/java/com/mhacks/app/ui/ticket/TicketDialogFragment.kt b/ui/src/main/java/com/mhacks/app/ui/ticket/TicketDialogFragment.kt index a0f4bc02..6946c443 100644 --- a/ui/src/main/java/com/mhacks/app/ui/ticket/TicketDialogFragment.kt +++ b/ui/src/main/java/com/mhacks/app/ui/ticket/TicketDialogFragment.kt @@ -8,8 +8,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.Observer +import com.google.android.material.snackbar.Snackbar import org.mhacks.mhacksui.R import com.mhacks.app.data.models.common.RetrofitException +import com.mhacks.app.extension.showSnackBar import com.mhacks.app.ui.common.BaseDialogFragment import kotlinx.android.synthetic.main.fragment_ticket_dialog.* import net.glxn.qrgen.android.QRCode @@ -93,31 +95,14 @@ class TicketDialogFragment : BaseDialogFragment() { } } }) + ticketViewModel.snackBarMessage.observe(this, Observer { textMessage -> + rootView?.showSnackBar( + Snackbar.LENGTH_SHORT, textMessage) + }) } -// private fun showProgressBar() { -// ticket_progressbar.visibility = View.VISIBLE -// ticket_main.visibility = View.INVISIBLE -// ticket_error_view.visibility = View.INVISIBLE -// } -// -// private fun showMainContent() { -// ticket_progressbar.visibility = View.INVISIBLE -// ticket_main.visibility = View.VISIBLE -// ticket_error_view.visibility = View.INVISIBLE -// } -// -// private fun showErrorView() { -// ticket_error_view.removeBackground() -// ticket_error_view.titleText = R.string.ticket_network_error -// ticket_error_view.iconDrawable = R.drawable.ic_cloud_off_black_24dp -// ticket_error_view.textColor = R.color.colorPrimaryDark -// ticket_progressbar.visibility = View.INVISIBLE -// ticket_main.visibility = View.INVISIBLE -// ticket_error_view.visibility = View.VISIBLE -// } - interface Callback { + fun startLoginActivity() } diff --git a/ui/src/main/java/com/mhacks/app/ui/welcome/WelcomeViewModel.kt b/ui/src/main/java/com/mhacks/app/ui/welcome/WelcomeViewModel.kt index 873b0d73..d8f54d06 100644 --- a/ui/src/main/java/com/mhacks/app/ui/welcome/WelcomeViewModel.kt +++ b/ui/src/main/java/com/mhacks/app/ui/welcome/WelcomeViewModel.kt @@ -4,21 +4,19 @@ import android.os.CountDownTimer import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.ViewModel -import com.mhacks.app.data.Constants +import com.mhacks.app.BuildConfig import com.mhacks.app.data.models.Configuration import com.mhacks.app.data.models.Result import com.mhacks.app.data.models.common.RetrofitException import com.mhacks.app.data.models.common.TextMessage import com.mhacks.app.ui.welcome.usecase.GetAndCacheConfigUseCase import org.mhacks.mhacksui.R -import org.threeten.bp.Instant -import org.threeten.bp.LocalDateTime -import org.threeten.bp.ZoneId -import org.threeten.bp.ZoneOffset +import org.threeten.bp.* import timber.log.Timber import java.text.DateFormat import java.text.SimpleDateFormat import java.util.* +import java.util.concurrent.TimeUnit import javax.inject.Inject class WelcomeViewModel @Inject constructor( @@ -56,10 +54,12 @@ class WelcomeViewModel @Inject constructor( _config.addSource(getAndCacheConfigResult) { if (it is Result.Success) { Timber.d("Config Success") - val duration = 129600000L - val startDate = LocalDateTime.parse(Constants.FIXED_START_DATE) - .toEpochSecond(ZoneOffset.UTC) - initCountdownIfNecessary(startDate, duration) + + val startDateTs = 1539403200000L + val endDateTs = 1539532800000L + + initCountdownIfNecessary(startDateTs, endDateTs) + } else if (it is Result.Error<*>) { Timber.d("Config Failure") (it.exception as? RetrofitException)?.let { retrofitException -> @@ -101,20 +101,12 @@ class WelcomeViewModel @Inject constructor( } private fun initCountdownIfNecessary(startDateTs: Long, endDateTs: Long) { - - val startDate = Instant.ofEpochSecond(startDateTs) - .atZone(ZoneId.systemDefault()).toLocalDateTime() - val duration = endDateTs - startDateTs - - val localDateTime = LocalDateTime.now() - - val curTime = localDateTime.toEpochSecond(ZoneOffset.UTC) - val startTime = startDate!!.toEpochSecond(ZoneOffset.UTC) - val endTime = startTime + duration - + val curTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) + val startTime = startDateTs + val endTime = endDateTs when { - curTime < startDate.toEpochSecond(ZoneOffset.UTC) -> + curTime < startTime -> _timerText.value = TextMessage(R.string.countdown_timer_default, null) curTime < endTime -> { // Calculate the time remaining and the total time of hacking diff --git a/ui/src/main/res/drawable/bottom_line_divider.xml b/ui/src/main/res/drawable/bottom_line_divider.xml deleted file mode 100644 index ddea70bf..00000000 --- a/ui/src/main/res/drawable/bottom_line_divider.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/ui/src/main/res/drawable/logo.xml b/ui/src/main/res/drawable/logo.xml new file mode 100644 index 00000000..f2606ba9 --- /dev/null +++ b/ui/src/main/res/drawable/logo.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/ui/src/main/res/drawable/mhacks_wallpaper.xml b/ui/src/main/res/drawable/mhacks_wallpaper.xml index 79c4271f..32a3a128 100644 --- a/ui/src/main/res/drawable/mhacks_wallpaper.xml +++ b/ui/src/main/res/drawable/mhacks_wallpaper.xml @@ -1,57 +1,6 @@ - - - - - - - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/ui/src/main/res/drawable/progressbar_circular_background.xml b/ui/src/main/res/drawable/progressbar_circular_background.xml deleted file mode 100644 index 6cefadf5..00000000 --- a/ui/src/main/res/drawable/progressbar_circular_background.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - \ No newline at end of file diff --git a/ui/src/main/res/drawable/progressbar_circular_progressdraw.xml b/ui/src/main/res/drawable/progressbar_circular_progressdraw.xml deleted file mode 100644 index 8f723dcb..00000000 --- a/ui/src/main/res/drawable/progressbar_circular_progressdraw.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/ui/src/main/res/drawable/splash.xml b/ui/src/main/res/drawable/splash.xml index fe88b201..9dfb897e 100644 --- a/ui/src/main/res/drawable/splash.xml +++ b/ui/src/main/res/drawable/splash.xml @@ -1,10 +1,10 @@ - + + android:src="@drawable/splash_logo" /> - + \ No newline at end of file diff --git a/ui/src/main/res/drawable/splash_background.xml b/ui/src/main/res/drawable/splash_background.xml new file mode 100644 index 00000000..4edb09e3 --- /dev/null +++ b/ui/src/main/res/drawable/splash_background.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/ui/src/main/res/drawable/splash_image.png b/ui/src/main/res/drawable/splash_image.png new file mode 100644 index 00000000..59a38050 Binary files /dev/null and b/ui/src/main/res/drawable/splash_image.png differ diff --git a/ui/src/main/res/layout/activity_main.xml b/ui/src/main/res/layout/activity_main.xml index 52b8196f..656617de 100644 --- a/ui/src/main/res/layout/activity_main.xml +++ b/ui/src/main/res/layout/activity_main.xml @@ -46,7 +46,7 @@ - @@ -47,6 +48,7 @@ android:layout_height="0dp" android:layout_width="match_parent" android:background="@null" + android:textColor="@color/black" android:padding="16dp" android:layout_weight="1" android:hint="@string/body" diff --git a/ui/src/main/res/layout/fragment_info.xml b/ui/src/main/res/layout/fragment_info.xml index 9f385f89..8d9e1a5c 100644 --- a/ui/src/main/res/layout/fragment_info.xml +++ b/ui/src/main/res/layout/fragment_info.xml @@ -11,6 +11,7 @@ android:layout_height="200dp" android:background="?colorPrimaryDark" android:clipToPadding="false" + android:paddingTop="12dp" android:paddingBottom="12dp" android:paddingStart="12dp" android:paddingEnd="12dp"/> @@ -33,26 +34,26 @@ + app:cardDescription="@string/collapsible_card_desc_1" + app:cardTitle="@string/collapsible_card_title_1"/> + app:cardDescription="@string/collapsible_card_desc_2" + app:cardTitle="@string/collapsible_card_title_2" /> + app:cardDescription="@string/collapsible_card_desc_3" + app:cardTitle="@string/collapsible_card_title_3" /> + app:cardDescription="@string/collapsible_card_desc_4" + app:cardTitle="@string/collapsible_card_title_4" /> diff --git a/ui/src/main/res/layout/fragment_ticket_dialog.xml b/ui/src/main/res/layout/fragment_ticket_dialog.xml index 8f86a820..42850dfb 100644 --- a/ui/src/main/res/layout/fragment_ticket_dialog.xml +++ b/ui/src/main/res/layout/fragment_ticket_dialog.xml @@ -16,7 +16,7 @@ android:layout_height="250dp" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" - android:layout_marginTop="32dp" + android:layout_marginTop="24dp" android:contentDescription="@string/qr_code" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -75,18 +75,18 @@ android:id="@+id/ticket_bottom_bar" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@color/colorPrimary" + android:background="?colorPrimary" app:layout_constraintBottom_toBottomOf="parent">