This commit is contained in:
2026-04-13 20:19:02 +02:00
commit 31c92aeae9
77 changed files with 4610 additions and 0 deletions

11
.gitignore vendored Executable file
View File

@@ -0,0 +1,11 @@
*.iml
.gradle
/local.properties
/.idea/
DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/legacy_code/

24
UNLICENSE Normal file
View File

@@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org/>

1
app/.gitignore vendored Executable file
View File

@@ -0,0 +1 @@
/build

68
app/build.gradle.kts Executable file
View File

@@ -0,0 +1,68 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "eu.konggdev.strikemaps"
compileSdk = 36
defaultConfig {
applicationId = "eu.konggdev.strikemaps"
minSdk = 24
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
}
}
dependencies {
implementation(libs.appcompat)
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
implementation(libs.viewpager2)
implementation("org.maplibre.gl:android-sdk:11.13.0")
implementation("com.github.mapsforge.vtm:vtm:0.27.0")
implementation("com.github.mapsforge.vtm:vtm-android:0.27.0")
implementation("com.github.mapsforge.vtm:vtm-http:0.27.0")
implementation ("com.github.mapsforge.vtm:vtm-android:0.27.0@jar")
runtimeOnly ("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-armeabi-v7a@jar")
runtimeOnly("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-arm64-v8a@jar")
runtimeOnly("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-x86@jar")
runtimeOnly("com.github.mapsforge.vtm:vtm-android:0.27.0:natives-x86_64@jar")
implementation("com.google.guava:guava:33.2.1-android")
implementation("com.caverock:androidsvg:1.4")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.0")
implementation("org.apache.commons:commons-lang3:3.14.0")
implementation(libs.core.ktx)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
}

21
app/proguard-rules.pro vendored Executable file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,26 @@
package eu.konggdev.strikemaps;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("eu.konggdev.strikemaps", appContext.getPackageName());
}
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.StrikeMaps"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"version": 8,
"name": "Satelite",
"icon": "assets://satelite.bmp",
"sources": {
"satelite": {
"type": "raster",
"tiles": [
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
],
"minzoom": 0,
"maxzoom": 18,
"scheme": "xyz",
"tileSize": 512
}
},
"sprite": "",
"glyphs": "https://orangemug.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf",
"layers": [
{
"id": "satelite",
"type": "raster",
"source": "satelite"
}
],
"id": "satellite"
}

View File

@@ -0,0 +1,5 @@
package eu.konggdev.strikemaps;
public interface Component {
//TODO: Implement base component methods
}

View File

@@ -0,0 +1,31 @@
package eu.konggdev.strikemaps;
import static org.maplibre.android.style.layers.PropertyFactory.lineColor;
import static org.maplibre.android.style.layers.PropertyFactory.lineWidth;
import eu.konggdev.strikemaps.app.AppController;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
AppController app;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = new AppController(this);
app.init();
}
public void logcat(String tag, String log) {
Log.i(tag, log);
}
public void logcat(String log) {
Log.i("LogcatGeneric", log);
}
}

View File

@@ -0,0 +1,45 @@
package eu.konggdev.strikemaps.app;
import android.content.SharedPreferences;
import androidx.appcompat.app.AppCompatActivity;
import eu.konggdev.strikemaps.MainActivity;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import static android.content.Context.MODE_PRIVATE;
public class AppController {
private final MainActivity appActivity;
private MapComponent map;
private UIComponent ui;
public AppController(MainActivity refActivity) {
appActivity = refActivity;
}
public void logcat(String log) {
appActivity.logcat(log);
}
public UIComponent getUi() {
if (ui == null) init();
return ui;
}
public MapComponent getMap() {
if (map == null) init();
return map;
}
public SharedPreferences getPrefs() {
return getActivity().getSharedPreferences("user_prefs", MODE_PRIVATE);
}
public AppCompatActivity getActivity() { return appActivity; }
public void init() {
if (getActivity().getSupportActionBar() != null)
getActivity().getSupportActionBar().hide();
if(map == null) map = new MapComponent(this);
if(ui == null) {
ui = new UIComponent(this, map);
ui.swapScreen(R.layout.screen_main); //Initial
}
}
}

View File

@@ -0,0 +1,41 @@
package eu.konggdev.strikemaps.factory;
import android.app.AlertDialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.ui.element.item.PreviewItem;
import org.maplibre.geojson.Feature;
import java.util.List;
import java.util.function.Consumer;
//FIXME: Move Item functions into specific classes for specific types - e.g. StyleItem
public final class AlertDialogFactory {
public static AlertDialog pointSelector(AppController app, List<Feature> features, Consumer<Feature> callback) {
LinearLayout layout = new LinearLayout(app.getActivity());
layout.setOrientation(LinearLayout.VERTICAL);
ScrollView scrollView = new ScrollView(app.getActivity());
scrollView.addView(layout);
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
.setView(scrollView)
.create();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#000000")));
for (Feature feature : features) {
View itemView = PreviewItem.fromFeature(feature).makeView(app.getUi(), v -> {
dialog.dismiss();
new android.os.Handler(android.os.Looper.getMainLooper())
.post(() -> callback.accept(feature));
});
layout.addView(itemView);
}
return dialog;
}
}

View File

@@ -0,0 +1,109 @@
package eu.konggdev.strikemaps.helper;
import android.content.res.AssetManager;
import android.os.Environment;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import eu.konggdev.strikemaps.app.AppController;
//FIXME: Ugly
public final class FileHelper {
public static String loadStringFromAssetFile(String filePath, AppController app) {
try (InputStream is = app.getActivity().getAssets().open(filePath)) {
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
return new String(buffer, StandardCharsets.UTF_8);
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
public static String loadStringFromUserFile(String filePath) {
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file)) {
int size = fis.available();
byte[] buffer = new byte[size];
fis.read(buffer);
return new String(buffer, StandardCharsets.UTF_8);
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
public static String[] getAssetFiles(String path, String fileExt, AppController app) {
AssetManager assetManager = app.getActivity().getAssets();
try {
if (path != null && path.startsWith("/")) {
path = path.substring(1);
}
String fullPath = (path == null || path.isEmpty()) ? "" : path;
String[] files = assetManager.list(fullPath);
if (files == null) return new String[0];
if (fileExt == null || fileExt.isEmpty())
return files;
List<String> filtered = new ArrayList<>();
for (String file : files) {
if (file.toLowerCase().endsWith(fileExt.toLowerCase())) {
filtered.add((fullPath.isEmpty() ? "" : fullPath + "/") + file);
}
}
return filtered.toArray(new String[0]);
} catch (IOException e) {
e.printStackTrace();
return new String[0];
}
}
public static InputStream openAssetStream(String path, AppController app) {
try {
return app.getActivity().getAssets().open(path);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String[] getUserFiles(String path, String fileExt, AppController app) {
String packageName = app.getActivity().getPackageName();
File userDirectory = new File(Environment.getExternalStorageDirectory(), "Android/data/" + packageName + "/" + path);
if (!userDirectory.exists() || !userDirectory.isDirectory())
return new String[0];
File[] files = userDirectory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
if (fileExt == null || fileExt.isEmpty()) {
return true;
}
return filename.toLowerCase().endsWith(fileExt.toLowerCase());
}
});
if (files == null || files.length == 0) {
return new String[0];
}
List<String> fileList = new ArrayList<>();
for (File file : files) {
fileList.add(file.getAbsolutePath());
}
return fileList.toArray(new String[0]);
}
}

View File

@@ -0,0 +1,40 @@
package eu.konggdev.strikemaps.helper;
import android.content.SharedPreferences;
public final class UserPrefsHelper {
private UserPrefsHelper() {} // prevent instantiation
//Keys
private static final String KEY_STARTUP_MAP_STYLE = "startupMapStyle";
private static final String KEY_MAP_RENDERER = "mapRenderer";
private static final String KEY_PERSIST_LOCATION_ENABLED = "persistLocationEnabled";
private static final String KEY_LAST_LOCATION_ENABLED = "lastLocationEnabled";
//Defaults
private static final String DEFAULT_MAP_STYLE = "bundled/style/classic.style.json";
private static final String DEFAULT_MAP_RENDERER = "mapLibre";
private static final boolean DEFAULT_PERSIST_LOCATION_ENABLED = true;
private static final boolean DEFAULT_LAST_LOCATION_ENABLED = false;
public static String startupMapStyle(SharedPreferences prefs) {
return prefs.getString(KEY_STARTUP_MAP_STYLE, DEFAULT_MAP_STYLE);
}
public static String mapRenderer(SharedPreferences prefs) {
return prefs.getString(KEY_MAP_RENDERER, DEFAULT_MAP_RENDERER);
}
public static boolean persistLocationEnabled(SharedPreferences prefs) {
return prefs.getBoolean(KEY_PERSIST_LOCATION_ENABLED, DEFAULT_PERSIST_LOCATION_ENABLED);
}
public static boolean lastLocationEnabled(SharedPreferences prefs) {
return prefs.getBoolean(KEY_LAST_LOCATION_ENABLED, DEFAULT_LAST_LOCATION_ENABLED);
}
public static boolean lastLocationEnabled(SharedPreferences prefs, boolean status) {
return prefs.edit().putBoolean(KEY_LAST_LOCATION_ENABLED, status).commit();
}
}

View File

@@ -0,0 +1,95 @@
package eu.konggdev.strikemaps.map;
import java.util.*;
import eu.konggdev.strikemaps.Component;
import eu.konggdev.strikemaps.factory.AlertDialogFactory;
import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.map.renderer.implementation.VtmRenderer;
import org.maplibre.android.geometry.LatLng;
import org.maplibre.geojson.Feature;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.renderer.implementation.MapLibreNativeRenderer;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentMap;
public class MapComponent implements Component {
MapRenderer mapRenderer;
AppController app;
public String style;
public Map<Class<? extends MapOverlay>, MapOverlay> overlays = new HashMap<>();
public MapComponent(AppController ref) {
this.app = ref;
switch(UserPrefsHelper.mapRenderer(app.getPrefs())) {
case "vtm":
this.mapRenderer = new VtmRenderer(app, this);
break;
case "mapLibre":
default: //This shouldn't happen
this.mapRenderer = new MapLibreNativeRenderer(app, this);
break;
};
}
public FragmentLayoutContentMap toFragment() {
return new FragmentLayoutContentMap(mapRenderer.getView());
}
public void setStyle(String style) {
this.style = style;
mapRenderer.reload();
}
public void switchOverlay(MapOverlay overlay) {
if (hasOverlay(overlay)) overlays.remove(overlay.getClass());
else overlays.put(overlay.getClass(), overlay);
update();
}
public boolean hasOverlay(MapOverlay overlay) {
return overlays.containsKey(overlay.getClass());
}
public boolean hasOverlay(Class<? extends MapOverlay> overlay) {
return overlays.containsKey(overlay);
}
public void selectPoint(Feature selection) {
//FIXME: Put back FragmentPointPreviewPopup (private code atm)
}
public void onOverlayUpdate() {
update();
}
public void update() {
if(mapRenderer != null && style != null) mapRenderer.reload();
}
public boolean onMapClick(LatLng point) {
List<Feature> features = mapRenderer.featuresAtPoint(point);
switch (features.size()) {
case 0:
//TODO: Implement point selection for no POI found (MIGHT be done on long click??)
//Maybe collapse UI? (Hide/show UI feature)... could be user configurable
break;
case 1:
selectPoint(features.get(0));
break;
default:
app.getUi().alert(
AlertDialogFactory.pointSelector(app, features, selectedItem -> {
selectPoint(selectedItem);
}));
}
return true;
}
public boolean onMapLongClick(LatLng point) {
//TODO: Likely Nonfeature(?) point selection
return true;
}
}

View File

@@ -0,0 +1,16 @@
package eu.konggdev.strikemaps.map.layer;
import org.maplibre.android.style.layers.Layer;
import org.maplibre.android.style.sources.GeoJsonSource;
import java.util.List;
//TOOD: Make not strictly MapLibre reliant
public class MapLayer {
public GeoJsonSource source;
public Layer layer;
public MapLayer(GeoJsonSource source, Layer layer) {
this.source = source;
this.layer = layer;
}
}

View File

@@ -0,0 +1,8 @@
package eu.konggdev.strikemaps.map.overlay;
import eu.konggdev.strikemaps.map.layer.MapLayer;
/* More or less a data-driven layer factory */
public interface MapOverlay {
public MapLayer makeLayer();
}

View File

@@ -0,0 +1,62 @@
package eu.konggdev.strikemaps.map.overlay.overlay;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import androidx.annotation.NonNull;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.layer.MapLayer;
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.provider.LocationDataProvider;
import org.maplibre.android.style.layers.CircleLayer;
import org.maplibre.android.style.layers.Property;
import org.maplibre.android.style.sources.GeoJsonSource;
import org.maplibre.geojson.Feature;
import org.maplibre.geojson.FeatureCollection;
import org.maplibre.geojson.Point;
import static org.maplibre.android.style.layers.PropertyFactory.*;
public class LocationOverlay implements MapOverlay, LocationListener {
LocationDataProvider locationDataProvider;
AppController app;
MapComponent map;
public Location currentLocation = null;
public LocationOverlay(AppController app) {
this.app = app;
this.map = app.getMap();
this.locationDataProvider = new LocationDataProvider(app.getActivity(), this);
}
@Override
public MapLayer makeLayer() {
GeoJsonSource source = new GeoJsonSource(
"location",
FeatureCollection.fromFeatures(new Feature[]{}) // empty
);
if (currentLocation != null)
source.setGeoJson(Feature.fromGeometry(Point.fromLngLat(currentLocation.getLongitude(), currentLocation.getLatitude())));
CircleLayer layer = new CircleLayer("location", "location");
layer.setProperties(
circleRadius(5f),
circleColor(Color.parseColor("#1E88E5")),
circleStrokeColor(Color.WHITE),
circleStrokeWidth(1.5f),
circlePitchAlignment(Property.CIRCLE_PITCH_ALIGNMENT_MAP)
);
return new MapLayer(source, layer);
}
@Override
public void onLocationChanged(@NonNull Location location) {
this.currentLocation = location;
map.onOverlayUpdate();
}
}

View File

@@ -0,0 +1,11 @@
package eu.konggdev.strikemaps.map.overlay.overlay;
import eu.konggdev.strikemaps.map.layer.MapLayer;
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
public class PointSelectionOverlay implements MapOverlay {
@Override
public MapLayer makeLayer() {
return null;
}
}

View File

@@ -0,0 +1,19 @@
package eu.konggdev.strikemaps.map.renderer;
import android.view.View;
import android.view.ViewGroup;
import eu.konggdev.strikemaps.map.layer.MapLayer;
import org.maplibre.android.style.layers.Layer;
import org.maplibre.android.geometry.LatLng;
import org.maplibre.geojson.Feature;
import java.util.List;
public interface MapRenderer {
void reload();
View getView();
List<Feature> featuresAtPoint(LatLng point);
}

View File

@@ -0,0 +1,78 @@
package eu.konggdev.strikemaps.map.renderer.implementation;
import android.view.View;
import androidx.annotation.NonNull;
import eu.konggdev.strikemaps.helper.FileHelper;
import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.map.overlay.MapOverlay;
import eu.konggdev.strikemaps.map.layer.MapLayer;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
import org.maplibre.android.MapLibre;
import org.maplibre.android.geometry.LatLng;
import org.maplibre.android.maps.MapLibreMap;
import org.maplibre.android.maps.MapView;
import org.maplibre.android.maps.OnMapReadyCallback;
import org.maplibre.android.maps.Style;
import org.maplibre.geojson.Feature;
import java.util.List;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.MapComponent;
public class MapLibreNativeRenderer implements MapRenderer, OnMapReadyCallback {
AppController app;
MapComponent controller;
MapLibreMap map;
final MapView mapView;
public MapLibreNativeRenderer(AppController app, MapComponent controller) {
this.app = app;
this.controller = controller;
MapLibre.getInstance(app.getActivity());
this.mapView = new MapView(app.getActivity());
mapView.onCreate(null);
mapView.getMapAsync(this);
}
void passLayer(MapLayer layer) {
map.getStyle().addSource(layer.source);
map.getStyle().addLayer(layer.layer);
}
@Override
public void reload() {
map.setStyle(new Style.Builder().fromJson(controller.style), style -> {
for(MapOverlay overlay : controller.overlays.values()) {
passLayer(overlay.makeLayer());
}
});
}
@Override
public View getView() {
return mapView;
}
@Override
public List<Feature> featuresAtPoint(LatLng point) {
return map.queryRenderedFeatures(map.getProjection().toScreenLocation(point));
}
@Override
public void onMapReady(@NonNull MapLibreMap maplibreMap) {
this.map = maplibreMap;
controller.style = FileHelper.loadStringFromAssetFile(UserPrefsHelper.startupMapStyle(app.getPrefs()), app);
//I have my own implementation of attribution that credits MapLibre among others, it's not as bad as it looks :)
map.getUiSettings().setLogoEnabled(false);
map.getUiSettings().setAttributionEnabled(false);
map.addOnMapClickListener(point -> controller.onMapClick(point));
map.addOnMapLongClickListener(point -> controller.onMapLongClick(point));
this.reload();
}
}

View File

@@ -0,0 +1,50 @@
package eu.konggdev.strikemaps.map.renderer.implementation;
import android.view.View;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.map.renderer.MapRenderer;
import okhttp3.OkHttpClient;
import org.maplibre.android.geometry.LatLng;
import org.maplibre.geojson.Feature;
import org.oscim.android.MapView;
import org.oscim.map.Map;
import org.oscim.tiling.source.OkHttpEngine;
import org.oscim.tiling.source.oscimap4.OSciMap4TileSource;
import java.util.Collections;
import java.util.List;
public class VtmRenderer implements MapRenderer {
AppController app;
MapComponent controller;
Map map;
final MapView mapView;
public VtmRenderer(AppController app, MapComponent controller) {
this.app = app;
this.controller = controller;
this.mapView = new MapView(app.getActivity());
this.map = mapView.map();
}
@Override
public void reload() {
//TODO
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OSciMap4TileSource tileSource = OSciMap4TileSource.builder().httpFactory(new OkHttpEngine.OkHttpFactory(builder)).build();
map.setBaseMap(tileSource);
}
@Override
public View getView() {
return mapView;
}
@Override
public List<Feature> featuresAtPoint(LatLng point) {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,12 @@
package eu.konggdev.strikemaps.map.source;
public class MapSource {
public final String url;
public final String type;
public final String schema;
public MapSource(String url, String type, String schema) {
this.url = url;
this.type = type;
this.schema = schema;
}
}

View File

@@ -0,0 +1,5 @@
package eu.konggdev.strikemaps.provider;
public class HttpDataProvider implements Provider {
//TODO
}

View File

@@ -0,0 +1,43 @@
package eu.konggdev.strikemaps.provider;
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 androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import java.util.List;
public class LocationDataProvider implements Provider {
private LocationManager locationManager;
private List<String> locationManagerProviders = List.of(LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER);
public LocationDataProvider(AppCompatActivity activity, LocationListener listener) {
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
//TODO: Move permission request to UI
if(ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Location initLocation = null;
for (String provider : locationManagerProviders) {
if(locationManager.isProviderEnabled(provider)) {
if (initLocation == null) {
initLocation = locationManager.getLastKnownLocation(provider);
if (initLocation != null)
listener.onLocationChanged(initLocation);
}
locationManager.requestLocationUpdates(
provider,
1000,
1,
listener
);
}
}
}
}
}

View File

@@ -0,0 +1,5 @@
package eu.konggdev.strikemaps.provider;
public interface Provider {
}

View File

@@ -0,0 +1,77 @@
package eu.konggdev.strikemaps.ui;
import android.app.AlertDialog;
import android.view.View;
import androidx.annotation.NonNull;
import com.google.common.collect.BiMap;
import eu.konggdev.strikemaps.Component;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.ui.element.UIRegion;
import eu.konggdev.strikemaps.ui.fragment.layout.FragmentLayoutControls;
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.FragmentLayoutContentSettings;
import eu.konggdev.strikemaps.ui.screen.Screen;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
public class UIComponent implements Component {
@NonNull AppController app;
private Map<Integer, Screen> screens;
private Integer currentScreen;
public UIComponent(AppController app, MapComponent map) {
this.app = app;
this.screens = Map.of(
//Main screen
R.layout.screen_main, new Screen(
//App reference
app,
//Map view
map.toFragment(), //FragmentLayoutContentMap
//Main screen init regions definition
Map.of(R.id.bottomUi, new UIRegion(new FragmentLayoutControls(app, R.id.bottomUi), R.id.bottomUi)), //TODO: Probably stop referencing layout 3(!) times everytime
//Layout
R.layout.screen_main //TODO: Define this for the Screen without duplicating the reference
),
//Settings screen
R.layout.screen_settings, new Screen(
app,
//Settings
new FragmentLayoutContentSettings(),
/* No regions defined in settings
Entire screen is just the main view */
new HashMap<>(),
//Layout
R.layout.screen_settings
)
);
}
public void swapScreen(Integer screen) {
currentScreen = screen;
getCurrentScreen().attachAll();
}
public Screen getCurrentScreen() {
return getScreen(currentScreen);
}
public Screen getScreen(Integer screen) {
return screens.get(screen);
}
public void alert(AlertDialog dialog) {
dialog.show();
}
public <T> void alert(AlertDialog dialog, Consumer<T> callback) {
dialog.show();
}
public View inflateUi(int layout) {
return app.getActivity().getLayoutInflater().inflate(layout, null);
}
}

View File

@@ -0,0 +1,44 @@
package eu.konggdev.strikemaps.ui.element;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.ui.fragment.layout.Layout;
import java.util.ArrayDeque;
public class UIRegion {
private final ArrayDeque<Fragment> previousFragments = new ArrayDeque<>();
private Fragment stockFragment;
private Fragment currentFragment;
public Integer layoutId;
public UIRegion(@NonNull Fragment initFragment, Integer refLayoutId) {
this.currentFragment = initFragment;
this.stockFragment = initFragment;
this.layoutId = refLayoutId;
}
public Fragment getFragment() {
return currentFragment;
}
public void setFragment(Fragment fragment) {
previousFragments.add(currentFragment);
currentFragment = fragment;
}
public void overwriteStockFragment(Fragment fragment) {
stockFragment = fragment;
}
public void back() {
if (!previousFragments.isEmpty()) {
currentFragment = previousFragments.pop();
} else {
currentFragment = stockFragment;
}
}
}

View File

@@ -0,0 +1,77 @@
package eu.konggdev.strikemaps.ui.element.item;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.helper.FileHelper;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import org.json.JSONObject;
import java.io.InputStream;
public class GenericItem implements UIItem {
@NonNull public String name;
public Bitmap image;
public Runnable onClick;
boolean hasImage;
public GenericItem(String refName) {
this.name = refName;
hasImage = false;
}
public GenericItem(String refName, Runnable onClick) {
this.name = refName;
this.onClick = onClick;
hasImage = false;
}
public GenericItem(String refName, Bitmap refImage) {
this.name = refName;
this.image = refImage;
hasImage = true;
}
public GenericItem(String refName, Bitmap refImage, Runnable onClick) {
this.name = refName;
this.image = refImage;
this.onClick = onClick;
hasImage = true;
}
//FIXME: Ugly glue static constructor
public final static GenericItem fromStyle(String style, AppController app, MapComponent map) {
try {
JSONObject styleJson = new JSONObject(style);
String name = "Unknown"; //Fallback name
if (styleJson.has("name")) name = styleJson.getString("name");
if (styleJson.has("icon")) {
switch(styleJson.getString("icon").split("//")[0]) {
//TODO: https
case "assets:":
Bitmap icon = BitmapFactory.decodeStream(FileHelper.openAssetStream("bundled/icon/" + styleJson.getString("icon").split("//")[1], app));
return new GenericItem(name, icon, () -> map.setStyle(style));
default:
app.logcat("Unimplemented icon source requested in style: " + name);
return new GenericItem(name, () -> map.setStyle(style));
}
}
return new GenericItem(name, () -> map.setStyle(style));
} catch (Exception e) {
e.printStackTrace();
return new GenericItem("Exception!", () -> map.setStyle(style));
}
}
public View makeView(UIComponent spawner) {
View v = spawner.inflateUi(R.layout.item_generic);
//FIXME: These shouldn't be casted like that!
((TextView) v.findViewById(R.id.name)).setText(name);
if(image != null) ((ImageButton) v.findViewById(R.id.image)).setImageBitmap(image);
if(onClick != null) v.findViewById(R.id.image).setOnClickListener(click(onClick));
return v;
}
}

View File

@@ -0,0 +1,41 @@
package eu.konggdev.strikemaps.ui.element.item;
import android.graphics.Bitmap;
import android.view.View;
import android.widget.TextView;
import eu.konggdev.strikemaps.ui.UIComponent;
import org.maplibre.geojson.Feature;
import eu.konggdev.strikemaps.R;
public class PreviewItem implements UIItem {
public String name;
public String type;
public Bitmap image;
boolean hasImage;
public PreviewItem(String refName, String refType) {
this.name = refName;
this.type = refType;
hasImage = false;
}
public PreviewItem(String refName, String refType, Bitmap refImage) {
this.name = refName;
this.type = refType;
this.image = refImage;
hasImage = true;
}
public static PreviewItem fromFeature(Feature feature) {
return new PreviewItem(feature.getStringProperty("name"), feature.getStringProperty("class"));
}
public View makeView(UIComponent spawner) {
View view = spawner.inflateUi(R.layout.item_preview);
((TextView) view.findViewById(R.id.choiceName)).setText(name);
((TextView) view.findViewById(R.id.type)).setText(type);
return view;
}
public View makeView(UIComponent spawner, View.OnClickListener onClick) {
View view = makeView(spawner);
view.setOnClickListener(onClick);
return view;
}
}

View File

@@ -0,0 +1,16 @@
package eu.konggdev.strikemaps.ui.element.item;
import android.view.View;
import eu.konggdev.strikemaps.ui.UIComponent;
public interface UIItem {
abstract View makeView(UIComponent spawner);
default View.OnClickListener click(Runnable action) {
return v -> action.run();
}
default View.OnLongClickListener longClick(Runnable action) { return v -> { action.run(); return true; };}
}

View File

@@ -0,0 +1,90 @@
package eu.konggdev.strikemaps.ui.fragment;
import android.view.MotionEvent;
import android.view.View;
import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.ui.element.UIRegion;
public interface ContainerFragment {
abstract public Integer getRegion();
abstract public Fragment toFragment();
//Helper methods (ugly)
//FIXME
default void setupButton(View view, int button, View.OnClickListener onClick) {
view.findViewById(button)
.setOnClickListener(onClick);
}
default void setupButton(View view, int button, View.OnClickListener onClick, View.OnLongClickListener onLongClick) {
View buttonView = view.findViewById(button);
buttonView.setOnClickListener(onClick);
buttonView.setOnLongClickListener(onLongClick);
}
default void setupButton(View view, int button, View.OnLongClickListener onLongClick) {
view.findViewById(button)
.setOnLongClickListener(onLongClick);
}
default View.OnClickListener click(Runnable action) {
return v -> action.run();
}
default View.OnLongClickListener longClick(Runnable action) { return v -> { action.run(); return true; };}
//TODO: Make animation less wonky
default void setupDragHandle(View dragHandle, View layout, Runnable closeAction) {
final float[] dY = new float[1];
dragHandle.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dY[0] = event.getRawY() - layout.getY();
return true;
case MotionEvent.ACTION_MOVE:
float newY = event.getRawY() - dY[0];
if (newY >= 0) {
layout.setY(newY);
}
return true;
case MotionEvent.ACTION_UP:
if (layout.getY() > layout.getHeight() / 4) {
layout.animate()
.scaleX(0f)
.scaleY(0f)
.alpha(0f)
.setDuration(300)
.withEndAction(new Runnable() {
@Override
public void run() {
layout.setVisibility(View.GONE);
closeAction.run();
layout.setScaleX(1f);
layout.setScaleY(1f);
layout.setAlpha(1f);
layout.setY(0f);
}
})
.start();
} else {
layout.animate()
.translationY(0f)
.setDuration(200)
.start();
}
return true;
default:
return false;
}
}
});
}
}

View File

@@ -0,0 +1,7 @@
package eu.konggdev.strikemaps.ui.fragment;
import androidx.fragment.app.Fragment;
public class FragmentEmptyPlaceholder extends Fragment {
//:)
}

View File

@@ -0,0 +1,120 @@
package eu.konggdev.strikemaps.ui.fragment.layout;
import android.Manifest;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import android.widget.TextView;
import android.widget.Toast;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.helper.UserPrefsHelper;
import eu.konggdev.strikemaps.map.overlay.overlay.LocationOverlay;
import eu.konggdev.strikemaps.ui.fragment.popup.FragmentMapChangePopup;
public class FragmentLayoutControls extends Fragment implements Layout {
AppController app;
View rootView;
private final Integer region;
// Action definitions
//*//
public void notImplemented() { //Should never be called in release
Toast.makeText(requireContext(), "Not implemented yet\nWait for release", Toast.LENGTH_SHORT).show();
}
public void toggleLocationService() {
if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
app.getMap().switchOverlay(new LocationOverlay(app));
setupView();
}
}
public void zoomToLocation() {
if(!app.getMap().hasOverlay(LocationOverlay.class)) {
Toast.makeText(requireContext(), "Hold to enable location", Toast.LENGTH_SHORT).show();
return;
}
}
public void attributtionDialog() {
AlertDialog dialog = new AlertDialog.Builder(app.getActivity())
.setTitle(app.getActivity().getString(R.string.attribution_title))
.setMessage(app.getActivity().getString(R.string.shipped_attribution))
.setPositiveButton("OK", null).show();
}
//*//
public FragmentLayoutControls(AppController app, Integer region) {
super(R.layout.fragment_controls);
this.app = app;
this.region = region;
}
@Override
public Integer getRegion() {
return region;
}
@Override
public Fragment toFragment() {
return this;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.rootView = view;
/* Restores location enabled status from user prefs,
TODO: Should be moved out of UI code in the future */
if(UserPrefsHelper.persistLocationEnabled(app.getPrefs()) && UserPrefsHelper.lastLocationEnabled(app.getPrefs()) && !app.getMap().hasOverlay(LocationOverlay.class))
toggleLocationService();
this.setupView();
}
public void setupView() {
if (rootView == null) return;
setupButton(rootView, R.id.layersButton, click(() -> app.getUi().getCurrentScreen().open(new FragmentMapChangePopup(app, R.id.bottomUi))));
setupButton(rootView, R.id.attributionButton, click(this::attributtionDialog));
setupButton(rootView, R.id.locationButton, click(this::zoomToLocation), longClick(this::toggleLocationService));
//TODO
setupButton(rootView, R.id.placesButton, click(this::notImplemented));
setupButton(rootView, R.id.placesButton, click(this::notImplemented));
setupButton(rootView, R.id.routeButton, click(this::notImplemented));
setupButton(rootView, R.id.modeButton, click(this::notImplemented));
TextView locationServiceStatusIndicator = rootView.findViewById(R.id.locationServiceStatusIndicator);
if (app.getMap().hasOverlay(LocationOverlay.class)) {
locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#00FF00")); //green
} else {
locationServiceStatusIndicator.setBackgroundColor(Color.parseColor("#FB0303")); //red
}
if(UserPrefsHelper.persistLocationEnabled(app.getPrefs()))
UserPrefsHelper.lastLocationEnabled(app.getPrefs(), app.getMap().hasOverlay(LocationOverlay.class));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) toggleLocationService();
else Toast.makeText(requireContext(), "You need to grant location permission", Toast.LENGTH_SHORT).show();
}
}
}

View File

@@ -0,0 +1,8 @@
package eu.konggdev.strikemaps.ui.fragment.layout;
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
public interface Layout extends ContainerFragment {
}

View File

@@ -0,0 +1,6 @@
package eu.konggdev.strikemaps.ui.fragment.layout.content;
import eu.konggdev.strikemaps.ui.fragment.layout.Layout;
public interface ContentLayout extends Layout {
}

View File

@@ -0,0 +1,33 @@
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.ui.element.UIRegion;
import eu.konggdev.strikemaps.R;
public class FragmentLayoutContentMap extends Fragment implements MainContentLayout {
View mapView;
public FragmentLayoutContentMap(View refMapView) {
super(R.layout.fragment_map);
this.mapView = refMapView;
}
@Override
public Fragment toFragment() {
return this;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LinearLayout layout = (LinearLayout) view;
layout.addView(mapView);
}
}

View File

@@ -0,0 +1,10 @@
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
import androidx.fragment.app.Fragment;
public class FragmentLayoutContentSettings implements MainContentLayout {
@Override
public Fragment toFragment() {
return null;
}
}

View File

@@ -0,0 +1,10 @@
package eu.konggdev.strikemaps.ui.fragment.layout.content.main;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.ui.fragment.layout.content.ContentLayout;
public interface MainContentLayout extends ContentLayout {
default Integer getRegion() {
return R.id.mainContentView;
}
}

View File

@@ -0,0 +1,61 @@
package eu.konggdev.strikemaps.ui.fragment.popup;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.widget.LinearLayout;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.helper.FileHelper;
import eu.konggdev.strikemaps.factory.AlertDialogFactory;
import eu.konggdev.strikemaps.map.MapComponent;
import eu.konggdev.strikemaps.ui.UIComponent;
import eu.konggdev.strikemaps.ui.element.item.GenericItem;
import org.apache.commons.lang3.ArrayUtils;
import java.util.ArrayList;
import java.util.List;
public class FragmentMapChangePopup extends Fragment implements Popup {
@NonNull AppController app;
@NonNull MapComponent map;
@NonNull UIComponent ui;
private final Integer region;
public FragmentMapChangePopup(AppController app, Integer region) {
super(R.layout.popup_map_change);
this.app = app;
this.map = app.getMap();
this.ui = app.getUi();
this.region = region;
}
@Override
public Integer getRegion() {
return region;
}
@Override
public Fragment toFragment() {
return this;
}
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
//FIXME
setupButton(view, R.id.closeButton, click(() -> ui.getCurrentScreen().closePopup()));
setupDragHandle(view, view, () -> ui.getCurrentScreen().closePopup());
String[] stylePaths = ArrayUtils.addAll(FileHelper.getAssetFiles("bundled/style", ".style.json", app), FileHelper.getUserFiles("style", ".style.json", app));
List<View> views = new ArrayList<>();
LinearLayout stylesLayout = view.findViewById(R.id.stylesLayout);
for(String i : stylePaths) {
if(i.startsWith("/storage")) stylesLayout.addView(GenericItem.fromStyle(FileHelper.loadStringFromUserFile(i), app, map).makeView(ui));
else stylesLayout.addView(GenericItem.fromStyle(FileHelper.loadStringFromAssetFile(i, app), app, map).makeView(ui));
}
}
}

View File

@@ -0,0 +1,8 @@
package eu.konggdev.strikemaps.ui.fragment.popup;
import androidx.fragment.app.Fragment;
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
public interface Popup extends ContainerFragment {
}

View File

@@ -0,0 +1,77 @@
package eu.konggdev.strikemaps.ui.screen;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import java.util.List;
import java.util.Map;
import eu.konggdev.strikemaps.R;
import eu.konggdev.strikemaps.app.AppController;
import eu.konggdev.strikemaps.ui.fragment.ContainerFragment;
import eu.konggdev.strikemaps.ui.fragment.layout.content.main.MainContentLayout;
import eu.konggdev.strikemaps.ui.fragment.popup.Popup;
import eu.konggdev.strikemaps.ui.element.UIRegion;
public class Screen {
@NonNull AppController app;
public Screen(AppController app, MainContentLayout mainContent, Map<Integer, UIRegion> regions, Integer layout) {
this.app = app;
this.layout = layout;
this.mainContent = mainContent;
this.uiRegions = regions;
}
private final Integer layout;
private MainContentLayout mainContent;
Map<Integer, UIRegion> uiRegions;
public Integer popup;
public void open(ContainerFragment fragment) {
if(fragment instanceof Popup && popup != null) return;
if(fragment instanceof Popup)
popup = fragment.getRegion();
setFragment(uiRegions.get(fragment.getRegion()), fragment.toFragment());
}
public void closePopup() {
if(popup != null) {
UIRegion popupRegion = uiRegions.get(popup);
popupRegion.back();
/* If newFragment is still a popup, assign the current popup value to the new fragment
otherwise, set the current popup value to null */
if(popupRegion.getFragment() instanceof Popup) {
popup = popupRegion.layoutId;
} else {
popup = null;
}
setFragment(popupRegion, popupRegion.getFragment());
}
}
public void setFragment(UIRegion region, Fragment fragment) {
if (region == null) return;
region.setFragment(fragment);
fragmentTransaction(region.layoutId, fragment);
}
public void fragmentTransaction(int layoutId, Fragment fragment) {
app.getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(layoutId, fragment)
.commit();
}
public void attachAll() {
app.getActivity().setContentView(layout);
fragmentTransaction(R.id.mainContentView, mainContent.toFragment());
for (UIRegion region : uiRegions.values()) {
setFragment(region, region.getFragment());
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<ImageButton
android:id="@+id/routeButton"
android:layout_width="65dp"
android:layout_height="42dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="36dp"
android:backgroundTint="#000000"
android:src="@android:drawable/ic_menu_directions"
app:layout_constraintBottom_toBottomOf="@+id/placesButton"
app:layout_constraintStart_toStartOf="parent" />
<ImageButton
android:id="@+id/placesButton"
android:layout_width="65dp"
android:layout_height="43dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="36dp"
android:backgroundTint="#000000"
app:layout_constraintBottom_toBottomOf="@+id/layersButton"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@android:drawable/ic_menu_myplaces" />
<ImageButton
android:id="@+id/layersButton"
android:layout_width="65dp"
android:layout_height="42dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="4dp"
android:backgroundTint="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/ic_styles_menu" />
<ImageButton
android:id="@+id/modeButton"
android:layout_width="60dp"
android:layout_height="36dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="44dp"
android:backgroundTint="#000000"
android:src="@android:drawable/ic_menu_manage"
app:layout_constraintBottom_toBottomOf="@+id/locationButtonContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0" />
<ImageButton
android:id="@+id/attributionButton"
android:layout_width="60dp"
android:layout_height="31dp"
android:layout_marginStart="272dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:backgroundTint="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.375"
app:srcCompat="@android:drawable/ic_menu_info_details" />
<FrameLayout
android:id="@+id/locationButtonContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toBottomOf="@+id/attributionButton"
app:layout_constraintEnd_toEndOf="parent">
<ImageButton
android:id="@+id/locationButton"
android:layout_width="60dp"
android:layout_height="47dp"
android:backgroundTint="#000000"
android:contentDescription="Location"
app:srcCompat="@android:drawable/ic_menu_mylocation" />
<TextView
android:id="@+id/locationServiceStatusIndicator"
android:layout_width="30dp"
android:layout_height="1dp"
android:layout_gravity="center|bottom"
android:gravity="center"
android:layout_marginBottom="7dp"
android:background="#FB0303"
android:textSize="5sp" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.widget.LinearLayout>

View File

@@ -0,0 +1,27 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:padding="8dp">
<ImageButton
android:id="@+id/image"
android:layout_width="54dp"
android:layout_height="47dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Style Image"
android:src="@android:drawable/ic_menu_gallery" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="Item Name"
android:textColor="#FFFFFF"
android:textSize="14sp" />
</LinearLayout>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#0E0000"
android:foregroundTint="#FFFFFF">
<TextView
android:id="@+id/choiceName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="12dp"
android:text="Choice Item"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:ellipsize="end"
android:maxLines="1"
android:scrollHorizontally="false"
android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="12sp"
android:autoSizeMaxTextSize="24sp"
android:autoSizeStepGranularity="1sp"
app:layout_constraintStart_toEndOf="@+id/poiIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/poiIcon"
android:layout_width="55dp"
android:layout_height="55dp"
android:layout_marginStart="7dp"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/maplibre_info_bg_selector" />
<TextView
android:id="@+id/type"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:text="Type"
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold"
android:ellipsize="end"
android:singleLine="true"
app:layout_constraintStart_toEndOf="@id/poiIcon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/choiceName"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000000"
android:padding="16dp">
<View
android:id="@+id/dragHandle"
android:layout_width="170dp"
android:layout_height="5dp"
android:background="#979797"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ImageButton
android:id="@+id/closeButton"
android:layout_width="30dp"
android:layout_height="30dp"
android:backgroundTint="#000000"
app:srcCompat="@android:drawable/ic_menu_close_clear_cancel"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/stylesLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Styles"
android:textColor="#FFFFFF"
android:textSize="18sp"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<HorizontalScrollView
android:id="@+id/styles"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@id/stylesLabel"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:id="@+id/stylesLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</HorizontalScrollView>
<!-- Sources selection to be implemented here -->
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" >
<LinearLayout
android:id="@+id/popupHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
</LinearLayout>
<LinearLayout
android:id="@+id/mainContentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
</LinearLayout>
<FrameLayout
android:id="@+id/bottomUi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/devIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DEVELOPMENT BUILD!"
android:textColor="#000000"
android:textSize="13sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/searchContainer"
android:layout_width="280dp"
android:layout_height="33dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:background="#000000"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<SearchView
android:id="@+id/searchView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:iconifiedByDefault="false"
android:queryHint="Search..."
android:background="@android:color/transparent" />
<ImageButton
android:id="@+id/hamburgerButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:contentDescription="Menu"
android:src="@drawable/ic_hamburger_menu" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

View File

@@ -0,0 +1,5 @@
<resources>
<string name="app_name">Strike Maps</string>
<string name="attribution_title"> Attribution </string>
<string name="shipped_attribution">Earth map data Included;\n - © OpenStreetMap Contributors\nMap Rendering libraries Included;\n - MapLibre developed by MapLibre Organization\n - Vtm developed by Mapsforge\nStrike Maps made with &lt;3 by konggdev</string>
</resources>

View File

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.StrikeMaps" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/black</item>
<item name="colorPrimaryVariant">@color/black</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="21">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@@ -0,0 +1,17 @@
package eu.konggdev.strikemaps;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

5
build.gradle.kts Executable file
View File

@@ -0,0 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
}

21
gradle.properties Executable file
View File

@@ -0,0 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. For more details, visit
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

30
gradle/libs.versions.toml Executable file
View File

@@ -0,0 +1,30 @@
[versions]
agp = "8.9.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
appcompat = "1.6.1"
material = "1.10.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
playServicesMaps = "19.0.0"
viewpager2 = "1.1.0"
kotlin = "2.3.10"
coreKtx = "1.18.0"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

BIN
gradle/wrapper/gradle-wrapper.jar vendored Executable file

Binary file not shown.

6
gradle/wrapper/gradle-wrapper.properties vendored Executable file
View File

@@ -0,0 +1,6 @@
#Wed Feb 19 10:31:32 CET 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored Executable file
View File

@@ -0,0 +1,185 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Executable file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

19
settings.gradle.kts Executable file
View File

@@ -0,0 +1,19 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}
rootProject.name = "StrikeMaps"
include(":app")