diff --git a/.gitignore b/.gitignore index 2c17da7..7c1819d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,80 +1,11 @@ -# Built application files -*.apk -*.ap_ -*.aab +\.idea/ -# Files for the ART/Dalvik VM -*.dex +\.gradle/ -# Java class files -*.class - -# Generated files -bin/ -gen/ -out/ - -# Gradle files -.gradle/ -build/ - -# Local configuration file (sdk path, etc) -local.properties - -# Proguard folder generated by Eclipse -proguard/ - -# Log Files -*.log - -# Android Studio Navigation editor temp files -.navigation/ - -# Android Studio captures folder -captures/ - -# IntelliJ *.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/assetWizardSettings.xml -.idea/dictionaries -.idea/libraries -.idea/caches -# Android Studio 3 in .gitignore file. -.idea/caches/build_file_checksums.ser -.idea/modules.xml - -# Keystore files -# Uncomment the following lines if you do not want to check your keystore files in. -#*.jks -#*.keystore - -# External native build folder generated in Android Studio 2.2 and later -.externalNativeBuild - -# Google Services (e.g. APIs or Firebase) -# google-services.json - -# Freeline -freeline.py -freeline/ -freeline_project_description.json -# fastlane -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots -fastlane/test_output -fastlane/readme.md +local\.properties -# Version control -vcs.xml +app/debug/ -# lint -lint/intermediates/ -lint/generated/ -lint/outputs/ -lint/tmp/ -# lint/reports/ \ No newline at end of file +app/release/ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 30aa626..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a1..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index f43d428..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 7bfef59..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml deleted file mode 100644 index b1e692e..0000000 --- a/.idea/navEditor.xml +++ /dev/null @@ -1,394 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/saveactions_settings.xml b/.idea/saveactions_settings.xml deleted file mode 100644 index 09fbfc6..0000000 --- a/.idea/saveactions_settings.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/android-studio-settings/settings.jar b/android-studio-settings/settings.jar deleted file mode 100644 index effeccb..0000000 Binary files a/android-studio-settings/settings.jar and /dev/null differ diff --git a/android-studio-settings/settings.zip b/android-studio-settings/settings.zip new file mode 100644 index 0000000..6980d27 Binary files /dev/null and b/android-studio-settings/settings.zip differ diff --git a/app/build.gradle b/app/build.gradle index b161b46..c6ee024 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,15 +39,35 @@ dependencies { implementation 'androidx.navigation:navigation-ui:2.0.0' implementation 'androidx.preference:preference:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' - implementation 'androidx.room:room-coroutines:2.1.0-alpha04' implementation 'androidx.room:room-runtime:2.0.0' - implementation 'androidx.room:room-rxjava2:2.0.0' + annotationProcessor 'androidx.room:room-compiler:2.0.0' implementation 'androidx.viewpager:viewpager:1.0.0' annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.0.0' - annotationProcessor 'androidx.room:room-compiler:2.0.0' - testImplementation 'androidx.room:room-testing:2.0.0' testImplementation 'androidx.arch.core:core-testing:2.0.1' + + // Google auth + implementation 'com.google.android.gms:play-services-auth:16.0.1' + + // Core library + androidTestImplementation 'androidx.test:core:1.1.0' + + // AndroidJUnitRunner and JUnit Rules androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test:rules:1.1.1' + + // Assertions + androidTestImplementation 'androidx.test.ext:junit:1.1.0' + androidTestImplementation 'androidx.test.ext:truth:1.1.0' + androidTestImplementation 'com.google.truth:truth:0.42' + + // Espresso dependencies + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.1' + androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' // Android Material Design @@ -55,6 +75,7 @@ dependencies { // Google play maps services implementation 'com.google.android.gms:play-services-maps:16.1.0' + implementation 'com.google.android.gms:play-services-location:16.0.0' // RetrofitService implementation 'com.squareup.retrofit2:retrofit:2.5.0' diff --git a/app/debug/app-debug.apk b/app/debug/app-debug.apk deleted file mode 100644 index 24d12a3..0000000 Binary files a/app/debug/app-debug.apk and /dev/null differ diff --git a/app/debug/output.json b/app/debug/output.json deleted file mode 100644 index f20a39f..0000000 --- a/app/debug/output.json +++ /dev/null @@ -1 +0,0 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-debug.apk","fullName":"debug","baseName":"debug"},"path":"app-debug.apk","properties":{}}] \ No newline at end of file diff --git a/app/release/app-release.apk b/app/release/app-release.apk deleted file mode 100644 index 91ccec9..0000000 Binary files a/app/release/app-release.apk and /dev/null differ diff --git a/app/release/output.json b/app/release/output.json deleted file mode 100644 index 9f0c959..0000000 --- a/app/release/output.json +++ /dev/null @@ -1 +0,0 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/sampledata/locations.json b/app/sampledata/places.json similarity index 85% rename from app/sampledata/locations.json rename to app/sampledata/places.json index d9ec130..a6d2bda 100644 --- a/app/sampledata/locations.json +++ b/app/sampledata/places.json @@ -1,33 +1,29 @@ { - "comment": "Localizaciones", + "comment": "Tours", "data": [ { - "name": "Localizacion 1", + "name": "Lugar 1", "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur non ullamcorper lectus, ac semper nibh. Vivamus dignissim egestas dapibus. Nullam mattis tortor est, in accumsan mi blandit et. Etiam pharetra non purus nec semper. Curabitur eu laoreet justo. Vivamus pellentesque, turpis vel hendrerit auctor, eros lacus consequat ex, in aliquam mi lorem vel urna. Fusce iaculis nibh metus, ut mollis mi egestas ut. Fusce ac lectus ac purus aliquet semper id quis lacus. Praesent eleifend vitae nisl eu varius. Nullam sodales vel lorem eget iaculis. Sed pretium diam est. Nulla feugiat ante at congue ultricies. Curabitur pellentesque fermentum libero, ac aliquet ante sollicitudin nec. Morbi tempus efficitur risus, a condimentum dolor lacinia vitae. Nullam non blandit neque. Sed at justo non risus malesuada varius. Morbi in feugiat sem. Cras auctor urna sed interdum placerat. Nam accumsan augue velit, a placerat mi suscipit sed. Mauris dictum, est ac placerat tincidunt, mi nulla varius augue, nec dictum mauris libero et diam. Nam viverra efficitur felis, quis scelerisque nulla consectetur et. Fusce vitae varius est. Vivamus diam lacus, malesuada eget fringilla eu, iaculis ac ante. Phasellus lacus est, vehicula id scelerisque congue, mattis vel diam. Cras quis aliquet nulla. Integer euismod consequat vestibulum. Pellentesque accumsan sodales tristique. Quisque sapien nibh, eleifend sit amet sem porta, cursus lacinia tellus. Morbi pellentesque scelerisque dolor vehicula pulvinar. Praesent vehicula justo sit amet quam bibendum, in ullamcorper nulla auctor. Praesent vel metus eget est blandit consequat non ut dolor. Donec id pretium ante. Cras eget maximus sapien. Suspendisse hendrerit, nisl tempus dictum fermentum, est mi accumsan est, sed tempus quam ipsum quis neque. Praesent vitae elit vel dolor ultrices congue. Vivamus tempor lacus ligula, quis porta mi venenatis non. Nunc pharetra orci at sapien pulvinar blandit. Aliquam id diam turpis. Aenean tincidunt tristique ipsum nec scelerisque. Aliquam.", "visits": "2.456", - "distance": "563m", - "image": "location_image.jpeg" + "distance": "563m" }, { - "name": "Localizacion 2", + "name": "Lugar 2", "description": "Descripcion 2", "visits": "2.456", - "distance": "563m", - "image": "location_image.jpeg" + "distance": "563m" }, { - "name": "Localizacion 3", + "name": "Lugar 3", "description": "Descripcion 3", "visits": "2.456", - "distance": "563m", - "image": "location_image.jpeg" + "distance": "563m" }, { - "name": "Localizacion 4", + "name": "Lugar 4", "description": "Descripcion 4", "visits": "2.456", - "distance": "563m", - "image": "location_image.jpeg" + "distance": "563m" } ] } \ No newline at end of file diff --git a/app/sampledata/maps.json b/app/sampledata/tours.json similarity index 79% rename from app/sampledata/maps.json rename to app/sampledata/tours.json index fb6c692..71636ea 100644 --- a/app/sampledata/maps.json +++ b/app/sampledata/tours.json @@ -7,7 +7,7 @@ "creator": "Creador 1", "progress": "50", "progress_text": "15/30", - "num_locations": "30 localizaciones" + "num_places": "30 localizaciones" }, { "name": "Mapa 2", @@ -15,7 +15,7 @@ "creator": "Creador 2", "progress": "50", "progress_text": "15/30", - "num_locations": "30 localizaciones" + "num_places": "30 localizaciones" }, { "name": "Mapa 3", @@ -23,7 +23,7 @@ "creator": "Creador 3", "progress": "50", "progress_text": "15/30", - "num_locations": "30 localizaciones" + "num_places": "30 localizaciones" }, { "name": "Mapa 4", @@ -31,7 +31,7 @@ "creator": "Creador 4", "progress": "50", "progress_text": "15/30", - "num_locations": "30 localizaciones" + "num_places": "30 localizaciones" }, { "name": "Mapa 5", @@ -39,7 +39,7 @@ "creator": "Creador 5", "progress": "50", "progress_text": "15/30", - "num_locations": "30 localizaciones" + "num_places": "30 localizaciones" } ] } \ No newline at end of file diff --git a/app/sampledata/user.json b/app/sampledata/user.json index 35d4d79..5713419 100644 --- a/app/sampledata/user.json +++ b/app/sampledata/user.json @@ -1,7 +1,7 @@ { "comment": "Usuario loggeado", "data": { - "name": "Martin Laiz Gómez", + "name": "Martin Laiz Gomez", "username": "martinlaizg", "email": "martinlaizg@gmail.com" } diff --git a/app/src/main/java/com/martinlaizg/geofind/GeoFind.java b/app/src/main/java/com/martinlaizg/geofind/GeoFind.java index edbeed4..2dc30be 100644 --- a/app/src/main/java/com/martinlaizg/geofind/GeoFind.java +++ b/app/src/main/java/com/martinlaizg/geofind/GeoFind.java @@ -2,7 +2,6 @@ import android.app.Application; - public class GeoFind extends Application { diff --git a/app/src/main/java/com/martinlaizg/geofind/adapter/CreatorLocationAdapter.java b/app/src/main/java/com/martinlaizg/geofind/adapter/CreatorLocationAdapter.java deleted file mode 100644 index 06d57e3..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/adapter/CreatorLocationAdapter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.martinlaizg.geofind.adapter; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.TextView; - -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.database.entity.Location; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -import androidx.recyclerview.widget.RecyclerView; - - -public class CreatorLocationAdapter - extends RecyclerView.Adapter { - - private List locations; - - public CreatorLocationAdapter() { - locations = new ArrayList<>(); - } - - @NotNull - @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_createdlocation, parent, false); - return new ViewHolder(view); - } - - @Override - public void onBindViewHolder(final ViewHolder holder, int position) { - holder.locName.setText(locations.get(position).getName()); - holder.deleteButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - locations.remove(position); - notifyDataSetChanged(); - } - }); - } - - @Override - public int getItemCount() { - return locations.size(); - } - - public void setLocations(List locs) { - if (locs != null) { - locations = locs; - notifyDataSetChanged(); - } - } - - class ViewHolder - extends RecyclerView.ViewHolder { - - final TextView locName; - final ImageButton deleteButton; - - ViewHolder(View view) { - super(view); - locName = view.findViewById(R.id.loc_name); - deleteButton = view.findViewById(R.id.delete_loc_bbutton); - } - - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/adapter/LocationListAdapter.java b/app/src/main/java/com/martinlaizg/geofind/adapter/LocationListAdapter.java deleted file mode 100644 index 9620cd9..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/adapter/LocationListAdapter.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.martinlaizg.geofind.adapter; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.enums.PlayLevel; -import com.martinlaizg.geofind.views.fragment.single.LocationFragment; - -import java.util.ArrayList; -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.cardview.widget.CardView; -import androidx.navigation.Navigation; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class LocationListAdapter - extends RecyclerView.Adapter { - - private List locations; - - public LocationListAdapter() { - locations = new ArrayList<>(); - } - - @NonNull - @Override - public LocationsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { - View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_location_item, viewGroup, false); - return new LocationsViewHolder(view); - } - - @Override - public void onBindViewHolder(@NonNull LocationsViewHolder holder, int position) { - Location l = locations.get(position); - holder.location_name.setText(l.getName()); - holder.location_description.setText(l.getDescription()); - Bundle b = new Bundle(); - b.putString(LocationFragment.LOC_ID, l.getId()); - holder.location_card.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.navLocation, b)); - } - - public void setLocations(List locations) { - this.locations = locations; - notifyDataSetChanged(); - } - - @Override - public int getItemCount() { - return locations.size(); - } - - public void setPlayLevel(PlayLevel playLevel) { - notifyDataSetChanged(); - } - - class LocationsViewHolder - extends RecyclerView.ViewHolder { - - @BindView(R.id.location_name) - TextView location_name; - @BindView(R.id.location_description) - TextView location_description; - @BindView(R.id.location_card) - CardView location_card; - - LocationsViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/adapter/MapListAdapter.java b/app/src/main/java/com/martinlaizg/geofind/adapter/MapListAdapter.java deleted file mode 100644 index 5a5cb99..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/adapter/MapListAdapter.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.martinlaizg.geofind.adapter; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.android.material.card.MaterialCardView; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.views.fragment.single.MapFragment; - -import java.util.ArrayList; -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class MapListAdapter - extends RecyclerView.Adapter { - - private List maps = new ArrayList<>(); - private NavController navController; - - @NonNull - @Override - public MapsViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { - View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_map_item, viewGroup, false); - return new MapsViewHolder(view); - } - - @Override - public void onBindViewHolder(@NonNull MapsViewHolder holder, final int i) { - final Map map = maps.get(i); - holder.mapName.setText(map.getName()); - holder.mapCreator.setText("Creador " + map.getCreator_id() + " TODO"); // Cambiar por valor real - holder.mapDescription.setText(map.getDescription()); - - Bundle b = new Bundle(); - b.putString(MapFragment.MAP_ID, maps.get(i).getId()); - holder.materialCardView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Navigation.findNavController(v).navigate(R.id.toMap, b); - } - }); - } - - @Override - public int getItemCount() { - return maps.size(); - } - - public void setMaps(List maps) { - this.maps = maps; - notifyDataSetChanged(); - } - - class MapsViewHolder - extends RecyclerView.ViewHolder { - - @BindView(R.id.map_name) - TextView mapName; - @BindView(R.id.map_creator) - TextView mapCreator; - @BindView(R.id.map_description) - TextView mapDescription; - @BindView(R.id.map_list_item) - MaterialCardView materialCardView; - - MapsViewHolder(@NonNull View itemView) { - super(itemView); - ButterKnife.bind(this, itemView); - } - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/config/Preferences.java b/app/src/main/java/com/martinlaizg/geofind/config/Preferences.java index 0bbe486..c57ec35 100644 --- a/app/src/main/java/com/martinlaizg/geofind/config/Preferences.java +++ b/app/src/main/java/com/martinlaizg/geofind/config/Preferences.java @@ -4,21 +4,15 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.martinlaizg.geofind.data.access.database.entity.User; +import com.martinlaizg.geofind.data.access.database.entities.User; import com.martinlaizg.geofind.utils.DateUtils; -public enum Preferences { +public class Preferences { - USER("loggedUser"); - - final String key; - - Preferences(String key) { - this.key = key; - } + private static final String USER = "loggedUser"; public static User getLoggedUser(SharedPreferences sp) { - String user_string = sp.getString(USER.getKey(), ""); + String user_string = sp.getString(USER, ""); Gson gson = new GsonBuilder().setDateFormat(DateUtils.DATE_FORMAT).create(); return gson.fromJson(user_string, User.class); @@ -27,16 +21,11 @@ public static User getLoggedUser(SharedPreferences sp) { public static void setLoggedUser(SharedPreferences sp, User user) { Gson gson = new GsonBuilder().setDateFormat(DateUtils.DATE_FORMAT).create(); String stringUser = user.toJson(); - sp.edit().putString(USER.getKey(), stringUser).apply(); + sp.edit().putString(USER, stringUser).apply(); } public static void logout(SharedPreferences sp) { - sp.edit().putString(USER.getKey(), null).apply(); - } - - - private String getKey() { - return key; + sp.edit().putString(USER, null).apply(); } } diff --git a/app/src/main/java/com/martinlaizg/geofind/data/Crypto.java b/app/src/main/java/com/martinlaizg/geofind/data/Crypto.java new file mode 100644 index 0000000..9597508 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/Crypto.java @@ -0,0 +1,33 @@ +package com.martinlaizg.geofind.data; + +import android.util.Log; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Crypto { + + private static final String TAG = Crypto.class.getSimpleName(); + private static MessageDigest mdSHA512; + + public static String hash(String toHash) { + String hashed = null; + try { + if(mdSHA512 == null) { + mdSHA512 = MessageDigest.getInstance("SHA-512"); + } + // mdSHA512.update(salt); + byte[] bytes = mdSHA512.digest(toHash.getBytes()); + StringBuilder sb = new StringBuilder(); + for(byte aByte : bytes) { + sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1)); + } + hashed = sb.toString(); + } catch(NoSuchAlgorithmException e) { + e.printStackTrace(); + } + Log.d(TAG, "hash: " + hashed); + return hashed; + + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/RestClient.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/RestClient.java new file mode 100644 index 0000000..b9541c5 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/RestClient.java @@ -0,0 +1,75 @@ +package com.martinlaizg.geofind.data.access.api; + +import com.martinlaizg.geofind.data.access.database.entities.PlacePlay; +import com.martinlaizg.geofind.data.access.database.entities.Play; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.access.database.entities.User; + +import java.util.List; +import java.util.Map; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.PUT; +import retrofit2.http.Path; +import retrofit2.http.QueryMap; + +public interface RestClient { + + // + // + // + // + // Tours + + // Get tours with optional filter + @GET("tours") + Call> getTours(@QueryMap java.util.Map params); + + @POST("tours") + Call createTour(@Body Tour tour); + + // Get single tourEntity + @GET("tours/{tour_id}") + Call getTour(@Path("tour_id") Integer tour_id); + + // Update tourEntity + @PUT("tours/{tour_id}") + Call update(@Path("tour_id") Integer tour_id, @Body Tour t); + + // + // + // + // + // User requests + + // Login user + @POST("login") + Call login(@Body User body); + + // Create a user + @POST("users") + Call registry(@Body User user); + + // + // + // + // + // Play requests + + // Get user play + @GET("plays") + Call getUserPlay(@QueryMap Map params); + + // Create user play + @POST("plays") + Call createUserPlay(@QueryMap Map params); + + @POST("plays/{play_id}/places") + Call createPlacePlay(@Path("play_id") Integer play_id, @Body PlacePlay placePlay); + + @POST("support") + Call sendSupportMessage(@QueryMap Map params); +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/RetrofitInstance.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/RetrofitInstance.java new file mode 100644 index 0000000..f7eb488 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/RetrofitInstance.java @@ -0,0 +1,30 @@ +package com.martinlaizg.geofind.data.access.api; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.martinlaizg.geofind.utils.DateUtils; + +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class RetrofitInstance { + + private static final String BASE_URL = "https://geofind1.herokuapp.com/api/"; + // private static final String BASE_URL = "http://192.168.1.36:8000/api/"; + private static Retrofit retrofitInstance; + + public static RestClient getRestClient() { + Retrofit rf = getRetrofitInstance(); + return rf.create(RestClient.class); + } + + public static Retrofit getRetrofitInstance() { + if(retrofitInstance == null) { + Gson gson = new GsonBuilder().setDateFormat(DateUtils.DATE_FORMAT).create(); + retrofitInstance = new Retrofit.Builder().baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)).build(); + } + + return retrofitInstance; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/APIError.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/APIError.java new file mode 100644 index 0000000..2198826 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/APIError.java @@ -0,0 +1,20 @@ +package com.martinlaizg.geofind.data.access.api.error; + +public class APIError { + + private final ErrorType type; + private final String message; + + public APIError(ErrorType type, String message) { + this.type = type; + this.message = message; + } + + public ErrorType getType() { + return type; + } + + public String getMessage() { + return message; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/ErrorType.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/ErrorType.java new file mode 100644 index 0000000..f6552b4 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/ErrorType.java @@ -0,0 +1,27 @@ +package com.martinlaizg.geofind.data.access.api.error; + +import com.google.gson.annotations.SerializedName; +import com.martinlaizg.geofind.R; + +/** + * Types of error from de server + */ +public enum ErrorType { + @SerializedName("other") OTHER(R.string.other_error), + @SerializedName("other") NETWORK(R.string.network_error), + @SerializedName("email") EMAIL(R.string.email_error), + @SerializedName("id") ID(R.string.id_error), + @SerializedName("tour_id") TOUR_ID(R.string.id_error), + @SerializedName("user_id") USER_ID(R.string.id_error), + @SerializedName("exist") EXIST(R.string.id_error), + @SerializedName("completed") COMPLETED(R.string.tour_is_completed); + + private final int message; + + ErrorType(int message) { + this.message = message; + } + + public int getMessage() { + return message; + }} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/ErrorUtils.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/ErrorUtils.java new file mode 100644 index 0000000..ad0804d --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/error/ErrorUtils.java @@ -0,0 +1,36 @@ +package com.martinlaizg.geofind.data.access.api.error; + +import com.martinlaizg.geofind.data.access.api.RetrofitInstance; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; + +import java.io.IOException; +import java.lang.annotation.Annotation; + +import okhttp3.ResponseBody; +import retrofit2.Converter; +import retrofit2.Response; + +public class ErrorUtils { + + /** + * Parse a response to a APIError + * + * @param response response to parse + * @return parsed response + */ + public static APIException parseError(Response response) { + Converter converter = RetrofitInstance.getRetrofitInstance() + .responseBodyConverter(APIException.class, new Annotation[0]); + + APIException error = null; + try { + if(response.errorBody() != null) { + error = converter.convert(response.errorBody()); + } + } catch(IOException e) { + return new APIException(ErrorType.OTHER); + } + + return error; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/PlaceService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/PlaceService.java new file mode 100644 index 0000000..89dc7ac --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/PlaceService.java @@ -0,0 +1,22 @@ +package com.martinlaizg.geofind.data.access.api.service; + +import com.martinlaizg.geofind.data.access.api.RestClient; +import com.martinlaizg.geofind.data.access.api.RetrofitInstance; + +public class PlaceService { + + private static PlaceService placeService; + private static RestClient restClient; + private final String TAG = PlaceService.class.getSimpleName(); + + public static PlaceService getInstance() { + if(restClient == null) { + restClient = RetrofitInstance.getRestClient(); + } + if(placeService == null) { + placeService = new PlaceService(); + } + return placeService; + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/PlayService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/PlayService.java new file mode 100644 index 0000000..5c34ede --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/PlayService.java @@ -0,0 +1,88 @@ +package com.martinlaizg.geofind.data.access.api.service; + +import android.util.Log; + +import com.martinlaizg.geofind.data.access.api.RestClient; +import com.martinlaizg.geofind.data.access.api.RetrofitInstance; +import com.martinlaizg.geofind.data.access.api.error.ErrorType; +import com.martinlaizg.geofind.data.access.api.error.ErrorUtils; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.PlacePlay; +import com.martinlaizg.geofind.data.access.database.entities.Play; + +import java.io.IOException; +import java.util.HashMap; + +import retrofit2.Response; + +public class PlayService { + + private static PlayService locationService; + private static RestClient restClient; + private final String TAG = PlayService.class.getSimpleName(); + + public static PlayService getInstance() { + if(restClient == null) { + restClient = RetrofitInstance.getRestClient(); + } + if(locationService == null) { + locationService = new PlayService(); + } + return locationService; + } + + public Play getUserPlay(int user_id, int tour_id) throws APIException { + Response response; + APIException apiException; + try { + HashMap params = new HashMap<>(); + params.put("user_id", String.valueOf(user_id)); + params.put("tour_id", String.valueOf(tour_id)); + response = restClient.getUserPlay(params).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "getPlace: ", e); + } + throw apiException; + } + + public Play createUserPlay(int user_id, int tour_id) throws APIException { + Response response; + APIException apiException; + try { + HashMap params = new HashMap<>(); + params.put("user_id", String.valueOf(user_id)); + params.put("tour_id", String.valueOf(tour_id)); + response = restClient.createUserPlay(params).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "getPlace: ", e); + } + throw apiException; + } + + public Play createPlacePlay(Integer play_id, Integer place_id) throws APIException { + Response response; + APIException apiException; + try { + PlacePlay pp = new PlacePlay(place_id, play_id); + response = restClient.createPlacePlay(play_id, pp).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "getPlace: ", e); + } + throw apiException; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/TourService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/TourService.java new file mode 100644 index 0000000..9e905a4 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/TourService.java @@ -0,0 +1,99 @@ +package com.martinlaizg.geofind.data.access.api.service; + +import android.util.Log; + +import com.martinlaizg.geofind.data.access.api.RestClient; +import com.martinlaizg.geofind.data.access.api.RetrofitInstance; +import com.martinlaizg.geofind.data.access.api.error.ErrorType; +import com.martinlaizg.geofind.data.access.api.error.ErrorUtils; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.Tour; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; + +import retrofit2.Response; + +public class TourService { + + private static TourService tourService; + private static RestClient restClient; + private final String TAG = TourService.class.getSimpleName(); + + public static TourService getInstance() { + if(restClient == null) { + restClient = RetrofitInstance.getRestClient(); + } + if(tourService == null) { + tourService = new TourService(); + } + return tourService; + } + + public List getAllTours() throws APIException { + Response> response; + APIException apiException; + try { + response = restClient.getTours(new HashMap<>()).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "getTours: ", e); + } + throw apiException; + } + + public Tour create(Tour tour) throws APIException { + Response response; + APIException apiException; + try { + response = restClient.createTour(tour).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "create: ", e); + } + throw apiException; + } + + public Tour getTour(Integer id) throws APIException { + Response response; + APIException apiException; + try { + response = restClient.getTour(id).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "getTour: ", e); + } + throw apiException; + } + + public Tour update(Tour tour) throws APIException { + Response response; + APIException apiException; + try { + response = restClient.update(tour.getId(), tour).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "update: ", e); + } + throw apiException; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/UserService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/UserService.java new file mode 100644 index 0000000..f394c2d --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/UserService.java @@ -0,0 +1,85 @@ +package com.martinlaizg.geofind.data.access.api.service; + +import android.util.Log; + +import com.martinlaizg.geofind.data.access.api.RestClient; +import com.martinlaizg.geofind.data.access.api.RetrofitInstance; +import com.martinlaizg.geofind.data.access.api.error.ErrorType; +import com.martinlaizg.geofind.data.access.api.error.ErrorUtils; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.User; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import retrofit2.Response; + +public class UserService { + + private static UserService userService; + private static RestClient restClient; + private final String TAG = UserService.class.getSimpleName(); + + public static UserService getInstance() { + if(restClient == null) { + restClient = RetrofitInstance.getRestClient(); + } + if(userService == null) { + userService = new UserService(); + } + return userService; + } + + public User login(User user) throws APIException { + Response response; + APIException apiException; + try { + response = restClient.login(user).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "login: ", e); + } + throw apiException; + } + + public User registry(User user) throws APIException { + Response response; + APIException apiException; + try { + response = restClient.registry(user).execute(); + if(response.isSuccessful()) { + return response.body(); + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "registry: ", e); + } + throw apiException; + } + + public boolean sendMessage(String title, String message) throws APIException { + Response response; + APIException apiException; + try { + Map params = new HashMap<>(); + params.put("title", title); + params.put("message", message); + + response = restClient.sendSupportMessage(params).execute(); + if(response.isSuccessful()) { + return true; + } + apiException = ErrorUtils.parseError(response); + } catch(IOException e) { + apiException = new APIException(ErrorType.NETWORK, e.getMessage()); + Log.e(TAG, "registry: ", e); + } + throw apiException; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/exceptions/APIException.java b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/exceptions/APIException.java new file mode 100644 index 0000000..380d085 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/api/service/exceptions/APIException.java @@ -0,0 +1,32 @@ +package com.martinlaizg.geofind.data.access.api.service.exceptions; + +import com.martinlaizg.geofind.data.access.api.error.ErrorType; + +/** + * Exception from API + */ +public class APIException + extends Throwable { + + private final ErrorType type; + private final String message; + + public String getMessage() { + return message; + } + + public APIException(ErrorType type) { + this.type = type; + this.message = null; + } + + public APIException(ErrorType type, String message) { + this.type = type; + this.message = message; + } + + public ErrorType getType() { + return type; + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/AppDatabase.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/AppDatabase.java index a85f212..40e58d4 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/AppDatabase.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/AppDatabase.java @@ -1,42 +1,40 @@ package com.martinlaizg.geofind.data.access.database; import android.content.Context; -import android.os.AsyncTask; -import com.martinlaizg.geofind.data.access.database.converter.DateTypeConverter; -import com.martinlaizg.geofind.data.access.database.converter.PlayLevelTypeConverter; -import com.martinlaizg.geofind.data.access.database.converter.UserTypeTypeConverter; -import com.martinlaizg.geofind.data.access.database.dao.LocationDAO; -import com.martinlaizg.geofind.data.access.database.dao.MapDAO; -import com.martinlaizg.geofind.data.access.database.dao.UserDAO; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.entity.User; - -import androidx.annotation.NonNull; import androidx.room.Database; import androidx.room.Room; import androidx.room.RoomDatabase; import androidx.room.TypeConverters; -import androidx.sqlite.db.SupportSQLiteDatabase; -@Database(entities = {User.class, Map.class, Location.class}, version = 1, exportSchema = false) -@TypeConverters({DateTypeConverter.class, PlayLevelTypeConverter.class, UserTypeTypeConverter.class}) +import com.martinlaizg.geofind.data.access.database.converter.DateTypeConverter; +import com.martinlaizg.geofind.data.access.database.converter.PlayLevelTypeConverter; +import com.martinlaizg.geofind.data.access.database.converter.UserTypeTypeConverter; +import com.martinlaizg.geofind.data.access.database.dao.PlaceDAO; +import com.martinlaizg.geofind.data.access.database.dao.PlayDAO; +import com.martinlaizg.geofind.data.access.database.dao.TourDAO; +import com.martinlaizg.geofind.data.access.database.dao.UserDAO; +import com.martinlaizg.geofind.data.access.database.dao.relations.PlacePlayDAO; +import com.martinlaizg.geofind.data.access.database.dao.relations.TourPlacesDAO; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.PlacePlay; +import com.martinlaizg.geofind.data.access.database.entities.Play; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.access.database.entities.User; + +@Database(entities = {User.class, Tour.class, Place.class, Play.class, PlacePlay.class}, + version = 5, exportSchema = false) +@TypeConverters( + {DateTypeConverter.class, PlayLevelTypeConverter.class, UserTypeTypeConverter.class}) public abstract class AppDatabase extends RoomDatabase { private static AppDatabase instance; - private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback() { - @Override - public void onCreate(@NonNull SupportSQLiteDatabase db) { - super.onCreate(db); - new PopulateDbAsyncTask(instance).execute(); - } - }; public static synchronized AppDatabase getInstance(Context context) { - if (instance == null) { - instance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "geo_find_database"). + if(instance == null) { + instance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, + "geo_find_database"). fallbackToDestructiveMigration(). build(); } @@ -45,28 +43,14 @@ public static synchronized AppDatabase getInstance(Context context) { public abstract UserDAO userDAO(); - public abstract MapDAO mapDAO(); + public abstract TourDAO tourDAO(); - public abstract LocationDAO locationDAO(); + public abstract PlaceDAO placeDAO(); - private static class PopulateDbAsyncTask - extends AsyncTask { - private final UserDAO userDAO; + public abstract PlayDAO playDAO(); - private PopulateDbAsyncTask(AppDatabase db) { - userDAO = db.userDAO(); - } + public abstract TourPlacesDAO tourPlacesDAO(); + + public abstract PlacePlayDAO playPlaceDAO(); - @Override - protected Void doInBackground(Void... voids) { - // Date date = new Date(Calendar.getInstance().getTime().getTime()); - // User user = new User(); - // user.setEmail("martinlaizg@gmail.com"); - // user.setName("Martin"); - // user.setPassword("martinlaizg"); - // user.setUser_type(UserType.ADMINISTRATOR); - // userDAO.insert(user); - return null; - } - } } diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/DBNaming.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/DBNaming.java deleted file mode 100644 index 910f7ad..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/DBNaming.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.martinlaizg.geofind.data.access.database; - -class DBNaming { - - // Tables - public static String USERS_TABLE = "users"; - public static String MAPS_TABLE = "maps"; - public static String LOCATIONS_TABLE = "locations"; - - - // Columnas - public static String USER_NAME = ""; - public static String USER_USERNAME = ""; - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/DateTypeConverter.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/DateTypeConverter.java index ba604f1..7c87bc6 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/DateTypeConverter.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/DateTypeConverter.java @@ -1,10 +1,11 @@ package com.martinlaizg.geofind.data.access.database.converter; -import java.sql.Date; - import androidx.room.TypeConverter; +import java.sql.Date; + public class DateTypeConverter { + @TypeConverter public static Date toDate(Long dateLong) { return dateLong == null ? diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/PlayLevelTypeConverter.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/PlayLevelTypeConverter.java index bc7e357..c54dade 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/PlayLevelTypeConverter.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/PlayLevelTypeConverter.java @@ -1,21 +1,24 @@ package com.martinlaizg.geofind.data.access.database.converter; -import com.martinlaizg.geofind.data.access.database.entity.enums.PlayLevel; - import androidx.room.TypeConverter; -public class PlayLevelTypeConverter { +import com.martinlaizg.geofind.data.enums.PlayLevel; +public class PlayLevelTypeConverter { @TypeConverter public static PlayLevel toPlayLevel(String playLevelString) { return playLevelString == null ? null : - PlayLevel.valueOf(playLevelString); + playLevelString.isEmpty() ? + PlayLevel.MAP : + PlayLevel.valueOf(playLevelString); } @TypeConverter public static String fromPlayLevel(PlayLevel playLevel) { - return playLevel.toString(); + return playLevel == null ? + "" : + playLevel.toString(); } } diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/UserTypeTypeConverter.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/UserTypeTypeConverter.java index 91be208..3d23073 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/UserTypeTypeConverter.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/converter/UserTypeTypeConverter.java @@ -1,11 +1,10 @@ package com.martinlaizg.geofind.data.access.database.converter; -import com.martinlaizg.geofind.data.access.database.entity.enums.UserType; - import androidx.room.TypeConverter; -public class UserTypeTypeConverter { +import com.martinlaizg.geofind.data.enums.UserType; +public class UserTypeTypeConverter { @TypeConverter public static UserType toPlayLevel(String userTypeString) { diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/LocationDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/LocationDAO.java deleted file mode 100644 index 680f0bd..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/LocationDAO.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.dao; - -import com.martinlaizg.geofind.data.access.database.entity.Location; - -import java.util.List; - -import androidx.room.Dao; -import androidx.room.Delete; -import androidx.room.Insert; -import androidx.room.OnConflictStrategy; -import androidx.room.Query; -import androidx.room.Update; - -@Dao -public interface LocationDAO { - - @Insert(onConflict = OnConflictStrategy.REPLACE) - void insert(Location location); - - @Update - void update(Location location); - - @Delete - void delete(Location location); - - @Query("DELETE FROM locations") - void deleteAllLocations(); - - @Query("SELECT * FROM locations") - List getAllLocations(); - - @Query("SELECT * FROM locations WHERE id = :loc_id") - Location getLocation(String loc_id); - - @Query("SELECT * FROM locations WHERE map_id = :map_id") - List getLocationsByMap(String map_id); -} \ No newline at end of file diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/MapDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/MapDAO.java deleted file mode 100644 index f3ab265..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/MapDAO.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.dao; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; - -import java.util.List; - -import androidx.room.Dao; -import androidx.room.Delete; -import androidx.room.Insert; -import androidx.room.OnConflictStrategy; -import androidx.room.Query; -import androidx.room.Update; - -@Dao -public interface MapDAO { - - @Insert(onConflict = OnConflictStrategy.REPLACE) - void insert(Map map); - - @Update - void update(Map map); - - @Delete - void delete(Map map); - - @Query("SELECT * FROM maps") - List getAllMaps(); - - @Query("DELETE FROM maps") - void deleteAllMaps(); - - @Query("SELECT * FROM maps WHERE id = :mapId") - Map getMap(String mapId); - - @Query("SELECT * FROM locations WHERE map_id = :map_id") - List getLocations(String map_id); -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/PlaceDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/PlaceDAO.java new file mode 100644 index 0000000..2516a3a --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/PlaceDAO.java @@ -0,0 +1,30 @@ +package com.martinlaizg.geofind.data.access.database.dao; + +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; +import androidx.room.Update; + +import com.martinlaizg.geofind.data.access.database.entities.Place; + +import java.util.List; + +@Dao +public interface PlaceDAO { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(Place place); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(List place); + + @Update + void update(Place place); + + @Query("DELETE FROM places WHERE tour_id = :tour_id") + void removeTourPlaces(Integer tour_id); + + @Query("SELECT * FROM places WHERE id = :placeId") + Place getPlace(int placeId); +} \ No newline at end of file diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/PlayDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/PlayDAO.java new file mode 100644 index 0000000..e57f819 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/PlayDAO.java @@ -0,0 +1,28 @@ +package com.martinlaizg.geofind.data.access.database.dao; + +import androidx.room.Dao; +import androidx.room.Delete; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Play; + +import java.util.List; + +@Dao +public interface PlayDAO { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(Play play); + + @Delete + void delete(Play play); + + @Query("SELECT * FROM plays WHERE tour_id = :tour_id AND user_id = :user_id") + Play getPlay(int user_id, int tour_id); + + @Query("SELECT p.* FROM places p INNER JOIN place_play pp ON p.id=pp.place_id WHERE pp.play_id = :play_id") + List getPlaces(Integer play_id); +} \ No newline at end of file diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/TourDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/TourDAO.java new file mode 100644 index 0000000..cf8e805 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/TourDAO.java @@ -0,0 +1,34 @@ +package com.martinlaizg.geofind.data.access.database.dao; + +import androidx.room.Dao; +import androidx.room.Delete; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; +import androidx.room.Update; + +import com.martinlaizg.geofind.data.access.database.entities.Tour; + +import java.util.List; + +@Dao +public interface TourDAO { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(Tour tour); + + @Update + void update(Tour tour); + + @Query("SELECT * FROM tours WHERE id = :tour_id") + Tour getTour(Integer tour_id); + + @Delete + void delete(Tour tour); + + @Query("DELETE FROM tours WHERE id = :tour_id") + void delete(int tour_id); + + @Query("SELECT * FROM tours") + List getAll(); +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserDAO.java index 7749eea..d581f05 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserDAO.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserDAO.java @@ -1,17 +1,15 @@ package com.martinlaizg.geofind.data.access.database.dao; -import com.martinlaizg.geofind.data.access.database.entity.User; - -import java.util.List; - -import androidx.lifecycle.LiveData; import androidx.room.Dao; -import androidx.room.Delete; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.Update; +import com.martinlaizg.geofind.data.access.database.entities.User; + +import java.util.List; + @Dao public interface UserDAO { @@ -21,12 +19,9 @@ public interface UserDAO { @Update void update(User user); - @Delete - void delete(User user); + @Query("SELECT * FROM users WHERE id = :user_id") + User getUser(int user_id); @Query("SELECT * FROM users") - LiveData> getAllUsers(); - - @Query("DELETE FROM users") - void deleteAllUsers(); + List getAll(); } diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserLocationDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserLocationDAO.java deleted file mode 100644 index 8df58da..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/UserLocationDAO.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.dao; - -import com.martinlaizg.geofind.data.access.database.entity.relation.MapAllLocations; - -import java.util.List; - -import androidx.room.Dao; -import androidx.room.Query; - -@Dao -public interface UserLocationDAO { - @Query("SELECT * from maps") - List loadUserAndPets(); -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/relations/PlacePlayDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/relations/PlacePlayDAO.java new file mode 100644 index 0000000..cedeaeb --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/relations/PlacePlayDAO.java @@ -0,0 +1,22 @@ +package com.martinlaizg.geofind.data.access.database.dao.relations; + +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; +import androidx.room.Transaction; + +import com.martinlaizg.geofind.data.access.database.entities.PlacePlay; +import com.martinlaizg.geofind.data.access.database.entities.relations.PlayWithPlaces; + +@Dao +public interface PlacePlayDAO { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(PlacePlay placePlay); + + @Transaction + @Query("SELECT * FROM plays WHERE id = :play_id") + PlayWithPlaces getPlayWithPlaces(int play_id); + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/relations/TourPlacesDAO.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/relations/TourPlacesDAO.java new file mode 100644 index 0000000..1a2b034 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/dao/relations/TourPlacesDAO.java @@ -0,0 +1,21 @@ +package com.martinlaizg.geofind.data.access.database.dao.relations; + +import androidx.room.Dao; +import androidx.room.Query; +import androidx.room.Transaction; + +import com.martinlaizg.geofind.data.access.database.entities.relations.TourCreatorPlaces; + +import java.util.List; + +@Dao +public interface TourPlacesDAO { + + @Transaction + @Query("SELECT t.*, username FROM tours as t LEFT JOIN users AS u ON u.id = t.creator_id;") + List getTourCreatorPlaces(); + + @Transaction + @Query("SELECT t.*, username FROM tours as t LEFT JOIN users AS u ON u.id = t.creator_id WHERE t.id = :tour_id;") + TourCreatorPlaces getTour(Integer tour_id); +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Place.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Place.java new file mode 100644 index 0000000..4f55725 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Place.java @@ -0,0 +1,152 @@ +package com.martinlaizg.geofind.data.access.database.entities; + +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Ignore; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +import com.google.android.gms.maps.model.LatLng; +import com.martinlaizg.geofind.utils.DateUtils; + +import java.sql.Date; +import java.util.Calendar; + +import static androidx.room.ForeignKey.CASCADE; + +@Entity(tableName = "places", foreignKeys = @ForeignKey(entity = Tour.class, parentColumns = "id", + childColumns = "tour_id", + onDelete = CASCADE), + indices = @Index("tour_id")) +public class Place { + + @PrimaryKey + private final int id; + private String name; + private Double lat; + private Double lon; + private Integer tour_id; + private String description; + private Integer order; + private Date created_at; + private Date updated_at; + private Date updated; + + public Place(Integer id, String name, Double lat, Double lon, Integer tour_id, + String description, Integer order, Date created_at, Date updated_at, Date updated) { + this.id = id; + this.name = name; + this.lat = lat; + this.lon = lon; + this.tour_id = tour_id; + this.description = description; + this.order = order; + this.created_at = created_at; + this.updated_at = updated_at; + this.updated = updated; + } + + @Ignore + public Place() { + id = 0; + } + + public int getId() { + return id; + } + + public Date getCreated_at() { + return created_at; + } + + public void setCreated_at(Date created_at) { + this.created_at = created_at; + } + + public Date getUpdated_at() { + return updated_at; + } + + public void setUpdated_at(Date updated_at) { + this.updated_at = updated_at; + } + + public Integer getTour_id() { + return tour_id; + } + + public void setTour_id(Integer tour_id) { + this.tour_id = tour_id; + } + + public LatLng getPosition() { + if(lat == null || lon == null) return null; + return new LatLng(lat, lon); + } + + public void setPosition(LatLng position) { + setLat(position.latitude); + setLon(position.longitude); + } + + public Integer getOrder() { + return order; + } + + public void setOrder(Integer order) { + this.order = order; + } + + boolean isValid() { + return getName() != null && !getName().isEmpty() && getDescription() != null && + !getDescription().isEmpty() && getLat() != null && getLon() != null; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public Double getLat() { + return lat; + } + + public Double getLon() { + return lon; + } + + public void setLat(Double lat) { + this.lat = lat; + } + + public void setLon(Double lon) { + this.lon = lon; + } + + public void setDescription(String description) { + this.description = description; + } + + public Date getUpdated() { + return new Date(Calendar.getInstance().getTime().getTime()); + } + + public void setUpdated(Date updated) { + if(updated == null) { + this.updated = new Date(Calendar.getInstance().getTime().getTime()); + } + this.updated = updated; + } + + public boolean isOutOfDate() { + return DateUtils.isDateExpire(updated); + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/PlacePlay.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/PlacePlay.java new file mode 100644 index 0000000..70148ec --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/PlacePlay.java @@ -0,0 +1,90 @@ +package com.martinlaizg.geofind.data.access.database.entities; + +import androidx.annotation.NonNull; +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Index; + +import com.martinlaizg.geofind.utils.DateUtils; + +import java.sql.Date; +import java.util.Calendar; + +import static androidx.room.ForeignKey.CASCADE; + +@Entity(tableName = "place_play", primaryKeys = {"play_id", "place_id"}, foreignKeys = { + @ForeignKey(entity = Play.class, parentColumns = "id", childColumns = "play_id", + onDelete = CASCADE), + @ForeignKey(entity = Place.class, parentColumns = "id", childColumns = "place_id", + onDelete = CASCADE)}, indices = @Index({"place_id", "play_id"})) +public class PlacePlay { + + @NonNull + private Integer place_id; + @NonNull + private Integer play_id; + @NonNull + private Date created_at; + @NonNull + private Date updated_at; + private Date updated; + + public PlacePlay(@NonNull Integer place_id, @NonNull Integer play_id) { + this.play_id = play_id; + this.place_id = place_id; + this.created_at = new Date(Calendar.getInstance().getTime().getTime()); + this.updated_at = new Date(Calendar.getInstance().getTime().getTime()); + } + + @NonNull + public Integer getPlay_id() { + return play_id; + } + + public void setPlay_id(@NonNull Integer play_id) { + this.play_id = play_id; + } + + @NonNull + public Integer getPlace_id() { + return place_id; + } + + public void setPlace_id(@NonNull Integer place_id) { + this.place_id = place_id; + } + + @NonNull + public Date getCreated_at() { + return created_at; + } + + public void setCreated_at(@NonNull Date created_at) { + this.created_at = created_at; + } + + @NonNull + public Date getUpdated_at() { + return updated_at; + } + + public void setUpdated_at(@NonNull Date updated_at) { + this.updated_at = updated_at; + } + + public Date getUpdated() { + return new Date(Calendar.getInstance().getTime().getTime()); + } + + public void setUpdated(Date updated) { + if(updated == null) { + this.updated = new Date(Calendar.getInstance().getTime().getTime()); + } + this.updated = updated; + } + + public boolean isOutOfDate() { + return DateUtils.isDateExpire(updated); + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Play.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Play.java new file mode 100644 index 0000000..2982361 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Play.java @@ -0,0 +1,141 @@ +package com.martinlaizg.geofind.data.access.database.entities; + +import androidx.annotation.NonNull; +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Ignore; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +import com.martinlaizg.geofind.utils.DateUtils; + +import java.sql.Date; +import java.util.Calendar; +import java.util.List; + +import static androidx.room.ForeignKey.CASCADE; + +@Entity(tableName = "plays", foreignKeys = { + @ForeignKey(entity = Tour.class, parentColumns = "id", childColumns = "tour_id", + onDelete = CASCADE), + @ForeignKey(entity = User.class, parentColumns = "id", childColumns = "user_id", + onDelete = CASCADE)}, + indices = {@Index({"tour_id", "user_id"}), @Index("user_id")}) +public class Play { + + @PrimaryKey + @NonNull + private final Integer id; + private Integer tour_id; + private Integer user_id; + private Date created_at; + private Date updated_at; + private Date updated; + + @Ignore + private Tour tour; + @Ignore + private User user; + @Ignore + private List places; + + public Play(@NonNull Integer id, Integer tour_id, Integer user_id, Date created_at, + Date updated_at, Date updated) { + this.id = id; + this.tour_id = tour_id; + this.user_id = user_id; + this.created_at = created_at; + this.updated_at = updated_at; + this.updated = updated; + } + + @Ignore + public Play() { + this.id = 0; + } + + @Ignore + public Play(int tour_id, int user_id) { + this.id = 0; + this.tour_id = tour_id; + this.user_id = user_id; + } + + @NonNull + public Integer getId() { + return id; + } + + public Integer getTour_id() { + return tour_id; + } + + public void setTour_id(Integer tour_id) { + this.tour_id = tour_id; + } + + public Integer getUser_id() { + return user_id; + } + + public void setUser_id(Integer user_id) { + this.user_id = user_id; + } + + public Date getCreated_at() { + return created_at; + } + + public void setCreated_at(Date created_at) { + this.created_at = created_at; + } + + public Date getUpdated_at() { + return updated_at; + } + + public void setUpdated_at(Date updated_at) { + this.updated_at = updated_at; + } + + public Tour getTour() { + return tour; + } + + public void setTour(Tour tour) { + this.tour_id = tour.getId(); + this.tour = tour; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user_id = user.getId(); + this.user = user; + } + + public List getPlaces() { + return places; + } + + public void setPlaces(List places) { + this.places = places; + } + + public boolean isOutOfDate() { + return DateUtils.isDateExpire(updated); + } + + public Date getUpdated() { + return new Date(Calendar.getInstance().getTime().getTime()); + } + + public void setUpdated(Date updated) { + if(updated == null) { + this.updated = new Date(Calendar.getInstance().getTime().getTime()); + } + this.updated = updated; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Tour.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Tour.java new file mode 100644 index 0000000..9898f5b --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/Tour.java @@ -0,0 +1,153 @@ +package com.martinlaizg.geofind.data.access.database.entities; + +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Ignore; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +import com.martinlaizg.geofind.data.enums.PlayLevel; +import com.martinlaizg.geofind.utils.DateUtils; + +import java.sql.Date; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import static androidx.room.ForeignKey.CASCADE; + +@Entity(tableName = "tours", foreignKeys = @ForeignKey(entity = User.class, parentColumns = "id", + childColumns = "creator_id", + onDelete = CASCADE), + indices = @Index("creator_id")) +public class Tour { + + @PrimaryKey + private final int id; + private String name; + private String description; + private PlayLevel min_level; + private Date created_at; + private Date updated_at; + private Integer creator_id; + private Date updated; + + @Ignore + private List places; + @Ignore + private User creator; + + public Tour(Integer id, String name, String description, PlayLevel min_level, Date created_at, + Date updated_at, Integer creator_id, Date updated) { + this.id = id; + this.name = name; + this.description = description; + this.min_level = min_level; + this.created_at = created_at; + this.updated_at = updated_at; + this.creator_id = creator_id; + this.updated = updated; + } + + @Ignore + public Tour() { + id = 0; + name = ""; + description = ""; + places = new ArrayList<>(); + } + + public int getId() { + return id; + } + + public Integer getCreator_id() { + return creator_id; + } + + public void setCreator_id(Integer creator_id) { + this.creator_id = creator_id; + } + + public Date getCreated_at() { + return created_at; + } + + public void setCreated_at(Date created_at) { + this.created_at = created_at; + } + + public Date getUpdated_at() { + return updated_at; + } + + public void setUpdated_at(Date updated_at) { + this.updated_at = updated_at; + } + + public User getCreator() { + return creator; + } + + public void setCreator(User creator) { + this.creator = creator; + } + + public boolean isValid() { + for(Place p : getPlaces()) { + if(!p.isValid()) return false; + } + return getName() != null && !getName().isEmpty() && // + getDescription() != null && !getDescription().isEmpty() && // + getMin_level() != null; + } + + public List getPlaces() { + return places; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + //------------------------- + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public PlayLevel getMin_level() { + return min_level; + } + + public void setMin_level(PlayLevel min_level) { + this.min_level = min_level; + } + + public void setPlaces(List places) { + this.places = places; + } + + public boolean isOutOfDate() { + return DateUtils.isDateExpire(updated); + } + + public Date getUpdated() { + return new Date(Calendar.getInstance().getTime().getTime()); + } + + public void setUpdated(Date updated) { + if(updated == null) { + this.updated = new Date(Calendar.getInstance().getTime().getTime()); + } + this.updated = updated; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/User.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/User.java similarity index 64% rename from app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/User.java rename to app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/User.java index c0f99b8..f6ae064 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/User.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/User.java @@ -1,63 +1,57 @@ -package com.martinlaizg.geofind.data.access.database.entity; +package com.martinlaizg.geofind.data.access.database.entities; +import androidx.room.Entity; +import androidx.room.Ignore; +import androidx.room.Index; +import androidx.room.PrimaryKey; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.martinlaizg.geofind.data.access.database.entity.enums.UserType; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; +import com.martinlaizg.geofind.data.enums.UserType; import com.martinlaizg.geofind.utils.DateUtils; import java.sql.Date; +import java.util.Calendar; +import java.util.List; -import androidx.annotation.NonNull; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -@Entity(tableName = "users") +@Entity(tableName = "users", indices = {@Index({"id"})}) public class User { @PrimaryKey - @NonNull - private String id; + private final int id; private String email; private String username; private String name; - private String password; - private Date bdate; private UserType user_type; private Date created_at; private Date updated_at; + private Date updated; @Ignore - private APIError error; - - public User() { - } - + private String password; @Ignore - public User(String email, String password) { + private List createdPlaces; + + public User(Integer id, String email, String username, String name, UserType user_type, + Date created_at, Date updated_at) { + this.id = id; this.email = email; - this.password = password; + this.username = username; + this.name = name; + this.user_type = user_type; + this.created_at = created_at; + this.updated_at = updated_at; } @Ignore - public User(String name, String username, String email, String password) { - this.name = name; - this.username = username; - this.email = email; - this.password = password; - user_type = UserType.USER; + public User() { + id = 0; } - public String getId() { + public int getId() { return id; } - public void setId(String id) { - this.id = id; - } - public String getEmail() { return email; } @@ -90,14 +84,6 @@ public void setPassword(String password) { this.password = password; } - public Date getBdate() { - return bdate; - } - - public void setBdate(Date bdate) { - this.bdate = bdate; - } - public UserType getUser_type() { return user_type; } @@ -122,17 +108,23 @@ public void setUpdated_at(Date updated_at) { this.updated_at = updated_at; } - public String toJson() { Gson gson = new GsonBuilder().setDateFormat(DateUtils.DATE_FORMAT).create(); return gson.toJson(this); } - public APIError getError() { - return error; + public boolean isOutOfDate() { + return DateUtils.isDateExpire(updated); + } + + public Date getUpdated() { + return new Date(Calendar.getInstance().getTime().getTime()); } - public void setError(APIError error) { - this.error = error; + public void setUpdated(Date updated) { + if(updated == null) { + this.updated = new Date(Calendar.getInstance().getTime().getTime()); + } + this.updated = updated; } } diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/relations/PlayWithPlaces.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/relations/PlayWithPlaces.java new file mode 100644 index 0000000..d558d83 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/relations/PlayWithPlaces.java @@ -0,0 +1,34 @@ +package com.martinlaizg.geofind.data.access.database.entities.relations; + +import androidx.room.Embedded; +import androidx.room.Relation; + +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Play; + +import java.util.List; + +public class PlayWithPlaces { + + @Embedded + public Play play; + + @Relation(parentColumn = "id", entityColumn = "id") + List places; + + public Play getPlay() { + return play; + } + + public void setPlay(Play play) { + this.play = play; + } + + public List getPlaces() { + return places; + } + + public void setPlaces(List places) { + this.places = places; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/relations/TourCreatorPlaces.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/relations/TourCreatorPlaces.java new file mode 100644 index 0000000..8f9e0d0 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entities/relations/TourCreatorPlaces.java @@ -0,0 +1,51 @@ +package com.martinlaizg.geofind.data.access.database.entities.relations; + +import androidx.room.Embedded; +import androidx.room.Relation; + +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.access.database.entities.User; + +import java.util.List; + +public class TourCreatorPlaces { + + @Embedded + private Tour tour; + + private String username; + + @Relation(parentColumn = "id", entityColumn = "tour_id") + private List places; + + public Tour getTour() { + return tour; + } + + public void setTour(Tour tour) { + this.tour = tour; + } + + public List getPlaces() { + return places; + } + + public void setPlaces(List places) { + this.places = places; + } + + public User getCreator() { + User u = new User(); + u.setUsername(getUsername()); + return u; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/Location.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/Location.java deleted file mode 100644 index 8dc1bb5..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/Location.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.entity; - -import com.google.android.gms.maps.model.LatLng; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; - -import org.jetbrains.annotations.NotNull; - -import java.sql.Date; -import java.util.UUID; - -import androidx.annotation.NonNull; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Ignore; -import androidx.room.Index; -import androidx.room.PrimaryKey; - -import static androidx.room.ForeignKey.CASCADE; - -@Entity(tableName = "locations", foreignKeys = @ForeignKey(entity = Map.class, parentColumns = "id", childColumns = "map_id", onDelete = CASCADE), indices = @Index("map_id")) -public class Location { - - @PrimaryKey - @NonNull - private String id; - private String name; - private String lat; - private String lon; - private String map_id; - private String description; - private Date created_at; - private Date updated_at; - - @Ignore - private APIError error; - - public Location(String name, String lat, String lon, String map_id, Date created_at, Date updated_at) { - id = UUID.randomUUID().toString(); - this.name = name; - this.lat = lat; - this.lon = lon; - this.map_id = map_id; - this.created_at = created_at; - this.updated_at = updated_at; - } - - @Ignore - public Location() { - id = UUID.randomUUID().toString(); - } - - @NotNull - public String getId() { - return id; - } - - public void setId(@NotNull String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLat() { - return lat; - } - - public void setLat(String lat) { - this.lat = lat; - } - - public String getLon() { - return lon; - } - - public void setLon(String lon) { - this.lon = lon; - } - - public Date getCreated_at() { - return created_at; - } - - public void setCreated_at(Date created_at) { - this.created_at = created_at; - } - - public Date getUpdated_at() { - return updated_at; - } - - public void setUpdated_at(Date updated_at) { - this.updated_at = updated_at; - } - - public String getMap_id() { - return map_id; - } - - public void setMap_id(String map_id) { - this.map_id = map_id; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public LatLng getLatLng() { - return new LatLng(Double.valueOf(getLat()), Double.valueOf(getLon())); - } - - public android.location.Location getAndroidLocation() { - android.location.Location l = new android.location.Location(getName()); - l.setLatitude(Double.valueOf(getLat())); - l.setLongitude(Double.valueOf(getLon())); - return l; - } - - public APIError getError() { - return error; - } - - public void setError(APIError error) { - this.error = error; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/Map.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/Map.java deleted file mode 100644 index 12fdeef..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/Map.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.entity; - -import com.martinlaizg.geofind.data.access.database.entity.enums.PlayLevel; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; - -import java.sql.Date; -import java.util.UUID; - -import androidx.annotation.NonNull; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -@Entity(tableName = "maps") -public class Map { - - @PrimaryKey - @NonNull - private String id; - private String name; - private String country; - private String state; - private String description; - private String city; - private PlayLevel min_level; - private Date created_at; - private Date updated_at; - private String creator_id; - - @Ignore - private APIError error; - - public Map(@NonNull String id, String name, String country, String state, String description, String city, PlayLevel min_level, Date created_at, Date updated_at, String creator_id) { - this.id = id; - this.name = name; - this.country = country; - this.state = state; - this.description = description; - this.city = city; - this.min_level = min_level; - this.created_at = created_at; - this.updated_at = updated_at; - this.creator_id = creator_id; - } - - @Ignore - public Map() { - id = UUID.randomUUID().toString(); - name = ""; - description = ""; - } - - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public PlayLevel getMin_level() { - return min_level; - } - - public void setMin_level(PlayLevel min_level) { - this.min_level = min_level; - } - - public Date getCreated_at() { - return created_at; - } - - public void setCreated_at(Date created_at) { - this.created_at = created_at; - } - - public Date getUpdated_at() { - return updated_at; - } - - public void setUpdated_at(Date updated_at) { - this.updated_at = updated_at; - } - - public String getCreator_id() { - return creator_id; - } - - public void setCreator_id(String creator_id) { - this.creator_id = creator_id; - } - - public APIError getError() { - return error; - } - - public void setError(APIError error) { - this.error = error; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/relation/MapAllLocations.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/relation/MapAllLocations.java deleted file mode 100644 index 715c44b..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/relation/MapAllLocations.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.entity.relation; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; - -import java.util.List; - -import androidx.room.Embedded; -import androidx.room.Relation; - -public class MapAllLocations { - @Embedded - public Map map; - @Relation(parentColumn = "id", entityColumn = "map_id", entity = Location.class) - public List locations; -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/LocationRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/LocationRepository.java deleted file mode 100644 index d3c6f8b..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/LocationRepository.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.repository; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.AppDatabase; -import com.martinlaizg.geofind.data.access.database.dao.LocationDAO; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.retrofit.service.LocationService; - -import java.util.List; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; - -public class LocationRepository { - - private final LocationService locationService; - - private final LocationDAO locDAO; - private LiveData> allLocations; - - public LocationRepository(Application application) { - AppDatabase database = AppDatabase.getInstance(application); - locDAO = database.locationDAO(); - locationService = LocationService.getInstance(); - } - - public LiveData> getAllLocations() { - return new MutableLiveData<>(); - } - - public void create(List locations) { - for (Location loc : locations) { - locationService.create(loc); - } - } - - public MutableLiveData> getLocationsByMap(String map_id) { - MutableLiveData> locations = new MutableLiveData<>(); - new Thread(new Runnable() { - @Override - public void run() { - List locs = locDAO.getLocationsByMap(map_id); - if (locs == null || locs.isEmpty()) { - locs = locationService.getLocationsByMap(map_id); - if (locs != null && !locs.isEmpty()) { - for (Location l : locs) { - locDAO.insert(l); - } - locs = locDAO.getLocationsByMap(map_id); - } - } - locations.postValue(locs); - } - }).start(); - - return locations; - } - - public MutableLiveData getLocation(String loc_id) { - MutableLiveData location = new MutableLiveData<>(); - new Thread(new Runnable() { - @Override - public void run() { - Location loc = locDAO.getLocation(loc_id); - if (loc == null) { - loc = locationService.getLocation(loc_id); - if (loc != null) { - locDAO.insert(loc); - loc = locDAO.getLocation(loc_id); - } - } - location.postValue(loc); - } - }).start(); - return location; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/MapRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/MapRepository.java deleted file mode 100644 index 18da81f..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/MapRepository.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.repository; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.AppDatabase; -import com.martinlaizg.geofind.data.access.database.dao.MapDAO; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.retrofit.service.MapService; - -import java.util.List; - -import androidx.lifecycle.MutableLiveData; - -public class MapRepository { - - private final MapService mapService; - private final MapDAO mapDAO; - - public MapRepository(Application application) { - AppDatabase database = AppDatabase.getInstance(application); - mapDAO = database.mapDAO(); - mapService = MapService.getInstance(); - } - - public MutableLiveData> getAllMaps() { - MutableLiveData> maps = new MutableLiveData<>(); - new Thread(new Runnable() { - @Override - public void run() { - List ms = mapDAO.getAllMaps(); - if (ms == null || ms.isEmpty()) { - ms = mapService.getAllMaps(); - if (ms != null) { - insertMaps(ms); - } - } - maps.postValue(ms); - } - }).start(); - return maps; - } - - private void insertMaps(List ms) { - for (Map m : ms) { - insertMap(m); - } - } - - public MutableLiveData getMap(String id) { - MutableLiveData map = new MutableLiveData<>(); - new Thread(new Runnable() { - @Override - public void run() { - Map m = mapDAO.getMap(id); - if (m == null) { - m = mapService.getMap(id); - } - map.postValue(m); - } - - }).start(); - return map; - } - - public void refreshMaps() { - List maps = mapService.getAllMaps(); - for (Map map : maps) { - mapDAO.insert(map); - } - } - - private void insertMap(Map map) { - mapDAO.insert(map); - } - - public Map create(Map map) { - Map map1 = mapService.create(map); - refreshMaps(); - return map1; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/UserRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/UserRepository.java deleted file mode 100644 index ba038e7..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/repository/UserRepository.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.martinlaizg.geofind.data.access.database.repository; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.AppDatabase; -import com.martinlaizg.geofind.data.access.database.dao.UserDAO; -import com.martinlaizg.geofind.data.access.database.entity.User; -import com.martinlaizg.geofind.data.access.retrofit.service.UserService; - -import androidx.lifecycle.MutableLiveData; - -public class UserRepository { - - private static final String TAG = UserRepository.class.getSimpleName(); - private final UserDAO userDAO; - private final UserService userService; - - public UserRepository(Application application) { - AppDatabase database = AppDatabase.getInstance(application); - userDAO = database.userDAO(); - userService = UserService.getInstance(); - } - - - public MutableLiveData login(String email, String password) { - MutableLiveData user = new MutableLiveData<>(); - new Thread(() -> { - User u = userService.login(new User(email, password)); - if (u != null) { - user.postValue(u); - userDAO.insert(u); - } - }).start(); - return user; - } - - public MutableLiveData registry(String name, String username, String email, String password) { - MutableLiveData user = new MutableLiveData<>(); - new Thread(() -> { - User u = userService.registry(new User(name, username, email, password)); - if (u != null) { - user.postValue(u); - if (u.getError() == null) userDAO.insert(u); - } - }).start(); - return user; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/RestClient.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/RestClient.java deleted file mode 100644 index 2b71ade..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/RestClient.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.entity.User; - -import java.util.List; - -import retrofit2.Call; -import retrofit2.http.Body; -import retrofit2.http.GET; -import retrofit2.http.POST; -import retrofit2.http.Path; -import retrofit2.http.QueryMap; - -public interface RestClient { - - // - // - // - // - // Maps requests - - // Get maps with optional filter - @GET("maps") - Call> getMaps(@QueryMap java.util.Map params); - - @POST("maps") - Call createMap(@Body Map map); - - // Get single map - @GET("maps/{id}") - Call getMap(@Path("id") String id); - - // Get locations by map - @GET("maps/{id}/locations") - Call> getLocationsByMap(@Path("id") String map_id); - - // Create a location by map - @POST("maps/{id}locations") - Call createLocationByMap(@Path("id") String map_id, @Body Location loc); - - - // - // - // - // - // Locations requests - - // Get locations - @GET("locations") - Call> getLocations(@QueryMap java.util.Map params); - - // Get single location - @GET("locations/{id}") - Call getLocation(@Path("id") String id); - - // Create a location - @POST("locations") - Call createLocation(@Body Location loc); - - - // - // - // - // - // User requests - - // Login user - @POST("login") - Call login(@Body User body); - - @POST("users") - Call> getUsers(@QueryMap java.util.Map params); - - @POST("users") - Call registry(@Body User user); -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/RetrofitService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/RetrofitService.java deleted file mode 100644 index 8b22436..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/RetrofitService.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import retrofit2.converter.gson.GsonConverterFactory; - -public class RetrofitService { - private static final String BASE_URL = "https://geo-find-martinlaizg.herokuapp.com/api/"; - // private static final String BASE_URL = "http://192.168.1.182:8000/api/"; - private static retrofit2.Retrofit retrofit; - - /** - * Create an instance of RetrofitService object - */ - public static retrofit2.Retrofit getRetrofitInstance() { - if (retrofit == null) { - Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); - retrofit = new retrofit2.Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).build(); - } - - return retrofit; - } - - public static RestClient getRestClient() { - retrofit2.Retrofit rf = getRetrofitInstance(); - return rf.create(RestClient.class); - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/APIError.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/APIError.java deleted file mode 100644 index 907f97d..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/APIError.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit.error; - -public class APIError { - - private ErrorType type; - private String message; - - - public ErrorType getType() { - return type; - } - - public void setType(ErrorType type) { - this.type = type; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/ErrorType.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/ErrorType.java deleted file mode 100644 index 6243a22..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/ErrorType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit.error; - -import com.google.gson.annotations.SerializedName; - -enum ErrorType { - @SerializedName("email") EMAIL; -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/ErrorUtils.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/ErrorUtils.java deleted file mode 100644 index 4f70dc3..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/error/ErrorUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit.error; - -import com.martinlaizg.geofind.data.access.retrofit.RetrofitService; - -import java.io.IOException; -import java.lang.annotation.Annotation; - -import okhttp3.ResponseBody; -import retrofit2.Converter; -import retrofit2.Response; - -public class ErrorUtils { - - /** - * Parse a response to a APIError - * - * @param response response to parse - * @return parsed response - */ - public static APIError parseError(Response response) { - Converter converter = RetrofitService.getRetrofitInstance().responseBodyConverter(APIError.class, new Annotation[0]); - - APIError error = null; - try { - if (response.errorBody() != null) { - error = converter.convert(response.errorBody()); - } - } catch (IOException e) { - return new APIError(); - } - - return error; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/LocationService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/LocationService.java deleted file mode 100644 index b277349..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/LocationService.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit.service; - -import android.util.Log; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.retrofit.RestClient; -import com.martinlaizg.geofind.data.access.retrofit.RetrofitService; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; -import com.martinlaizg.geofind.data.access.retrofit.error.ErrorUtils; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import retrofit2.Response; - -public class LocationService { - - private static LocationService locationService; - private static RestClient restClient; - private final String TAG = LocationService.class.getSimpleName(); - - public static LocationService getInstance() { - if (restClient == null) { - restClient = RetrofitService.getRestClient(); - } - if (locationService == null) { - locationService = new LocationService(); - } - return locationService; - } - - public List getAllLocations() { - Response> response = null; - try { - response = restClient.getLocations(new HashMap<>()).execute(); - if (response.isSuccessful()) { - return response.body(); - } - APIError apiError = ErrorUtils.parseError(response); - Location l = new Location(); - l.setError(apiError); - return Collections.singletonList(l); - } catch (IOException ex) { - Log.e(TAG, "getAllLocations: ", ex); - } - return new ArrayList<>(); - } - - public void create(Location loc) { - try { - Response response = restClient.createLocation(loc).execute(); - if (!response.isSuccessful()) { - APIError apiError = ErrorUtils.parseError(response); - } - } catch (IOException e) { - Log.e(TAG, "createLocation: ", e); - } - } - - public List getLocationsByMap(String id) { - Response> response = null; - try { - response = restClient.getLocationsByMap(id).execute(); - if (response.isSuccessful()) { - return response.body(); - } - APIError apiError = ErrorUtils.parseError(response); - } catch (IOException ex) { - Log.e(TAG, "getLocationsByMap: ", ex); - } - return new ArrayList<>(); - } - - public Location getLocation(String loc_id) { - Response response = null; - try { - response = restClient.getLocation(loc_id).execute(); - if (response.isSuccessful()) { - return response.body(); - } - APIError apiError = ErrorUtils.parseError(response); - } catch (IOException ex) { - Log.e(TAG, "getLocationsByMap: ", ex); - } - return new Location(); - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/MapService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/MapService.java deleted file mode 100644 index 3804c5e..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/MapService.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit.service; - -import android.util.Log; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.retrofit.RestClient; -import com.martinlaizg.geofind.data.access.retrofit.RetrofitService; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; -import com.martinlaizg.geofind.data.access.retrofit.error.ErrorUtils; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import retrofit2.Response; - -public class MapService { - - private static MapService mapService; - private static RestClient restClient; - private final String TAG = MapService.class.getSimpleName(); - - public static MapService getInstance() { - if (restClient == null) { - restClient = RetrofitService.getRestClient(); - } - if (mapService == null) { - mapService = new MapService(); - } - return mapService; - } - - public List getAllMaps() { - try { - Response> response = restClient.getMaps(new HashMap<>()).execute(); - return response.body(); - } catch (IOException e) { - Log.e(TAG, "getAllMaps: ", e); - } - return new ArrayList<>(); - } - - - public List getLocations(String map_id) { - Response> execute = null; - try { - execute = restClient.getLocationsByMap(map_id).execute(); - return execute.body(); - } catch (IOException e) { - Log.e(TAG, "getLocationsByMap", e); - } - return new ArrayList<>(); - } - - public Map create(Map map) { - Response response = null; - try { - response = restClient.createMap(map).execute(); - if (response.isSuccessful()) { - return response.body(); - } - APIError apiError = ErrorUtils.parseError(response); - Map m = new Map(); - m.setError(apiError); - } catch (IOException e) { - Log.e(TAG, "createMap: ", e); - } - return null; - } - - public Map getMap(String id) { - Response response = null; - try { - response = restClient.getMap(id).execute(); - if (response.isSuccessful()) { - return response.body(); - } - APIError apiError = ErrorUtils.parseError(response); - Map m = new Map(); - m.setError(apiError); - } catch (IOException e) { - Log.e(TAG, "createMap: ", e); - } - return null; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/UserService.java b/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/UserService.java deleted file mode 100644 index 129e201..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/retrofit/service/UserService.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.martinlaizg.geofind.data.access.retrofit.service; - -import android.util.Log; - -import com.martinlaizg.geofind.data.access.database.entity.User; -import com.martinlaizg.geofind.data.access.retrofit.RestClient; -import com.martinlaizg.geofind.data.access.retrofit.RetrofitService; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; -import com.martinlaizg.geofind.data.access.retrofit.error.ErrorUtils; - -import java.io.IOException; - -import retrofit2.Response; - -public class UserService { - - private static UserService userService; - private static RestClient restClient; - private final String TAG = UserService.class.getSimpleName(); - - public static UserService getInstance() { - if (restClient == null) { - restClient = RetrofitService.getRestClient(); - } - if (userService == null) { - userService = new UserService(); - } - return userService; - } - - - public User login(User user) { - try { - Response response = restClient.login(user).execute(); - return response.body(); - } catch (IOException e) { - Log.e(TAG, "run: login", e); - } - return null; - } - - public User registry(User user) { - try { - Response response = restClient.registry(user).execute(); - if (response.isSuccessful()) { - return response.body(); - } - APIError apiError = ErrorUtils.parseError(response); - User u = new User(); - u.setError(apiError); - return u; - } catch (IOException e) { - Log.e(TAG, "run: login", e); - } - return null; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/enums/PlayLevel.java b/app/src/main/java/com/martinlaizg/geofind/data/enums/PlayLevel.java similarity index 79% rename from app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/enums/PlayLevel.java rename to app/src/main/java/com/martinlaizg/geofind/data/enums/PlayLevel.java index 36b028c..aa2a5dc 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/enums/PlayLevel.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/enums/PlayLevel.java @@ -1,4 +1,4 @@ -package com.martinlaizg.geofind.data.access.database.entity.enums; +package com.martinlaizg.geofind.data.enums; import com.google.gson.annotations.SerializedName; diff --git a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/enums/UserType.java b/app/src/main/java/com/martinlaizg/geofind/data/enums/UserType.java similarity index 73% rename from app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/enums/UserType.java rename to app/src/main/java/com/martinlaizg/geofind/data/enums/UserType.java index 7ca2f91..47ef6df 100644 --- a/app/src/main/java/com/martinlaizg/geofind/data/access/database/entity/enums/UserType.java +++ b/app/src/main/java/com/martinlaizg/geofind/data/enums/UserType.java @@ -1,4 +1,4 @@ -package com.martinlaizg.geofind.data.access.database.entity.enums; +package com.martinlaizg.geofind.data.enums; import com.google.gson.annotations.SerializedName; @@ -8,5 +8,4 @@ public enum UserType { @SerializedName("creator") CREATOR, @SerializedName("admin") ADMINISTRATOR - } diff --git a/app/src/main/java/com/martinlaizg/geofind/data/repository/PlaceRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/repository/PlaceRepository.java new file mode 100644 index 0000000..f22e09c --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/repository/PlaceRepository.java @@ -0,0 +1,57 @@ +package com.martinlaizg.geofind.data.repository; + +import android.app.Application; + +import com.martinlaizg.geofind.data.access.api.service.PlayService; +import com.martinlaizg.geofind.data.access.database.AppDatabase; +import com.martinlaizg.geofind.data.access.database.dao.PlaceDAO; +import com.martinlaizg.geofind.data.access.database.dao.relations.PlacePlayDAO; +import com.martinlaizg.geofind.data.access.database.entities.Place; + +import java.util.List; + +public class PlaceRepository { + + private final PlaceDAO placeDAO; + private final PlayService playService; + private final PlacePlayDAO placePlayDAO; + + PlaceRepository(Application application) { + AppDatabase database = AppDatabase.getInstance(application); + placeDAO = database.placeDAO(); + placePlayDAO = database.playPlaceDAO(); + playService = PlayService.getInstance(); + } + + /** + * TODO + * + * @return + */ + public void insert(List places) { + for(Place p : places) insert(p); + } + + /** + * TODO + * + * @return + */ + public void insert(Place place) { + Place p = placeDAO.getPlace(place.getId()); + if(p == null) { + placeDAO.insert(place); + } else { + placeDAO.update(place); + } + } + + /** + * TODO + * + * @return + */ + public void getPlaceOnStart(int userId) { + // TODO + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/repository/PlayRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/repository/PlayRepository.java new file mode 100644 index 0000000..2a652d0 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/repository/PlayRepository.java @@ -0,0 +1,131 @@ +package com.martinlaizg.geofind.data.repository; + +import android.app.Application; +import android.util.Log; + +import com.martinlaizg.geofind.data.access.api.service.PlayService; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.AppDatabase; +import com.martinlaizg.geofind.data.access.database.dao.PlayDAO; +import com.martinlaizg.geofind.data.access.database.dao.relations.PlacePlayDAO; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.PlacePlay; +import com.martinlaizg.geofind.data.access.database.entities.Play; + +import java.util.List; + +public class PlayRepository { + + private static final String TAG = PlayRepository.class.getSimpleName(); + private final PlayDAO playDAO; + private final PlayService playService; + + private final TourRepository tourRepo; + private final UserRepository userRepo; + private final PlaceRepository placeRepo; + + private final PlacePlayDAO placePlayDAO; + + PlayRepository(Application application) { + AppDatabase database = AppDatabase.getInstance(application); + playDAO = database.playDAO(); + playService = PlayService.getInstance(); + + placePlayDAO = database.playPlaceDAO(); + + tourRepo = RepositoryFactory.getTourRepository(application); + userRepo = RepositoryFactory.getUserRepository(application); + placeRepo = RepositoryFactory.getPlaceRepository(application); + } + + /** + * TODO + * + * @return + */ + public Play getPlay(int user_id, int tour_id) throws APIException { + Play p = getPlayDAO(user_id, tour_id); + if(p == null) { + try { + p = playService.getUserPlay(user_id, tour_id); + } catch(APIException e) { + Log.i(TAG, "getPlay: ", e); + return null; + } + p.setUser_id(p.getUser().getId()); + p.setTour_id(p.getTour().getId()); + insert(p); + } + return p; + } + + /** + * TODO + * + * @return + */ + private Play getPlayDAO(int user_id, int tour_id) throws APIException { + Play p = playDAO.getPlay(user_id, tour_id); + if(p == null) { + return null; + } + if(p.isOutOfDate()) { + playDAO.delete(p); + return null; + } + p.setTour(tourRepo.getTour(tour_id)); + p.setUser(userRepo.getUser(user_id)); + p.setPlaces(getPlacesByPlay(p.getId())); + return p; + } + + /** + * TODO + * + * @return + */ + private void insert(Play p) { + if(p != null) { + userRepo.insert(p.getUser()); + tourRepo.insert(p.getTour()); + playDAO.insert(p); + placeRepo.insert(p.getPlaces()); + } + } + + /** + * TODO + * + * @return + */ + private List getPlacesByPlay(Integer play_id) { + return playDAO.getPlaces(play_id); + } + + /** + * TODO + * + * @return + */ + public Play completePlay(Integer play_id, Integer place_id) throws APIException { + Play p = playService.createPlacePlay(play_id, place_id); + PlacePlay pp = new PlacePlay(place_id, play_id); + placePlayDAO.insert(pp); + return p; + } + + /** + * TODO + * + * @return + */ + public void getPlayOnStart(int userId) { + // TODO + } + + public Play createPlay(int user_id, int tour_id) throws APIException { + Play p = playService.createUserPlay(user_id, tour_id); + insert(p); + return p; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/repository/RepositoryFactory.java b/app/src/main/java/com/martinlaizg/geofind/data/repository/RepositoryFactory.java new file mode 100644 index 0000000..dfd0ab9 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/repository/RepositoryFactory.java @@ -0,0 +1,31 @@ +package com.martinlaizg.geofind.data.repository; + +import android.app.Application; + +public class RepositoryFactory { + + private static UserRepository userRepository; + private static TourRepository tourRepository; + private static PlaceRepository placeRepository; + private static PlayRepository playRepository; + + public static UserRepository getUserRepository(Application application) { + if(userRepository == null) userRepository = new UserRepository(application); + return userRepository; + } + + public static TourRepository getTourRepository(Application application) { + if(tourRepository == null) tourRepository = new TourRepository(application); + return tourRepository; + } + + public static PlaceRepository getPlaceRepository(Application application) { + if(placeRepository == null) placeRepository = new PlaceRepository(application); + return placeRepository; + } + + public static PlayRepository getPlayRepository(Application application) { + if(playRepository == null) playRepository = new PlayRepository(application); + return playRepository; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/repository/TourRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/repository/TourRepository.java new file mode 100644 index 0000000..7f81ae5 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/repository/TourRepository.java @@ -0,0 +1,188 @@ +package com.martinlaizg.geofind.data.repository; + +import android.app.Application; +import android.util.Log; + +import com.martinlaizg.geofind.data.access.api.service.TourService; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.AppDatabase; +import com.martinlaizg.geofind.data.access.database.dao.TourDAO; +import com.martinlaizg.geofind.data.access.database.dao.relations.TourPlacesDAO; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.access.database.entities.relations.TourCreatorPlaces; + +import java.util.ArrayList; +import java.util.List; + +public class TourRepository { + + private static final String TAG = TourRepository.class.getSimpleName(); + private final TourService tourService; + private final TourDAO tourDAO; + private final TourPlacesDAO tourPlacesDAO; + + private final PlaceRepository placeRepo; + private final UserRepository userRepo; + + TourRepository(Application application) { + AppDatabase database = AppDatabase.getInstance(application); + tourDAO = database.tourDAO(); + tourService = TourService.getInstance(); + tourPlacesDAO = database.tourPlacesDAO(); + + placeRepo = RepositoryFactory.getPlaceRepository(application); + userRepo = RepositoryFactory.getUserRepository(application); + } + + /** + * Get the TourCreatorPlaces list from local and update each item from server + * + * @return the list of elements + */ + public List getAllTours() { + List tcps = tourPlacesDAO.getTourCreatorPlaces(); + Tour tour = tourDAO.getTour(1); + if(tcps != null) { + for(int i = 0; i < tcps.size(); i++) { + tcps.get(i).getTour().setPlaces(tcps.get(i).getPlaces()); + if(tcps.get(i).getTour().isOutOfDate()) { + Tour newTour = refresh(tcps.get(i).getTour()); + if(newTour == null) { + tcps.remove(i); + i--; + continue; + } + insert(newTour); + TourCreatorPlaces tcp = new TourCreatorPlaces(); + tcp.setTour(newTour); + tcp.setPlaces(newTour.getPlaces()); + tcp.setUsername(newTour.getCreator().getUsername()); + tcps.set(i, tcp); + } + } + } + return tcps; + } + + /** + * Refresh the tour from the server and insert into the local database + * + * @param tour the tour to refresh, return null on error + * @return the tour refreshed + */ + private Tour refresh(Tour tour) { + try { + tour = tourService.getTour(tour.getId()); + if(tour != null) { + insert(tour); + } + return tour; + } catch(APIException e) { + Log.e(TAG, "refresh: ", e); + } + return null; + } + + /** + * Insert a Tour to the local database + * Insert the User creator and the list of Place recursively + * + * @param tour Tour to insert + */ + public void insert(Tour tour) { + if(tour != null) { + userRepo.insert(tour.getCreator()); + Tour t = tourDAO.getTour(tour.getId()); + if(t == null) { + tourDAO.insert(tour); + } else { + tourDAO.update(tour); + } + placeRepo.insert(tour.getPlaces()); + } + } + + /** + * Update the tour on server and local + * If the tour is removed from server, return null + * + * @param tour tour to update + * @return tour updated or null if no exist on server + * @throws APIException exception from server + */ + public Tour update(Tour tour) throws APIException { + int tour_id = tour.getId(); + tour = tourService.update(tour); + if(tour != null) { + insert(tour); + } else { + tourDAO.delete(tour_id); + } + return tour; + } + + /** + * Create a tour on server and insert into local database + * + * @param tour tour to insert + * @return inserted tour + * @throws APIException the exception from API + */ + public Tour create(Tour tour) throws APIException { + tour = tourService.create(tour); + if(tour != null) insert(tour); + return tour; + } + + /** + * Get the tour with this id + * + * @param id the tour id + * @return the tour + * @throws APIException the server exception + */ + public Tour getTour(Integer id) throws APIException { + TourCreatorPlaces tcp = tourPlacesDAO.getTour(id); + Tour t; + if(tcp == null) { + t = tourService.getTour(id); + } else { + t = tcp.getTour(); + t.setCreator(tcp.getCreator()); + t.setPlaces(tcp.getPlaces()); + } + return t; + } + + /** + * TODO + * + * @return + */ + public void getToursOnStart(int userId) { + // TODO + } + + /** + * Load tours from server and insert into de local database + * + * @return the list of {@link TourCreatorPlaces} from server + * @throws APIException the server exception + */ + public List refreshTours() throws APIException { + + List tcps = new ArrayList<>(); + List tours = tourService.getAllTours(); + for(Tour t : tours) { + insert(t); + TourCreatorPlaces tcp = new TourCreatorPlaces(); + tcp.setTour(t); + tcp.setPlaces(t.getPlaces()); + tcp.setUsername(t.getCreator().getUsername()); + tcps.add(tcp); + } + tcps = tourPlacesDAO.getTourCreatorPlaces(); + Tour t = tourDAO.getTour(1); + return tcps; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/data/repository/UserRepository.java b/app/src/main/java/com/martinlaizg/geofind/data/repository/UserRepository.java new file mode 100644 index 0000000..c25615a --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/data/repository/UserRepository.java @@ -0,0 +1,84 @@ +package com.martinlaizg.geofind.data.repository; + +import android.app.Application; + +import com.martinlaizg.geofind.data.access.api.service.UserService; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.AppDatabase; +import com.martinlaizg.geofind.data.access.database.dao.UserDAO; +import com.martinlaizg.geofind.data.access.database.entities.User; + +public class UserRepository { + + private final UserDAO userDAO; + private final UserService userService; + + UserRepository(Application application) { + AppDatabase database = AppDatabase.getInstance(application); + userDAO = database.userDAO(); + userService = UserService.getInstance(); + } + + /** + * TODO + * + * @return + */ + public User login(User u) throws APIException { + u = userService.login(u); + if(u != null) { + userDAO.insert(u); + } + return u; + } + + /** + * TODO + * + * @return + */ + public User registry(User u) throws APIException { + u = userService.registry(u); + if(u != null) { + userDAO.insert(u); + } + return u; + } + + /** + * TODO + * + * @return + */ + public void insert(User user) { + if(user != null) { + User u = userDAO.getUser(user.getId()); + if(u == null) { + userDAO.insert(user); + } else { + userDAO.update(user); + } + } + } + + /** + * TODO + * + * @return + */ + public User getUser(int user_id) { + return userDAO.getUser(user_id); + } + + /** + * Send message to support + * + * @param title the title + * @param message the message + * @return the response + * @throws APIException the exception + */ + public boolean sendMessage(String title, String message) throws APIException { + return userService.sendMessage(title, message); + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/utils/DateUtils.java b/app/src/main/java/com/martinlaizg/geofind/utils/DateUtils.java index 4744b12..0fc2152 100644 --- a/app/src/main/java/com/martinlaizg/geofind/utils/DateUtils.java +++ b/app/src/main/java/com/martinlaizg/geofind/utils/DateUtils.java @@ -1,5 +1,14 @@ package com.martinlaizg.geofind.utils; +import java.sql.Date; +import java.util.Calendar; + public class DateUtils { + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + public static final long TIME_TO_EXPIRE = 20 * 1000; + + public static boolean isDateExpire(Date fromDate) { + return Calendar.getInstance().getTime().getTime() - fromDate.getTime() > TIME_TO_EXPIRE; + } } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/activity/MainActivity.java b/app/src/main/java/com/martinlaizg/geofind/views/activity/MainActivity.java index 6a58d75..1c24652 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/activity/MainActivity.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/activity/MainActivity.java @@ -1,23 +1,38 @@ package com.martinlaizg.geofind.views.activity; +import android.content.SharedPreferences; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.widget.TextView; -import com.google.android.material.navigation.NavigationView; -import com.martinlaizg.geofind.R; - import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.drawerlayout.widget.DrawerLayout; import androidx.navigation.NavController; import androidx.navigation.Navigation; +import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; +import androidx.preference.PreferenceManager; + +import com.google.android.material.navigation.NavigationView; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.config.Preferences; +import com.martinlaizg.geofind.data.access.database.entities.User; +import com.martinlaizg.geofind.data.repository.PlaceRepository; +import com.martinlaizg.geofind.data.repository.PlayRepository; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; +import com.martinlaizg.geofind.data.repository.TourRepository; + +import java.util.HashSet; +import java.util.Set; + import butterknife.BindView; import butterknife.ButterKnife; public class MainActivity extends AppCompatActivity { + private static final String TAG = MainActivity.class.getSimpleName(); @BindView(R.id.drawer_layout) @@ -28,13 +43,48 @@ public class MainActivity @BindView(R.id.drawer_nav_view) NavigationView navigationView; + NavController navController; + private SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(MainActivity.this); - setupNavigation(); + sp = PreferenceManager.getDefaultSharedPreferences(this); + + navController = Navigation.findNavController(this, R.id.main_fragment_holder); + + Set topLevelDestinations = new HashSet<>(); + topLevelDestinations.add(R.id.navMain); + topLevelDestinations.add(R.id.navTourList); + AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( + topLevelDestinations).setDrawerLayout(drawer_layout).build(); + + setSupportActionBar(toolbar); + NavigationUI.setupWithNavController(navigationView, navController); + NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration); + + loadDatabase(); + } + + private void loadDatabase() { + new Thread(() -> { + Log.i(TAG, "loadDatabaseOnStart "); + User user = Preferences.getLoggedUser(sp); + if(user != null && user.getId() > 0) { // is logged + // load user plays + TourRepository tourRepository = RepositoryFactory + .getTourRepository(getApplication()); + tourRepository.getToursOnStart(user.getId()); + PlayRepository playRepository = RepositoryFactory + .getPlayRepository(getApplication()); + playRepository.getPlayOnStart(user.getId()); + PlaceRepository placeRepository = RepositoryFactory + .getPlaceRepository(getApplication()); + placeRepository.getPlaceOnStart(user.getId()); + } + }).start(); } public void setDrawerHeader(String username, String name) { @@ -45,18 +95,11 @@ public void setDrawerHeader(String username, String name) { public void disableToolbarAndDrawer(boolean visibility) { toolbar.setVisibility(visibility ? - View.VISIBLE : - View.GONE); + View.VISIBLE : + View.GONE); drawer_layout.setDrawerLockMode(visibility ? - DrawerLayout.LOCK_MODE_UNLOCKED : - DrawerLayout.LOCK_MODE_LOCKED_CLOSED); - } - - private void setupNavigation() { - setSupportActionBar(toolbar); - NavController navController = Navigation.findNavController(this, R.id.main_fragment_holder); - NavigationUI.setupWithNavController(toolbar, navController, drawer_layout); - NavigationUI.setupWithNavController(navigationView, navController); + DrawerLayout.LOCK_MODE_UNLOCKED : + DrawerLayout.LOCK_MODE_LOCKED_CLOSED); } } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/adapter/CreatorPlacesAdapter.java b/app/src/main/java/com/martinlaizg/geofind/views/adapter/CreatorPlacesAdapter.java new file mode 100644 index 0000000..28a6724 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/adapter/CreatorPlacesAdapter.java @@ -0,0 +1,96 @@ +package com.martinlaizg.geofind.views.adapter; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.navigation.Navigation; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.button.MaterialButton; +import com.google.android.material.card.MaterialCardView; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.views.fragment.creator.CreatePlaceFragment; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class CreatorPlacesAdapter + extends RecyclerView.Adapter { + + private List places; + + @NonNull + @Override + public CreatorPlacesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.fragment_editable_place, parent, false); + return new CreatorPlacesViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull final CreatorPlacesViewHolder holder, int position) { + holder.place_name.setText(places.get(position).getName()); + holder.place_delete_button.setOnClickListener(v -> { + remove(position); + }); + Bundle b = new Bundle(); + b.putInt(CreatePlaceFragment.PLACE_POSITION, position); + holder.place_card.setOnClickListener( + Navigation.createNavigateOnClickListener(R.id.toCreatePlace, b)); + } + + private void remove(int position) { + places.remove(position); + for(int i = 0; i < places.size(); i++) { + places.get(i).setOrder(i); + } + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return places.size(); + } + + public CreatorPlacesAdapter() { + places = new ArrayList<>(); + } + + public void setPlaces(List places) { + if(places != null) { + // sort elements + places.sort((o1, o2) -> o1.getOrder() > o2.getOrder() ? + 1 : + o1.getOrder() < o2.getOrder() ? + -1 : + 0); + this.places = places; + notifyDataSetChanged(); + } + } + + class CreatorPlacesViewHolder + extends RecyclerView.ViewHolder { + + @BindView(R.id.place_card) + MaterialCardView place_card; + @BindView(R.id.place_delete_button) + MaterialButton place_delete_button; + @BindView(R.id.place_name) + TextView place_name; + + CreatorPlacesViewHolder(View view) { + super(view); + ButterKnife.bind(this, view); + } + + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/adapter/PlaceListAdapter.java b/app/src/main/java/com/martinlaizg/geofind/views/adapter/PlaceListAdapter.java new file mode 100644 index 0000000..84a97cd --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/adapter/PlaceListAdapter.java @@ -0,0 +1,85 @@ +package com.martinlaizg.geofind.views.adapter; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.navigation.Navigation; +import androidx.recyclerview.widget.RecyclerView; + +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.views.fragment.single.PlaceFragment; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class PlaceListAdapter + extends RecyclerView.Adapter { + + private final int disabled_color; + private final boolean completed; + private List places; + + @NonNull + @Override + public PlaceViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { + View view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.fragment_place_item, viewGroup, false); + return new PlaceViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull PlaceViewHolder holder, int position) { + Place l = places.get(position); + holder.place_name.setText(l.getName()); + holder.place_description.setText(l.getDescription()); + Bundle b = new Bundle(); + b.putInt(PlaceFragment.PLACE_ID, l.getId()); + holder.place_card + .setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toPlace, b)); + if(completed) { + holder.place_name.setTextColor(disabled_color); + holder.place_description.setTextColor(disabled_color); + } + } + + @Override + public int getItemCount() { + return places.size(); + } + + public PlaceListAdapter(boolean completed, int disabled_color) { + places = new ArrayList<>(); + this.completed = completed; + this.disabled_color = disabled_color; + } + + public void setPlaces(List places) { + this.places = places; + notifyDataSetChanged(); + } + + class PlaceViewHolder + extends RecyclerView.ViewHolder { + + @BindView(R.id.place_name) + TextView place_name; + @BindView(R.id.place_description) + TextView place_description; + @BindView(R.id.place_card) + CardView place_card; + + PlaceViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/adapter/TourListAdapter.java b/app/src/main/java/com/martinlaizg/geofind/views/adapter/TourListAdapter.java new file mode 100644 index 0000000..374a621 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/adapter/TourListAdapter.java @@ -0,0 +1,78 @@ +package com.martinlaizg.geofind.views.adapter; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.navigation.Navigation; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.card.MaterialCardView; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.database.entities.relations.TourCreatorPlaces; +import com.martinlaizg.geofind.views.fragment.single.TourFragment; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class TourListAdapter + extends RecyclerView.Adapter { + + private List tours = new ArrayList<>(); + + @NonNull + @Override + public ToursViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { + View view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.fragment_tour_item, viewGroup, false); + return new ToursViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ToursViewHolder holder, final int i) { + final TourCreatorPlaces tour = tours.get(i); + holder.tourName.setText(tour.getTour().getName()); + holder.tourCreator.setText(tour.getUsername()); + holder.tourDescription.setText(tour.getTour().getDescription()); + + Bundle b = new Bundle(); + b.putInt(TourFragment.TOUR_ID, tours.get(i).getTour().getId()); + holder.materialCardView + .setOnClickListener(v -> Navigation.findNavController(v).navigate(R.id.toTour, b)); + } + + @Override + public int getItemCount() { + return tours.size(); + } + + public void setTours(List tours) { + this.tours = tours; + notifyDataSetChanged(); + } + + class ToursViewHolder + extends RecyclerView.ViewHolder { + + @BindView(R.id.tour_name) + TextView tourName; + @BindView(R.id.tour_creator) + TextView tourCreator; + @BindView(R.id.tour_description) + TextView tourDescription; + @BindView(R.id.tour_card) + MaterialCardView materialCardView; + + ToursViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/MainFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/MainFragment.java index f0a8608..9815853 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/MainFragment.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/MainFragment.java @@ -1,53 +1,46 @@ package com.martinlaizg.geofind.views.fragment; - import android.content.SharedPreferences; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.config.Preferences; -import com.martinlaizg.geofind.data.access.database.entity.User; -import com.martinlaizg.geofind.views.activity.MainActivity; - -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; - +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.navigation.Navigation; import androidx.preference.PreferenceManager; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.config.Preferences; +import com.martinlaizg.geofind.data.access.database.entities.User; +import com.martinlaizg.geofind.views.activity.MainActivity; + public class MainFragment extends Fragment { - - public MainFragment() { - // Required empty public constructor - } - @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - if (!isLogged()) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + if(!isLogged()) { return null; } return inflater.inflate(R.layout.fragment_main, container, false); } private boolean isLogged() { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(getActivity())); + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(requireActivity()); User u = Preferences.getLoggedUser(sp); - MainActivity mainActivity = (MainActivity) getActivity(); - if (u != null && !u.getEmail().isEmpty()) { + MainActivity mainActivity = (MainActivity) requireActivity(); + if(u != null && !u.getEmail().isEmpty()) { mainActivity.setDrawerHeader(u.getUsername(), u.getName()); mainActivity.disableToolbarAndDrawer(true); return true; } // If user is not logged, go to LoginFragment mainActivity.disableToolbarAndDrawer(false); - Navigation.findNavController(getActivity(), R.id.main_fragment_holder).navigate(R.id.toLogin); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .navigate(R.id.toLogin); return false; } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/SearchFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/SearchFragment.java index 2453013..8086a07 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/SearchFragment.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/SearchFragment.java @@ -1,28 +1,26 @@ package com.martinlaizg.geofind.views.fragment; - import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.martinlaizg.geofind.R; - -import org.jetbrains.annotations.NotNull; - +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import com.martinlaizg.geofind.R; + public class SearchFragment extends Fragment { + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_search, container, false); + } public SearchFragment() { // Required empty public constructor } - @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_search, container, false); - } - } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateLocationFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateLocationFragment.java deleted file mode 100644 index ab45a3f..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateLocationFragment.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.creator; - - -import android.Manifest; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.Location; -import android.location.LocationManager; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - -import com.google.android.gms.maps.CameraUpdate; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.OnMapReadyCallback; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.MarkerOptions; -import com.google.android.material.textfield.TextInputLayout; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.views.viewmodel.MapCreatorViewModel; - -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProviders; -import androidx.navigation.Navigation; -import butterknife.BindView; -import butterknife.ButterKnife; - - -public class CreateLocationFragment - extends Fragment - implements View.OnClickListener, OnMapReadyCallback { - - private static final int CAMERA_UPDATE_ZOOM = 15; - private static final String MAP_NAME = "MAP_NAME"; - private static final String MAP_DESCRIPTION = "MAP_DESCRIPTION"; - - @BindView(R.id.new_location_name_layout) - TextInputLayout new_location_name; - @BindView(R.id.new_location_description_layout) - TextInputLayout new_location_description; - @BindView(R.id.alert_no_locaiton_text) - TextView alert_no_locaiton_text; - - @BindView(R.id.create_location) - Button create_button; - - @BindView(R.id.new_location_map_view) - MapView new_location_map_view; - - private MapCreatorViewModel viewModel; - private MarkerOptions marker; - - @Override - public View onCreateView( - @NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_create_locations, container, false); - ButterKnife.bind(this, view); - new_location_map_view.onCreate(savedInstanceState); - new_location_map_view.onResume(); - new_location_map_view.getMapAsync(this); - return view; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - viewModel = ViewModelProviders.of(getActivity()).get(MapCreatorViewModel.class); - create_button.setOnClickListener(this); - - } - - @Override - public void onClick(View v) { - alert_no_locaiton_text.setVisibility(View.GONE); - try { - if (Objects.requireNonNull(new_location_name.getEditText()).getText().toString().trim().isEmpty()) { - new_location_name.setError(getString(R.string.required_name)); - return; - } - if (new_location_name.getEditText().getText().toString().length() > getResources().getInteger(R.integer.max_name_length)) { - new_location_name.setError(getString(R.string.you_oversized)); - return; - } - new_location_name.setError(""); - if (Objects.requireNonNull(new_location_description.getEditText()).getText().toString().trim().isEmpty()) { - new_location_description.setError(getString(R.string.required_description)); - return; - } - if (new_location_description.getEditText().getText().toString().length() > getResources().getInteger(R.integer.max_description_length)) { - new_location_description.setError(getString(R.string.you_oversized)); - return; - } - new_location_description.setError(""); - if (marker == null) { - alert_no_locaiton_text.setVisibility(View.VISIBLE); - return; - } - } catch (NullPointerException ex) { - Toast.makeText(getContext(), ex.getMessage(), Toast.LENGTH_SHORT).show(); - return; - } - - String name = new_location_name.getEditText().getText().toString().trim(); - String description = new_location_description.getEditText().getText().toString().trim(); - viewModel.addLocation(name, description, String.valueOf(marker.getPosition().latitude), String.valueOf(marker.getPosition().longitude)); - - Navigation.findNavController(getActivity(), R.id.main_fragment_holder).popBackStack(); - } - - @Override - public void onMapReady(GoogleMap googleMap) { - - LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE); - if (getActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && - getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - Toast.makeText(getActivity(), getString(R.string.no_location_permissions), Toast.LENGTH_SHORT).show(); - return; - } - Location usrLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); - googleMap.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() { - @Override - public void onMapLongClick(LatLng latLng) { - alert_no_locaiton_text.setVisibility(View.GONE); - MarkerOptions m = new MarkerOptions().position(latLng); - googleMap.clear(); - googleMap.addMarker(m); - marker = m; - } - }); - googleMap.setMyLocationEnabled(true); - googleMap.getUiSettings().setMyLocationButtonEnabled(true); - googleMap.getUiSettings().setZoomControlsEnabled(true); - googleMap.getUiSettings().setMapToolbarEnabled(false); - googleMap.getUiSettings().setTiltGesturesEnabled(false); - googleMap.getUiSettings().setScrollGesturesEnabledDuringRotateOrZoom(false); - - LatLng usrLatLng = new LatLng(usrLocation.getLatitude(), usrLocation.getLongitude()); - CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(usrLatLng, CAMERA_UPDATE_ZOOM); - googleMap.animateCamera(cameraUpdate); - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateMapFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateMapFragment.java deleted file mode 100644 index d6c5c2d..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateMapFragment.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.creator; - - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Spinner; -import android.widget.Toast; - -import com.google.android.material.button.MaterialButton; -import com.google.android.material.textfield.TextInputLayout; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.config.Preferences; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.entity.User; -import com.martinlaizg.geofind.data.access.database.entity.enums.PlayLevel; -import com.martinlaizg.geofind.views.viewmodel.MapCreatorViewModel; - -import java.util.Objects; - -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProviders; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; -import androidx.preference.PreferenceManager; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class CreateMapFragment - extends Fragment { - - @BindView(R.id.new_map_name_layout) - TextInputLayout new_map_name; - @BindView(R.id.new_map_description_layout) - TextInputLayout new_map_description; - - @BindView(R.id.done_button) - MaterialButton doneButton; - @BindView(R.id.add_image_button) - MaterialButton add_image_button; - @BindView(R.id.dificulty_spinner) - Spinner dificultySpinner; - - private MapCreatorViewModel viewModel; - private NavController navController; - - public CreateMapFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { - // Inflate the layout for this fragment - final View view = inflater.inflate(R.layout.fragment_create_map, container, false); - ButterKnife.bind(this, view); - viewModel = ViewModelProviders.of(getActivity()).get(MapCreatorViewModel.class); - - doneButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - if (Objects.requireNonNull(new_map_name.getEditText()).getText().toString().trim().isEmpty()) { - new_map_name.setError(getString(R.string.required_name)); - return; - } - if (new_map_name.getEditText().getText().toString().trim().length() > getResources().getInteger(R.integer.max_name_length)) { - new_map_name.setError(getString(R.string.you_oversized)); - return; - } - if (Objects.requireNonNull(new_map_description.getEditText()).getText().toString().trim().isEmpty()) { - new_map_description.setError(getString(R.string.required_description)); - return; - } - if (new_map_description.getEditText().getText().toString().trim().length() > getResources().getInteger(R.integer.max_description_length)) { - new_map_description.setError(getString(R.string.you_oversized)); - return; - } - } catch (NullPointerException ex) { - Toast.makeText(getContext(), "View incorrecto", Toast.LENGTH_SHORT).show(); - return; - } - - String name = new_map_name.getEditText().getText().toString().trim(); - String description = new_map_description.getEditText().getText().toString().trim(); - PlayLevel pl = PlayLevel.getPlayLevel(dificultySpinner.getSelectedItemPosition()); - - User user = Preferences.getLoggedUser(PreferenceManager.getDefaultSharedPreferences(getContext())); - viewModel.setMap(name, description, user.getId(), pl); - Navigation.findNavController(getActivity(), R.id.main_fragment_holder).popBackStack(); - } - }); - - setInputs(); - - return view; - } - - private void setInputs() { - Map m = viewModel.getCreatedMap(); - if (!m.getName().isEmpty()) { - Objects.requireNonNull(new_map_name.getEditText()).setText(m.getName()); - } - if (!m.getDescription().isEmpty()) { - Objects.requireNonNull(new_map_description.getEditText()).setText(m.getDescription()); - } - if (m.getMin_level() != null) { - dificultySpinner.setSelection(m.getMin_level().ordinal()); - } - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatePlaceFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatePlaceFragment.java new file mode 100644 index 0000000..1ac8d4b --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatePlaceFragment.java @@ -0,0 +1,233 @@ +package com.martinlaizg.geofind.views.fragment.creator; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationManager; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.navigation.Navigation; + +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.material.textfield.TextInputLayout; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.views.viewmodel.CreatorViewModel; + +import java.util.List; +import java.util.Objects; + +import butterknife.BindView; +import butterknife.ButterKnife; + +import static android.content.Context.LOCATION_SERVICE; + +public class CreatePlaceFragment + extends Fragment + implements View.OnClickListener, OnMapReadyCallback, GoogleMap.OnMapLongClickListener { + + public static final String PLACE_POSITION = "PLACE_POSITION"; + + private static final String TAG = CreatePlaceFragment.class.getSimpleName(); + private static final int CAMERA_UPDATE_ZOOM = 15; + private static final int PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION = 1; + + @BindView(R.id.new_place_name_layout) + TextInputLayout new_place_name; + @BindView(R.id.new_place_description_layout) + TextInputLayout new_place_description; + @BindView(R.id.alert_no_place_text) + TextView alert_no_place_text; + @BindView(R.id.create_place) + Button create_button; + @BindView(R.id.new_place_map_view) + MapView new_place_map_view; + + private CreatorViewModel viewModel; + private MarkerOptions marker; + private GoogleMap gMap; + private Place place; + + @Override + public void onClick(View v) { + alert_no_place_text.setVisibility(View.GONE); + try { + if(Objects.requireNonNull(new_place_name.getEditText()).getText().toString().trim() + .isEmpty()) { + new_place_name.setError(getString(R.string.required_name)); + return; + } + if(new_place_name.getEditText().getText().toString().length() > + getResources().getInteger(R.integer.max_name_length)) { + new_place_name.setError(getString(R.string.text_too_long)); + return; + } + new_place_name.setError(""); + if(Objects.requireNonNull(new_place_description.getEditText()).getText().toString() + .trim().isEmpty()) { + new_place_description.setError(getString(R.string.required_description)); + return; + } + if(new_place_description.getEditText().getText().toString().length() > + getResources().getInteger(R.integer.max_description_length)) { + new_place_description.setError(getString(R.string.text_too_long)); + return; + } + new_place_description.setError(""); + if(marker == null) { + alert_no_place_text.setVisibility(View.VISIBLE); + return; + } + } catch(NullPointerException ex) { + Toast.makeText(getContext(), ex.getMessage(), Toast.LENGTH_SHORT).show(); + return; + } + + place.setName(new_place_name.getEditText().getText().toString().trim()); + place.setDescription(new_place_description.getEditText().getText().toString().trim()); + place.setPosition(marker.getPosition()); + + viewModel.setPlace(place); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder).popBackStack(); + } + + @Override + public void onMapReady(GoogleMap googleMap) { + gMap = googleMap; + if(requireActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != + PackageManager.PERMISSION_GRANTED && + requireActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != + PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, + android.Manifest.permission.ACCESS_FINE_LOCATION}, + PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION); + Toast.makeText(requireActivity(), getString(R.string.rejected_location_access), + Toast.LENGTH_SHORT).show(); + return; + } + setPlace(); + } + + @SuppressLint("MissingPermission") + private void setPlace() { + Location usrLocation = getLastKnownLocation(); + if(gMap != null) { + gMap.setMyLocationEnabled(true); + gMap.setOnMapLongClickListener(this); + gMap.getUiSettings().setMyLocationButtonEnabled(true); + gMap.getUiSettings().setMapToolbarEnabled(false); + gMap.getUiSettings().setTiltGesturesEnabled(false); + + LatLng usrLatLng = new LatLng(usrLocation.getLatitude(), usrLocation.getLongitude()); + gMap.clear(); + if(marker != null) { + gMap.moveCamera(CameraUpdateFactory + .newLatLngZoom(marker.getPosition(), CAMERA_UPDATE_ZOOM)); + gMap.addMarker(marker); + } else { + gMap.animateCamera( + CameraUpdateFactory.newLatLngZoom(usrLatLng, CAMERA_UPDATE_ZOOM)); + } + } + } + + @SuppressLint("MissingPermission") + private Location getLastKnownLocation() { + LocationManager locationManager = (LocationManager) requireActivity() + .getSystemService(LOCATION_SERVICE); + List providers = locationManager.getProviders(true); + Location bestLocation = null; + for(String provider : providers) { + Location l = locationManager.getLastKnownLocation(provider); + if(l == null) { + continue; + } + if(bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy()) { + // Found best last known location: %s", l); + bestLocation = l; + } + } + return bestLocation; + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + if(requestCode == PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION) { + if(permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION) && + grantResults[0] == PackageManager.PERMISSION_GRANTED && + permissions[1].equals(Manifest.permission.ACCESS_FINE_LOCATION) && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + setPlace(); + } + } + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_create_place, container, false); + ButterKnife.bind(this, view); + + new_place_map_view.onCreate(savedInstanceState); + new_place_map_view.onResume(); + new_place_map_view.getMapAsync(this); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + viewModel = ViewModelProviders.of(requireActivity()).get(CreatorViewModel.class); + viewModel.setLoad(false); + Bundle b = getArguments(); + if(b != null) { + int position = b.getInt(PLACE_POSITION, viewModel.getPlaces().size()); + place = viewModel.getPlace(position); + if(place != null) { + if(place.getName() != null) { + Objects.requireNonNull(new_place_name.getEditText()).setText(place.getName()); + } + if(place.getDescription() != null) { + Objects.requireNonNull(new_place_description.getEditText()) + .setText(place.getDescription()); + } + if(place.getPosition() != null) { + onMapLongClick(place.getPosition()); + } + } else { + Toast.makeText(requireContext(), getResources().getString(R.string.invalid_place), + Toast.LENGTH_SHORT).show(); + } + } + create_button.setOnClickListener(this); + if(marker != null) create_button.setText(R.string.update_place); + } + + @Override + public void onMapLongClick(LatLng latLng) { + alert_no_place_text.setVisibility(View.GONE); + MarkerOptions m = new MarkerOptions().position(latLng); + if(gMap != null) { + gMap.clear(); + gMap.addMarker(m); + } + marker = m; + + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateTourFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateTourFragment.java new file mode 100644 index 0000000..6db9417 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreateTourFragment.java @@ -0,0 +1,118 @@ +package com.martinlaizg.geofind.views.fragment.creator; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Spinner; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.navigation.Navigation; +import androidx.preference.PreferenceManager; + +import com.google.android.material.button.MaterialButton; +import com.google.android.material.textfield.TextInputLayout; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.config.Preferences; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.access.database.entities.User; +import com.martinlaizg.geofind.data.enums.PlayLevel; +import com.martinlaizg.geofind.views.viewmodel.CreatorViewModel; + +import java.util.Objects; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class CreateTourFragment + extends Fragment + implements View.OnClickListener { + + @BindView(R.id.tour_name_layout) + TextInputLayout tour_name_layout; + @BindView(R.id.tour_description_layout) + TextInputLayout tour_description_layout; + + @BindView(R.id.done_button) + MaterialButton done_button; + @BindView(R.id.add_image_button) + MaterialButton add_image_button; + @BindView(R.id.difficulty_spinner) + Spinner difficulty_spinner; + + private CreatorViewModel viewModel; + + @Override + public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container, + final Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.fragment_create_tour, container, false); + ButterKnife.bind(this, view); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + viewModel = ViewModelProviders.of(requireActivity()).get(CreatorViewModel.class); + Tour m = viewModel.getTour(); + viewModel.setLoad(false); + if(m != null) { + if(!m.getName().isEmpty()) { + Objects.requireNonNull(tour_name_layout.getEditText()).setText(m.getName()); + } + if(!m.getDescription().isEmpty()) { + Objects.requireNonNull(tour_description_layout.getEditText()) + .setText(m.getDescription()); + } + if(m.getMin_level() != null) { + difficulty_spinner.setSelection(m.getMin_level().ordinal()); + } + } + done_button.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + try { + tour_name_layout.setError(""); + if(Objects.requireNonNull(tour_name_layout.getEditText()).getText().toString().trim() + .isEmpty()) { + tour_name_layout.setError(getString(R.string.required_name)); + return; + } + tour_name_layout.setError(""); + if(tour_name_layout.getEditText().getText().toString().trim().length() > + getResources().getInteger(R.integer.max_name_length)) { + tour_name_layout.setError(getString(R.string.text_too_long)); + return; + } + tour_description_layout.setError(""); + if(Objects.requireNonNull(tour_description_layout.getEditText()).getText().toString() + .trim().isEmpty()) { + tour_description_layout.setError(getString(R.string.required_description)); + return; + } + if(tour_description_layout.getEditText().getText().toString().trim().length() > + getResources().getInteger(R.integer.max_description_length)) { + tour_description_layout.setError(getString(R.string.text_too_long)); + return; + } + } catch(NullPointerException ex) { + Toast.makeText(getContext(), "View incorrect", Toast.LENGTH_SHORT).show(); + return; + } + + String name = tour_name_layout.getEditText().getText().toString().trim(); + String description = tour_description_layout.getEditText().getText().toString().trim(); + PlayLevel pl = PlayLevel.getPlayLevel(difficulty_spinner.getSelectedItemPosition()); + + User user = Preferences + .getLoggedUser(PreferenceManager.getDefaultSharedPreferences(requireContext())); + viewModel.setCreatedTour(name, description, user.getId(), pl); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder).popBackStack(); + + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatorFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatorFragment.java index 6d48e22..91a56cb 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatorFragment.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/creator/CreatorFragment.java @@ -7,56 +7,53 @@ import android.widget.TextView; import android.widget.Toast; -import com.google.android.material.button.MaterialButton; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.adapter.CreatorLocationAdapter; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.views.viewmodel.MapCreatorViewModel; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; -import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.button.MaterialButton; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.views.adapter.CreatorPlacesAdapter; +import com.martinlaizg.geofind.views.fragment.single.TourFragment; +import com.martinlaizg.geofind.views.viewmodel.CreatorViewModel; + +import java.util.Objects; + import butterknife.BindView; import butterknife.ButterKnife; - public class CreatorFragment extends Fragment implements View.OnClickListener { + public static final String TOUR_ID = "TOUR_ID"; + // View - @BindView(R.id.create_map_name) - TextView mapName; - @BindView(R.id.create_map_description) - TextView mapDescription; - - @BindView(R.id.add_location_button) - MaterialButton add_location_button; - @BindView(R.id.create_map_button) - MaterialButton create_map_button; + @BindView(R.id.tour_name) + TextView tour_name; + @BindView(R.id.tour_description) + TextView tour_description; + + @BindView(R.id.add_place_button) + MaterialButton add_place_button; + @BindView(R.id.create_tour_button) + MaterialButton create_tour_button; @BindView(R.id.edit_button) MaterialButton edit_button; - @BindView(R.id.rec_view_loc_list) - RecyclerView recyclerView; - - private MapCreatorViewModel viewModel; - - public CreatorFragment() { - // Required empty public constructor - } + @BindView(R.id.places_list) + RecyclerView places_list; + private CreatorViewModel viewModel; @Override - public View onCreateView( - LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - // Inflate the layout for this fragment + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_creator, container, false); ButterKnife.bind(this, view); return view; @@ -64,45 +61,60 @@ public View onCreateView( @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - NavController navController = Navigation.findNavController(getActivity(), R.id.main_fragment_holder); - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - CreatorLocationAdapter adapter = new CreatorLocationAdapter(); - recyclerView.setAdapter(adapter); - - add_location_button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toCreateLocation)); - edit_button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toCreateMap)); - create_map_button.setOnClickListener(this); - - viewModel = ViewModelProviders.of(getActivity()).get(MapCreatorViewModel.class); - - Map map = viewModel.getCreatedMap(); - if (!map.getName().isEmpty()) { - mapName.setText(map.getName()); - } - if (!map.getDescription().isEmpty()) { - mapDescription.setText(map.getDescription()); - } - - adapter.setLocations(viewModel.getCreatedLocations()); + viewModel = ViewModelProviders.of(requireActivity()).get(CreatorViewModel.class); + CreatorPlacesAdapter adapter = new CreatorPlacesAdapter(); + places_list.setLayoutManager(new LinearLayoutManager(requireActivity())); + places_list.setAdapter(adapter); + + // Load tour + Bundle b = getArguments(); + Integer tour_id = Objects.requireNonNull(b).getInt(TOUR_ID); + viewModel.loadTour(tour_id).observe(this, tour -> { + if(tour != null) { + adapter.setPlaces(tour.getPlaces()); + if(tour.getId() != 0) { + create_tour_button.setText(R.string.update_tour); + } + if(!tour.getName().isEmpty()) { + tour_name.setText(tour.getName()); + } + if(!tour.getDescription().isEmpty()) { + tour_description.setText(tour.getDescription()); + } + } + }); + + // set buttons + add_place_button.setOnClickListener(v -> { + Bundle p = new Bundle(); + p.putInt(CreatePlaceFragment.PLACE_POSITION, viewModel.getPlaces().size()); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .navigate(R.id.toCreatePlace, p); + }); + edit_button.setOnClickListener( + v -> Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .navigate(R.id.toCreateTour)); + create_tour_button.setOnClickListener(this); } @Override public void onClick(View v) { - - create_map_button.setEnabled(false); - - if (!viewModel.isValid()) { - Toast.makeText(getActivity(), "Algo está mal", Toast.LENGTH_SHORT).show(); - return; - } - viewModel.createMap().observe(this, new Observer() { - @Override - public void onChanged(Map map) { - - create_map_button.setEnabled(true); - // TODO navigate to created map + create_tour_button.setEnabled(false); + viewModel.createTour().observe(this, tour -> { + create_tour_button.setEnabled(true); + if(tour == null) { + APIException err = viewModel.getError(); + Toast.makeText(requireActivity(), err.getType().getMessage(), Toast.LENGTH_LONG) + .show(); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .popBackStack(R.id.navTourList, false); + return; } + Toast.makeText(requireActivity(), R.string.tour_created, Toast.LENGTH_SHORT).show(); + Bundle b = new Bundle(); + b.putInt(TourFragment.TOUR_ID, tour.getId()); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .navigate(R.id.toNewTour, b); }); } } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/LocationListFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/LocationListFragment.java deleted file mode 100644 index f3a3587..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/LocationListFragment.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.list; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.adapter.LocationListAdapter; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.views.viewmodel.LocationViewModel; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProviders; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class LocationListFragment - extends Fragment { - - private static final String TAG = LocationListFragment.class.getSimpleName(); - - @BindView(R.id.location_list) - RecyclerView recyclerView; - - private LocationListAdapter adapter; - - - @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_location_list, container, false); - ButterKnife.bind(this, view); - ArrayList locations = new ArrayList<>(); - - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - adapter = new LocationListAdapter(); - recyclerView.setAdapter(adapter); - - - LocationViewModel locationViewModel = ViewModelProviders.of(this).get(LocationViewModel.class); - - locationViewModel.getAllLocations().observe(this, new Observer>() { - @Override - public void onChanged(List locations) { - adapter.setLocations(locations); - } - }); - - - return view; - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/MapListFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/MapListFragment.java deleted file mode 100644 index 551a742..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/MapListFragment.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.list; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.adapter.MapListAdapter; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.views.viewmodel.MapListViewModel; - -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProviders; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class MapListFragment - extends Fragment { - - private static final String TAG = MapListFragment.class.getSimpleName(); - - @BindView(R.id.map_list) - RecyclerView recyclerView; - - private MapListViewModel mapListViewModel; - private MapListAdapter adapter; - - @Nullable - @Override - public View onCreateView( - @NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { - final View view = inflater.inflate(R.layout.fragment_maps_list, container, false); - ButterKnife.bind(this, view); - - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - adapter = new MapListAdapter(); - recyclerView.setAdapter(adapter); - - mapListViewModel = ViewModelProviders.of(this).get(MapListViewModel.class); - - mapListViewModel.getAllMaps().observe(this, new Observer>() { - @Override - public void onChanged(List maps) { - adapter.setMaps(maps); - } - }); - - return view; - } - - private void loadMaps() { - mapListViewModel.refreshMaps(); - } - - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/TourListFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/TourListFragment.java new file mode 100644 index 0000000..8be80d3 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/list/TourListFragment.java @@ -0,0 +1,73 @@ +package com.martinlaizg.geofind.views.fragment.list; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.navigation.Navigation; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.api.error.ErrorType; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.views.adapter.TourListAdapter; +import com.martinlaizg.geofind.views.viewmodel.TourListViewModel; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class TourListFragment + extends Fragment { + + private static final String TAG = TourListFragment.class.getSimpleName(); + + @BindView(R.id.tour_list) + RecyclerView tour_list; + + @BindView(R.id.create_tour_button) + FloatingActionButton create_tour_button; + + private TourListViewModel viewModel; + private TourListAdapter adapter; + + @Nullable + @Override + public View onCreateView(@NonNull final LayoutInflater inflater, + @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.fragment_tour_list, container, false); + ButterKnife.bind(this, view); + + tour_list.setLayoutManager(new LinearLayoutManager(requireActivity())); + adapter = new TourListAdapter(); + tour_list.setAdapter(adapter); + + viewModel = ViewModelProviders.of(this).get(TourListViewModel.class); + viewModel.getTours().observe(this, tours -> { + if(tours != null) { + adapter.setTours(tours); + } else { + APIException error = viewModel.getError(); + if(error.getType() == ErrorType.NETWORK) { + Toast.makeText(requireContext(), + getResources().getString(R.string.network_error), + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(requireActivity(), error.getMessage(), Toast.LENGTH_SHORT) + .show(); + } + } + }); + viewModel.refresh(); + create_tour_button + .setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toCreator)); + return view; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/LoginFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/LoginFragment.java index 12d8194..83baf1c 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/LoginFragment.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/LoginFragment.java @@ -2,39 +2,35 @@ import android.os.Bundle; import android.text.TextUtils; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.navigation.Navigation; +import androidx.preference.PreferenceManager; + +import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.material.button.MaterialButton; import com.google.android.material.textfield.TextInputLayout; import com.martinlaizg.geofind.R; import com.martinlaizg.geofind.config.Preferences; import com.martinlaizg.geofind.views.viewmodel.LoginViewModel; -import org.jetbrains.annotations.NotNull; - import java.util.Objects; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProviders; -import androidx.navigation.Navigation; -import androidx.preference.PreferenceManager; import butterknife.BindView; import butterknife.ButterKnife; - public class LoginFragment extends Fragment implements View.OnClickListener { private static final String TAG = LoginFragment.class.getSimpleName(); - private static final String EMAIL = "EMAIL"; - private static final String PASSWORD = "PASSWORD"; @BindView(R.id.email_input) TextInputLayout email_input; @@ -49,12 +45,9 @@ public class LoginFragment private LoginViewModel viewModel; - public LoginFragment() { - // Required empty public constructor - } - @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_login, container, false); ButterKnife.bind(this, view); return view; @@ -63,37 +56,19 @@ public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - checkArguments(); viewModel = ViewModelProviders.of(this).get(LoginViewModel.class); login_button.setOnClickListener(this); - registry_button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toRegistry)); - } - - private void checkArguments() { - Bundle b = getArguments(); - if (b != null) { - try { - String email = b.getString(EMAIL); - if (email != null && !email.isEmpty()) { - Objects.requireNonNull(email_input.getEditText()).setText(email); - } - String password = b.getString(PASSWORD); - if (password != null && !password.isEmpty()) { - Objects.requireNonNull(password_input.getEditText()).setText(password); - } - } catch (NullPointerException ex) { - Log.e(TAG, "checkArguments", ex); - } - } + registry_button + .setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toRegistry)); } @Override public void onClick(View v) { - if (TextUtils.isEmpty(Objects.requireNonNull(email_input.getEditText()).getText())) { + if(TextUtils.isEmpty(Objects.requireNonNull(email_input.getEditText()).getText())) { email_input.setError(getString(R.string.required_email)); return; } - if (TextUtils.isEmpty(Objects.requireNonNull(password_input.getEditText()).getText())) { + if(TextUtils.isEmpty(Objects.requireNonNull(password_input.getEditText()).getText())) { password_input.setError(getString(R.string.required_password)); return; } @@ -104,15 +79,18 @@ public void onClick(View v) { String password = password_input.getEditText().getText().toString().trim(); viewModel.setLogin(email, password); viewModel.login().observe(this, user -> { - if (user == null) { + if(user == null) { email_input.setError(getString(R.string.wrong_email_password)); password_input.setError(getString(R.string.wrong_email_password)); return; } - Preferences.setLoggedUser(PreferenceManager.getDefaultSharedPreferences(Objects.requireNonNull(getContext())), user); + Credential credential = new Credential.Builder(email).setPassword(password).build(); + Preferences.setLoggedUser(PreferenceManager.getDefaultSharedPreferences( + Objects.requireNonNull(getContext())), user); login_button.setEnabled(true); loading_spinner.setVisibility(View.GONE); - Navigation.findNavController(Objects.requireNonNull(getActivity()), R.id.main_fragment_holder).navigate(R.id.toMainLogged); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .popBackStack(); }); } } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/RegistryFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/RegistryFragment.java index 0448ecb..a65cb75 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/RegistryFragment.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/login/RegistryFragment.java @@ -1,6 +1,5 @@ package com.martinlaizg.geofind.views.fragment.login; - import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -8,25 +7,21 @@ import android.view.ViewGroup; import android.widget.Toast; -import com.google.android.material.button.MaterialButton; -import com.google.android.material.textfield.TextInputLayout; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.retrofit.error.APIError; -import com.martinlaizg.geofind.views.viewmodel.LoginViewModel; - -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProviders; import androidx.navigation.Navigation; + +import com.google.android.material.button.MaterialButton; +import com.google.android.material.textfield.TextInputLayout; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.views.viewmodel.LoginViewModel; + import butterknife.BindView; import butterknife.ButterKnife; - public class RegistryFragment extends Fragment { @@ -44,12 +39,13 @@ public class RegistryFragment @BindView(R.id.c_password_input) TextInputLayout c_password_input; @BindView(R.id.btn_registry) - MaterialButton btn_registr; + MaterialButton btn_registry; - LoginViewModel viewModel; + private LoginViewModel viewModel; @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_registry, container, false); ButterKnife.bind(this, view); return view; @@ -58,49 +54,44 @@ public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - viewModel = ViewModelProviders.of(Objects.requireNonNull(getActivity())).get(LoginViewModel.class); + viewModel = ViewModelProviders.of(requireActivity()).get(LoginViewModel.class); String email = viewModel.getEmail(); - if (email != null && !email.isEmpty()) { + if(email != null && !email.isEmpty()) { email_input.getEditText().setText(email); } - btn_registr.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(final View v) { - registry(); - } - }); + btn_registry.setOnClickListener(v -> registry()); } private void registry() { - btn_registr.setEnabled(false); + btn_registry.setEnabled(false); try { - if (name_input.getEditText().getText().toString().trim().isEmpty()) { + if(name_input.getEditText().getText().toString().trim().isEmpty()) { name_input.setError(getString(R.string.required_name)); return; } - if (username_input.getEditText().getText().toString().trim().isEmpty()) { + if(username_input.getEditText().getText().toString().trim().isEmpty()) { username_input.setError(getString(R.string.required_username)); return; } - if (email_input.getEditText().getText().toString().trim().isEmpty()) { + if(email_input.getEditText().getText().toString().trim().isEmpty()) { email_input.setError(getString(R.string.required_password)); return; } String password = password_input.getEditText().getText().toString().trim(); - if (password.isEmpty()) { + if(password.isEmpty()) { password_input.setError(getString(R.string.required_verify_password)); return; } final String c_password = c_password_input.getEditText().getText().toString().trim(); - if (c_password.isEmpty()) { + if(c_password.isEmpty()) { password_input.setError(getString(R.string.required_verify_password)); return; } - if (!c_password.equals(password)) { - password_input.setError(getString(R.string.no_match_password)); + if(!c_password.equals(password)) { + password_input.setError(getString(R.string.password_does_not_match)); return; } - } catch (NullPointerException ex) { + } catch(NullPointerException ex) { Log.e(TAG, "registry: ", ex); } @@ -110,19 +101,19 @@ private void registry() { String password = password_input.getEditText().getText().toString().trim(); viewModel.setRegistry(name, username, email, password); viewModel.registry().observe(this, (user) -> { - btn_registr.setEnabled(true); - if (user == null) { - Toast.makeText(getActivity(), "Algo ha ido mal", Toast.LENGTH_SHORT).show(); + btn_registry.setEnabled(true); + if(user == null) { + APIException error = viewModel.getError(); + Toast.makeText(requireActivity(), + getResources().getString(error.getType().getMessage()), + Toast.LENGTH_SHORT).show(); return; } - APIError error = user.getError(); - if (error != null) { - // TODO: manage API error - Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(getActivity(), "Registrado correctamente", Toast.LENGTH_LONG).show(); - Navigation.findNavController(getActivity(), R.id.main_fragment_holder).popBackStack(); - } + Toast.makeText(requireActivity(), getResources().getString(R.string.registry), + Toast.LENGTH_LONG).show(); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .popBackStack(); + }); // TODO: add loading image } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/CompletePlace.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/CompletePlace.java new file mode 100644 index 0000000..e4dbc5f --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/CompletePlace.java @@ -0,0 +1,22 @@ +package com.martinlaizg.geofind.views.fragment.play; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import com.martinlaizg.geofind.R; + +public class CompletePlace + extends Fragment { + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_complete_place, container, false); + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/CompleteTour.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/CompleteTour.java new file mode 100644 index 0000000..f042cf3 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/CompleteTour.java @@ -0,0 +1,22 @@ +package com.martinlaizg.geofind.views.fragment.play; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; + +import com.martinlaizg.geofind.R; + +public class CompleteTour + extends Fragment { + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_complete_tour, container, false); + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayCompassFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayCompassFragment.java new file mode 100644 index 0000000..740dd1d --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayCompassFragment.java @@ -0,0 +1,49 @@ +package com.martinlaizg.geofind.views.fragment.play; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.martinlaizg.geofind.R; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class PlayCompassFragment + extends PlayTourFragment { + + private static final String TAG = PlayCompassFragment.class.getSimpleName(); + + @BindView(R.id.navigation_image) + ImageView navigation_image; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_play_compass, container, false); + ButterKnife.bind(this, view); + return view; + } + + @Override + protected String TAG() { + return TAG; + } + + @Override + void updateView() { + if(usrLocation != null && placeLocation != null) { + // Rotate image + float bearing = usrLocation.bearingTo(placeLocation); + Log.d(TAG, "updateView: rotate image=" + bearing); + navigation_image.setRotation(bearing); + } + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayMapFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayMapFragment.java new file mode 100644 index 0000000..5b910df --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayMapFragment.java @@ -0,0 +1,116 @@ +package com.martinlaizg.geofind.views.fragment.play; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; + +import com.google.android.gms.maps.CameraUpdate; +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.LatLngBounds; +import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.material.button.MaterialButton; +import com.martinlaizg.geofind.R; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class PlayMapFragment + extends PlayTourFragment + implements OnMapReadyCallback { + + private static final String TAG = PlayMapFragment.class.getSimpleName(); + + private final static float MAX_ZOOM = 18.6f; + private static final float DISTANCE_TO_FIX_ZOOM = 100; + private static final int MAP_PADDING = 200; + + @BindView(R.id.map_type_button) + MaterialButton map_type_button; + @BindView(R.id.map_view) + MapView map_view; + + private GoogleMap googleMap; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_play_map, container, false); + ButterKnife.bind(this, view); + map_view.onCreate(savedInstanceState); + map_view.onResume(); + map_view.getMapAsync(this); + + String[] options = getResources().getStringArray(R.array.mapTypes); + int[] mapTypes = {GoogleMap.MAP_TYPE_NORMAL, GoogleMap.MAP_TYPE_SATELLITE}; + map_type_button.setOnClickListener(v -> { + AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + builder.setTitle(getResources().getString(R.string.map_type)); + builder.setItems(options, (dialog, item) -> googleMap.setMapType(mapTypes[item])); + AlertDialog alert = builder.create(); + alert.show(); + }); + return view; + } + + @Override + public void onMapReady(GoogleMap googleMap) { + this.googleMap = googleMap; + if(requireActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != + PackageManager.PERMISSION_GRANTED && + requireActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != + PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION}, + PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION); + return; + } + this.googleMap.setMyLocationEnabled(true); + this.googleMap.getUiSettings().setMyLocationButtonEnabled(false); + this.googleMap.getUiSettings().setMapToolbarEnabled(false); + updateView(); + } + + @Override + protected String TAG() { + return TAG; + } + + protected void updateView() { + + if(googleMap != null && usrLocation != null) { + + CameraUpdate cu; + LatLngBounds.Builder builder = new LatLngBounds.Builder(); + builder.include(new LatLng(usrLocation.getLatitude(), usrLocation.getLongitude())); + if(place != null) { + // Add place to camera update + builder.include(place.getPosition()); + + // Add place marker + googleMap.clear(); + googleMap.addMarker(new MarkerOptions().position(place.getPosition())); + } + LatLngBounds cameraPosition = builder.build(); + if(place == null || distance < DISTANCE_TO_FIX_ZOOM) { + cu = CameraUpdateFactory.newLatLngZoom(cameraPosition.getCenter(), MAX_ZOOM); + } else { + cu = CameraUpdateFactory.newLatLngBounds(cameraPosition, MAP_PADDING); + } + googleMap.getUiSettings().setMyLocationButtonEnabled(true); + googleMap.animateCamera(cu); + Log.d(TAG, "updateView: zoom=" + googleMap.getCameraPosition().zoom); + + } + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayThermFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayThermFragment.java new file mode 100644 index 0000000..2bc723d --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayThermFragment.java @@ -0,0 +1,52 @@ +package com.martinlaizg.geofind.views.fragment.play; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.cardview.widget.CardView; + +import com.martinlaizg.geofind.R; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class PlayThermFragment + extends PlayTourFragment { + + private static final String TAG = PlayThermFragment.class.getSimpleName(); + + @BindView(R.id.therm_card) + CardView therm_card; + + private float lastDistance = 0; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_play_therm, container, false); + ButterKnife.bind(this, view); + return view; + } + + @Override + protected String TAG() { + return TAG; + } + + @Override + void updateView() { + if(distance != null) { + if(distance > lastDistance) { + therm_card.setCardBackgroundColor(getResources().getColor(R.color.red)); + } else { + therm_card.setCardBackgroundColor(getResources().getColor(R.color.green)); + } + lastDistance = distance; + } + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayTourFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayTourFragment.java new file mode 100644 index 0000000..a995e5c --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/PlayTourFragment.java @@ -0,0 +1,183 @@ +package com.martinlaizg.geofind.views.fragment.play; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.navigation.Navigation; + +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.config.Preferences; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.User; +import com.martinlaizg.geofind.views.viewmodel.PlayTourViewModel; + +import butterknife.BindView; + +abstract class PlayTourFragment + extends Fragment + implements LocationListener { + + public static final String TOUR_ID = "TOUR_ID"; + + static final int PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION = 1; + + private static final float DISTANCE_TO_COMPLETE = 15; + private static final long LOC_TIME_REQ = 200; + private static final float LOC_DIST_REQ = 2; + + @BindView(R.id.place_name) + TextView place_name; + @BindView(R.id.place_description) + TextView place_description; + @BindView(R.id.place_complete) + TextView place_complete; + @BindView(R.id.place_distance) + TextView place_distance; + + Place place; + PlayTourViewModel viewModel; + Location usrLocation; + Location placeLocation; + Float distance; + + private LocationManager locationManager; + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + if(requestCode == PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION && permissions.length >= 2) { + if(permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION) && + grantResults[0] == PackageManager.PERMISSION_GRANTED && + permissions[1].equals(Manifest.permission.ACCESS_FINE_LOCATION) && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + Log.d(TAG(), "onRequestPermissionsResult: success"); + } + Log.d(TAG(), "onRequestPermissionsResult: deny"); + } + } + + protected abstract String TAG(); + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + viewModel = ViewModelProviders.of(requireActivity()).get(PlayTourViewModel.class); + Bundle b = getArguments(); + int tour_id = 0; + if(b != null) { + tour_id = b.getInt(TOUR_ID); + } + User u = Preferences + .getLoggedUser(PreferenceManager.getDefaultSharedPreferences(requireContext())); + viewModel.loadPlay(u.getId(), tour_id).observe(requireActivity(), place -> { + if(place == null) { + Log.i(TAG(), "onViewCreated: tour completed"); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .navigate(R.id.toCompleteTour); + return; + } + setPlace(place); + }); + } + + @Override + public void onResume() { + super.onResume(); + Log.i(TAG(), "onResume: check location permissions"); + locationManager = (LocationManager) requireActivity() + .getSystemService(Context.LOCATION_SERVICE); + if(requireActivity().checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != + PackageManager.PERMISSION_GRANTED && + requireActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != + PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION}, + PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION); + return; + } + usrLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + Log.i(TAG(), "onResume: start request location updates"); + locationManager + .requestLocationUpdates(LocationManager.GPS_PROVIDER, LOC_TIME_REQ, LOC_DIST_REQ, + this); + updateView(); + } + + @Override + public void onPause() { + super.onPause(); + Log.i(TAG(), "onPause: delete location updates"); + locationManager.removeUpdates(this); + } + + abstract void updateView(); + + private void setPlace(Place nextPlace) { + place = nextPlace; + placeLocation = new Location(""); + placeLocation.setLatitude(place.getLat()); + placeLocation.setLongitude(place.getLon()); + place_name.setText(place.getName()); + place_description.setText(place.getDescription()); + int numCompletedPlaces = viewModel.getPlay().getPlaces().size() + 1; + int numPlaces = viewModel.getPlay().getTour().getPlaces().size(); + place_complete.setText( + getResources().getString(R.string.tour_completenes, numCompletedPlaces, numPlaces)); + } + + @Override + public void onLocationChanged(@NonNull Location location) { + Log.d(TAG(), "onLocationChanged: "); + usrLocation = location; + + // Set distance + if(placeLocation != null) { + distance = usrLocation.distanceTo(placeLocation); + place_distance.setText( + getResources().getString(R.string.place_distance, distance.intValue())); + Log.d(TAG(), "updateView: distance=" + distance + "m"); + if(distance < DISTANCE_TO_COMPLETE) { + Log.d(TAG(), "updateView: user arrive to the place"); + viewModel.completePlace(place.getId()).observe(this, done -> { + if(!done) { + Toast.makeText(requireContext(), viewModel.getError().getMessage(), + Toast.LENGTH_SHORT).show(); + return; + } + Log.d(TAG(), "updateView: Place done"); + setPlace(viewModel.getNextPlace()); + }); + } + updateView(); + } + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + Log.i(TAG(), "onStatusChanged: "); + } + + @Override + public void onProviderEnabled(String provider) { + Log.i(TAG(), "onProviderEnabled: "); + } + + @Override + public void onProviderDisabled(String provider) { + Log.i(TAG(), "onProviderDisabled: "); + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/compass/PlayMapOnCompassFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/compass/PlayMapOnCompassFragment.java deleted file mode 100644 index 61bc987..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/compass/PlayMapOnCompassFragment.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.play.compass; - - -import android.app.Fragment; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.martinlaizg.geofind.R; - - -/** - * A simple {@link Fragment} subclass. - */ -public class PlayMapOnCompassFragment - extends Fragment { - - - public PlayMapOnCompassFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView( - LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_play_map_on_compass, container, false); - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/map/PlayLocationOnMapFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/map/PlayLocationOnMapFragment.java deleted file mode 100644 index 9978fbd..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/map/PlayLocationOnMapFragment.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.play.map; - -import android.Manifest; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.location.LocationListener; -import android.location.LocationManager; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.android.gms.maps.CameraUpdate; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.OnMapReadyCallback; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; -import com.google.android.gms.maps.model.MarkerOptions; -import com.google.android.material.button.MaterialButton; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.views.viewmodel.MapViewModel; - -import org.jetbrains.annotations.NotNull; - -import java.util.Locale; -import java.util.Objects; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProviders; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class PlayLocationOnMapFragment - extends Fragment - implements OnMapReadyCallback, LocationListener { - - static final String LOCATION_ID = "LOCATION_ID"; - private static final String TAG = PlayLocationOnMapFragment.class.getSimpleName(); - private static final int PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION = 1; - // Minimum time (ms) between location updates - private static final long MIN_MS_LOC_UPDATE = 500; - // Minimum distance (meters) between location updates - private static final float MIN_METERS_LOC_UPDATE = 1; - // Padding (px) between markers and border in location_map_view - private static final int MAP_PADDING = 100; - - @BindView(R.id.location_name) - TextView location_name; - @BindView(R.id.location_description) - TextView location_description; - @BindView(R.id.navigate_button) - MaterialButton navigate_button; - - @BindView(R.id.location_map_view) - MapView location_map_view; - - private Location location; - private GoogleMap gMap; - - @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_play_location_on_map, container, false); - ButterKnife.bind(this, view); - location_map_view.onCreate(savedInstanceState); - location_map_view.onResume(); - location_map_view.getMapAsync(this); - navigate_button.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String uri = String.format(Locale.ENGLISH, "google.navigation:q=%f,%f", Float.valueOf(location.getLat()), Float.valueOf(location.getLon())); - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); - getActivity().startActivity(intent); - } - }); - return view; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - Bundle b = getArguments(); - String loc_id = ""; - if (b != null) { - loc_id = b.getString(LOCATION_ID); - } - MapViewModel viewModel = ViewModelProviders.of(getActivity()).get(MapViewModel.class); - location = viewModel.getLocation(loc_id); - - location_name.setText(location.getName()); - location_description.setText(location.getDescription()); - } - - @Override - public void onMapReady(GoogleMap googleMap) { - gMap = googleMap; - if (Objects.requireNonNull(getActivity()).checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && - getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION); - } - gMap.setMyLocationEnabled(true); - LocationManager locationManager = (LocationManager) Objects.requireNonNull(getActivity()).getSystemService(Context.LOCATION_SERVICE); - updateLocation(locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if (Objects.requireNonNull(getActivity()).checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && - getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION); - } - LocationManager locationManager = (LocationManager) Objects.requireNonNull(getActivity()).getSystemService(Context.LOCATION_SERVICE); - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_MS_LOC_UPDATE, MIN_METERS_LOC_UPDATE, this); - updateLocation(locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)); - } - - private void updateLocation(android.location.Location usrLocation) { - Log.i(TAG, "Location updated"); - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - builder.include(location.getLatLng()); - builder.include(new LatLng(usrLocation.getLatitude(), usrLocation.getLongitude())); - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, MAP_PADDING); - - if (gMap == null) return; - gMap.addMarker(new MarkerOptions().position(location.getLatLng())); - gMap.getUiSettings().setMyLocationButtonEnabled(false); - gMap.getUiSettings().setMapToolbarEnabled(false); - gMap.moveCamera(cu); - } - - - @Override - public void onLocationChanged(android.location.Location usrLocation) { - updateLocation(usrLocation); - } - - @Override - public void onStatusChanged(String provider, int status, Bundle extras) { - - } - - @Override - public void onProviderEnabled(String provider) { - - } - - @Override - public void onProviderDisabled(String provider) { - - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/map/PlayMapOnMapFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/map/PlayMapOnMapFragment.java deleted file mode 100644 index 1e0054c..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/map/PlayMapOnMapFragment.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.play.map; - -import android.Manifest; -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.pm.PackageManager; -import android.location.LocationManager; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.android.gms.maps.CameraUpdate; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.OnMapReadyCallback; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; -import com.google.android.gms.maps.model.Marker; -import com.google.android.gms.maps.model.MarkerOptions; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.views.viewmodel.MapViewModel; - -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Objects; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModelProviders; -import androidx.navigation.Navigation; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class PlayMapOnMapFragment - extends Fragment - implements OnMapReadyCallback, GoogleMap.OnInfoWindowClickListener { - - private static final int MAP_PADDING = 80; - private static final int PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION = 1; - private static final String TAG = PlayMapOnMapFragment.class.getSimpleName(); - @BindView(R.id.map_name) - TextView map_name; - @BindView(R.id.map_description) - TextView map_description; - - @BindView(R.id.map_view) - MapView map_view; - private MapViewModel viewModel; - private GoogleMap gMap; - - @Override - public View onCreateView( - @NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_play_map_on_map, container, false); - ButterKnife.bind(this, view); - map_view.onCreate(savedInstanceState); - map_view.onResume(); - map_view.getMapAsync(this); - return view; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - viewModel = ViewModelProviders.of(getActivity()).get(MapViewModel.class); - Map map = viewModel.getMap(); - map_name.setText(map.getName()); - map_description.setText(map.getDescription()); - } - - - @Override - public void onMapReady(GoogleMap googleMap) { - // TODO: refactor - gMap = googleMap; - if (Objects.requireNonNull(getActivity()).checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && - getActivity().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION); - return; - } - setLocations(); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if (requestCode == PERMISSION_ACCESS_COARSE_AND_FINE_LOCATION) { - if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION) && grantResults[0] == PackageManager.PERMISSION_GRANTED && - permissions[1].equals(Manifest.permission.ACCESS_FINE_LOCATION) && grantResults[1] == PackageManager.PERMISSION_GRANTED) { - setLocations(); - } - } - - } - - @SuppressLint("MissingPermission") - private void setLocations() { - List locs = viewModel.getLocations(); - LatLngBounds.Builder builder = new LatLngBounds.Builder(); - for (Location l : locs) { // Add the locations to the builder - MarkerOptions m = new MarkerOptions().position(l.getLatLng()).title(l.getName()); - gMap.addMarker(m); - builder.include(m.getPosition()); - } - - LocationManager locationManager = (LocationManager) Objects.requireNonNull(getActivity()).getSystemService(Context.LOCATION_SERVICE); - android.location.Location usrLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); - builder.include(new LatLng(usrLocation.getLatitude(), usrLocation.getLongitude())); // Add the user location to the builder - gMap.setMyLocationEnabled(true); - gMap.getUiSettings().setMyLocationButtonEnabled(false); - gMap.getUiSettings().setMapToolbarEnabled(false); - gMap.getUiSettings().setTiltGesturesEnabled(false); - gMap.setOnInfoWindowClickListener(this); - - LatLngBounds bounds = builder.build(); - CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, MAP_PADDING); - gMap.moveCamera(cu); - } - - @Override - public void onInfoWindowClick(Marker marker) { - String name = marker.getTitle(); - Location l = viewModel.getLocationByName(name); - if (l == null) { - Log.e(TAG, "onInfoWindowClick: location no exist", null); - return; - } - Bundle b = new Bundle(); - b.putString(PlayLocationOnMapFragment.LOCATION_ID, l.getId()); - Navigation.findNavController(getActivity(), R.id.main_fragment_holder).navigate(R.id.toPlayLocationOnMap, b); - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/therm/PlayMapOnThermFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/therm/PlayMapOnThermFragment.java deleted file mode 100644 index f4647c7..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/play/therm/PlayMapOnThermFragment.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.play.therm; - - -import android.app.Fragment; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.martinlaizg.geofind.R; - - -/** - * A simple {@link Fragment} subclass. - */ -public class PlayMapOnThermFragment - extends Fragment { - - - public PlayMapOnThermFragment() { - // Required empty public constructor - } - - - @Override - public View onCreateView( - LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_play_map_on_therm, container, false); - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/LocationFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/LocationFragment.java deleted file mode 100644 index 68fd230..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/LocationFragment.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.single; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.views.viewmodel.LocationViewModel; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProviders; -import butterknife.BindView; -import butterknife.ButterKnife; - -public class LocationFragment - extends Fragment { - - - public static final String LOC_ID = "LOCATION_ID"; - - @BindView(R.id.location_name) - TextView location_name; - @BindView(R.id.location_description) - TextView location_description; - @BindView(R.id.location_visits) - TextView location_visits; - @BindView(R.id.location_image) - ImageView location_image; - - private String loc_id; - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_location, container, false); - ButterKnife.bind(this, view); - Bundle b = getArguments(); - if (b != null) { - loc_id = b.getString(LOC_ID); - } - return view; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - LocationViewModel viewModel = ViewModelProviders.of(this).get(LocationViewModel.class); - - viewModel.getLocation(loc_id).observe(this, new Observer() { - @Override - public void onChanged(Location location) { - setLocation(location); - } - }); - } - - private void setLocation(Location location) { - if (location != null) { - location_name.setText(location.getName()); - location_description.setText(location.getDescription()); // TODO cambiar por el valor real - location_visits.setText("2.594 TODO"); // TODO cambiar por el valor real - location_image.setImageResource(R.drawable.default_map_image); - } - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/MapFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/MapFragment.java deleted file mode 100644 index 0268faa..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/MapFragment.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.martinlaizg.geofind.views.fragment.single; - - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.android.material.button.MaterialButton; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.adapter.LocationListAdapter; -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.entity.enums.PlayLevel; -import com.martinlaizg.geofind.views.viewmodel.MapViewModel; - -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.ConstraintLayout; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProviders; -import androidx.navigation.Navigation; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; - - -public class MapFragment - extends Fragment { - - public static final String MAP_ID = "MAP_ID"; - private static final String PLAY_LEVEL = "PLAY_LEVEL"; - private static final String TAG = MapFragment.class.getSimpleName(); - - @BindView(R.id.map_name) - TextView map_name; - @BindView(R.id.map_description) - TextView map_description; - @BindView(R.id.map_creator) - TextView map_creator; - @BindView(R.id.map_num_locations) - TextView map_num_locations; - - @BindView(R.id.play_therm_button) - MaterialButton play_therm_button; - @BindView(R.id.play_compass_button) - MaterialButton play_compass_button; - @BindView(R.id.play_map_button) - MaterialButton play_map_button; - - - @BindView(R.id.location_list) - RecyclerView recyclerView; - @BindView(R.id.play_buttons) - ConstraintLayout play_buttons; - - private LocationListAdapter adapter; - private String map_id; - private PlayLevel play_level; - - - public MapFragment() { - } - - @Override - public View onCreateView(@NotNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_map, container, false); - ButterKnife.bind(this, view); - Bundle b = getArguments(); - if (b != null) { - map_id = b.getString(MAP_ID); - int p = b.getInt(PLAY_LEVEL, -1); - if (p >= 0) { // play level selected - play_level = PlayLevel.values()[p]; - play_buttons.setVisibility(View.GONE); - } else { // play level not selected - play_buttons.setVisibility(View.VISIBLE); - } - } - return view; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - adapter = new LocationListAdapter(); - adapter.setPlayLevel(play_level); - recyclerView.setAdapter(adapter); - - play_map_button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toPlayMapOnMap)); - // TODO change to the correct navigation - play_compass_button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toPlayMapOnMap)); - // TODO change to the correct navigation - play_therm_button.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.toPlayMapOnMap)); - - MapViewModel viewModel = ViewModelProviders.of(getActivity()).get(MapViewModel.class); - viewModel.getMap(map_id).observe(getActivity(), new Observer() { - @Override - public void onChanged(Map map) { - setMap(map); - } - }); - viewModel.getLocations(map_id).observe(getActivity(), new Observer>() { - @Override - public void onChanged(List locations) { - adapter.setLocations(locations); - map_num_locations.setText(String.format(getString(R.string.num_locations), locations.size())); - } - }); - } - - private void setMap(Map map) { - if (map != null) { - map_name.setText(map.getName()); - map_description.setText(map.getDescription()); - map_creator.setText(String.format(getString(R.string.num_creator), map.getCreator_id())); // TODO cambiar por valor real - setPlayLevel(map.getMin_level()); - } - } - - private void setPlayLevel(PlayLevel min_level) { - play_map_button.setEnabled(false); - play_compass_button.setEnabled(false); - play_therm_button.setEnabled(false); - switch (min_level) { - case MAP: - play_map_button.setEnabled(true); - case COMPASS: - play_compass_button.setEnabled(true); - case THERMOMETER: - play_therm_button.setEnabled(true); - } - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/PlaceFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/PlaceFragment.java new file mode 100644 index 0000000..3ee357c --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/PlaceFragment.java @@ -0,0 +1,96 @@ +package com.martinlaizg.geofind.views.fragment.single; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; + +import com.google.android.gms.maps.CameraUpdate; +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.model.MarkerOptions; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.views.viewmodel.TourViewModel; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class PlaceFragment + extends Fragment + implements OnMapReadyCallback { + + public static final String PLACE_ID = "PLACE_ID"; + private static final float MAP_ZOOM = 14.5f; + + @BindView(R.id.place_name) + TextView place_name; + @BindView(R.id.place_description) + TextView place_description; + @BindView(R.id.place_position) + TextView place_position; + @BindView(R.id.place_image) + ImageView place_image; + @BindView(R.id.place_map) + MapView place_map; + + private int place_id; + private GoogleMap googleMap; + private TourViewModel viewModel; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_place, container, false); + ButterKnife.bind(this, view); + place_map.onCreate(savedInstanceState); + place_map.onResume(); + place_map.getMapAsync(this); + Bundle b = getArguments(); + if(b != null) { + place_id = b.getInt(PLACE_ID); + } + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + viewModel = ViewModelProviders.of(requireActivity()).get(TourViewModel.class); + + viewModel.loadPlace(place_id).observe(this, this::setPlace); + } + + private void setPlace(Place place) { + if(place != null) { + place_name.setText(place.getName()); + place_description.setText(place.getDescription()); + place_image.setImageResource(R.drawable.default_map_image); + int number = place.getOrder() + 1; + int total = viewModel.getPlaces().size(); + place_position.setText(getResources().getString(R.string.place_completeness, number, total)); + if(googleMap != null) { + googleMap.addMarker(new MarkerOptions().position(place.getPosition())); + CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(place.getPosition(), MAP_ZOOM); + googleMap.moveCamera(cu); + } + } + } + + @Override + public void onMapReady(GoogleMap googleMap) { + googleMap.getUiSettings().setAllGesturesEnabled(false); + googleMap.getUiSettings().setMyLocationButtonEnabled(false); + googleMap.getUiSettings().setMapToolbarEnabled(false); + this.googleMap = googleMap; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/TourFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/TourFragment.java new file mode 100644 index 0000000..d9d8c83 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/fragment/single/TourFragment.java @@ -0,0 +1,167 @@ +package com.martinlaizg.geofind.views.fragment.single; + +import android.app.AlertDialog; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.navigation.Navigation; +import androidx.preference.PreferenceManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.button.MaterialButton; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.config.Preferences; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.access.database.entities.User; +import com.martinlaizg.geofind.data.enums.PlayLevel; +import com.martinlaizg.geofind.views.adapter.PlaceListAdapter; +import com.martinlaizg.geofind.views.fragment.creator.CreatorFragment; +import com.martinlaizg.geofind.views.fragment.play.PlayMapFragment; +import com.martinlaizg.geofind.views.viewmodel.TourViewModel; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class TourFragment + extends Fragment { + + public static final String TOUR_ID = "TOUR_ID"; + private static final String TAG = TourFragment.class.getSimpleName(); + + @BindView(R.id.tour_name) + TextView tour_name; + @BindView(R.id.tour_description) + TextView tour_description; + @BindView(R.id.tour_creator) + TextView tour_creator; + @BindView(R.id.tour_num_places) + TextView tour_num_places; + @BindView(R.id.edit_button) + MaterialButton edit_button; + @BindView(R.id.places_list) + RecyclerView places_list; + @BindView(R.id.other_places) + RecyclerView other_places; + + @BindView(R.id.play_button) + MaterialButton play_button; + + @BindView(R.id.empty_text) + TextView empty_text; + + private PlaceListAdapter adapterCompleted; + private PlaceListAdapter adapterNoCompleted; + private AlertDialog alert; + private TourViewModel viewModel; + private User user; + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_tour, container, false); + ButterKnife.bind(this, view); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(requireActivity()); + user = Preferences.getLoggedUser(sp); + + adapterCompleted = new PlaceListAdapter(true, getResources().getColor(R.color.grey)); + places_list.setLayoutManager(new LinearLayoutManager(requireActivity())); + places_list.setAdapter(adapterCompleted); + + adapterNoCompleted = new PlaceListAdapter(false, 0); + other_places.setLayoutManager(new LinearLayoutManager(requireActivity())); + other_places.setAdapter(adapterNoCompleted); + + int tour_id = 0; + Bundle b = getArguments(); + if(b != null) { + tour_id = b.getInt(TOUR_ID); + } + if(tour_id == 0) { + Toast.makeText(requireContext(), + requireContext().getString(R.string.tour_not_permitted), + Toast.LENGTH_SHORT).show(); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .popBackStack(); + } + viewModel = ViewModelProviders.of(requireActivity()).get(TourViewModel.class); + viewModel.loadTour(tour_id, user.getId()).observe(requireActivity(), this::setTour); + + } + + private void setTour(Tour tour) { + if(tour != null) { + tour_name.setText(tour.getName()); + tour_description.setText(tour.getDescription()); + tour_creator.setText(tour.getCreator().getUsername()); + if(tour.getPlaces().isEmpty()) { + empty_text.setVisibility(View.VISIBLE); + } + if(user != null && user.getId() == tour.getCreator_id()) { + Bundle b = new Bundle(); + b.putInt(CreatorFragment.TOUR_ID, tour.getId()); + edit_button.setOnClickListener( + Navigation.createNavigateOnClickListener(R.id.toEditTour, b)); + edit_button.setVisibility(View.VISIBLE); + } + + // Set places + List places = tour.getPlaces(); + adapterCompleted.setPlaces(viewModel.getCompletedPlaces()); + adapterNoCompleted.setPlaces(viewModel.getNoCompletedPlaces()); + tour_num_places.setText(String.format(getString(R.string.num_places), places.size())); + + play_button.setOnClickListener(v -> alert.show()); + + setDifficultyDialog(tour.getId(), tour.getMin_level()); + } + } + + private void setDifficultyDialog(int tour_id, PlayLevel min_level) { + Bundle c = new Bundle(); + c.putInt(PlayMapFragment.TOUR_ID, tour_id); + + // Get all of the difficulties + List difficulties = new ArrayList<>( + Arrays.asList(getResources().getStringArray(R.array.difficulties))); + int numDiff = difficulties.size(); + // Get only the allowed difficulties + difficulties = difficulties.subList(min_level.ordinal(), difficulties.size()); + + // Copy difficulties + String[] items = new String[difficulties.size()]; + for(int i = 0; i < difficulties.size(); i++) { + items[i] = difficulties.get(i); + } + + int offset = numDiff - items.length; + AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + builder.setTitle(getResources().getString(R.string.select_play_difficulty)); + builder.setItems(items, (dialog, item) -> { + int[] destinations = {R.id.toPlayTour, R.id.toPlayCompass, R.id.toPlayTherm}; + int destPos = item + offset; + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .navigate(destinations[destPos], c); + }); + alert = builder.create(); + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/preferences/SettingsFragment.java b/app/src/main/java/com/martinlaizg/geofind/views/preferences/SettingsFragment.java index f8f12ae..5715d39 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/preferences/SettingsFragment.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/preferences/SettingsFragment.java @@ -1,39 +1,104 @@ package com.martinlaizg.geofind.views.preferences; - +import android.app.AlertDialog; import android.content.SharedPreferences; import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Toast; -import com.martinlaizg.geofind.R; -import com.martinlaizg.geofind.config.Preferences; - +import androidx.lifecycle.ViewModelProviders; import androidx.navigation.Navigation; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; +import com.google.android.material.button.MaterialButton; +import com.google.android.material.textfield.TextInputLayout; +import com.martinlaizg.geofind.R; +import com.martinlaizg.geofind.config.Preferences; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.views.viewmodel.SettingsViewModel; + +import java.util.Objects; public class SettingsFragment extends PreferenceFragmentCompat { + private static final String TAG = SettingsFragment.class.getSimpleName(); + private AlertDialog dialog; + private SettingsViewModel viewModel; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + viewModel = ViewModelProviders.of(requireActivity()).get(SettingsViewModel.class); + } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.app_preferences); - setLogoutPreference(); + findPreference(getString(R.string.log_out)) + .setOnPreferenceClickListener(getLogOutListener()); + setupSupportMessageDialog(); + findPreference("support").setOnPreferenceClickListener(getSupportListener()); } + private Preference.OnPreferenceClickListener getLogOutListener() { + return preference -> { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(requireContext()); + Preferences.logout(sp); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .popBackStack(); + return true; + }; + } - private void setLogoutPreference() { - findPreference(getString(R.string.preferences_log_out)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); - Preferences.logout(sp); - Navigation.findNavController(getActivity(), R.id.main_fragment_holder).popBackStack(R.id.main, false); - return true; + private void setupSupportMessageDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); + View view = getLayoutInflater().inflate(R.layout.support_message, null); + TextInputLayout title_layout = view.findViewById(R.id.title_layout); + TextInputLayout message_text_layout = view.findViewById(R.id.message_text_layout); + MaterialButton send_button = view.findViewById(R.id.send_button); + send_button.setOnClickListener(v -> { + if(Objects.requireNonNull(title_layout.getEditText()).getText().toString().trim() + .isEmpty()) { + title_layout.setError("You should fill it"); + return; } + if(Objects.requireNonNull(message_text_layout.getEditText()).getText().toString().trim() + .isEmpty()) { + message_text_layout.setError("You should fill it"); + return; + } + + String title = title_layout.getEditText().getText().toString(); + String message = message_text_layout.getEditText().getText().toString(); + + viewModel.sendMessage(title, message).observe(requireActivity(), (ok) -> { + if(ok == null) { + APIException e = viewModel.getError(); + Log.e(TAG, "setLogoutPreference: " + e.getType().getMessage()); + } else if(ok) { + Toast.makeText(requireContext(), "Message sent", Toast.LENGTH_SHORT).show(); + Navigation.findNavController(requireActivity(), R.id.main_fragment_holder) + .popBackStack(); + dialog.dismiss(); + } else { + Toast.makeText(requireContext(), "Message no sent", Toast.LENGTH_SHORT).show(); + } + }); + }); + builder.setView(view); + dialog = builder.create(); + } + + private Preference.OnPreferenceClickListener getSupportListener() { + return preference -> { + dialog.show(); + return true; + }; } } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/CreatorViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/CreatorViewModel.java new file mode 100644 index 0000000..99068ee --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/CreatorViewModel.java @@ -0,0 +1,136 @@ +package com.martinlaizg.geofind.views.viewmodel; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.MutableLiveData; + +import com.martinlaizg.geofind.data.access.api.error.ErrorType; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.enums.PlayLevel; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; +import com.martinlaizg.geofind.data.repository.TourRepository; + +import java.util.ArrayList; +import java.util.List; + +public class CreatorViewModel + extends AndroidViewModel { + + private final TourRepository tourRepo; + private Tour tour; + private APIException error; + private boolean load; + + public CreatorViewModel(@NonNull Application application) { + super(application); + tourRepo = RepositoryFactory.getTourRepository(application); + load = true; + } + + public MutableLiveData createTour() { + MutableLiveData m = new MutableLiveData<>(); + new Thread(() -> { + if(!tour.isValid()) { + setError(new APIException(ErrorType.OTHER, "No data")); + m.postValue(null); + return; + } + load = true; + if(tour.getId() == 0) { // Create tour + try { + tour = tourRepo.create(tour); + } catch(APIException e) { + setError(e); + m.postValue(null); + return; + } + } else { // Update tour + try { + tour = tourRepo.update(tour); + } catch(APIException e) { + setError(e); + m.postValue(null); + return; + } + } + m.postValue(tour); + }).start(); + return m; + } + + public void setCreatedTour(String name, String description, Integer creator_id, PlayLevel pl) { + if(tour == null) tour = new Tour(); + tour.setName(name); + tour.setDescription(description); + tour.setCreator_id(creator_id); + tour.setMin_level(pl); + } + + public MutableLiveData loadTour(Integer tour_id) { + MutableLiveData t = new MutableLiveData<>(); + new Thread(() -> { + if(load) { + tour = new Tour(); + if(tour_id > 0) { + try { + tour = tourRepo.getTour(tour_id); + } catch(APIException e) { + setError(e); + tour = null; + } + } + } + load = true; + t.postValue(tour); + }).start(); + return t; + } + + public Tour getTour() { + return tour; + } + + // ============================================ + + public void setTour(Tour tour) { + this.tour = tour; + } + + public APIException getError() { + return error; + } + + public void setError(APIException error) { + this.error = error; + } + + public void setLoad(boolean load) { + this.load = load; + } + + public List getPlaces() { + List places = tour.getPlaces(); + return places == null ? + new ArrayList<>() : + places; + } + + public Place getPlace(int position) { + if(position > tour.getPlaces().size()) return null; + if(position < tour.getPlaces().size()) return tour.getPlaces().remove(position); + return new Place(); + } + + public void setPlace(Place place) { + if(place.getOrder() == null) { + place.setOrder(tour.getPlaces().size()); + tour.getPlaces().add(place); + } else { + tour.getPlaces().add(place.getOrder(), place); + } + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LocationViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LocationViewModel.java deleted file mode 100644 index fc47657..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LocationViewModel.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.martinlaizg.geofind.views.viewmodel; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.repository.LocationRepository; - -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; - -public class LocationViewModel - extends AndroidViewModel { - - private final LocationRepository locRepo; - private final LiveData> allLocations; - - - public LocationViewModel(@NonNull Application application) { - super(application); - locRepo = new LocationRepository(application); - allLocations = locRepo.getAllLocations(); - } - - public LiveData> getAllLocations() { - return allLocations; - } - - public MutableLiveData getLocation(String loc_id) { - return locRepo.getLocation(loc_id); - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LoginViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LoginViewModel.java index 905d6c1..a6534f4 100644 --- a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LoginViewModel.java +++ b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/LoginViewModel.java @@ -2,57 +2,83 @@ import android.app.Application; -import com.martinlaizg.geofind.data.access.database.entity.User; -import com.martinlaizg.geofind.data.access.database.repository.UserRepository; - import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.MutableLiveData; +import com.martinlaizg.geofind.data.Crypto; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.User; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; +import com.martinlaizg.geofind.data.repository.UserRepository; + public class LoginViewModel extends AndroidViewModel { - private final UserRepository repository; + private final UserRepository userRepo; - private String email; - private String password; - private String name; - private String username; + private User user; + private APIException error; public LoginViewModel(Application application) { super(application); - repository = new UserRepository(application); - name = ""; - email = ""; - password = ""; + userRepo = RepositoryFactory.getUserRepository(application); + user = new User(); } public MutableLiveData login() { - return repository.login(email, password); + MutableLiveData u = new MutableLiveData<>(); + new Thread(() -> { + try { + user = userRepo.login(user); + u.postValue(user); + } catch(APIException e) { + setError(e); + u.postValue(null); + } + }).start(); + return u; } public MutableLiveData registry() { - return repository.registry(name, username, email, password); + + MutableLiveData u = new MutableLiveData<>(); + new Thread(() -> { + try { + user = userRepo.registry(user); + u.postValue(user); + } catch(APIException e) { + setError(e); + u.postValue(null); + } + }).start(); + return u; } public void setLogin(String email, String password) { - this.email = email; - this.password = password; + user.setEmail(email); + user.setPassword(Crypto.hash(password)); } - public void setRegistry(String name, String username, String email, String password) { - this.name = name; - this.username = username; - this.email = email; - this.password = password; + user.setName(name); + user.setUsername(username); + user.setEmail(email); + user.setPassword(Crypto.hash(password)); } public String getEmail() { - return email; + return user.getEmail(); } public void setEmail(String email) { - this.email = email; + user.setEmail(email); } + public APIException getError() { + return error; + } + + public void setError(APIException error) { + this.error = error; + } } diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapCreatorViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapCreatorViewModel.java deleted file mode 100644 index 3b7f9cf..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapCreatorViewModel.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.martinlaizg.geofind.views.viewmodel; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.entity.enums.PlayLevel; -import com.martinlaizg.geofind.data.access.database.repository.LocationRepository; -import com.martinlaizg.geofind.data.access.database.repository.MapRepository; - -import java.util.ArrayList; -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.MutableLiveData; - -public class MapCreatorViewModel - extends AndroidViewModel { - - private final MapRepository mapRepo; - private final LocationRepository locRepo; - private Map createdMap; - private List createdLocations; - - - public MapCreatorViewModel(@NonNull Application application) { - super(application); - mapRepo = new MapRepository(application); - locRepo = new LocationRepository(application); - } - - - public MutableLiveData createMap() { - MutableLiveData m = new MutableLiveData<>(); - new Thread(new Runnable() { - @Override - public void run() { - createdMap = mapRepo.create(createdMap); - for (int i = 0; i < createdLocations.size(); i++) { - createdLocations.get(i).setMap_id(createdMap.getId()); - } - locRepo.create(createdLocations); - m.postValue(createdMap); - } - }).start(); - return m; - } - - public List getCreatedLocations() { - return createdLocations; - } - - public Map getCreatedMap() { - if (createdMap == null) { - createdMap = new Map(); - } - return createdMap; - } - - public void addLocation(String name, String description, String lat, String lon) { - Location l = new Location(); - l.setName(name); - l.setDescription(description); - l.setLat(lat); - l.setLon(lon); - if (createdLocations == null) { - createdLocations = new ArrayList<>(); - } - createdLocations.add(l); - } - - - public void setMap(String name, String description, String creator_id, PlayLevel pl) { - if (createdMap == null) { - createdMap = new Map(); - } - createdMap.setName(name); - createdMap.setDescription(description); - createdMap.setCreator_id(creator_id); - createdMap.setMin_level(pl); - } - - public boolean isValid() { - if (!isMapValid(createdMap)) { - return false; - } - for (Location l : createdLocations) { - if (!isLocationValid(l)) { - return false; - } - } - return true; - } - - private boolean isMapValid(Map createdMap) { - return !createdMap.getName().isEmpty() && !createdMap.getDescription().isEmpty(); - } - - private boolean isLocationValid(Location l) { - return !l.getName().isEmpty() && !l.getDescription().isEmpty() && !l.getLat().isEmpty() && !l.getLon().isEmpty(); - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapListViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapListViewModel.java deleted file mode 100644 index d74d617..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapListViewModel.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.martinlaizg.geofind.views.viewmodel; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.repository.MapRepository; -import com.martinlaizg.geofind.views.fragment.list.MapListFragment; - -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.MutableLiveData; - -public class MapListViewModel - extends AndroidViewModel { - - private final MapRepository repository; - MapListFragment fragment; - - - public MapListViewModel(@NonNull Application application) { - super(application); - repository = new MapRepository(application); - } - - - public MutableLiveData> getAllMaps() { - return repository.getAllMaps(); - } - - public void refreshMaps() { - new Thread(new Runnable() { - @Override - public void run() { - repository.refreshMaps(); - - } - }).start(); - } - -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapViewModel.java deleted file mode 100644 index b02dd00..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/MapViewModel.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.martinlaizg.geofind.views.viewmodel; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.entity.Location; -import com.martinlaizg.geofind.data.access.database.entity.Map; -import com.martinlaizg.geofind.data.access.database.repository.LocationRepository; -import com.martinlaizg.geofind.data.access.database.repository.MapRepository; - -import java.util.List; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.MutableLiveData; - -public class MapViewModel - extends AndroidViewModel { - - private final MapRepository mapRepo; - private final LocationRepository locRepo; - private MutableLiveData map; - private MutableLiveData> locations; - - - public MapViewModel(@NonNull Application application) { - super(application); - mapRepo = new MapRepository(application); - locRepo = new LocationRepository(application); - map = new MutableLiveData<>(); - locations = new MutableLiveData<>(); - } - - public MutableLiveData getMap(String map_id) { - map = mapRepo.getMap(map_id); - return map; - } - - public Map getMap() { - return map.getValue(); - } - - public MutableLiveData> getLocations(String map_id) { - locations = locRepo.getLocationsByMap(map_id); - return locations; - } - - public List getLocations() { - return locations.getValue(); - } - - public Location getLocationByName(String name) { - for (Location l : locations.getValue()) { - if (l.getName().equals(name)) { - return l; - } - } - return null; - } - - public Location getLocation(String loc_id) { - for (Location l : locations.getValue()) { - if (l.getId().equals(loc_id)) { - return l; - } - } - return null; - } -} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/PlayTourViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/PlayTourViewModel.java new file mode 100644 index 0000000..68176e1 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/PlayTourViewModel.java @@ -0,0 +1,86 @@ +package com.martinlaizg.geofind.views.viewmodel; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.MutableLiveData; + +import com.martinlaizg.geofind.data.access.api.error.ErrorType; +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Play; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.repository.PlayRepository; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; + +public class PlayTourViewModel + extends AndroidViewModel { + + private final PlayRepository playRepo; + + private APIException error; + private Play play; + + public PlayTourViewModel(@NonNull Application application) { + super(application); + playRepo = RepositoryFactory.getPlayRepository(application); + } + + public MutableLiveData loadPlay(int user_id, int tour_id) { + MutableLiveData m = new MutableLiveData<>(); + new Thread(() -> { + try { + play = playRepo.getPlay(user_id, tour_id); + if(play == null) { + play = playRepo.createPlay(user_id, tour_id); + } + m.postValue(getNextPlace()); + } catch(APIException e) { + setError(e); + } + }).start(); + return m; + } + + public Place getNextPlace() { + int numPlaces = play.getPlaces().size(); + if(numPlaces >= play.getTour().getPlaces().size()) { + setError(new APIException(ErrorType.COMPLETED)); + return null; + } + return play.getTour().getPlaces().get(numPlaces); + } + + public APIException getError() { + return error; + } + + public void setError(APIException error) { + this.error = error; + } + + public Play getPlay() { + return play; + } + + public MutableLiveData completePlace(Integer place_id) { + MutableLiveData c = new MutableLiveData<>(); + new Thread(() -> { + boolean b = false; + try { + play = playRepo.completePlay(play.getId(), place_id); + b = true; + } catch(APIException e) { + setError(e); + } + c.postValue(b); + }).start(); + return c; + } + + public Tour getTour() { + return play.getTour(); + } + +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/SettingsViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/SettingsViewModel.java new file mode 100644 index 0000000..db09434 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/SettingsViewModel.java @@ -0,0 +1,47 @@ +package com.martinlaizg.geofind.views.viewmodel; + +import android.app.Application; +import android.util.Log; + +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.MutableLiveData; + +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; +import com.martinlaizg.geofind.data.repository.UserRepository; + +public class SettingsViewModel + extends AndroidViewModel { + + private static final String TAG = SettingsViewModel.class.getSimpleName(); + private final UserRepository userRepo; + + private APIException error; + + public SettingsViewModel(Application application) { + super(application); + userRepo = RepositoryFactory.getUserRepository(application); + } + + public APIException getError() { + return error; + } + + public MutableLiveData sendMessage(String title, String message) { + MutableLiveData r = new MutableLiveData<>(); + new Thread(() -> { + try { + r.postValue(userRepo.sendMessage(title, message)); + } catch(APIException e) { + Log.e(TAG, "sendMessage: ", e); + setError(e); + r.postValue(null); + } + }).start(); + return r; + } + + public void setError(APIException error) { + this.error = error; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/TourListViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/TourListViewModel.java new file mode 100644 index 0000000..c1bc5a9 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/TourListViewModel.java @@ -0,0 +1,57 @@ +package com.martinlaizg.geofind.views.viewmodel; + +import android.app.Application; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.MutableLiveData; + +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.relations.TourCreatorPlaces; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; +import com.martinlaizg.geofind.data.repository.TourRepository; + +import java.util.List; + +public class TourListViewModel + extends AndroidViewModel { + + private static final String TAG = TourListViewModel.class.getSimpleName(); + + private final TourRepository tourRepo; + private APIException error; + + public TourListViewModel(@NonNull Application application) { + super(application); + tourRepo = RepositoryFactory.getTourRepository(application); + } + + public MutableLiveData> getTours() { + MutableLiveData> tours = new MutableLiveData<>(); + new Thread(() -> { + tours.postValue(tourRepo.getAllTours()); + + }).start(); + return tours; + } + + public void refresh() { + new Thread(() -> { + try { + tourRepo.refreshTours(); + } catch(APIException e) { + Log.e(TAG, "getTours: ", e); + setError(e); + } + }).start(); + } + + public APIException getError() { + return error; + } + + public void setError(APIException error) { + this.error = error; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/TourViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/TourViewModel.java new file mode 100644 index 0000000..e4a8b72 --- /dev/null +++ b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/TourViewModel.java @@ -0,0 +1,97 @@ +package com.martinlaizg.geofind.views.viewmodel; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.MutableLiveData; + +import com.martinlaizg.geofind.data.access.api.service.exceptions.APIException; +import com.martinlaizg.geofind.data.access.database.entities.Place; +import com.martinlaizg.geofind.data.access.database.entities.Play; +import com.martinlaizg.geofind.data.access.database.entities.Tour; +import com.martinlaizg.geofind.data.repository.PlayRepository; +import com.martinlaizg.geofind.data.repository.RepositoryFactory; +import com.martinlaizg.geofind.data.repository.TourRepository; + +import java.util.ArrayList; +import java.util.List; + +public class TourViewModel + extends AndroidViewModel { + + private final TourRepository tourRepo; + private final PlayRepository playRepo; + + private APIException error; + private Tour tour; + private Play userPlay; + + public TourViewModel(@NonNull Application application) { + super(application); + tourRepo = RepositoryFactory.getTourRepository(application); + playRepo = RepositoryFactory.getPlayRepository(application); + } + + public MutableLiveData loadTour(int tour_id, int user_id) { + MutableLiveData m = new MutableLiveData<>(); + new Thread(() -> { + try { + tour = tourRepo.getTour(tour_id); + userPlay = playRepo.getPlay(user_id, tour_id); + } catch(APIException e) { + setError(e); + tour = null; + } + m.postValue(tour); + }).start(); + return m; + } + + public MutableLiveData loadPlace(int place_id) { + MutableLiveData p = new MutableLiveData<>(); + new Thread(() -> { + for(Place place : tour.getPlaces()) { + if(place.getId() == place_id) { + p.postValue(place); + return; + } + } + }).start(); + return p; + } + + public APIException getError() { + return error; + } + + public void setError(APIException error) { + this.error = error; + } + + public List getPlaces() { + return tour.getPlaces(); + } + + public List getCompletedPlaces() { + List places = new ArrayList<>(); + if(userPlay != null) places.addAll(userPlay.getPlaces()); + return places; + } + + public List getNoCompletedPlaces() { + List places = tour.getPlaces(); + if(userPlay == null) { + return places; + } + List noCompleted = new ArrayList<>(); + for(Place tp : places) { + boolean completed = false; + for(Place pp : userPlay.getPlaces()) { + if(tp.getId() == pp.getId()) completed = true; + } + if(!completed) noCompleted.add(tp); + } + return noCompleted; + } +} diff --git a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/UserViewModel.java b/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/UserViewModel.java deleted file mode 100644 index d2b3ef0..0000000 --- a/app/src/main/java/com/martinlaizg/geofind/views/viewmodel/UserViewModel.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.martinlaizg.geofind.views.viewmodel; - -import android.app.Application; - -import com.martinlaizg.geofind.data.access.database.repository.UserRepository; - -import androidx.annotation.NonNull; -import androidx.lifecycle.AndroidViewModel; - -class UserViewModel - extends AndroidViewModel { - - - public UserViewModel(@NonNull Application application) { - super(application); - UserRepository repository = new UserRepository(application); - } -} diff --git a/app/src/main/res/anim/slide_in_left.xml b/app/src/main/res/anim/slide_in_left.xml new file mode 100644 index 0000000..214b136 --- /dev/null +++ b/app/src/main/res/anim/slide_in_left.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml new file mode 100644 index 0000000..201f739 --- /dev/null +++ b/app/src/main/res/anim/slide_in_right.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml new file mode 100644 index 0000000..1bf217f --- /dev/null +++ b/app/src/main/res/anim/slide_out_left.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/slide_out_right.xml b/app/src/main/res/anim/slide_out_right.xml new file mode 100644 index 0000000..56b3e67 --- /dev/null +++ b/app/src/main/res/anim/slide_out_right.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/drawable_selected_item.xml b/app/src/main/res/drawable/drawable_selected_item.xml new file mode 100644 index 0000000..32d4930 --- /dev/null +++ b/app/src/main/res/drawable/drawable_selected_item.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.xml b/app/src/main/res/drawable/ic_add.xml new file mode 100644 index 0000000..a4e0939 --- /dev/null +++ b/app/src/main/res/drawable/ic_add.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_navigation.xml b/app/src/main/res/drawable/ic_arrow_navigation.xml new file mode 100644 index 0000000..69f0d19 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_navigation.xml @@ -0,0 +1,6 @@ + + + diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml new file mode 100644 index 0000000..96463ae --- /dev/null +++ b/app/src/main/res/drawable/ic_delete.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index bcb164c..a6c6f25 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,93 +1,94 @@ - - - - - - - - - - - - - - - - - - - - - - + android:width="108dp" + android:height="108dp" + android:viewportWidth="1095.2468" + android:viewportHeight="1095.2468"> + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_location.xml b/app/src/main/res/drawable/ic_location.xml index 94bb787..8d8f3cb 100644 --- a/app/src/main/res/drawable/ic_location.xml +++ b/app/src/main/res/drawable/ic_location.xml @@ -1,5 +1,10 @@ - - + + diff --git a/app/src/main/res/drawable/ic_user_black.xml b/app/src/main/res/drawable/ic_user_black.xml index 7678580..00fe546 100644 --- a/app/src/main/res/drawable/ic_user_black.xml +++ b/app/src/main/res/drawable/ic_user_black.xml @@ -1,9 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 629cddc..c87d57b 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -20,8 +20,7 @@ + android:layout_height="wrap_content" /> \ No newline at end of file diff --git a/app/src/main/res/layout/drawer_header.xml b/app/src/main/res/layout/drawer_header.xml index e51166a..ec53f2f 100644 --- a/app/src/main/res/layout/drawer_header.xml +++ b/app/src/main/res/layout/drawer_header.xml @@ -2,20 +2,21 @@ + android:layout_height="wrap_content" + android:background="@color/colorPrimary"> @@ -25,11 +26,10 @@ android:id="@+id/drawer_header_name" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="16dp" + android:layout_marginStart="16dp" + android:layout_marginTop="2dp" android:layout_marginEnd="32dp" - android:textColor="@color/secondaryTextColor" - android:textSize="@dimen/normal_text" + android:textColor="@color/background" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/imageView" app:layout_constraintTop_toTopOf="@+id/imageView" @@ -37,16 +37,14 @@ diff --git a/app/src/main/res/layout/fragment_complete_place.xml b/app/src/main/res/layout/fragment_complete_place.xml new file mode 100644 index 0000000..d78c049 --- /dev/null +++ b/app/src/main/res/layout/fragment_complete_place.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_complete_tour.xml b/app/src/main/res/layout/fragment_complete_tour.xml new file mode 100644 index 0000000..5ee0614 --- /dev/null +++ b/app/src/main/res/layout/fragment_complete_tour.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_create_map.xml b/app/src/main/res/layout/fragment_create_map.xml deleted file mode 100644 index 6a922e9..0000000 --- a/app/src/main/res/layout/fragment_create_map.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_create_locations.xml b/app/src/main/res/layout/fragment_create_place.xml similarity index 61% rename from app/src/main/res/layout/fragment_create_locations.xml rename to app/src/main/res/layout/fragment_create_place.xml index dc0a53b..639d786 100644 --- a/app/src/main/res/layout/fragment_create_locations.xml +++ b/app/src/main/res/layout/fragment_create_place.xml @@ -1,39 +1,25 @@ - - + app:layout_constraintTop_toTopOf="parent"> + app:layout_constraintTop_toBottomOf="@id/new_place_name_layout"> - - + app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/layout/fragment_create_tour.xml b/app/src/main/res/layout/fragment_create_tour.xml new file mode 100644 index 0000000..797b143 --- /dev/null +++ b/app/src/main/res/layout/fragment_create_tour.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_createdlocation.xml b/app/src/main/res/layout/fragment_createdlocation.xml deleted file mode 100644 index 9040e8d..0000000 --- a/app/src/main/res/layout/fragment_createdlocation.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_creator.xml b/app/src/main/res/layout/fragment_creator.xml index 4483052..ab235d1 100644 --- a/app/src/main/res/layout/fragment_creator.xml +++ b/app/src/main/res/layout/fragment_creator.xml @@ -16,9 +16,8 @@ android:clickable="true" android:elevation="6dp" android:focusable="true" - app:cardCornerRadius="16dp" + app:cardCornerRadius="4dp" app:cardElevation="2dp" - app:contentPadding="@dimen/small_margin" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> @@ -28,42 +27,45 @@ android:layout_height="match_parent"> + app:layout_constraintTop_toTopOf="@+id/edit_button" + tools:text="@sample/tours.json/data/name[0]" /> + tools:text="@sample/tours.json/data/description[0]" /> + app:layout_constraintBottom_toTopOf="@id/add_place_button" + app:layout_constraintTop_toBottomOf="@id/text_new_places_list" + tools:itemCount="3" + tools:listitem="@layout/fragment_editable_place" /> + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_location.xml b/app/src/main/res/layout/fragment_location.xml deleted file mode 100644 index 2d7e6ab..0000000 --- a/app/src/main/res/layout/fragment_location.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml index ee54fb8..36b87d7 100644 --- a/app/src/main/res/layout/fragment_login.xml +++ b/app/src/main/res/layout/fragment_login.xml @@ -21,7 +21,7 @@ + android:hint="@string/email" + android:inputType="textEmailAddress" /> + android:hint="@string/password" + android:inputType="textPassword" /> diff --git a/app/src/main/res/layout/fragment_map.xml b/app/src/main/res/layout/fragment_map.xml deleted file mode 100644 index 574aa75..0000000 --- a/app/src/main/res/layout/fragment_map.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_place.xml b/app/src/main/res/layout/fragment_place.xml new file mode 100644 index 0000000..1b81d70 --- /dev/null +++ b/app/src/main/res/layout/fragment_place.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_location_item.xml b/app/src/main/res/layout/fragment_place_item.xml similarity index 74% rename from app/src/main/res/layout/fragment_location_item.xml rename to app/src/main/res/layout/fragment_place_item.xml index b983b33..554013a 100644 --- a/app/src/main/res/layout/fragment_location_item.xml +++ b/app/src/main/res/layout/fragment_place_item.xml @@ -6,12 +6,9 @@ android:layout_height="wrap_content"> + tools:text="@sample/places.json/data/name" /> + app:layout_constraintStart_toStartOf="@+id/place_name" + app:layout_constraintTop_toBottomOf="@+id/place_name" + tools:text="@sample/places.json/data/description" /> diff --git a/app/src/main/res/layout/fragment_location_list.xml b/app/src/main/res/layout/fragment_place_list.xml similarity index 90% rename from app/src/main/res/layout/fragment_location_list.xml rename to app/src/main/res/layout/fragment_place_list.xml index 1adf114..62eafe6 100644 --- a/app/src/main/res/layout/fragment_location_list.xml +++ b/app/src/main/res/layout/fragment_place_list.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent"> + tools:listitem="@layout/fragment_place_item" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_compass.xml b/app/src/main/res/layout/fragment_play_compass.xml new file mode 100644 index 0000000..fdca2c5 --- /dev/null +++ b/app/src/main/res/layout/fragment_play_compass.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_location_on_map.xml b/app/src/main/res/layout/fragment_play_location_on_map.xml deleted file mode 100644 index 14547d6..0000000 --- a/app/src/main/res/layout/fragment_play_location_on_map.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_map.xml b/app/src/main/res/layout/fragment_play_map.xml new file mode 100644 index 0000000..28e7523 --- /dev/null +++ b/app/src/main/res/layout/fragment_play_map.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_map_on_compass.xml b/app/src/main/res/layout/fragment_play_map_on_compass.xml deleted file mode 100644 index 83dd6b5..0000000 --- a/app/src/main/res/layout/fragment_play_map_on_compass.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_map_on_map.xml b/app/src/main/res/layout/fragment_play_map_on_map.xml deleted file mode 100644 index e9892f6..0000000 --- a/app/src/main/res/layout/fragment_play_map_on_map.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_map_on_therm.xml b/app/src/main/res/layout/fragment_play_map_on_therm.xml deleted file mode 100644 index 39eb1d9..0000000 --- a/app/src/main/res/layout/fragment_play_map_on_therm.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_therm.xml b/app/src/main/res/layout/fragment_play_therm.xml new file mode 100644 index 0000000..833f5ba --- /dev/null +++ b/app/src/main/res/layout/fragment_play_therm.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_registry.xml b/app/src/main/res/layout/fragment_registry.xml index f2d8d7c..07b5a97 100644 --- a/app/src/main/res/layout/fragment_registry.xml +++ b/app/src/main/res/layout/fragment_registry.xml @@ -1,7 +1,6 @@ @@ -23,7 +22,7 @@ + android:maxLines="1" /> + android:maxLines="1" /> + android:maxLines="1" /> + android:maxLines="1" /> + android:maxLines="1" /> - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_tour.xml b/app/src/main/res/layout/fragment_tour.xml new file mode 100644 index 0000000..cf7f1f5 --- /dev/null +++ b/app/src/main/res/layout/fragment_tour.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_map_item.xml b/app/src/main/res/layout/fragment_tour_item.xml similarity index 72% rename from app/src/main/res/layout/fragment_map_item.xml rename to app/src/main/res/layout/fragment_tour_item.xml index 320dfc1..ec3f784 100644 --- a/app/src/main/res/layout/fragment_map_item.xml +++ b/app/src/main/res/layout/fragment_tour_item.xml @@ -7,7 +7,7 @@ android:layout_height="wrap_content"> - + tools:text="@sample/tours.json/data/name" /> + android:maxLines="1" + android:textAppearance="?android:attr/textAppearanceSmall" + app:layout_constraintEnd_toEndOf="@+id/tour_name" + app:layout_constraintStart_toStartOf="@+id/tour_name" + app:layout_constraintTop_toBottomOf="@+id/tour_name" + tools:text="@sample/tours.json/data/creator" /> + app:layout_constraintEnd_toEndOf="@+id/tour_creator" + app:layout_constraintStart_toStartOf="@+id/tour_name" + app:layout_constraintTop_toBottomOf="@+id/tour_creator" + tools:text="@sample/tours.json/data/description" /> diff --git a/app/src/main/res/layout/fragment_maps_list.xml b/app/src/main/res/layout/fragment_tour_list.xml similarity index 57% rename from app/src/main/res/layout/fragment_maps_list.xml rename to app/src/main/res/layout/fragment_tour_list.xml index d4f9588..cf1ba99 100644 --- a/app/src/main/res/layout/fragment_maps_list.xml +++ b/app/src/main/res/layout/fragment_tour_list.xml @@ -6,7 +6,7 @@ android:layout_height="match_parent"> + tools:listitem="@layout/fragment_tour_item" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/preferences_about.xml b/app/src/main/res/layout/preferences_about.xml index bbafcf7..8617bd1 100644 --- a/app/src/main/res/layout/preferences_about.xml +++ b/app/src/main/res/layout/preferences_about.xml @@ -7,52 +7,49 @@ diff --git a/app/src/main/res/layout/support_message.xml b/app/src/main/res/layout/support_message.xml new file mode 100644 index 0000000..7e6ba3e --- /dev/null +++ b/app/src/main/res/layout/support_message.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + +