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