Merge branch 'develop' into imperial-system
This commit is contained in:
@@ -1,18 +1,17 @@
|
|||||||
package com.a1.nextlocation;
|
package com.a1.nextlocation;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.DialogFragment;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentManager;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
|
||||||
import com.a1.nextlocation.fragments.HelpPopup;
|
import com.a1.nextlocation.fragments.HelpPopup;
|
||||||
import com.a1.nextlocation.fragments.HomeFragment;
|
import com.a1.nextlocation.fragments.HomeFragment;
|
||||||
import com.a1.nextlocation.fragments.Refreshable;
|
import com.a1.nextlocation.fragments.Refreshable;
|
||||||
@@ -33,6 +32,7 @@ public class MainActivity extends AppCompatActivity implements Refreshable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* onCreate method that creates the main activity
|
* onCreate method that creates the main activity
|
||||||
|
*
|
||||||
* @param savedInstanceState the saved instance state of the app
|
* @param savedInstanceState the saved instance state of the app
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -67,6 +67,7 @@ public class MainActivity extends AppCompatActivity implements Refreshable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* loads the saved language from SharedPreferences
|
* loads the saved language from SharedPreferences
|
||||||
|
*
|
||||||
* @return the language as string
|
* @return the language as string
|
||||||
*/
|
*/
|
||||||
private String loadLocale() {
|
private String loadLocale() {
|
||||||
@@ -76,6 +77,7 @@ public class MainActivity extends AppCompatActivity implements Refreshable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the language of the application to the desired one
|
* sets the language of the application to the desired one
|
||||||
|
*
|
||||||
* @param language the desired language
|
* @param language the desired language
|
||||||
*/
|
*/
|
||||||
private void setLocale(String language) {
|
private void setLocale(String language) {
|
||||||
@@ -87,7 +89,7 @@ public class MainActivity extends AppCompatActivity implements Refreshable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private BottomNavigationView.OnNavigationItemSelectedListener navListener = item -> {
|
private final BottomNavigationView.OnNavigationItemSelectedListener navListener = item -> {
|
||||||
Fragment selectedFragment = null;
|
Fragment selectedFragment = null;
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
@@ -119,7 +121,7 @@ public class MainActivity extends AppCompatActivity implements Refreshable {
|
|||||||
bottomNav.setSelectedItemId(id);
|
bottomNav.setSelectedItemId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private View.OnClickListener onInfoClickListener = new View.OnClickListener() {
|
private final View.OnClickListener onInfoClickListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public enum Data {
|
|||||||
this.zoom = zoom;
|
this.zoom = zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<String> visitedNames = new ArrayList<>();
|
private final ArrayList<String> visitedNames = new ArrayList<>();
|
||||||
|
|
||||||
public void addDistance(double d) {
|
public void addDistance(double d) {
|
||||||
distanceTraveled += d;
|
distanceTraveled += d;
|
||||||
@@ -51,5 +51,4 @@ public enum Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,28 +2,15 @@ package com.a1.nextlocation.data;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.os.Environment;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class FileIO<T> {
|
public class FileIO<T> {
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ public class Location implements Parcelable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* calculates the distance between two coordinates
|
* calculates the distance between two coordinates
|
||||||
|
*
|
||||||
* @param lat1 the first latitude
|
* @param lat1 the first latitude
|
||||||
* @param lon1 the first longitude
|
* @param lon1 the first longitude
|
||||||
* @param lat2 the second latitude
|
* @param lat2 the second latitude
|
||||||
@@ -139,18 +140,18 @@ public class Location implements Parcelable {
|
|||||||
|
|
||||||
double c = 2 * Math.asin(Math.sqrt(a));
|
double c = 2 * Math.asin(Math.sqrt(a));
|
||||||
|
|
||||||
|
double distance;
|
||||||
// Radius of earth in kilometers. Use 3956
|
// Radius of earth in kilometers. Use 3956
|
||||||
// for miles
|
// for miles
|
||||||
// if(miles) {
|
// if(miles) {
|
||||||
// double r = 3956;
|
// double r = 3956;
|
||||||
|
// distance = c * r;
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
double r = 6371;
|
double r = 6371;
|
||||||
// }
|
distance = c * r;
|
||||||
// calculate the result
|
|
||||||
double distance = c * r;
|
|
||||||
|
|
||||||
distance *= 1000;
|
distance *= 1000;
|
||||||
|
// }
|
||||||
return Math.floor(distance);
|
return Math.floor(distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public enum RouteHandler {
|
|||||||
public boolean isFollowingRoute(Route route) {
|
public boolean isFollowingRoute(Route route) {
|
||||||
return isFollowingRoute && route.equals(currentRoute);
|
return isFollowingRoute && route.equals(currentRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFollowingRoute(boolean followingRoute) {
|
public void setFollowingRoute(boolean followingRoute) {
|
||||||
isFollowingRoute = followingRoute;
|
isFollowingRoute = followingRoute;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,16 @@ package com.a1.nextlocation.fragments;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Coupon;
|
import com.a1.nextlocation.data.Coupon;
|
||||||
import com.a1.nextlocation.recyclerview.CouponAdapter;
|
import com.a1.nextlocation.recyclerview.CouponAdapter;
|
||||||
@@ -64,6 +63,7 @@ public class CouponFragment extends Fragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* shows the popup of a coupon
|
* shows the popup of a coupon
|
||||||
|
*
|
||||||
* @param coupon the coupon that will be displayed
|
* @param coupon the coupon that will be displayed
|
||||||
*/
|
*/
|
||||||
private void showPopup(Coupon coupon) {
|
private void showPopup(Coupon coupon) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.a1.nextlocation.fragments;
|
|||||||
|
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
@@ -12,7 +11,6 @@ import android.location.LocationManager;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
@@ -26,17 +24,15 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.RouteHandler;
|
|
||||||
import com.a1.nextlocation.data.Data;
|
import com.a1.nextlocation.data.Data;
|
||||||
|
import com.a1.nextlocation.data.RouteHandler;
|
||||||
import com.a1.nextlocation.json.DirectionsResult;
|
import com.a1.nextlocation.json.DirectionsResult;
|
||||||
import com.a1.nextlocation.network.ApiHandler;
|
import com.a1.nextlocation.network.ApiHandler;
|
||||||
import com.a1.nextlocation.network.DirectionsListener;
|
|
||||||
import com.a1.nextlocation.recyclerview.LocationListManager;
|
import com.a1.nextlocation.recyclerview.LocationListManager;
|
||||||
|
|
||||||
import org.osmdroid.api.IMapController;
|
import org.osmdroid.api.IMapController;
|
||||||
import org.osmdroid.config.Configuration;
|
import org.osmdroid.config.Configuration;
|
||||||
import org.osmdroid.util.GeoPoint;
|
import org.osmdroid.util.GeoPoint;
|
||||||
import org.osmdroid.views.CustomZoomButtonsController;
|
|
||||||
import org.osmdroid.views.MapView;
|
import org.osmdroid.views.MapView;
|
||||||
import org.osmdroid.views.overlay.ItemizedIconOverlay;
|
import org.osmdroid.views.overlay.ItemizedIconOverlay;
|
||||||
import org.osmdroid.views.overlay.Overlay;
|
import org.osmdroid.views.overlay.Overlay;
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
package com.a1.nextlocation.fragments;
|
package com.a1.nextlocation.fragments;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -14,6 +9,9 @@ import android.widget.ImageButton;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Location;
|
import com.a1.nextlocation.data.Location;
|
||||||
import com.a1.nextlocation.recyclerview.LocationListManager;
|
import com.a1.nextlocation.recyclerview.LocationListManager;
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
package com.a1.nextlocation.fragments;
|
package com.a1.nextlocation.fragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Location;
|
import com.a1.nextlocation.data.Location;
|
||||||
import com.a1.nextlocation.recyclerview.LocationAdapter;
|
import com.a1.nextlocation.recyclerview.LocationAdapter;
|
||||||
|
|||||||
@@ -3,19 +3,18 @@ package com.a1.nextlocation.fragments;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Location;
|
import com.a1.nextlocation.data.Location;
|
||||||
import com.a1.nextlocation.data.Route;
|
import com.a1.nextlocation.data.Route;
|
||||||
@@ -38,6 +37,7 @@ public class RouteDetailFragment extends Fragment {
|
|||||||
if (context instanceof Refreshable)
|
if (context instanceof Refreshable)
|
||||||
this.refreshable = (Refreshable) context;
|
this.refreshable = (Refreshable) context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@@ -83,6 +83,7 @@ public class RouteDetailFragment extends Fragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Button onclick method that starts the route that is being viewed.
|
* Button onclick method that starts the route that is being viewed.
|
||||||
|
*
|
||||||
* @param view the button
|
* @param view the button
|
||||||
*/
|
*/
|
||||||
public void startRoute(View view) {
|
public void startRoute(View view) {
|
||||||
@@ -95,6 +96,7 @@ public class RouteDetailFragment extends Fragment {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the distance between points
|
* Calculates the distance between points
|
||||||
|
*
|
||||||
* @param route the route that is calculated
|
* @param route the route that is calculated
|
||||||
* @return the total distance of a route
|
* @return the total distance of a route
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package com.a1.nextlocation.fragments;
|
package com.a1.nextlocation.fragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -9,23 +13,12 @@ import androidx.fragment.app.FragmentActivity;
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Route;
|
import com.a1.nextlocation.data.Route;
|
||||||
import com.a1.nextlocation.recyclerview.RouteAdapter;
|
import com.a1.nextlocation.recyclerview.RouteAdapter;
|
||||||
import com.a1.nextlocation.recyclerview.RouteListManager;
|
import com.a1.nextlocation.recyclerview.RouteListManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import com.a1.nextlocation.data.Location;
|
|
||||||
import com.a1.nextlocation.data.Route;
|
|
||||||
import com.a1.nextlocation.json.DirectionsResult;
|
|
||||||
import com.a1.nextlocation.network.ApiHandler;
|
|
||||||
import com.a1.nextlocation.network.DirectionsListener;
|
|
||||||
|
|
||||||
public class RouteFragment extends Fragment {
|
public class RouteFragment extends Fragment {
|
||||||
private static final String TAG = RouteFragment.class.getCanonicalName();
|
private static final String TAG = RouteFragment.class.getCanonicalName();
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ import android.content.Context;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.appcompat.widget.SwitchCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -19,6 +13,11 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -90,6 +89,7 @@ public class SettingsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Changes the font settings depending on the state of the toggle
|
//Changes the font settings depending on the state of the toggle
|
||||||
|
|
||||||
fontSwitch.setOnClickListener(view1 -> {
|
fontSwitch.setOnClickListener(view1 -> {
|
||||||
if(fontSwitch.isChecked())
|
if(fontSwitch.isChecked())
|
||||||
{
|
{
|
||||||
@@ -126,6 +126,7 @@ public class SettingsFragment extends Fragment {
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNothingSelected(AdapterView<?> parent) {
|
public void onNothingSelected(AdapterView<?> parent) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,16 @@ package com.a1.nextlocation.fragments;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Coupon;
|
import com.a1.nextlocation.data.Coupon;
|
||||||
import com.a1.nextlocation.data.Data;
|
import com.a1.nextlocation.data.Data;
|
||||||
@@ -37,6 +36,9 @@ public class StatisticFragment extends Fragment {
|
|||||||
initializeDistanceTextView(view);
|
initializeDistanceTextView(view);
|
||||||
TextView locs = view.findViewById(R.id.statistics_locations_visited);
|
TextView locs = view.findViewById(R.id.statistics_locations_visited);
|
||||||
TextView timeText = view.findViewById(R.id.statistics_time_value);
|
TextView timeText = view.findViewById(R.id.statistics_time_value);
|
||||||
|
|
||||||
|
double dist = Data.INSTANCE.getDistanceTraveled() / 1000;
|
||||||
|
distance.setText("" + String.format("%.1f", dist) + " km");
|
||||||
locs.setText("" + Data.INSTANCE.getLocationsVisited());
|
locs.setText("" + Data.INSTANCE.getLocationsVisited());
|
||||||
|
|
||||||
long seconds = Data.INSTANCE.getTotalTime() / 1000;
|
long seconds = Data.INSTANCE.getTotalTime() / 1000;
|
||||||
@@ -44,7 +46,7 @@ public class StatisticFragment extends Fragment {
|
|||||||
long p2 = seconds / 60;
|
long p2 = seconds / 60;
|
||||||
long p3 = p2 % 60;
|
long p3 = p2 % 60;
|
||||||
p2 = p2 / 60;
|
p2 = p2 / 60;
|
||||||
timeText.setText(p2 + ":" + p3 + ":" + p1);
|
timeText.setText(p2 + "u, " + p3 + "m, " + p1 + "s");
|
||||||
|
|
||||||
|
|
||||||
//loads the couponList
|
//loads the couponList
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ import com.google.gson.JsonObject;
|
|||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.osmdroid.util.GeoPoint;
|
import org.osmdroid.util.GeoPoint;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -24,7 +22,7 @@ public class DirectionsResult {
|
|||||||
private double distance;
|
private double distance;
|
||||||
private double duration;
|
private double duration;
|
||||||
private double[][] wayPointCoordinates;
|
private double[][] wayPointCoordinates;
|
||||||
private GeoPoint[] startAndEndPoint = new GeoPoint[2];
|
private final GeoPoint[] startAndEndPoint = new GeoPoint[2];
|
||||||
|
|
||||||
public List<DirectionsStep> getSteps() {
|
public List<DirectionsStep> getSteps() {
|
||||||
return steps;
|
return steps;
|
||||||
@@ -60,6 +58,7 @@ public class DirectionsResult {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* converts all the geopoints in all the steps into an arraylist to display it on the map
|
* converts all the geopoints in all the steps into an arraylist to display it on the map
|
||||||
|
*
|
||||||
* @return the list of geopoints
|
* @return the list of geopoints
|
||||||
*/
|
*/
|
||||||
public ArrayList<GeoPoint> getGeoPoints() {
|
public ArrayList<GeoPoint> getGeoPoints() {
|
||||||
@@ -110,6 +109,7 @@ public class DirectionsResult {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* parses the given json string into this object. This method is used for when you have requested directions from the API for a {@link com.a1.nextlocation.data.Route route object}
|
* parses the given json string into this object. This method is used for when you have requested directions from the API for a {@link com.a1.nextlocation.data.Route route object}
|
||||||
|
*
|
||||||
* @param json the json string
|
* @param json the json string
|
||||||
*/
|
*/
|
||||||
public void parseRoute(String json) {
|
public void parseRoute(String json) {
|
||||||
@@ -147,6 +147,7 @@ public class DirectionsResult {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* parses different segments, and the steps in it using {@link DirectionsResult#parseSteps(JsonArray, Gson) the method for parsing steps}
|
* parses different segments, and the steps in it using {@link DirectionsResult#parseSteps(JsonArray, Gson) the method for parsing steps}
|
||||||
|
*
|
||||||
* @param segments the segments to parse
|
* @param segments the segments to parse
|
||||||
* @param gson the gson object to use
|
* @param gson the gson object to use
|
||||||
*/
|
*/
|
||||||
@@ -166,6 +167,7 @@ public class DirectionsResult {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* parses the given steps into this object, transforms them into a {@link DirectionsStep} object.
|
* parses the given steps into this object, transforms them into a {@link DirectionsStep} object.
|
||||||
|
*
|
||||||
* @param steps the steps to parse
|
* @param steps the steps to parse
|
||||||
* @param gson the gson object to use
|
* @param gson the gson object to use
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package com.a1.nextlocation.json;
|
|||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* source: https://github.com/GIScience/openrouteservice-docs#geometry-decoding
|
* source: https://github.com/GIScience/openrouteservice-docs#geometry-decoding
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,13 +6,11 @@ import com.a1.nextlocation.data.Location;
|
|||||||
import com.a1.nextlocation.data.Route;
|
import com.a1.nextlocation.data.Route;
|
||||||
import com.a1.nextlocation.json.DirectionsResult;
|
import com.a1.nextlocation.json.DirectionsResult;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
@@ -27,19 +25,20 @@ public enum ApiHandler {
|
|||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
private static String TAG = ApiHandler.class.getCanonicalName();
|
private static final String TAG = ApiHandler.class.getCanonicalName();
|
||||||
|
|
||||||
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
|
||||||
private final String BASE_URL = "https://api.openrouteservice.org/v2/directions/";
|
private final String BASE_URL = "https://api.openrouteservice.org/v2/directions/";
|
||||||
private final String API_KEY = "5b3ce3597851110001cf6248d4eee2099f724255918adc71cc502b2a";
|
private final String API_KEY = "5b3ce3597851110001cf6248d4eee2099f724255918adc71cc502b2a";
|
||||||
private final String DIRECTIONS_MODE = "foot-walking";
|
private final String DIRECTIONS_MODE = "foot-walking";
|
||||||
|
|
||||||
private List<DirectionsListener> listeners = new ArrayList<>();
|
private final List<DirectionsListener> listeners = new ArrayList<>();
|
||||||
|
|
||||||
private OkHttpClient client = new OkHttpClient();
|
private final OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets directions from the start location to the end location
|
* gets directions from the start location to the end location
|
||||||
|
*
|
||||||
* @param startLocation the start location
|
* @param startLocation the start location
|
||||||
* @param endLocation the end location
|
* @param endLocation the end location
|
||||||
*/
|
*/
|
||||||
@@ -49,6 +48,7 @@ public enum ApiHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gets directions from the start location latitude and longitude and the end location latitude and longitude
|
* gets directions from the start location latitude and longitude and the end location latitude and longitude
|
||||||
|
*
|
||||||
* @param startLat the start latitude
|
* @param startLat the start latitude
|
||||||
* @param startLong the start longitude
|
* @param startLong the start longitude
|
||||||
* @param endLat the end latitude
|
* @param endLat the end latitude
|
||||||
@@ -60,6 +60,7 @@ public enum ApiHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the directions from the start location to the end location. An example location would be "3.543543,5.7675765"
|
* Gets the directions from the start location to the end location. An example location would be "3.543543,5.7675765"
|
||||||
|
*
|
||||||
* @param startLocation the start location represented as <i>startlat,startlong</i>
|
* @param startLocation the start location represented as <i>startlat,startlong</i>
|
||||||
* @param endLocation the end location represented as <i>endlat,endlong</i>
|
* @param endLocation the end location represented as <i>endlat,endlong</i>
|
||||||
*/
|
*/
|
||||||
@@ -108,6 +109,7 @@ public enum ApiHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* adds a listener for when a result of an api call is available
|
* adds a listener for when a result of an api call is available
|
||||||
|
*
|
||||||
* @param listener the new listener
|
* @param listener the new listener
|
||||||
*/
|
*/
|
||||||
public void addListener(DirectionsListener listener) {
|
public void addListener(DirectionsListener listener) {
|
||||||
@@ -116,6 +118,7 @@ public enum ApiHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* gets directions for the given {@link Route}
|
* gets directions for the given {@link Route}
|
||||||
|
*
|
||||||
* @param route the route to get directions for
|
* @param route the route to get directions for
|
||||||
*/
|
*/
|
||||||
public void getDirections(Route route) {
|
public void getDirections(Route route) {
|
||||||
@@ -182,6 +185,4 @@ public enum ApiHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.a1.nextlocation.network;
|
package com.a1.nextlocation.network;
|
||||||
|
|
||||||
import com.a1.nextlocation.data.Route;
|
|
||||||
import com.a1.nextlocation.json.DirectionsResult;
|
import com.a1.nextlocation.json.DirectionsResult;
|
||||||
|
|
||||||
public interface DirectionsListener {
|
public interface DirectionsListener {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.a1.nextlocation.recyclerview;
|
package com.a1.nextlocation.recyclerview;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -16,8 +16,8 @@ import java.util.List;
|
|||||||
|
|
||||||
public class CouponAdapter extends RecyclerView.Adapter<CouponAdapter.CouponViewHolder> {
|
public class CouponAdapter extends RecyclerView.Adapter<CouponAdapter.CouponViewHolder> {
|
||||||
|
|
||||||
private Context appContext;
|
private final Context appContext;
|
||||||
private List<Coupon> couponList;
|
private final List<Coupon> couponList;
|
||||||
private OnItemClickListener clickListener;
|
private OnItemClickListener clickListener;
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
public interface OnItemClickListener {
|
||||||
@@ -35,6 +35,7 @@ public class CouponAdapter extends RecyclerView.Adapter<CouponAdapter.CouponView
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the text of the coupon
|
* Sets the text of the coupon
|
||||||
|
*
|
||||||
* @param text the text that will be set
|
* @param text the text that will be set
|
||||||
*/
|
*/
|
||||||
public void setTextViewName(String text) {
|
public void setTextViewName(String text) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public class CouponLoader implements Loader<List<Coupon>> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the Arraylist of coupons out of the JSON
|
* Loads the Arraylist of coupons out of the JSON
|
||||||
|
*
|
||||||
* @return Arraylist of coupons
|
* @return Arraylist of coupons
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -32,7 +33,8 @@ public class CouponLoader implements Loader<List<Coupon>> {
|
|||||||
if (!selectedLanguage.equals("en")) {
|
if (!selectedLanguage.equals("en")) {
|
||||||
fileName += "-" + selectedLanguage;
|
fileName += "-" + selectedLanguage;
|
||||||
}
|
}
|
||||||
ArrayList<Coupon> res = fileIO.readFileData(context, fileName + ".json", new TypeToken<ArrayList<Coupon>>(){}.getType());
|
ArrayList<Coupon> res = fileIO.readFileData(context, fileName + ".json", new TypeToken<ArrayList<Coupon>>() {
|
||||||
|
}.getType());
|
||||||
Log.d(TAG, "load: " + res);
|
Log.d(TAG, "load: " + res);
|
||||||
|
|
||||||
return res == null ? new ArrayList<>() : res;
|
return res == null ? new ArrayList<>() : res;
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import java.util.List;
|
|||||||
|
|
||||||
public class LocationAdapter extends RecyclerView.Adapter<LocationAdapter.LocationViewHolder> {
|
public class LocationAdapter extends RecyclerView.Adapter<LocationAdapter.LocationViewHolder> {
|
||||||
|
|
||||||
private Context appContext;
|
private final Context appContext;
|
||||||
private List<Location> locationList;
|
private final List<Location> locationList;
|
||||||
private OnItemClickListener clickListener;
|
private final OnItemClickListener clickListener;
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
public interface OnItemClickListener {
|
||||||
void onItemClick(int clickedPosition);
|
void onItemClick(int clickedPosition);
|
||||||
@@ -44,6 +44,7 @@ public class LocationAdapter extends RecyclerView.Adapter<LocationAdapter.Locati
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the text of the location name
|
* Sets the text of the location name
|
||||||
|
*
|
||||||
* @param text the text that will be set
|
* @param text the text that will be set
|
||||||
*/
|
*/
|
||||||
public void setTextViewText(String text) {
|
public void setTextViewText(String text) {
|
||||||
@@ -53,6 +54,7 @@ public class LocationAdapter extends RecyclerView.Adapter<LocationAdapter.Locati
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the image of the locatoin
|
* Sets the image of the locatoin
|
||||||
|
*
|
||||||
* @param text the text of the image filename
|
* @param text the text of the image filename
|
||||||
*/
|
*/
|
||||||
public void setImageViewImage(String text) {
|
public void setImageViewImage(String text) {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import android.content.Context;
|
|||||||
|
|
||||||
import com.a1.nextlocation.data.Location;
|
import com.a1.nextlocation.data.Location;
|
||||||
|
|
||||||
import org.osmdroid.util.GeoPoint;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import com.a1.nextlocation.data.Location;
|
|||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class LocationLoader implements Loader<List<Location>> {
|
public class LocationLoader implements Loader<List<Location>> {
|
||||||
@@ -19,6 +18,7 @@ public class LocationLoader implements Loader<List<Location>> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* loads the array list from a JSON file
|
* loads the array list from a JSON file
|
||||||
|
*
|
||||||
* @return array list with locations
|
* @return array list with locations
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -32,7 +32,8 @@ public class LocationLoader implements Loader<List<Location>> {
|
|||||||
fileName += "-" + selectedLanguage;
|
fileName += "-" + selectedLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Location> res = fileIO.readFileData(context,fileName + ".json",new TypeToken<ArrayList<Location>>(){}.getType());
|
ArrayList<Location> res = fileIO.readFileData(context, fileName + ".json", new TypeToken<ArrayList<Location>>() {
|
||||||
|
}.getType());
|
||||||
|
|
||||||
return res == null ? new ArrayList<>() : res;
|
return res == null ? new ArrayList<>() : res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.a1.nextlocation.recyclerview;
|
package com.a1.nextlocation.recyclerview;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -11,16 +10,15 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.a1.nextlocation.R;
|
import com.a1.nextlocation.R;
|
||||||
import com.a1.nextlocation.data.Location;
|
|
||||||
import com.a1.nextlocation.data.Route;
|
import com.a1.nextlocation.data.Route;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class RouteAdapter extends RecyclerView.Adapter<RouteAdapter.RouteViewHolder> {
|
public class RouteAdapter extends RecyclerView.Adapter<RouteAdapter.RouteViewHolder> {
|
||||||
|
|
||||||
private Context appContext;
|
private final Context appContext;
|
||||||
private List<Route> routeList;
|
private final List<Route> routeList;
|
||||||
private CouponAdapter.OnItemClickListener clickListener;
|
private final CouponAdapter.OnItemClickListener clickListener;
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
public interface OnItemClickListener {
|
||||||
void onItemClick(int clickedPosition);
|
void onItemClick(int clickedPosition);
|
||||||
@@ -43,6 +41,7 @@ public class RouteAdapter extends RecyclerView.Adapter<RouteAdapter.RouteViewHol
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the text of the route name
|
* sets the text of the route name
|
||||||
|
*
|
||||||
* @param text the text that will be set
|
* @param text the text that will be set
|
||||||
*/
|
*/
|
||||||
public void setTextViewText(String text) {
|
public void setTextViewText(String text) {
|
||||||
|
|||||||
@@ -3,12 +3,10 @@ package com.a1.nextlocation.recyclerview;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.a1.nextlocation.data.FileIO;
|
import com.a1.nextlocation.data.FileIO;
|
||||||
import com.a1.nextlocation.data.Location;
|
|
||||||
import com.a1.nextlocation.data.Route;
|
import com.a1.nextlocation.data.Route;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class RouteLoader implements Loader<List<Route>> {
|
public class RouteLoader implements Loader<List<Route>> {
|
||||||
@@ -20,6 +18,7 @@ public class RouteLoader implements Loader<List<Route>> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* loads an array list from a JSON
|
* loads an array list from a JSON
|
||||||
|
*
|
||||||
* @return an array list with routes
|
* @return an array list with routes
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -34,7 +33,8 @@ public class RouteLoader implements Loader<List<Route>> {
|
|||||||
fileName += "-" + selectedLanguage;
|
fileName += "-" + selectedLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<Route> res = fileIO.readFileData(context, fileName + ".json",new TypeToken<ArrayList<Route>>(){}.getType());
|
ArrayList<Route> res = fileIO.readFileData(context, fileName + ".json", new TypeToken<ArrayList<Route>>() {
|
||||||
|
}.getType());
|
||||||
return res == null ? new ArrayList<>() : res;
|
return res == null ? new ArrayList<>() : res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user