diff --git a/OsmAnd-telegram/AndroidManifest.xml b/OsmAnd-telegram/AndroidManifest.xml index 73e2e856ca..4e8ab332dc 100644 --- a/OsmAnd-telegram/AndroidManifest.xml +++ b/OsmAnd-telegram/AndroidManifest.xml @@ -19,7 +19,10 @@ android:launchMode="singleTask" android:screenOrientation="unspecified" android:supportsRtl="true" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" + android:hasFragileUserData="true" + android:requestLegacyExternalStorage="true"> + - - service.serviceErrorInterval && handler != null) { - handler.postDelayed({ - // if lock is not anymore held - if (lock.isHeld) { - lock.release() - locationManager.removeUpdates(service) - } - }, service.serviceErrorInterval) - } - } catch (e: RuntimeException) { - e.printStackTrace() - } - } -} \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramApplication.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramApplication.kt index b6927dc610..b9fcb3112d 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramApplication.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramApplication.kt @@ -8,12 +8,13 @@ import android.net.ConnectivityManager import android.net.NetworkInfo import android.os.Build import android.os.Handler +import androidx.core.content.ContextCompat import net.osmand.PlatformUtil -import net.osmand.telegram.ui.TrackerLogcatActivity import net.osmand.telegram.helpers.* import net.osmand.telegram.helpers.OsmandAidlHelper.OsmandHelperListener import net.osmand.telegram.helpers.OsmandAidlHelper.UpdatesListener import net.osmand.telegram.notifications.NotificationHelper +import net.osmand.telegram.ui.TrackerLogcatActivity import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.UiUtils import java.io.File @@ -146,35 +147,21 @@ class TelegramApplication : Application() { return internetConnectionAvailable } - private fun startTelegramService(intent: Int, serviceOffInterval: Long = 0) { + private fun startTelegramService(intent: Int) { var i = intent - var interval = serviceOffInterval val serviceIntent = Intent(this, TelegramService::class.java) - val telegramService = telegramService if (telegramService != null) { i = intent or telegramService.usedBy - interval = if (TelegramService.isOffIntervalDepended(intent)) { - Math.min(telegramService.serviceOffInterval, interval) - } else { - telegramService.serviceOffInterval - } telegramService.stopSelf() } - serviceIntent.putExtra(TelegramService.USAGE_INTENT, i) - serviceIntent.putExtra(TelegramService.USAGE_OFF_INTERVAL, interval) serviceIntent.putExtra(TelegramService.SEND_LOCATION_INTERVAL, settings.sendMyLocInterval) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(serviceIntent) - } else { - startService(serviceIntent) - } + ContextCompat.startForegroundService(this, serviceIntent) } fun startMyLocationService() { - val interval = settings.sendMyLocInterval - startTelegramService(TelegramService.USED_BY_MY_LOCATION, TelegramService.normalizeOffInterval(interval)) + startTelegramService(TelegramService.USED_BY_MY_LOCATION) } fun stopMyLocationService() { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramLocationProvider.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramLocationProvider.kt index d0f283df01..71611f7cf3 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramLocationProvider.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramLocationProvider.kt @@ -166,7 +166,7 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve registerOrUnregisterCompassListener(true) } - fun redownloadAGPS() { + private fun redownloadAGPS() { try { val service = app.getSystemService(Context.LOCATION_SERVICE) as LocationManager service.sendExtraCommand(LocationManager.GPS_PROVIDER, "delete_aiding_data", null) diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt index ee05034cb7..29503dfa27 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt @@ -1,16 +1,14 @@ package net.osmand.telegram import android.annotation.SuppressLint -import android.app.AlarmManager -import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent +import android.content.pm.ServiceInfo import android.location.Location import android.location.LocationListener import android.location.LocationManager import android.os.* -import android.util.Log import android.widget.Toast import net.osmand.PlatformUtil import net.osmand.telegram.TelegramSettings.ShareChatInfo @@ -26,7 +24,7 @@ private const val UPDATE_LIVE_MESSAGES_INTERVAL_MS = 10000L // 10 sec private const val UPDATE_LIVE_TRACKS_INTERVAL_MS = 30000L // 30 sec class TelegramService : Service(), LocationListener, TelegramIncomingMessagesListener, - TelegramOutgoingMessagesListener { + TelegramOutgoingMessagesListener { private val log = PlatformUtil.getLog(TelegramService::class.java) @@ -43,21 +41,14 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis private var updateWidgetHandler: Handler? = null private var updateWidgetThread = HandlerThread("WidgetUpdateServiceThread") - var handler: Handler? = null - private set var usedBy = 0 private set var serviceOffProvider: String = LocationManager.GPS_PROVIDER private set - var serviceOffInterval = 0L - private set - var serviceErrorInterval = 0L - private set var sendLocationInterval = 0L private set private var lastLocationSentTime = 0L - private var pendingIntent: PendingIntent? = null class LocationServiceBinder : Binder() @@ -71,7 +62,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis updateWidgetHandler = Handler(updateWidgetThread.looper) } - override fun onBind(intent: Intent): IBinder? { + override fun onBind(intent: Intent): IBinder { return binder } @@ -86,13 +77,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis ctx.stopService(serviceIntent) } isUsedByMyLocation(usedBy) -> { - val app = app() - if (app.settings.sendMyLocInterval >= OFF_INTERVAL_THRESHOLD && serviceOffInterval == 0L) { - serviceOffInterval = app.settings.sendMyLocInterval - setupServiceErrorInterval() - setupAlarm() - } - app.notificationHelper.refreshNotification(NotificationType.LOCATION) + app().notificationHelper.refreshNotification(NotificationType.LOCATION) } isUsedByUsersLocations(usedBy) -> removeLocationUpdates() } @@ -100,19 +85,21 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { val app = app() - handler = Handler() val usageIntent = intent.getIntExtra(USAGE_INTENT, 0) usedBy = usageIntent or usedBy - serviceOffInterval = intent.getLongExtra(USAGE_OFF_INTERVAL, 0) sendLocationInterval = intent.getLongExtra(SEND_LOCATION_INTERVAL, 0) - setupServiceErrorInterval() app.telegramHelper.addIncomingMessagesListener(this) app.telegramHelper.addOutgoingMessagesListener(this) app.telegramService = this + val locationNotification = app.notificationHelper.locationNotification + val notification = app.notificationHelper.buildNotification(locationNotification) + startForeground(locationNotification.telegramNotificationId, notification) + app.notificationHelper.refreshNotification(locationNotification.type) + if (isUsedByMyLocation(usedBy)) { initLocationUpdates() startShareInfoUpdates() @@ -124,21 +111,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis } app.shareLocationHelper.checkAndSendBufferMessages() - val locationNotification = app.notificationHelper.locationNotification - val notification = app.notificationHelper.buildNotification(locationNotification) - startForeground(locationNotification.telegramNotificationId, notification) - app.notificationHelper.refreshNotification(locationNotification.type) - return Service.START_REDELIVER_INTENT - } - - private fun setupServiceErrorInterval() { - serviceErrorInterval = serviceOffInterval / 5 - // 1. not more than 12 mins - serviceErrorInterval = Math.min(serviceErrorInterval, 12 * 60 * 1000) - // 2. not less than 30 seconds - serviceErrorInterval = Math.max(serviceErrorInterval, 30 * 1000) - // 3. not more than serviceOffInterval - serviceErrorInterval = Math.min(serviceErrorInterval, serviceOffInterval) + return START_REDELIVER_INTENT } override fun onDestroy() { @@ -158,13 +131,6 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis removeLocationUpdates() - if (!isContinuous()) { - val lock = getLock(this) - if (lock.isHeld) { - lock.release() - } - } - if (shouldCleanupResources) { app.cleanupResources() } @@ -176,7 +142,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis fun updateSendLocationInterval(newInterval: Long) { sendLocationInterval = newInterval } - + fun forceLocationUpdate() { val location = getFirstTimeRunDefaultLocation() app().shareLocationHelper.updateLocation(location) @@ -186,21 +152,16 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis val firstLocation = getFirstTimeRunDefaultLocation() app().shareLocationHelper.updateLocation(firstLocation) - // requesting - if (isContinuous()) { - // request location updates - val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager - try { - locationManager.requestLocationUpdates(serviceOffProvider, 0, 0f, this@TelegramService) - } catch (e: SecurityException) { - Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show() - Log.d(PlatformUtil.TAG, "Location service permission not granted") //$NON-NLS-1$ - } catch (e: IllegalArgumentException) { - Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show() - Log.d(PlatformUtil.TAG, "GPS location provider not available") //$NON-NLS-1$ - } - } else { - setupAlarm() + // request location updates + val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager + try { + locationManager.requestLocationUpdates(serviceOffProvider, 0, 0f, this@TelegramService) + } catch (e: SecurityException) { + Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show() + log.debug("Location service permission not granted") + } catch (e: IllegalArgumentException) { + Toast.makeText(this, R.string.gps_not_available, Toast.LENGTH_LONG).show() + log.debug("GPS location provider not available") } } @@ -254,7 +215,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis startWidgetUpdates() }, UPDATE_WIDGET_INTERVAL_MS) } - + @SuppressLint("MissingPermission") private fun getFirstTimeRunDefaultLocation(): net.osmand.Location? { val app = app() @@ -282,43 +243,19 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis return location } - private fun setupAlarm() { - val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager - pendingIntent = PendingIntent.getBroadcast(this, 0, Intent(this, OnTelegramServiceAlarmReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT) - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 500, serviceOffInterval, pendingIntent) - } - private fun removeLocationUpdates() { // remove updates val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager try { locationManager.removeUpdates(this) } catch (e: SecurityException) { - Log.d(PlatformUtil.TAG, "Location service permission not granted") + log.debug("Location service permission not granted") } } - private fun isContinuous(): Boolean { - return serviceOffInterval == 0L - } - override fun onLocationChanged(l: Location?) { val location = convertLocation(l) - if (!isContinuous()) { - // unregister listener and wait next time - val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager - try { - locationManager.removeUpdates(this) - } catch (e: Throwable) { - Log.d(PlatformUtil.TAG, "Location service permission not granted") //$NON-NLS-1$ - } - - val lock = getLock(this) - if (lock.isHeld) { - lock.release() - } - app().shareLocationHelper.updateLocation(location) - } else if (System.currentTimeMillis() - lastLocationSentTime > sendLocationInterval * 1000) { + if (System.currentTimeMillis() - lastLocationSentTime > sendLocationInterval * 1000) { lastLocationSentTime = System.currentTimeMillis() app().shareLocationHelper.updateLocation(location) } @@ -373,7 +310,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis } override fun onSendLiveLocationError(code: Int, message: String, shareInfo: ShareChatInfo, messageType: Int) { - Log.d(PlatformUtil.TAG, "Send live location error: $code - $message") + log.debug("Send live location error: $code - $message") when (messageType) { TelegramHelper.MESSAGE_TYPE_TEXT -> shareInfo.pendingTdLibText-- TelegramHelper.MESSAGE_TYPE_MAP -> { @@ -388,26 +325,8 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis const val USED_BY_MY_LOCATION: Int = 1 const val USED_BY_USERS_LOCATIONS: Int = 2 const val USAGE_INTENT = "SERVICE_USED_BY" - const val USAGE_OFF_INTERVAL = "SERVICE_OFF_INTERVAL" const val SEND_LOCATION_INTERVAL = "SEND_LOCATION_INTERVAL" - const val OFF_INTERVAL_THRESHOLD: Long = 30000L - - private var lockStatic: PowerManager.WakeLock? = null - - @Synchronized - fun getLock(context: Context): PowerManager.WakeLock { - var lockStatic = lockStatic - return if (lockStatic == null) { - val mgr = context.getSystemService(Context.POWER_SERVICE) as PowerManager - lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "OsmandServiceLock") - this.lockStatic = lockStatic - lockStatic - } else { - lockStatic - } - } - fun isUsedByMyLocation(usedBy: Int): Boolean { return (usedBy and USED_BY_MY_LOCATION) > 0 } @@ -416,14 +335,6 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis return (usedBy and USED_BY_USERS_LOCATIONS) > 0 } - fun isOffIntervalDepended(usedBy: Int): Boolean { - return isUsedByMyLocation(usedBy) - } - - fun normalizeOffInterval(interval: Long): Long { - return if (interval < OFF_INTERVAL_THRESHOLD) 0 else interval - } - fun convertLocation(l: Location?): net.osmand.Location? { if (l == null) { return null diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt index fee5d83151..7d87ce3b1d 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt @@ -21,7 +21,6 @@ import android.widget.* import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.google.android.material.appbar.AppBarLayout import net.osmand.PlatformUtil import net.osmand.telegram.* @@ -42,7 +41,7 @@ private const val SUGGESTED = 2 private const val SHARE_LOCATION_CHAT = 1 private const val DEFAULT_CHAT = 0 -private const val ADAPTER_UPDATE_INTERVAL_MIL = 5 * 1000L // 5 sec +private const val ADAPTER_UPDATE_INTERVAL_MS = 5 * 1000L // 5 sec class MyLocationTabFragment : Fragment(), TelegramListener { @@ -380,7 +379,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener { updateContent() startHandler() } - }, ADAPTER_UPDATE_INTERVAL_MIL) + }, ADAPTER_UPDATE_INTERVAL_MS) } private fun animateStartSharingBtn(show: Boolean) { diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index 3b49991789..610cf4435a 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -4049,6 +4049,6 @@ Automóvil Error, vuelve a comprobar los parámetros Copiar dirección - Motor de ruta en línea + Motor de navegación en línea Motores de navegación en línea \ No newline at end of file diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index 59bc5514c9..4af14aab63 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -4005,4 +4005,14 @@ Последний раз использовалось Разрешить прерывистые водные пути Разрешить прерывистые водные пути + • Добавлена возможность экспорта и импорта всех данных, включая настройки, ресурсы, мои места. +\n +\n• Планирование маршрута: графики для сегментов трека с маршрутом, добавлена возможность создавать и редактировать несколько сегментов трека. +\n +\n• Добавлен OAuth метод аутентификации для OpenStreetMap, улучшен интерфейс диалоговых OSM. +\n +\n • Поддержка пользовательских цветов для избранного и путевых точек трека. +\n +\n + Скопировать адрес \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java index 1a107eb61b..0d097eabfb 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java @@ -93,18 +93,20 @@ public class AmenityMenuBuilder extends MenuBuilder { protected void buildNearestPoiRow(View view) { } - private void buildRow(View view, int iconId, String text, String textPrefix, + private void buildRow(View view, int iconId, String text, String textPrefix, String socialMediaUrl, boolean collapsable, final CollapsableView collapsableView, int textColor, boolean isWiki, boolean isText, boolean needLinks, boolean isPhoneNumber, boolean isUrl, boolean matchWidthDivider, int textLinesLimit) { - buildRow(view, iconId == 0 ? null : getRowIcon(iconId), text, textPrefix, collapsable, collapsableView, textColor, + buildRow(view, iconId == 0 ? null : getRowIcon(iconId), text, textPrefix, socialMediaUrl, + collapsable, collapsableView, textColor, isWiki, isText, needLinks, isPhoneNumber, isUrl, matchWidthDivider, textLinesLimit); } protected void buildRow(final View view, Drawable icon, final String text, final String textPrefix, - boolean collapsable, final CollapsableView collapsableView, - int textColor, boolean isWiki, boolean isText, boolean needLinks, - boolean isPhoneNumber, boolean isUrl, boolean matchWidthDivider, int textLinesLimit) { + final String socialMediaUrl, boolean collapsable, + final CollapsableView collapsableView, int textColor, boolean isWiki, + boolean isText, boolean needLinks, boolean isPhoneNumber, boolean isUrl, + boolean matchWidthDivider, int textLinesLimit) { if (!isFirstRow()) { buildRowDivider(view); @@ -312,8 +314,9 @@ public class AmenityMenuBuilder extends MenuBuilder { WikipediaArticleWikiLinkFragment.showInstance(mapActivity.getSupportFragmentManager(), text); } } else { + String uri = socialMediaUrl == null ? text : socialMediaUrl; Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(text)); + intent.setData(Uri.parse(uri)); v.getContext().startActivity(intent); } } @@ -366,6 +369,7 @@ public class AmenityMenuBuilder extends MenuBuilder { continue; } + String socialMediaUrl = null; String textPrefix = ""; CollapsableView collapsableView = null; boolean collapsable = false; @@ -397,6 +401,11 @@ public class AmenityMenuBuilder extends MenuBuilder { if (vl.startsWith("http://") || vl.startsWith("https://") || vl.startsWith("HTTP://") || vl.startsWith("HTTPS://")) { isUrl = true; + } else { + socialMediaUrl = getSocialMediaUrl(key, vl); + if (socialMediaUrl != null) { + isUrl = true; + } } if (pType != null && !pType.isText()) { @@ -557,16 +566,16 @@ public class AmenityMenuBuilder extends MenuBuilder { AmenityInfoRow row; if (isDescription) { row = new AmenityInfoRow(key, R.drawable.ic_action_note_dark, textPrefix, - vl, collapsable, collapsableView, 0, false, true, - true, 0, "", false, false, matchWidthDivider, 0); + vl, null, collapsable, collapsableView, 0, false, + true, true, 0, "", false, false, matchWidthDivider, 0); } else if (icon != null) { - row = new AmenityInfoRow(key, icon, textPrefix, vl, collapsable, collapsableView, - textColor, isWiki, isText, needLinks, poiTypeOrder, poiTypeKeyName, - isPhoneNumber, isUrl, matchWidthDivider, 0); + row = new AmenityInfoRow(key, icon, textPrefix, vl, socialMediaUrl, collapsable, + collapsableView, textColor, isWiki, isText, needLinks, poiTypeOrder, + poiTypeKeyName, isPhoneNumber, isUrl, matchWidthDivider, 0); } else { - row = new AmenityInfoRow(key, iconId, textPrefix, vl, collapsable, collapsableView, - textColor, isWiki, isText, needLinks, poiTypeOrder, poiTypeKeyName, - isPhoneNumber, isUrl, matchWidthDivider, 0); + row = new AmenityInfoRow(key, iconId, textPrefix, vl, socialMediaUrl, collapsable, + collapsableView, textColor, isWiki, isText, needLinks, poiTypeOrder, + poiTypeKeyName, isPhoneNumber, isUrl, matchWidthDivider, 0); } if (isDescription) { descriptions.add(row); @@ -613,8 +622,11 @@ public class AmenityMenuBuilder extends MenuBuilder { } boolean cuisineOrDish = categoryName.equals(Amenity.CUISINE) || categoryName.equals(Amenity.DISH); CollapsableView collapsableView = getPoiTypeCollapsableView(view.getContext(), true, categoryTypes, true, cuisineOrDish ? cuisineRow : null); - infoRows.add(new AmenityInfoRow(poiAdditionalCategoryName, icon, pType.getPoiAdditionalCategoryTranslation(), sb.toString(), true, collapsableView, - 0, false, false, false, pType.getOrder(), pType.getKeyName(), false, false, false, 1)); + infoRows.add(new AmenityInfoRow(poiAdditionalCategoryName, icon, + pType.getPoiAdditionalCategoryTranslation(), sb.toString(), null, + true, collapsableView, 0, false, false, + false, pType.getOrder(), pType.getKeyName(), false, + false, false, 1)); } } @@ -629,8 +641,10 @@ public class AmenityMenuBuilder extends MenuBuilder { } sb.append(pt.getTranslation()); } - infoRows.add(new AmenityInfoRow(poiCategory.getKeyName(), icon, poiCategory.getTranslation(), sb.toString(), true, collapsableView, - 0, false, false, false, 40, poiCategory.getKeyName(), false, false, false, 1)); + infoRows.add(new AmenityInfoRow(poiCategory.getKeyName(), icon, + poiCategory.getTranslation(), sb.toString(), null, true, + collapsableView, 0, false, false, false, 40, + poiCategory.getKeyName(), false, false, false, 1)); } Collections.sort(infoRows, new Comparator() { @@ -670,7 +684,8 @@ public class AmenityMenuBuilder extends MenuBuilder { if (processNearestWiki() && nearestWiki.size() > 0) { AmenityInfoRow wikiInfo = new AmenityInfoRow( - "nearest_wiki", R.drawable.ic_plugin_wikipedia, null, app.getString(R.string.wiki_around) + " (" + nearestWiki.size() + ")", true, + "nearest_wiki", R.drawable.ic_plugin_wikipedia, null, app.getString(R.string.wiki_around) + " (" + nearestWiki.size() + ")", + null, true, getCollapsableView(view.getContext(), true, nearestWiki), 0, false, false, false, 1000, null, false, false, false, 0); buildAmenityRow(view, wikiInfo); @@ -678,8 +693,8 @@ public class AmenityMenuBuilder extends MenuBuilder { if (processNearestPoi() && nearestPoi.size() > 0) { AmenityInfoRow poiInfo = new AmenityInfoRow( - "nearest_poi", AmenityMenuController.getRightIconId(amenity), null, - app.getString(R.string.speak_poi) + " \"" + AmenityMenuController.getTypeStr(amenity) + "\" (" + nearestPoi.size() + ")", true, + "nearest_poi", AmenityMenuController.getRightIconId(amenity), null, app.getString(R.string.speak_poi) + " (" + nearestPoi.size() + ")", + null, true, getCollapsableView(view.getContext(), true, nearestPoi), 0, false, false, false, 1000, null, false, false, false, 0); buildAmenityRow(view, poiInfo); @@ -784,12 +799,14 @@ public class AmenityMenuBuilder extends MenuBuilder { public void buildAmenityRow(View view, AmenityInfoRow info) { if (info.icon != null) { - buildRow(view, info.icon, info.text, info.textPrefix, info.collapsable, info.collapsableView, - info.textColor, info.isWiki, info.isText, info.needLinks, info.isPhoneNumber, + buildRow(view, info.icon, info.text, info.textPrefix, info.socialMediaUrl, + info.collapsable, info.collapsableView, info.textColor, info.isWiki, info.isText, + info.needLinks, info.isPhoneNumber, info.isUrl, info.matchWidthDivider, info.textLinesLimit); } else { - buildRow(view, info.iconId, info.text, info.textPrefix, info.collapsable, info.collapsableView, - info.textColor, info.isWiki, info.isText, info.needLinks, info.isPhoneNumber, + buildRow(view, info.iconId, info.text, info.textPrefix, info.socialMediaUrl, + info.collapsable, info.collapsableView, info.textColor, info.isWiki, info.isText, + info.needLinks, info.isPhoneNumber, info.isUrl, info.matchWidthDivider, info.textLinesLimit); } } @@ -893,12 +910,45 @@ public class AmenityMenuBuilder extends MenuBuilder { return new CollapsableView(view, this, collapsed); } + private String getSocialMediaUrl(String key, String value) { + // Remove leading and closing slashes + StringBuilder sb = new StringBuilder(value.trim()); + if (sb.charAt(0) == '/') { + sb.deleteCharAt(0); + } + int lastIdx = sb.length() - 1; + if (sb.charAt(lastIdx) == '/') { + sb.deleteCharAt(lastIdx); + } + + // It cannot be username + if (sb.indexOf("/") != -1) { + return "https://" + value; + } + + Map urls = new HashMap<>(7); + urls.put("facebook", "https://facebook.com/%s"); + urls.put("vk", "https://vk.com/%s"); + urls.put("instagram", "https://instagram.com/%s"); + urls.put("twitter", "https://twitter.com/%s"); + urls.put("ok", "https://ok.ru/%s"); + urls.put("telegram", "https://t.me/%s"); + urls.put("flickr", "https://flickr.com/%s"); + + if (urls.containsKey(key)) { + return String.format(urls.get(key), value); + } else { + return null; + } + } + private static class AmenityInfoRow { private String key; private Drawable icon; private int iconId; private String textPrefix; private String text; + private String socialMediaUrl; private CollapsableView collapsableView; private boolean collapsable; private int textColor; @@ -913,14 +963,16 @@ public class AmenityMenuBuilder extends MenuBuilder { private int textLinesLimit; public AmenityInfoRow(String key, Drawable icon, String textPrefix, String text, - boolean collapsable, CollapsableView collapsableView, - int textColor, boolean isWiki, boolean isText, boolean needLinks, - int order, String name, boolean isPhoneNumber, boolean isUrl, + String socialMediaUrl, boolean collapsable, + CollapsableView collapsableView, int textColor, boolean isWiki, + boolean isText, boolean needLinks, int order, String name, + boolean isPhoneNumber, boolean isUrl, boolean matchWidthDivider, int textLinesLimit) { this.key = key; this.icon = icon; this.textPrefix = textPrefix; this.text = text; + this.socialMediaUrl = socialMediaUrl; this.collapsable = collapsable; this.collapsableView = collapsableView; this.textColor = textColor; @@ -936,14 +988,16 @@ public class AmenityMenuBuilder extends MenuBuilder { } public AmenityInfoRow(String key, int iconId, String textPrefix, String text, - boolean collapsable, CollapsableView collapsableView, - int textColor, boolean isWiki, boolean isText, boolean needLinks, - int order, String name, boolean isPhoneNumber, boolean isUrl, + String socialMediaUrl, boolean collapsable, + CollapsableView collapsableView, int textColor, boolean isWiki, + boolean isText, boolean needLinks, int order, String name, + boolean isPhoneNumber, boolean isUrl, boolean matchWidthDivider, int textLinesLimit) { this.key = key; this.iconId = iconId; this.textPrefix = textPrefix; this.text = text; + this.socialMediaUrl = socialMediaUrl; this.collapsable = collapsable; this.collapsableView = collapsableView; this.textColor = textColor;