mirror of
https://github.com/russok/FitoTrack.git
synced 2025-10-29 00:32:11 -07:00
#13 Different OSM map layers
- App switches between layers depending on activity
This commit is contained in:
parent
28535f653a
commit
420e2f19f0
@ -53,6 +53,7 @@ import de.tadris.fitness.data.Workout;
|
|||||||
import de.tadris.fitness.location.LocationListener;
|
import de.tadris.fitness.location.LocationListener;
|
||||||
import de.tadris.fitness.location.WorkoutRecorder;
|
import de.tadris.fitness.location.WorkoutRecorder;
|
||||||
import de.tadris.fitness.map.MapManager;
|
import de.tadris.fitness.map.MapManager;
|
||||||
|
import de.tadris.fitness.map.tilesource.TileSources;
|
||||||
import de.tadris.fitness.util.ThemeManager;
|
import de.tadris.fitness.util.ThemeManager;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
|
|
||||||
@ -115,7 +116,13 @@ public class RecordWorkoutActivity extends FitoTrackActivity implements Location
|
|||||||
|
|
||||||
private void setupMap(){
|
private void setupMap(){
|
||||||
this.mapView= new MapView(this);
|
this.mapView= new MapView(this);
|
||||||
downloadLayer= MapManager.setupMap(mapView);
|
TileSources.Purpose purpose;
|
||||||
|
if(ACTIVITY.equals(Workout.WORKOUT_TYPE_CYCLING)){
|
||||||
|
purpose= TileSources.Purpose.CYCLING;
|
||||||
|
}else{
|
||||||
|
purpose= TileSources.Purpose.OUTDOOR;
|
||||||
|
}
|
||||||
|
downloadLayer= MapManager.setupMap(mapView, purpose);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLine(){
|
private void updateLine(){
|
||||||
|
|||||||
@ -19,18 +19,13 @@
|
|||||||
|
|
||||||
package de.tadris.fitness.activity;
|
package de.tadris.fitness.activity;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -39,8 +34,6 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
import com.github.mikephil.charting.charts.LineChart;
|
import com.github.mikephil.charting.charts.LineChart;
|
||||||
@ -60,9 +53,7 @@ import org.mapsforge.map.android.view.MapView;
|
|||||||
import org.mapsforge.map.layer.download.TileDownloadLayer;
|
import org.mapsforge.map.layer.download.TileDownloadLayer;
|
||||||
import org.mapsforge.map.layer.overlay.FixedPixelCircle;
|
import org.mapsforge.map.layer.overlay.FixedPixelCircle;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -76,10 +67,11 @@ import de.tadris.fitness.data.WorkoutManager;
|
|||||||
import de.tadris.fitness.data.WorkoutSample;
|
import de.tadris.fitness.data.WorkoutSample;
|
||||||
import de.tadris.fitness.map.MapManager;
|
import de.tadris.fitness.map.MapManager;
|
||||||
import de.tadris.fitness.map.WorkoutLayer;
|
import de.tadris.fitness.map.WorkoutLayer;
|
||||||
import de.tadris.fitness.util.gpx.GpxExporter;
|
import de.tadris.fitness.map.tilesource.TileSources;
|
||||||
import de.tadris.fitness.util.ThemeManager;
|
import de.tadris.fitness.util.ThemeManager;
|
||||||
import de.tadris.fitness.util.unit.UnitUtils;
|
|
||||||
import de.tadris.fitness.util.WorkoutTypeCalculator;
|
import de.tadris.fitness.util.WorkoutTypeCalculator;
|
||||||
|
import de.tadris.fitness.util.gpx.GpxExporter;
|
||||||
|
import de.tadris.fitness.util.unit.UnitUtils;
|
||||||
import de.tadris.fitness.view.ProgressDialogController;
|
import de.tadris.fitness.view.ProgressDialogController;
|
||||||
|
|
||||||
public class ShowWorkoutActivity extends FitoTrackActivity {
|
public class ShowWorkoutActivity extends FitoTrackActivity {
|
||||||
@ -267,9 +259,7 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
|
|
||||||
void addMap(){
|
void addMap(){
|
||||||
map= new MapView(this);
|
map= new MapView(this);
|
||||||
downloadLayer= MapManager.setupMap(map);
|
downloadLayer= MapManager.setupMap(map, TileSources.Purpose.DEFAULT);
|
||||||
map.setZoomLevelMin((byte)2);
|
|
||||||
map.setZoomLevelMax((byte)18);
|
|
||||||
|
|
||||||
WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
|
WorkoutLayer workoutLayer= new WorkoutLayer(samples, getThemePrimaryColor());
|
||||||
map.addLayer(workoutLayer);
|
map.addLayer(workoutLayer);
|
||||||
@ -277,7 +267,7 @@ public class ShowWorkoutActivity extends FitoTrackActivity {
|
|||||||
final BoundingBox bounds= new BoundingBox(workoutLayer.getLatLongs()).extendMeters(50);
|
final BoundingBox bounds= new BoundingBox(workoutLayer.getLatLongs()).extendMeters(50);
|
||||||
mHandler.postDelayed(() -> {
|
mHandler.postDelayed(() -> {
|
||||||
map.getModel().mapViewPosition.setMapPosition(new MapPosition(bounds.getCenterPoint(),
|
map.getModel().mapViewPosition.setMapPosition(new MapPosition(bounds.getCenterPoint(),
|
||||||
(byte)(LatLongUtils.zoomForBounds(map.getDimension(), bounds, map.getModel().displayModel.getTileSize()))));
|
(LatLongUtils.zoomForBounds(map.getDimension(), bounds, map.getModel().displayModel.getTileSize()))));
|
||||||
map.animate().alpha(1f).setDuration(1000).start();
|
map.animate().alpha(1f).setDuration(1000).start();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
|||||||
@ -26,19 +26,33 @@ import org.mapsforge.map.android.view.MapView;
|
|||||||
import org.mapsforge.map.layer.cache.TileCache;
|
import org.mapsforge.map.layer.cache.TileCache;
|
||||||
import org.mapsforge.map.layer.download.TileDownloadLayer;
|
import org.mapsforge.map.layer.download.TileDownloadLayer;
|
||||||
|
|
||||||
|
import de.tadris.fitness.map.tilesource.FitoTrackTileSource;
|
||||||
|
import de.tadris.fitness.map.tilesource.MapnikTileSource;
|
||||||
|
import de.tadris.fitness.map.tilesource.ThunderforestTileSource;
|
||||||
|
import de.tadris.fitness.map.tilesource.TileSources;
|
||||||
|
|
||||||
public class MapManager {
|
public class MapManager {
|
||||||
|
|
||||||
public static TileDownloadLayer setupMap(MapView mapView){
|
public static TileDownloadLayer setupMap(MapView mapView, TileSources.Purpose purpose){
|
||||||
mapView.setZoomLevelMin((byte) 18);
|
FitoTrackTileSource tileSource;
|
||||||
mapView.setZoomLevelMax((byte) 18);
|
switch (purpose){
|
||||||
|
case OUTDOOR: tileSource= ThunderforestTileSource.OUTDOORS; break;
|
||||||
|
case CYCLING: tileSource= ThunderforestTileSource.CYLE_MAP; break;
|
||||||
|
|
||||||
|
case DEFAULT:
|
||||||
|
default:
|
||||||
|
tileSource= MapnikTileSource.INSTANCE; break;
|
||||||
|
}
|
||||||
|
tileSource.setUserAgent("mapsforge-android");
|
||||||
|
|
||||||
|
mapView.setZoomLevelMin(tileSource.getZoomLevelMin());
|
||||||
|
mapView.setZoomLevelMax(tileSource.getZoomLevelMax());
|
||||||
mapView.setBuiltInZoomControls(false);
|
mapView.setBuiltInZoomControls(false);
|
||||||
|
|
||||||
TileCache tileCache = AndroidUtil.createTileCache(mapView.getContext(), "mapcache",
|
TileCache tileCache = AndroidUtil.createTileCache(mapView.getContext(), tileSource.getName(),
|
||||||
mapView.getModel().displayModel.getTileSize(), 1f,
|
mapView.getModel().displayModel.getTileSize(), 1f,
|
||||||
mapView.getModel().frameBufferModel.getOverdrawFactor(), true);
|
mapView.getModel().frameBufferModel.getOverdrawFactor(), true);
|
||||||
|
|
||||||
HumanitarianTileSource tileSource = HumanitarianTileSource.INSTANCE;
|
|
||||||
tileSource.setUserAgent("mapsforge-android");
|
|
||||||
TileDownloadLayer downloadLayer = new TileDownloadLayer(tileCache, mapView.getModel().mapViewPosition, tileSource, AndroidGraphicFactory.INSTANCE);
|
TileDownloadLayer downloadLayer = new TileDownloadLayer(tileCache, mapView.getModel().mapViewPosition, tileSource, AndroidGraphicFactory.INSTANCE);
|
||||||
|
|
||||||
mapView.getLayerManager().getLayers().add(downloadLayer);
|
mapView.getLayerManager().getLayers().add(downloadLayer);
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.map.tilesource;
|
||||||
|
|
||||||
|
import org.mapsforge.map.layer.download.tilesource.AbstractTileSource;
|
||||||
|
|
||||||
|
public abstract class FitoTrackTileSource extends AbstractTileSource {
|
||||||
|
|
||||||
|
public FitoTrackTileSource(String[] hostNames, int port) {
|
||||||
|
super(hostNames, port);
|
||||||
|
defaultTimeToLive = 8279000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAlpha() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getName();
|
||||||
|
}
|
||||||
@ -17,15 +17,14 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.tadris.fitness.map;
|
package de.tadris.fitness.map.tilesource;
|
||||||
|
|
||||||
import org.mapsforge.core.model.Tile;
|
import org.mapsforge.core.model.Tile;
|
||||||
import org.mapsforge.map.layer.download.tilesource.AbstractTileSource;
|
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
public class HumanitarianTileSource extends AbstractTileSource {
|
public class HumanitarianTileSource extends FitoTrackTileSource {
|
||||||
|
|
||||||
public static HumanitarianTileSource INSTANCE= new HumanitarianTileSource(new String[]{"tile-a.openstreetmap.fr", "tile-b.openstreetmap.fr", "tile-c.openstreetmap.fr"}, 443);
|
public static HumanitarianTileSource INSTANCE= new HumanitarianTileSource(new String[]{"tile-a.openstreetmap.fr", "tile-b.openstreetmap.fr", "tile-c.openstreetmap.fr"}, 443);
|
||||||
|
|
||||||
@ -33,10 +32,15 @@ public class HumanitarianTileSource extends AbstractTileSource {
|
|||||||
private static final String PROTOCOL = "https";
|
private static final String PROTOCOL = "https";
|
||||||
private static final int ZOOM_LEVEL_MAX = 18;
|
private static final int ZOOM_LEVEL_MAX = 18;
|
||||||
private static final int ZOOM_LEVEL_MIN = 0;
|
private static final int ZOOM_LEVEL_MIN = 0;
|
||||||
|
private static final String NAME = "Humanitarian";
|
||||||
|
|
||||||
public HumanitarianTileSource(String[] hostNames, int port) {
|
public HumanitarianTileSource(String[] hostNames, int port) {
|
||||||
super(hostNames, port);
|
super(hostNames, port);
|
||||||
defaultTimeToLive = 864000000; // Ten days
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,8 +64,4 @@ public class HumanitarianTileSource extends AbstractTileSource {
|
|||||||
return ZOOM_LEVEL_MIN;
|
return ZOOM_LEVEL_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasAlpha() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.map.tilesource;
|
||||||
|
|
||||||
|
import org.mapsforge.core.model.Tile;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class MapnikTileSource extends FitoTrackTileSource {
|
||||||
|
|
||||||
|
public static final MapnikTileSource INSTANCE = new MapnikTileSource(new String[]{
|
||||||
|
"a.tile.openstreetmap.org", "b.tile.openstreetmap.org", "c.tile.openstreetmap.org"}, 443);
|
||||||
|
private static final int PARALLEL_REQUESTS_LIMIT = 8;
|
||||||
|
private static final String PROTOCOL = "https";
|
||||||
|
private static final int ZOOM_LEVEL_MAX = 18;
|
||||||
|
private static final int ZOOM_LEVEL_MIN = 0;
|
||||||
|
private static final String NAME = "OSM Mapnik";
|
||||||
|
|
||||||
|
public MapnikTileSource(String[] hostNames, int port) {
|
||||||
|
super(hostNames, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getParallelRequestsLimit() {
|
||||||
|
return PARALLEL_REQUESTS_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getTileUrl(Tile tile) throws MalformedURLException {
|
||||||
|
|
||||||
|
return new URL(PROTOCOL, getHostName(), this.port, "/" + tile.zoomLevel + '/' + tile.tileX + '/' + tile.tileY + ".png");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getZoomLevelMax() {
|
||||||
|
return ZOOM_LEVEL_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getZoomLevelMin() {
|
||||||
|
return ZOOM_LEVEL_MIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.map.tilesource;
|
||||||
|
|
||||||
|
import org.mapsforge.core.model.Tile;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class ThunderforestTileSource extends FitoTrackTileSource{
|
||||||
|
|
||||||
|
public static final String API_KEY= "87b07337e42c405db6d8d39b1c0c179e";
|
||||||
|
|
||||||
|
public static final ThunderforestTileSource OUTDOORS = new ThunderforestTileSource("outdoors", "Outdoor");
|
||||||
|
public static final ThunderforestTileSource CYLE_MAP = new ThunderforestTileSource("cycle", "Cycle Map");
|
||||||
|
private static final int PARALLEL_REQUESTS_LIMIT = 8;
|
||||||
|
private static final String PROTOCOL = "https";
|
||||||
|
private static final int ZOOM_LEVEL_MAX = 22;
|
||||||
|
private static final int ZOOM_LEVEL_MIN = 0;
|
||||||
|
|
||||||
|
private String mapName;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public ThunderforestTileSource(String mapName, String name) {
|
||||||
|
super(new String[]{"tile.thunderforest.com"}, 443);
|
||||||
|
this.mapName = mapName;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getParallelRequestsLimit() {
|
||||||
|
return PARALLEL_REQUESTS_LIMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getTileUrl(Tile tile) throws MalformedURLException {
|
||||||
|
|
||||||
|
return new URL(PROTOCOL, getHostName(), this.port, "/" + mapName + "/" + tile.zoomLevel + '/' + tile.tileX + '/' + tile.tileY + ".png?apikey=" + API_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getZoomLevelMax() {
|
||||||
|
return ZOOM_LEVEL_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte getZoomLevelMin() {
|
||||||
|
return ZOOM_LEVEL_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Jannis Scheibe <jannis@tadris.de>
|
||||||
|
*
|
||||||
|
* This file is part of FitoTrack
|
||||||
|
*
|
||||||
|
* FitoTrack is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FitoTrack is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.tadris.fitness.map.tilesource;
|
||||||
|
|
||||||
|
|
||||||
|
public class TileSources {
|
||||||
|
|
||||||
|
public static FitoTrackTileSource[] tileSources= new FitoTrackTileSource[]{
|
||||||
|
MapnikTileSource.INSTANCE, HumanitarianTileSource.INSTANCE, ThunderforestTileSource.OUTDOORS, ThunderforestTileSource.CYLE_MAP
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum Purpose{
|
||||||
|
DEFAULT, OUTDOOR, CYCLING
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user