Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various updates #847

Merged
merged 18 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Alternatively, you can [checkout](https://www.jetbrains.com/help/idea/set-up-a-g

People who use Nix(OS) can use the `flake.nix` file in the repo for a dev shell.
Note that we don't build the app using flakes; it's only used for a dev shell.
Additionally, the flake is very flaky, since Android development in Nixpkgs currently isn't the best.

### Keys
If you want to use the Google Maps integration, you will need the API keys. You can contact us for more information and to obtain the keys. _This is not required to compile and build the app._
Expand Down
9 changes: 9 additions & 0 deletions android-versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Common file with version numbers, used by the different subprojects
# Also used by the flake file to get the correct versions if you need it.
# IMPORTANT: this file is read as a "Java Properties file" by Gradle
# AND as a "TOML file" by Nix. So it needs to be valid in both.
# Since properties strings are not quoted, we unquote the values in Gradle.
cmdLineToolsVersion = "12.0-rc15"
platformToolsVersion = "34.0.4"
buildToolsVersions = "34.0.0"
platformVersions = "34"
68 changes: 39 additions & 29 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@ apply plugin: 'com.google.firebase.crashlytics'

// Read our properties, see bottom for details.
def props = loadProperties()
def versions = loadAndroidVersions()

android {
buildToolsVersion "33.0.0"
// We need this for Nix flakes
//noinspection GrDeprecatedAPIUsage
buildToolsVersion versions.buildToolsVersions

defaultConfig {
compileSdk 33
compileSdk versions.platformVersions as Integer

applicationId "be.ugent.zeus.hydra"
minSdk 21
targetSdk 33
targetSdk 34
versionCode 36000
versionName "3.6.0"
vectorDrawables.useSupportLibrary = true
Expand Down Expand Up @@ -101,8 +104,8 @@ android {

compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}

buildTypes {
Expand Down Expand Up @@ -158,7 +161,7 @@ android {
namespace 'be.ugent.zeus.hydra'

lint {
disable 'RtlSymmetry', 'VectorPath', 'InsecureBaseConfiguration', 'Overdraw', 'GradleDependency', 'OldTargetApi', 'ObsoleteLintCustomCheck', 'NotificationPermission'
disable 'RtlSymmetry', 'VectorPath', 'Overdraw', 'GradleDependency', 'NotificationPermission'
showAll true
warningsAsErrors true
}
Expand All @@ -167,34 +170,24 @@ android {
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'

// Needed until all dependencies will be fixed
constraints {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.10") {
because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib")
}
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.10") {
because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
}
}

implementation 'androidx.core:core:1.10.1'
implementation 'androidx.core:core:1.12.0'
implementation 'androidx.media:media:1.6.0'
implementation 'androidx.fragment:fragment:1.6.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.3.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.browser:browser:1.5.0'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.browser:browser:1.6.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.6.2'
implementation 'androidx.lifecycle:lifecycle-livedata:2.6.2'
implementation 'androidx.lifecycle:lifecycle-livedata:2.6.2'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.6.2'
implementation 'androidx.viewpager2:viewpager2:1.0.0'
implementation 'androidx.room:room-runtime:2.5.2'
annotationProcessor 'androidx.room:room-compiler:2.5.2'
implementation 'androidx.room:room-runtime:2.6.0'
annotationProcessor 'androidx.room:room-compiler:2.6.0'
implementation 'com.artemzin.rxjava:proguard-rules:1.3.3.0'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.squareup.moshi:moshi:1.15.0'
Expand All @@ -207,8 +200,8 @@ dependencies {
implementation 'com.github.niqdev:ipcam-view:2.4.0'

// Dependencies for the Play Store version.
storeImplementation 'com.google.android.gms:play-services-maps:18.1.0'
storeImplementation 'com.google.firebase:firebase-analytics:21.3.0'
storeImplementation 'com.google.android.gms:play-services-maps:18.2.0'
storeImplementation 'com.google.firebase:firebase-analytics:21.4.0'
storeImplementation 'com.google.firebase:firebase-crashlytics:18.5.0'
storeImplementation 'com.google.android.gms:play-services-code-scanner:16.1.0'

Expand All @@ -224,15 +217,15 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
// Once final classes can be mocked, go back to mockito-core.
testImplementation 'org.mockito:mockito-inline:5.2.0'
testImplementation 'org.robolectric:robolectric:4.10.3'
testImplementation 'org.robolectric:robolectric:4.11-beta-2'
testImplementation 'androidx.test:core:1.5.0'
testImplementation 'androidx.test.ext:junit:1.1.5'
testImplementation 'androidx.test:rules:1.5.0'
testImplementation 'androidx.test.espresso:espresso-core:3.5.1'
testImplementation 'androidx.test.espresso:espresso-intents:3.5.1'
testImplementation 'androidx.test.espresso:espresso-contrib:3.5.1'
testImplementation 'androidx.arch.core:core-testing:2.2.0'
testImplementation 'androidx.room:room-testing:2.5.2'
testImplementation 'androidx.room:room-testing:2.6.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:4.11.0'
testImplementation 'nl.jqno.equalsverifier:equalsverifier:3.15.2'
testImplementation 'com.shazam:shazamcrest:0.11'
Expand All @@ -244,9 +237,10 @@ dependencies {


// Disable Google services for open variant.
android.applicationVariants.all { variant ->
def googleTask = tasks.findByName("process${variant.name.capitalize()}GoogleServices")
googleTask.enabled = "open" != variant.flavorName
android.applicationVariants.configureEach { variant ->
tasks.named("process${variant.name.capitalize()}GoogleServices").configure {
it.enabled = "open" != variant.flavorName
}
}

/**
Expand Down Expand Up @@ -282,3 +276,19 @@ def loadProperties() {

return actualKeys
}

/**
* Loads the default properties, and the user properties. This will also load the
* secret keys.
*/
def loadAndroidVersions() {
def defaultProps = new Properties()
defaultProps.load(file("../android-versions.toml").newReader())

def strippedProps = new Properties()
for (e in defaultProps) {
strippedProps.setProperty(e.key, e.value.replaceAll('"', ''))
}

return strippedProps
}
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<!-- Urgent stuff -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

<!-- Read tags for Zeus -->
<uses-permission android:name="android.permission.NFC" />
Expand All @@ -55,6 +56,7 @@
android:supportsRtl="false"
android:theme="@style/Hydra.Material"
android:localeConfig="@xml/locales_config"
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute"
tools:replace="android:supportsRtl">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public Association() {
// Moshi uses this!
}

/** @noinspection ProtectedMemberInFinalClass*/
protected Association(Parcel in) {
abbreviation = in.readString();
name = in.readString();
Expand Down Expand Up @@ -86,7 +87,7 @@ public int describeContents() {
return 0;
}

public static final Creator<Association> CREATOR = new Creator<Association>() {
public static final Creator<Association> CREATOR = new Creator<>() {
@Override
public Association createFromParcel(Parcel in) {
return new Association(in);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,19 +119,14 @@ public Duration getCacheDuration() {
}
}

@NonNull
public static Request<AssociationList> createRawAssociationRequest(@NonNull Context context) {
return new RawRequest(context);
}

@NonNull
public static Request<List<Association>> createListRequest(@NonNull Context context) {
return new RawRequest(context)
.map(AssociationList::getAssociations);
}

public static Request<Pair<AssociationMap, List<EventItem>>> createItemFilteredEventRequest(@NonNull Context context, EventFilter filter) {
return createRawAssociationRequest(context)
return new RawRequest(context)
.andThen((Function<AssociationList, Request<Pair<List<EventItem>, Set<String>>>>) data -> {
EventRequest.Filter newFilter = filter.toRequestFilter(context, data.getAssociations());
Set<String> requestedAssociations = newFilter.getRequestedAssociations();
Expand All @@ -144,7 +139,7 @@ public static Request<Pair<AssociationMap, List<EventItem>>> createItemFilteredE
}

public static Request<Pair<AssociationMap, List<Event>>> createFilteredEventRequest(@NonNull Context context) {
return createRawAssociationRequest(context)
return new RawRequest(context)
.andThen((Function<AssociationList, Request<Pair<List<Event>, Set<String>>>>) data -> {
EventFilter eventFilter = new EventFilter();
EventRequest.Filter newFilter = eventFilter.toRequestFilter(context, data.getAssociations());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(event, header, isLastOfSection);
}

void markAsLastOfSection() {
this.isLastOfSection = true;
}

public OffsetDateTime getDate() {
if (isItem()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@

/**
* Get the events for all associations.
*
* The general event flow it like this:
*
* <p>
* The general event flow is like this:
* <p>
* 1. We get the list of associations from the server.
* 2. Use the filter to update the blacklist.
* 3. Use the blacklist to get a whitelist.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.IntentCompat;
import androidx.core.text.util.LinkifyCompat;
import androidx.core.view.WindowCompat;

Expand Down Expand Up @@ -80,8 +81,8 @@ protected void onCreate(Bundle savedInstanceState) {
boolean hasDescription = true;

// Get data from saved instance, or from intent.
event = getIntent().getParcelableExtra(PARCEL_EVENT);
Association association = getIntent().getParcelableExtra(PARCEL_ASSOCIATION);
event = IntentCompat.getParcelableExtra(getIntent(), PARCEL_EVENT, Event.class);
Association association = IntentCompat.getParcelableExtra(getIntent(), PARCEL_ASSOCIATION, Association.class);
assert event != null;
assert association != null;

Expand All @@ -95,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) {

if (event.getDescription() != null && !event.getDescription().trim().isEmpty()) {
binding.description.setText(event.getDescription());
LinkifyCompat.addLinks(binding.description, Linkify.ALL);
LinkifyCompat.addLinks(binding.description, Linkify.EMAIL_ADDRESSES | Linkify.WEB_URLS);
} else {
hasDescription = false;
binding.eventDescriptionBlock.setVisibility(View.GONE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@

package be.ugent.zeus.hydra.association.event;

import java.util.Map;
import java.util.Objects;

/**
* @author Niko Strijbol
*/
public final class EventList {

/** @noinspection unused*/
private EventPage page;

public EventList() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
*/
public final class EventPage {

/** @noinspection unused*/
private List<Event> entries;

public List<Event> getEntries() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuProvider;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
Expand All @@ -59,6 +61,7 @@
import com.google.android.material.datepicker.MaterialDatePicker;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.TextInputLayout;
import org.jetbrains.annotations.NotNull;

import static be.ugent.zeus.hydra.common.utils.FragmentUtils.requireBaseActivity;

Expand All @@ -83,12 +86,6 @@ public class EventFragment extends Fragment implements MainActivity.ScheduledRem
private TextInputLayout startTime;
private TextInputLayout endTime;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Expand All @@ -99,6 +96,27 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);

requireActivity().addMenuProvider(new MenuProvider() {
@Override
public void onCreateMenu(@NonNull @NotNull Menu menu, @NonNull @NotNull MenuInflater menuInflater) {
menuInflater.inflate(R.menu.menu_main_events, menu);
requireBaseActivity(EventFragment.this).tintToolbarIcons(menu, R.id.action_refresh, R.id.action_search);
}

@Override
public boolean onMenuItemSelected(@NonNull @NotNull MenuItem menuItem) {
int itemId = menuItem.getItemId();
if (itemId == R.id.action_refresh) {
viewModel.onRefresh();
return true;
} else if (itemId == R.id.action_search) {
showSheet();
return true;
}
return false;
}
}, getViewLifecycleOwner(), Lifecycle.State.RESUMED);

bottomSheet = requireActivity().findViewById(R.id.bottom_sheet);
// Load the options.
getLayoutInflater().inflate(R.layout.item_search_filter, bottomSheet, true);
Expand Down Expand Up @@ -221,26 +239,6 @@ private void onError(Throwable throwable) {
.show();
}

@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main_events, menu);
requireBaseActivity(this).tintToolbarIcons(menu, R.id.action_refresh, R.id.action_search);
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.action_refresh) {
viewModel.onRefresh();
return true;
} else if (itemId == R.id.action_search) {
showSheet();
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
public void onRemovalScheduled() {
hideExternalViews();
Expand Down
Loading