Skip to content

Commit

Permalink
Merge pull request #568 from ZeusWPI/zeus
Browse files Browse the repository at this point in the history
Add integration for Tap/Tab
  • Loading branch information
niknetniko authored May 25, 2022
2 parents 8d61aba + 9497541 commit 3475462
Show file tree
Hide file tree
Showing 100 changed files with 6,254 additions and 53 deletions.
10 changes: 6 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ apply plugin: 'com.google.firebase.crashlytics'
def props = loadProperties()

android {
compileSdkVersion 31
buildToolsVersion "31.0.0"
compileSdkVersion 32
buildToolsVersion "32.0.0"

//noinspection GroovyMissingReturnStatement
defaultConfig {
applicationId "be.ugent.zeus.hydra"
minSdkVersion 21
targetSdkVersion 31
targetSdkVersion 32
versionCode 30400
versionName "3.0.4"
vectorDrawables.useSupportLibrary = true
Expand Down Expand Up @@ -179,7 +179,7 @@ dependencies {
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.browser:browser:1.4.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.lifecycle:lifecycle-common-java8:2.4.1"
Expand All @@ -199,9 +199,11 @@ dependencies {
storeImplementation 'com.google.android.gms:play-services-maps:18.0.2'
storeImplementation 'com.google.firebase:firebase-analytics:20.1.2'
storeImplementation 'com.google.firebase:firebase-crashlytics:18.2.10'
storeImplementation 'com.google.android.gms:play-services-code-scanner:16.0.0-beta1'

// Dependencies for open version.
openImplementation 'org.osmdroid:osmdroid-android:6.1.11'
openImplementation 'com.journeyapps:zxing-android-embedded:4.3.0'

if (props.getProperty("hydra.debug.leaks").toBoolean()) {
logger.info("Leak tracking enabled...")
Expand Down
28 changes: 27 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2021 The Hydra authors
~ Copyright (c) 2022 The Hydra authors
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -148,6 +148,32 @@
android:parentActivityName=".MainActivity"
android:theme="@style/Hydra.Material.System" />


<!-- Zeus-related activities -->
<activity
android:theme="@style/Zeus.Material"
android:name=".wpi.account.ApiKeyManagementActivity"
android:label="@string/wpi_api_key_management_title"
android:parentActivityName=".wpi.WpiActivity"/>

<activity
android:theme="@style/Zeus.Material"
android:name=".wpi.WpiActivity"
android:launchMode="singleTop"
android:parentActivityName=".MainActivity"/>

<activity
android:theme="@style/Zeus.Material"
android:name=".wpi.tab.create.FormActivity"
android:label="@string/wpi_tab_form_title"
android:parentActivityName=".wpi.WpiActivity" />

<activity
android:theme="@style/Zeus.Material"
android:name=".wpi.tap.cart.CartActivity"
android:label="@string/wpi_cart_title"
android:parentActivityName=".wpi.WpiActivity" />

<!-- Urgent stuff -->
<!-- This is a music service without sensitive data and thus does not require permissions -->
<service
Expand Down
29 changes: 26 additions & 3 deletions app/src/main/java/be/ugent/zeus/hydra/MainActivity.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 The Hydra authors
* Copyright (c) 2022 The Hydra authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -60,6 +60,8 @@
import com.google.android.material.navigation.NavigationView;
import com.google.android.material.shape.MaterialShapeDrawable;
import com.google.android.material.tabs.TabLayout;
import be.ugent.zeus.hydra.wpi.EnableManager;
import be.ugent.zeus.hydra.wpi.WpiActivity;
import dev.chrisbanes.insetter.Insetter;
import jonathanfinerty.once.Once;

Expand Down Expand Up @@ -187,7 +189,6 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> implements N
static final String ONCE_DRAWER = "once_drawer";
private static final String TAG = "BaseActivity";
private static final String UFORA = "com.d2l.brightspace.student.android";
private static final int ONBOARDING_REQUEST = 5;
private static final String STATE_IS_ONBOARDING_OPEN = "state_is_onboarding_open";
private static final String FRAGMENT_MENU_ID = "backStack";

Expand All @@ -196,6 +197,9 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> implements N
private static final String SHORTCUT_EVENTS = "events";
private static final String SHORTCUT_LIBRARIES = "libraries";

private static final int ONBOARDING_REQUEST = 5;
private static final int PREFERENCES_REQUEST = 5693;

private ActionBarDrawerToggle toggle;

private boolean isOnboardingOpen;
Expand Down Expand Up @@ -277,6 +281,8 @@ public void onDrawerClosed(View drawerView) {
}
}
});

updateMenuVisibility();

// If the instance is null, we must initialise a fragment, otherwise android does it for us.
if (savedInstanceState == null) {
Expand All @@ -302,6 +308,12 @@ public void onDrawerClosed(View drawerView) {
binding.drawerLayout.openDrawer(GravityCompat.START);
}
}

private void updateMenuVisibility() {
// Show Zeus-mode if enabled.
MenuItem item = binding.navigationView.getMenu().findItem(R.id.drawer_zeus);
item.setVisible(EnableManager.isZeusModeEnabled(this));
}

@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
Expand Down Expand Up @@ -335,7 +347,15 @@ private void selectDrawerItem(@NonNull MenuItem menuItem, @NavigationSource int
// First check if it are settings, then we don't update anything.
if (menuItem.getItemId() == R.id.drawer_pref) {
binding.drawerLayout.closeDrawer(GravityCompat.START);
PreferenceActivity.start(this, null);
Intent preferenceIntent = PreferenceActivity.startIntent(this, null);
startActivityForResult(preferenceIntent, PREFERENCES_REQUEST);
return;
}

if (menuItem.getItemId() == R.id.drawer_zeus) {
binding.drawerLayout.closeDrawer(GravityCompat.START);
Intent intent = new Intent(this, WpiActivity.class);
startActivity(intent);
return;
}

Expand Down Expand Up @@ -551,6 +571,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.w(TAG, "Onboarding failed, stop app.");
finish();
}
} else if (requestCode == PREFERENCES_REQUEST) {
// Don't care about the actual status.
updateMenuVisibility();
}
// We need to call this for the fragments to work properly.
super.onActivityResult(requestCode, resultCode, data);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2022 Niko Strijbol
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package be.ugent.zeus.hydra.common.converter;

import android.util.Pair;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.squareup.moshi.*;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
* @author Niko Strijbol
*/
public class PairJsonAdapter<L, R> extends JsonAdapter<Pair<L, R>> {

private final JsonAdapter<L> leftAdapter;
private final JsonAdapter<R> rightAdapter;

public PairJsonAdapter(JsonAdapter<L> leftAdapter, JsonAdapter<R> rightAdapter) {
this.leftAdapter = leftAdapter;
this.rightAdapter = rightAdapter;
}

@Nullable
@Override
public Pair<L, R> fromJson(JsonReader reader) throws IOException {
if (reader.peek() == JsonReader.Token.NULL) {
return null;
}
reader.beginArray();
L lValue = leftAdapter.fromJson(reader);
R rValue = rightAdapter.fromJson(reader);
reader.endArray();
return Pair.create(lValue, rValue);
}

@Override
public void toJson(@NonNull JsonWriter writer, @Nullable Pair<L, R> value) throws IOException {
if (value == null) {
writer.nullValue();
return;
}
writer.beginArray();
leftAdapter.toJson(writer, value.first);
rightAdapter.toJson(writer, value.second);
writer.endArray();
}

public static class Factory implements JsonAdapter.Factory {

@Nullable
@Override
public JsonAdapter<?> create(@NonNull Type type, @NonNull Set<? extends Annotation> annotations, @NonNull Moshi moshi) {
if (!annotations.isEmpty()) {
return null; // Annotations? This factory doesn't apply.
}

if (!(type instanceof ParameterizedType)) {
return null; // No type parameter? This factory doesn't apply.
}

ParameterizedType parameterizedType = (ParameterizedType) type;
if (parameterizedType.getRawType() != Pair.class) {
return null; // Not a pair? This factory doesn't apply.
}

Type leftType = parameterizedType.getActualTypeArguments()[0];
Type rightType = parameterizedType.getActualTypeArguments()[1];

JsonAdapter<?> leftAdapter = moshi.adapter(leftType);
JsonAdapter<?> rightAdapter = moshi.adapter(rightType);

return new PairJsonAdapter<>(leftAdapter, rightAdapter).nullSafe();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,8 @@ public interface Endpoints {
String ZEUS_V1 = "https://hydra.ugent.be/api/1.0/";
String ZEUS_V2 = "https://hydra.ugent.be/api/2.0/";

String TAP = "https://tap.zeus.gent/";
String TAB = "https://tab.zeus.gent/";

String LIBRARY = "https://widgets.lib.ugent.be/";
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@

import java.io.File;

import be.ugent.zeus.hydra.common.converter.BooleanJsonAdapter;
import be.ugent.zeus.hydra.common.converter.DateThreeTenAdapter;
import be.ugent.zeus.hydra.common.converter.DateTypeConverters;
import be.ugent.zeus.hydra.common.converter.*;
import com.squareup.moshi.Moshi;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
Expand Down Expand Up @@ -76,14 +74,14 @@ public static synchronized OkHttpClient getClient(Context context) {
return getClient(cacheDir);
}

@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public static synchronized Moshi getMoshi() {
if (moshi == null) {
moshi = new Moshi.Builder()
.add(new BooleanJsonAdapter())
.add(new DateThreeTenAdapter())
.add(new DateTypeConverters.GsonOffset())
.add(new DateTypeConverters.LocalZonedDateTimeInstance())
.add(new PairJsonAdapter.Factory())
.build();
}
return moshi;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
/**
* @author Niko Strijbol
*/
class InvalidFormatException extends RequestException {
public class InvalidFormatException extends RequestException {

InvalidFormatException(String message, Throwable cause) {
public InvalidFormatException(String message, Throwable cause) {
super(message, cause);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,10 @@
import java.util.concurrent.TimeUnit;

import be.ugent.zeus.hydra.common.arch.data.BaseLiveData;
import be.ugent.zeus.hydra.common.reporting.Reporting;
import be.ugent.zeus.hydra.common.reporting.Tracker;
import be.ugent.zeus.hydra.common.request.Request;
import be.ugent.zeus.hydra.common.request.Result;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonDataException;
import com.squareup.moshi.Moshi;
import okhttp3.CacheControl;
import okhttp3.OkHttpClient;
import okhttp3.Response;

/**
Expand All @@ -66,16 +61,13 @@
* @author Niko Strijbol
*/
@SuppressWarnings("WeakerAccess")
public abstract class JsonOkHttpRequest<D> implements Request<D> {
public abstract class JsonOkHttpRequest<D> extends OkHttpRequest<D> {

private static final String TAG = "JsonOkHttpRequest";

private static final String ALLOW_STALENESS = "be.ugent.zeus.hydra.data.staleness";

private final Moshi moshi;
private final OkHttpClient client;
private final Type typeToken;
private final Tracker tracker;

/**
* Construct a new request. As this constructor is not type-safe, it must only be used internally.
Expand All @@ -84,10 +76,8 @@ public abstract class JsonOkHttpRequest<D> implements Request<D> {
* @param token The type token of the return type.
*/
JsonOkHttpRequest(@NonNull Context context, @NonNull Type token) {
this.moshi = InstanceProvider.getMoshi();
this.client = InstanceProvider.getClient(context);
super(context);
this.typeToken = token;
this.tracker = Reporting.getTracker(context);
}

/**
Expand Down Expand Up @@ -187,7 +177,8 @@ protected Result<D> executeRequest(JsonAdapter<D> adapter, @NonNull Bundle args)
protected okhttp3.Request.Builder constructRequest(@NonNull Bundle arguments) {
return new okhttp3.Request.Builder()
.url(getAPIUrl())
.cacheControl(constructCacheControl(arguments));
.cacheControl(constructCacheControl(arguments))
.addHeader("Accept", "application/json");
}

protected CacheControl constructCacheControl(@NonNull Bundle arguments) {
Expand Down
Loading

0 comments on commit 3475462

Please sign in to comment.