Compare commits

...

16 Commits

Author SHA1 Message Date
Johan von Forstner
87421e450a fix missing API key in Google variant, hotfix release 2020-08-28 15:17:05 +02:00
johan12345
479917fad1 fix wrong position of layers button in case of display cutout (fixes #51) 2020-08-24 22:57:02 +02:00
johan12345
dfaf841160 Release 0.3.4 2020-08-24 22:20:43 +02:00
johan12345
c18ea5b15d add link “report new station” to main menu (fixes #53) 2020-08-24 20:11:44 +02:00
johan12345
62116473c8 Navigation component: add settings as top-level destination 2020-08-24 19:46:32 +02:00
johan12345
bc8106bd81 add Google Maps API key only to Google variant 2020-08-23 23:35:46 +02:00
johan12345
7bd89b9ecb get rid of Mapbox telemetry dependency 2020-08-23 23:31:01 +02:00
Johan von Forstner
898b61945e Make links under "general information" and "amenities" clickable 2020-08-23 12:25:38 +02:00
Johan von Forstner
38e022b547 Add links to Twitter account and GoingElectric.de forum thread 2020-08-22 20:07:33 +02:00
Johan von Forstner
b8c438503c add new icon for "more than one connector" 2020-08-22 09:20:05 +02:00
Johan von Forstner
2ca6a8e3e8 fix vertical position of markers 2020-08-22 08:21:13 +02:00
Johan von Forstner
0ae201e363 MultiSelectDialog: case-insensitive sorting (fixes #44) 2020-08-22 08:11:50 +02:00
Johan von Forstner
9e0f535a13 Release 0.3.3 2020-08-16 13:47:23 +02:00
Johan von Forstner
d4a6789b00 Dark mode: fix icon tint for layers FAB 2020-08-16 13:46:00 +02:00
Johan von Forstner
d9415ed7a0 fix LocaleContextWrapper 2020-08-16 13:42:13 +02:00
Johan von Forstner
778d7293f4 set up fastlane and download metadata 2020-08-13 21:18:38 +02:00
48 changed files with 587 additions and 55 deletions

3
.gitignore vendored
View File

@@ -10,4 +10,5 @@
apikeys.xml
/app/**/*.aab
/app/**/*.apk
/_img/connectors/*.ai
/_img/connectors/*.ai
api-7125266970515251116-798419-8e2dda660c80.json

3
Gemfile Normal file
View File

@@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"

178
Gemfile.lock Normal file
View File

@@ -0,0 +1,178 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
atomos (0.1.3)
aws-eventstream (1.1.0)
aws-partitions (1.354.0)
aws-sdk-core (3.104.3)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.36.0)
aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.78.0)
aws-sdk-core (~> 3, >= 3.104.3)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.3)
claide (1.0.3)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
declarative (0.0.20)
declarative-option (0.1.0)
digest-crc (0.6.1)
rake (~> 13.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
emoji_regex (3.0.0)
excon (0.76.0)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (1.0.0)
faraday (~> 1.0)
fastimage (2.2.0)
fastlane (2.156.1)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.37.0, < 0.39.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
gh_inspector (1.1.3)
google-api-client (0.38.0)
addressable (~> 2.5, >= 2.5.1)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.12)
google-cloud-core (1.5.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.3.3)
faraday (>= 0.17.3, < 2.0)
google-cloud-errors (1.0.1)
google-cloud-storage (1.27.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.13.1)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.14)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
jmespath (1.4.0)
json (2.3.1)
jwt (2.2.1)
memoist (0.16.2)
mini_magick (4.10.1)
mini_mime (1.0.2)
multi_json (1.15.0)
multipart-post (2.0.0)
nanaimo (0.3.0)
naturally (2.2.0)
os (1.1.1)
plist (3.5.0)
public_suffix (4.0.5)
rake (13.0.1)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
rubyzip (2.3.0)
security (0.1.3)
signet (0.14.0)
addressable (~> 2.3)
faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.8)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
tty-cursor (0.7.1)
tty-screen (0.8.1)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7-x64-mingw32)
unicode-display_width (1.7.0)
word_wrap (1.0.0)
xcodeproj (1.18.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
x64-mingw32
DEPENDENCIES
fastlane
BUNDLED WITH
2.1.2

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?><!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 233.8 368.4" style="enable-background:new 0 0 233.8 368.4;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#B5B5B5;}
.st2{fill:#808080;}
</style>
<g>
<g>
<g>
<path class="st0" d="M109.8,0h13.6c33.9,1.9,67.1,18.5,87.7,45.8c13.5,17.2,21,38.6,22.7,60.3v8.1c-0.8,42.1-27.7,76.6-51,109.4
c-26.2,37-50.4,77.3-57.1,122.9c-1.8,7.7,0.4,18.5-8.9,22c-2.2-1.7-4.7-3.1-6.2-5.4c-2.7-25.5-9.1-50.7-20-73.9
c-12.3-27.1-29.5-51.6-47-75.6C33,199,23,184.2,14.7,168.3c-13-23.8-17.9-51.9-12.5-78.6C6.6,68.6,17.6,49.1,32.8,34
C53.3,14,81.1,1.8,109.8,0z" />
</g>
</g>
</g>
<g>
<polygon class="st1"
points="143.2,109.4 123.5,143.2 123.5,181.3 166.9,106.9 144.7,106.9 " />
<path class="st1"
d="M122.2,101.9h16.7h5.7l22.3-44.6c0,0-10.2,0-22.4,0l-1.1,2.2L122.2,101.9z" />
<path class="st2" d="M138.9,57.3c-9.7,0-19.8,0-26.4,0c-2.5,0-5.1,0-7.6,0c-8.2,0-16.1,0-21.4,0c-4.1,0-6.6,0-6.6,0v68.2h18.6v55.8
l43.4-74.4h-24.8L138.9,57.3z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -13,8 +13,8 @@ android {
applicationId "net.vonforst.evmap"
minSdkVersion 21
targetSdkVersion 29
versionCode 23
versionName "0.3.2"
versionCode 26
versionName "0.3.4a"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -78,7 +78,7 @@ android {
variant.resValue "string", "goingelectric_key", goingelectricKey
}
def googleMapsKey = env.GOOGLE_MAPS_API_KEY ?: project.findProperty("GOOGLE_MAPS_API_KEY")
if (googleMapsKey != null) {
if (googleMapsKey != null && variant.flavorName == 'google') {
variant.resValue "string", "google_maps_key", googleMapsKey
}
def mapboxKey = env.MAPBOX_API_KEY ?: project.findProperty("MAPBOX_API_KEY")
@@ -116,7 +116,7 @@ dependencies {
implementation 'com.mapzen.android:lost:3.0.2'
// AnyMaps
def anyMapsVersion = 'e6e014dd11'
def anyMapsVersion = '894f6d62ac'
implementation "com.github.johan12345.AnyMaps:anymaps-base:$anyMapsVersion"
googleImplementation "com.github.johan12345.AnyMaps:anymaps-google:$anyMapsVersion"
implementation "com.github.johan12345.AnyMaps:anymaps-mapbox:$anyMapsVersion"
@@ -136,7 +136,10 @@ dependencies {
googleImplementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
// Mapbox places (autocomplete)
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-places-v9:0.12.0'
implementation('com.mapbox.mapboxsdk:mapbox-android-plugin-places-v9:0.12.0') {
exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-accounts'
exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-telemetry'
}
// navigation library
def nav_version = "2.3.0"

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.vonforst.evmap">
<application>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
</application>
</manifest>

View File

@@ -14,17 +14,6 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/apikeys.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<meta-data
android:name="com.mapbox.ACCESS_TOKEN"
android:value="@string/mapbox_key" />

View File

@@ -53,7 +53,8 @@ class MapsActivity : AppCompatActivity() {
setOf(
R.id.map,
R.id.favs,
R.id.about
R.id.about,
R.id.settings
),
findViewById<DrawerLayout>(R.id.drawer_layout)
)

View File

@@ -59,6 +59,14 @@ class AboutFragment : PreferenceFragmentCompat() {
findNavController().navigate(R.id.action_about_to_donateFragment)
true
}
"twitter" -> {
(activity as? MapsActivity)?.openUrl(getString(R.string.twitter_url))
true
}
"goingelectric" -> {
(activity as? MapsActivity)?.openUrl(getString(R.string.goingelectric_forum_url))
true
}
else -> super.onPreferenceTreeClick(preference)
}
}

View File

@@ -169,6 +169,18 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
binding.detailAppBar.toolbar.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = insets.systemWindowInsetTop
}
// margin of layers button
val density = resources.displayMetrics.density
// status bar height + toolbar height + margin
val margin =
insets.systemWindowInsetTop + (48 * density).toInt() + (24 * density).toInt()
binding.fabLayers.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = margin
}
binding.layersSheet.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = margin
}
insets
}
@@ -421,7 +433,10 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
markers.forEach { (m, c) ->
m.setIcon(
chargerIconGenerator.getBitmapDescriptor(
getMarkerTint(c, vm.filteredConnectors.value), fault = c.faultReport != null
getMarkerTint(c, vm.filteredConnectors.value),
highlight = false,
fault = c.faultReport != null,
multi = getMarkerMulti(c, vm.filteredConnectors.value)
)
)
}
@@ -434,7 +449,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
chargerIconGenerator.getBitmapDescriptor(
getMarkerTint(charger, vm.filteredConnectors.value),
highlight = true,
fault = charger.faultReport != null
fault = charger.faultReport != null,
multi = getMarkerMulti(charger, vm.filteredConnectors.value)
)
)
animator.animateMarkerBounce(marker)
@@ -444,13 +460,31 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
if (m != marker) {
m.setIcon(
chargerIconGenerator.getBitmapDescriptor(
getMarkerTint(c, vm.filteredConnectors.value), fault = c.faultReport != null
getMarkerTint(c, vm.filteredConnectors.value),
highlight = false,
fault = c.faultReport != null,
multi = getMarkerMulti(c, vm.filteredConnectors.value)
)
)
}
}
}
private fun getMarkerMulti(charger: ChargeLocation, filteredConnectors: Set<String>?): Boolean {
var chargepoints = charger.chargepointsMerged
.filter { filteredConnectors?.contains(it.type) ?: true }
if (charger.maxPower(filteredConnectors) >= 43) {
// fast charger -> only count fast chargers
chargepoints = chargepoints.filter { it.power >= 43 }
}
val connectors = chargepoints.map { it.type }.distinct().toSet()
// check if there is more than one plug for any connector type
val chargepointsPerConnector =
connectors.map { conn -> chargepoints.filter { it.type == conn }.sumBy { it.count } }
return chargepointsPerConnector.any { it > 1 }
}
private fun updateFavoriteToggle() {
val favs = vm.favorites.value ?: return
val charger = vm.chargerSparse.value ?: return
@@ -703,7 +737,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
chargerIconGenerator.getBitmapDescriptor(
getMarkerTint(charger, vm.filteredConnectors.value),
highlight = charger == vm.chargerSparse.value,
fault = charger.faultReport != null
fault = charger.faultReport != null,
multi = getMarkerMulti(charger, vm.filteredConnectors.value)
)
)
}
@@ -720,7 +755,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
val tint = getMarkerTint(charger, vm.filteredConnectors.value)
val highlight = charger == vm.chargerSparse.value
val fault = charger.faultReport != null
animator.animateMarkerDisappear(marker, tint, highlight, fault)
val multi = getMarkerMulti(charger, vm.filteredConnectors.value)
animator.animateMarkerDisappear(marker, tint, highlight, fault, multi)
} else {
animator.deleteMarker(marker)
}
@@ -734,6 +770,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
val tint = getMarkerTint(charger, vm.filteredConnectors.value)
val highlight = charger == vm.chargerSparse.value
val fault = charger.faultReport != null
val multi = getMarkerMulti(charger, vm.filteredConnectors.value)
val marker = map.addMarker(
MarkerOptions()
.position(LatLng(charger.coordinates.lat, charger.coordinates.lng))
@@ -743,12 +780,13 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
0,
255,
highlight,
fault
fault,
multi
)
)
.anchor(0.5f, 1f)
)
animator.animateMarkerAppear(marker, tint, highlight, fault)
animator.animateMarkerAppear(marker, tint, highlight, fault, multi)
markers[marker] = charger
}
}

View File

@@ -71,7 +71,7 @@ class MultiSelectDialog : AppCompatDialogFragment() {
list.layoutManager = LinearLayoutManager(view.context)
items = data.entries.toList()
.sortedBy { it.value }
.sortedBy { it.value.toLowerCase(Locale.getDefault()) }
.sortedByDescending { commonChoices?.contains(it.key) == true }
.map { MultiSelectItem(it.key, it.value, it.key in selected) }
adapter.submitList(items)

View File

@@ -0,0 +1,50 @@
package net.vonforst.evmap.navigation
import android.app.Activity
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.util.AttributeSet
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import androidx.core.content.withStyledAttributes
import androidx.navigation.NavDestination
import androidx.navigation.NavOptions
import androidx.navigation.Navigator
import net.vonforst.evmap.R
@Navigator.Name("chrome")
class ChromeCustomTabsNavigator(
private val context: Context
) : Navigator<ChromeCustomTabsNavigator.Destination>() {
override fun createDestination() =
Destination(this)
override fun navigate(
destination: Destination,
args: Bundle?,
navOptions: NavOptions?,
navigatorExtras: Extras?
): NavDestination? {
val intent = CustomTabsIntent.Builder()
.setToolbarColor(ContextCompat.getColor(context, R.color.colorPrimary))
.build()
intent.launchUrl(context, destination.url!!)
return null // Do not add to the back stack, managed by Chrome Custom Tabs
}
override fun popBackStack() = true // Managed by Chrome Custom Tabs
@NavDestination.ClassType(Activity::class)
class Destination(navigator: Navigator<out NavDestination>) : NavDestination(navigator) {
var url: Uri? = null
override fun onInflate(context: Context, attrs: AttributeSet) {
super.onInflate(context, attrs)
context.withStyledAttributes(attrs, R.styleable.ChromeCustomTabsNavigator, 0, 0) {
url = Uri.parse(getString(R.styleable.ChromeCustomTabsNavigator_url))
}
}
}
}

View File

@@ -0,0 +1,15 @@
package net.vonforst.evmap.navigation
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
class NavHostFragment : NavHostFragment() {
override fun onCreateNavController(navController: NavController) {
super.onCreateNavController(navController)
navController.navigatorProvider.addNavigator(
ChromeCustomTabsNavigator(
requireContext()
)
)
}
}

View File

@@ -47,14 +47,17 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa
val scale: Int,
val alpha: Int,
val highlight: Boolean,
val fault: Boolean
val fault: Boolean,
val multi: Boolean
)
val cacheSize = 420; // 420 items: 21 sizes, 5 colors, highlight on/off, fault on/off
val cacheSize = 840; // 840 items: 21 sizes, 5 colors, highlight, fault, multi on/off
val cache = LruCache<BitmapData, BitmapDescriptor>(cacheSize)
val oversize = 1.4f // increase to add padding for fault icon or scale > 1
val icon = R.drawable.ic_map_marker_charging
val multiIcon = R.drawable.ic_map_marker_charging_multiple
val highlightIcon = R.drawable.ic_map_marker_highlight
val highlightIconMulti = R.drawable.ic_map_marker_charging_highlight_multiple
val faultIcon = R.drawable.ic_map_marker_fault
init {
@@ -72,9 +75,11 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa
)
for (fault in listOf(false, true)) {
for (highlight in listOf(false, true)) {
for (tint in tints) {
for (scale in 0..20) {
getBitmapDescriptor(tint, scale, 255, highlight, fault)
for (multi in listOf(false, true)) {
for (tint in tints) {
for (scale in 0..20) {
getBitmapDescriptor(tint, scale, 255, highlight, fault, multi)
}
}
}
}
@@ -86,9 +91,10 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa
scale: Int = 20,
alpha: Int = 255,
highlight: Boolean = false,
fault: Boolean = false
fault: Boolean = false,
multi: Boolean = false
): BitmapDescriptor? {
val data = BitmapData(tint, scale, alpha, highlight, fault)
val data = BitmapData(tint, scale, alpha, highlight, fault, multi)
val cachedImg = cache[data]
return if (cachedImg != null) {
cachedImg
@@ -101,13 +107,14 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa
}
private fun generateBitmap(data: BitmapData): Bitmap {
val vd: Drawable = context.getDrawable(icon)!!
val icon = if (data.multi) multiIcon else icon
val vd: Drawable = ContextCompat.getDrawable(context, icon)!!
DrawableCompat.setTint(vd, ContextCompat.getColor(context, data.tint));
DrawableCompat.setTintMode(vd, PorterDuff.Mode.MULTIPLY);
val leftPadding = vd.intrinsicWidth * (oversize - 1) / 2
val topPadding = vd.intrinsicWidth * (oversize - 1)
val topPadding = vd.intrinsicHeight * (oversize - 1)
vd.setBounds(
leftPadding.toInt(), topPadding.toInt(),
leftPadding.toInt() + vd.intrinsicWidth,
@@ -132,7 +139,8 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa
vd.draw(canvas)
if (data.highlight) {
val highlightDrawable = context.getDrawable(highlightIcon)!!
val hIcon = if (data.multi) highlightIconMulti else highlightIcon
val highlightDrawable = ContextCompat.getDrawable(context, hIcon)!!
highlightDrawable.setBounds(
leftPadding.toInt(), topPadding.toInt(),
leftPadding.toInt() + vd.intrinsicWidth,
@@ -143,7 +151,7 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa
}
if (data.fault) {
val faultDrawable = context.getDrawable(faultIcon)!!
val faultDrawable = ContextCompat.getDrawable(context, faultIcon)!!
val faultSize = 0.75
val faultShift = 0.25
val base = vd.intrinsicWidth

View File

@@ -28,7 +28,8 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
marker: Marker,
tint: Int,
highlight: Boolean,
fault: Boolean
fault: Boolean,
multi: Boolean
) {
animatingMarkers[marker]?.let {
it.cancel()
@@ -45,7 +46,8 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
tint,
scale = scale,
highlight = highlight,
fault = fault
fault = fault,
multi = multi
)
)
}
@@ -63,7 +65,8 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
marker: Marker,
tint: Int,
highlight: Boolean,
fault: Boolean
fault: Boolean,
multi: Boolean
) {
animatingMarkers[marker]?.let {
it.cancel()
@@ -80,7 +83,8 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
tint,
scale = scale,
highlight = highlight,
fault = fault
fault = fault,
multi = multi
)
)
}

View File

@@ -4,32 +4,40 @@ import android.content.Context
import android.content.ContextWrapper
import android.content.res.Configuration
import android.os.Build
import androidx.core.os.ConfigurationCompat
import java.util.*
class LocaleContextWrapper(base: Context?) : ContextWrapper(base) {
companion object {
fun wrap(context: Context, language: String): ContextWrapper {
val config: Configuration = context.resources.configuration
var sysLocale: Locale? = null
sysLocale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
config.locales.get(0)
} else {
@Suppress("DEPRECATION")
config.locale
}
val sysConfig: Configuration = context.applicationContext.resources.configuration
val appConfig: Configuration = context.resources.configuration
var ctx = context
if (language != "" && language != "default" && sysLocale.language != language) {
if (language == "" || language == "default") {
// set default locale
Locale.setDefault(ConfigurationCompat.getLocales(sysConfig)[0])
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
appConfig.setLocales(sysConfig.locales)
} else {
@Suppress("DEPRECATION")
appConfig.locale = sysConfig.locale
}
} else {
// set selected locale
val locale = Locale(language)
Locale.setDefault(locale)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
config.setLocale(locale)
appConfig.setLocale(locale)
} else {
@Suppress("DEPRECATION")
config.locale = locale
appConfig.locale = locale
}
ctx = context.createConfigurationContext(config)
}
ctx = context.createConfigurationContext(appConfig)
return LocaleContextWrapper(ctx)
}
}

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
</vector>

View File

@@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="44.11976dp"
android:viewportWidth="233.8"
android:viewportHeight="368.4">
<path
android:fillColor="#FFFFFF"
android:fillAlpha="0.8"
android:pathData="M143.2,109.4l-19.7,33.8l0,38.1l43.4,-74.4l-22.2,0z" />
<path
android:fillColor="#FFFFFF"
android:fillAlpha="0.8"
android:pathData="M122.2,101.9h16.7h5.7l22.3,-44.6c0,0 -10.2,0 -22.4,0l-1.1,2.2L122.2,101.9z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M138.9,57.3c-9.7,0 -19.8,0 -26.4,0c-2.5,0 -5.1,0 -7.6,0c-8.2,0 -16.1,0 -21.4,0c-4.1,0 -6.6,0 -6.6,0v68.2h18.6v55.8l43.4,-74.4h-24.8L138.9,57.3z" />
</vector>

View File

@@ -0,0 +1,18 @@
<vector android:height="44.11976dp"
android:viewportHeight="368.4"
android:viewportWidth="233.8"
android:width="28dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="#FFFFFF"
android:pathData="M109.8,0h13.6c33.9,1.9 67.1,18.5 87.7,45.8c13.5,17.2 21,38.6 22.7,60.3v8.1c-0.8,42.1 -27.7,76.6 -51,109.4c-26.2,37 -50.4,77.3 -57.1,122.9c-1.8,7.7 0.4,18.5 -8.9,22c-2.2,-1.7 -4.7,-3.1 -6.2,-5.4c-2.7,-25.5 -9.1,-50.7 -20,-73.9c-12.3,-27.1 -29.5,-51.6 -47,-75.6C33,199 23,184.2 14.7,168.3c-13,-23.8 -17.9,-51.9 -12.5,-78.6C6.6,68.6 17.6,49.1 32.8,34C53.3,14 81.1,1.8 109.8,0z" />
<path
android:fillColor="#B5B5B5"
android:pathData="M143.2,109.4l-19.7,33.8l0,38.1l43.4,-74.4l-22.2,0z" />
<path
android:fillColor="#B5B5B5"
android:pathData="M122.2,101.9h16.7h5.7l22.3,-44.6c0,0 -10.2,0 -22.4,0l-1.1,2.2L122.2,101.9z" />
<path
android:fillColor="#808080"
android:pathData="M138.9,57.3c-9.7,0 -19.8,0 -26.4,0c-2.5,0 -5.1,0 -7.6,0c-8.2,0 -16.1,0 -21.4,0c-4.1,0 -6.6,0 -6.6,0v68.2h18.6v55.8l43.4,-74.4h-24.8L138.9,57.3z" />
</vector>

View File

@@ -7,7 +7,7 @@
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:name="net.vonforst.evmap.navigation.NavHostFragment"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fitsSystemWindows="true"

View File

@@ -139,6 +139,8 @@
android:layout_marginTop="2dp"
android:text="@{charger.data.amenities}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:autoLink="web"
android:linksClickable="true"
app:goneUnless="@{charger.data.amenities != null}"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintHorizontal_bias="0.0"
@@ -167,6 +169,8 @@
android:layout_marginTop="2dp"
android:text="@{charger.data.generalInformation}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:autoLink="web"
android:linksClickable="true"
app:goneUnless="@{charger.data.generalInformation != null}"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintHorizontal_bias="0.0"

View File

@@ -158,8 +158,8 @@
android:layout_gravity="top|end"
android:layout_marginEnd="12dp"
android:layout_marginTop="96dp"
android:tint="?colorControlNormal"
android:elevation="-1dp"
app:tint="?android:colorControlNormal"
app:backgroundTint="?android:colorBackground"
app:borderWidth="0dp"
app:fabSize="mini"

View File

@@ -13,6 +13,14 @@
android:icon="@drawable/ic_fav"
android:title="@string/menu_favs" />
</group>
<group
android:id="@+id/nav_group_links"
android:checkableBehavior="single">
<item
android:id="@+id/report_new_charger"
android:icon="@drawable/ic_add"
android:title="@string/menu_report_new_charger" />
</group>
<group
android:id="@+id/nav_group_settings"
android:checkableBehavior="single">

View File

@@ -63,4 +63,7 @@
android:name="net.vonforst.evmap.fragment.DonateFragment"
android:label="@string/donate"
tools:layout="@layout/fragment_donate" />
<chrome
android:id="@+id/report_new_charger"
app:url="@string/report_new_charger_url" />
</navigation>

View File

@@ -103,6 +103,10 @@
<string name="charge_cards">Ladetarife</string>
<string name="and_n_others">und %d weitere</string>
<string name="pref_map_provider">Kartenanbieter</string>
<string name="twitter">Twitter</string>
<string name="goingelectric_forum">Forenthread bei GoingElectric.de</string>
<string name="contact">Kontakt</string>
<string name="menu_report_new_charger">Ladesäule melden</string>
<plurals name="charge_cards_compatible_num">
<item quantity="one">%d kompatibler Ladetarif</item>
<item quantity="other">%d kompatible Ladetarife</item>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ChromeCustomTabsNavigator">
<attr name="url" format="reference" />
</declare-styleable>
</resources>

View File

@@ -4,4 +4,8 @@
<string name="github_link">https://github.com/johan12345/EVMap</string>
<string name="privacy_link">https://evmap.vonforst.net/privacy.html</string>
<string name="faq_link">https://evmap.vonforst.net/faq.html</string>
<string name="twitter_handle">\@ev_map</string>
<string name="twitter_url">https://twitter.com/ev_map</string>
<string name="goingelectric_forum_url"><![CDATA[https://www.goingelectric.de/forum/viewtopic.php?f=5&t=56342]]></string>
<string name="report_new_charger_url">https://www.goingelectric.de/stromtankstellen/new/</string>
</resources>

View File

@@ -102,6 +102,10 @@
<string name="charge_cards">Payment methods</string>
<string name="and_n_others">and %d others</string>
<string name="pref_map_provider">Map provider</string>
<string name="twitter">Twitter</string>
<string name="goingelectric_forum">Forum thread at GoingElectric.de</string>
<string name="contact">Contact</string>
<string name="menu_report_new_charger">Report new charger</string>
<plurals name="charge_cards_compatible_num">
<item quantity="one">%d compatible payment method</item>
<item quantity="other">%d compatible payment methods</item>

View File

@@ -21,6 +21,18 @@
<Preference
android:key="donate"
android:title="@string/donate" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/contact">
<Preference
android:key="twitter"
android:title="@string/twitter"
android:summary="@string/twitter_handle" />
<Preference
android:key="goingelectric"
android:title="@string/goingelectric_forum" />
</PreferenceCategory>

2
fastlane/Appfile Normal file
View File

@@ -0,0 +1,2 @@
json_key_file("api-7125266970515251116-798419-8e2dda660c80.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
package_name("net.vonforst.evmap") # e.g. com.krausefx.app

38
fastlane/Fastfile Normal file
View File

@@ -0,0 +1,38 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:android)
platform :android do
desc "Runs all the tests"
lane :test do
gradle(task: "test")
end
desc "Submit a new Beta Build to Crashlytics Beta"
lane :beta do
gradle(task: "clean assembleRelease")
crashlytics
# sh "your_script.sh"
# You can also use other beta testing services here
end
desc "Deploy a new version to the Google Play"
lane :deploy do
gradle(task: "clean assembleRelease")
upload_to_play_store
end
end

View File

@@ -0,0 +1,4 @@
Verbesserungen:
- Verändertes Layout für Filter nach Anschluss (bessere Stabilität)
- Absturz bei fehlender Internetverbindung behoben
- Fehlende Übersetzungen eingefügt

View File

@@ -0,0 +1,6 @@
Verbesserungen:
- Sortierung in Filterdialogen unabhängig von Groß- und Kleinschreibung
- Vertikale Position der Marker auf der Karte korrigiert
- Neues Icon für Ladestationen mit mehr als einem Anschluss (bei Schnelladern: mehr als ein schnelladefähiger Anschluss)
- "Über EVMap": Links zu Twitter-Account @ev_map und Thread im GoingElectric-Forum hinzugefügt
- Button "Ladesäule melden" im Hauptmenü hinzugefügt

View File

@@ -0,0 +1,17 @@
Mit EVMap kannst du Stromtankstellen in deiner Nähe komfortabel über dein Android-Smartphone finden. Die Datenbank von GoingElectric.de wird als Datenquelle genutzt und bietet Community-gepflegte Informationen zu mehr als 100.000 Ladepunkten an über 40.000 Standorten in 48 Ländern (die meisten in Europa). Für viele Ladepunkte kann zusätzlich der aktuelle Status (verfügbar oder belegt) angezeigt werden.
Funktionen:
- Zeitgemäßes Material Design
- Anzeige der Stromtankstellen aus dem GoingElectric-Stromtankstellenverzeichnis
- Echtzeit-Verfügbarkeitsanzeige für viele Ladesäulen
- Direkte Links zu Chargeprice.app für einen Preisvergleich für die jeweilige Ladesäule
- Markierung des aktuellen Standorts
- Google Maps-Verkehrsdaten
- Suche nach Orten
- Erweiterte Filterfunktionen
- Favoritenliste, auch mit Anzeige der Verfügbarkeit
- Keine nervige Werbung
EVMap ist ein Open-Source-Projekt und unter https://github.com/johan12345/EVMap zu finden.
Die App ist kein offizielles Angebot von GoingElectric.de, sondern nutzt die öffentliche API dieser Seite.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

View File

@@ -0,0 +1 @@
Finde Elektroauto-Ladestationen in deiner Nähe

View File

@@ -0,0 +1 @@
EVMap - Elektroauto-Ladestationen

View File

View File

@@ -0,0 +1,4 @@
Improvements:
- Different layout for filtering by connector (with better stability)
- Crash fixed when internet is not available
- Added missing German translations

View File

@@ -0,0 +1,6 @@
Improvements:
- Sorting of filter dialogs is case-insensitive
- Vertical positions of map markers fixed
- New icon for chargers with more than one connector (for fast chargers: more than one fast-charging connector)
- "About EVMap": Added links to Twitter account @ev_map and GoingElectric.de forum thread
- Added button "rerport new charger" in main menu

View File

@@ -0,0 +1,2 @@
Crash fixed
Fix wrong position of layers button on devices with camera cutout

View File

@@ -0,0 +1,16 @@
Using EVMap, you can find electric vehicle chargers comfortably using your Android phone. It provides mobile access to the community-driven database from GoingElectric.de, containing more than 100,000 chargepoints at 40,000 locations in 48 countries (focusing on Europe). For many chargepoints, you can see real-time status information.
Features:
- Material Design
- Shows all charging stations from the community-maintained GoingElectric.de directory
- Realtime availability information (beta)
- Direct link to Chargeprice.app for comparing prices
- Marker for current location
- Search places
- Favorites list, also with availability information
- Advanced filtering options
- No ads, fully open source
EVMap is an open source project and can be found at https://github.com/johan12345/EVMap.
This app is not an official product of GoingElectric.de, but only uses its public API.

View File

@@ -0,0 +1 @@
Find electric vehicle charging stations

View File

@@ -0,0 +1 @@
EVMap - Electric vehicle chargers

View File