diff --git a/PennMobile/src/main/AndroidManifest.xml b/PennMobile/src/main/AndroidManifest.xml index c510c0cf..d280bc7f 100644 --- a/PennMobile/src/main/AndroidManifest.xml +++ b/PennMobile/src/main/AndroidManifest.xml @@ -27,6 +27,7 @@ android:theme="@style/AppTheme.Launcher" android:usesCleartextTraffic="true" tools:targetApi="m"> + @@ -39,6 +40,19 @@ android:resource="@xml/dining_hall_widget_info" /> + + + + + + + + + + ?>() {}.type, + Serializer.GsrReservationSerializer(), + ) + + val gson = gsonBuilder.create() + val okHttpClient = OkHttpClient() + okHttpClient.setConnectTimeout(35, TimeUnit.SECONDS) // Connection timeout + okHttpClient.setReadTimeout(35, TimeUnit.SECONDS) // Read timeout + okHttpClient.setWriteTimeout(35, TimeUnit.SECONDS) // Write timeout + + val restAdapter = + RestAdapter + .Builder() + .setConverter(GsonConverter(gson)) + .setClient(OkClient(okHttpClient)) + .setEndpoint("https://pennmobile.org/api") + .build() + mGSRReservationsRequest = restAdapter.create(GsrReservationsRequest::class.java) + } + return mGSRReservationsRequest!! + } + } +} diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt index e7b1ca4f..d40712f9 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/MainActivity.kt @@ -130,6 +130,15 @@ class MainActivity : AppCompatActivity() { if (diningWidgetBroadCast != -1) { setTab(DINING_ID) } + + var gsrReservationWidgetBroadCast = 0 + if (intent != null) { + gsrReservationWidgetBroadCast = + intent.getIntExtra("Gsr_Tab_Switch", -1) + } + if (gsrReservationWidgetBroadCast != -1) { + setTab(GSR_ID) + } } private fun onExpandableBottomNavigationItemSelected() { diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/GsrReservationWidgetAdapter.kt b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/GsrReservationWidgetAdapter.kt new file mode 100644 index 00000000..8d2e2039 --- /dev/null +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/adapters/GsrReservationWidgetAdapter.kt @@ -0,0 +1,137 @@ +package com.pennapps.labs.pennmobile.adapters + +import android.appwidget.AppWidgetManager +import android.content.Context +import android.content.Intent +import android.graphics.BitmapFactory +import android.os.Bundle +import android.widget.RemoteViews +import android.widget.RemoteViewsService +import androidx.preference.PreferenceManager +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.pennapps.labs.pennmobile.GsrReservationWidget +import com.pennapps.labs.pennmobile.R +import com.pennapps.labs.pennmobile.api.GsrReservationsRequest +import com.pennapps.labs.pennmobile.classes.GSRReservation +import org.joda.time.format.DateTimeFormat +import org.joda.time.format.DateTimeFormatter +import rx.Observable +import java.net.HttpURLConnection +import java.net.URL + +class GsrReservationWidgetAdapter : RemoteViewsService() { + override fun onGetViewFactory(intent: Intent): RemoteViewsFactory = GsrReservationWidgetFactory(applicationContext, intent) + + class GsrReservationWidgetFactory( + private val context: Context, + intent: Intent, + ) : RemoteViewsFactory { + private var mGsrReservationsRequest: GsrReservationsRequest? = null + private var appWidgetId: Int = + intent.getIntExtra( + AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID, + ) + private var dataSet: List = emptyList() + private var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + + override fun onCreate() { + mGsrReservationsRequest = GsrReservationWidget.gsrReservationsRequestInstance + getWidgetGsrReservations() + } + + // Not used since already handled + override fun onDataSetChanged() { + } + + override fun onDestroy() { + } + + override fun getCount(): Int = dataSet.size + + // TODO("Get building name(?), and hopefully support click behavior") + override fun getViewAt(index: Int): RemoteViews { + val reservation = dataSet[index] + val roomName = reservation.name + + val formatter: DateTimeFormatter = + DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ") + val from = formatter.parseDateTime(reservation.fromDate) + val to = formatter.parseDateTime(reservation.toDate) + val day = from.toString("EEEE, MMMM d") + val fromHour = from.toString("h:mm a") + val toHour = to.toString("h:mm a") + + val imageUrl = + reservation.info?.get("thumbnail") + ?: "https://s3.us-east-2.amazonaws.com/labs.api/dining/MBA+Cafe.jpg" + + val views = RemoteViews(context.packageName, R.layout.gsr_reservation_widget_item) + views.setTextViewText(R.id.gsr_reservation_widget_item_location_tv, roomName) + views.setTextViewText( + R.id.gsr_reservation_widget_item_time_tv, + "$day\n$fromHour-$toHour", + ) + + try { + val urlConnection = URL(imageUrl) + val connection = + urlConnection + .openConnection() as HttpURLConnection + connection.doInput = true + connection.connect() + val input = connection.inputStream + val myBitmap = BitmapFactory.decodeStream(input) + views.setImageViewBitmap(R.id.gsr_reservation_widget_item_iv, myBitmap) + } catch (e: Exception) { + e.printStackTrace() + } + + val extras = Bundle() + val fillInIntent = Intent() + fillInIntent.putExtras(extras) + views.setOnClickFillInIntent(R.id.gsr_reservation_widget_item_root, fillInIntent) + + return views + } + + override fun getLoadingView(): RemoteViews? = null + + override fun getViewTypeCount(): Int = 1 + + override fun getItemId(id: Int): Long = id.toLong() + + override fun hasStableIds(): Boolean = true + + private fun getWidgetGsrReservations() { + try { + if (mGsrReservationsRequest != null) { + val token = + sharedPreferences.getString( + context.getString(R.string.access_token), + "", + ) + mGsrReservationsRequest!! + .getGsrReservations("Bearer $token") + .flatMap { reservations -> Observable.from(reservations) } + .flatMap { reservation -> + Observable.just(reservation) + }.toList() + .subscribe { reservations -> + dataSet = reservations + println("subscribed") + val appWidgetManager: AppWidgetManager = + AppWidgetManager.getInstance(context) + appWidgetManager.notifyAppWidgetViewDataChanged( + appWidgetId, + R.id.gsr_reservation_widget_stack_view, + ) + } + } + } catch (e: Exception) { + FirebaseCrashlytics.getInstance().recordException(e) + e.printStackTrace() + } + } + } +} diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/DiningRequest.java b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/DiningRequest.java index 4ac8bcc0..7f21aa23 100644 --- a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/DiningRequest.java +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/DiningRequest.java @@ -11,4 +11,4 @@ public interface DiningRequest { @GET("/dining/venues") Observable> venues(); -} +} \ No newline at end of file diff --git a/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/GsrReservationsRequest.java b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/GsrReservationsRequest.java new file mode 100644 index 00000000..a2e45af6 --- /dev/null +++ b/PennMobile/src/main/java/com/pennapps/labs/pennmobile/api/GsrReservationsRequest.java @@ -0,0 +1,22 @@ +package com.pennapps.labs.pennmobile.api; + +import com.pennapps.labs.pennmobile.classes.AccessTokenResponse; +import com.pennapps.labs.pennmobile.classes.GSRReservation; +import com.pennapps.labs.pennmobile.classes.Venue; + +import java.util.List; + +import retrofit.Callback; +import retrofit.http.Field; +import retrofit.http.FormUrlEncoded; +import retrofit.http.GET; +import retrofit.http.Header; +import retrofit.http.POST; +import rx.Observable; + +public interface GsrReservationsRequest { + @GET("/gsr/reservations") + Observable> getGsrReservations( + @Header("Authorization") String bearerToken + ); +} \ No newline at end of file diff --git a/PennMobile/src/main/res/layout/gsr_reservation_widget.xml b/PennMobile/src/main/res/layout/gsr_reservation_widget.xml new file mode 100644 index 00000000..5e315798 --- /dev/null +++ b/PennMobile/src/main/res/layout/gsr_reservation_widget.xml @@ -0,0 +1,33 @@ + + + + + + + \ No newline at end of file diff --git a/PennMobile/src/main/res/layout/gsr_reservation_widget_item.xml b/PennMobile/src/main/res/layout/gsr_reservation_widget_item.xml new file mode 100644 index 00000000..5a979c13 --- /dev/null +++ b/PennMobile/src/main/res/layout/gsr_reservation_widget_item.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/PennMobile/src/main/res/xml/gsr_reservation_widget_info.xml b/PennMobile/src/main/res/xml/gsr_reservation_widget_info.xml new file mode 100644 index 00000000..adb16ca4 --- /dev/null +++ b/PennMobile/src/main/res/xml/gsr_reservation_widget_info.xml @@ -0,0 +1,13 @@ + + \ No newline at end of file