From 08abddc7fc035921f1e2ee311ac6ae7226a44034 Mon Sep 17 00:00:00 2001 From: Harry Bond Date: Sat, 23 Aug 2025 22:44:42 +0100 Subject: [PATCH] [android] Add support for check_date & check_date:opening_hours Signed-off-by: Harry Bond --- .../widget/placepage/PlacePageView.java | 12 +++++-- .../PlacePageOpeningHoursFragment.java | 21 ++++++++++++- .../main/res/layout/place_page_details.xml | 9 ++++++ .../place_page_opening_hours_fragment.xml | 13 ++++++++ android/app/src/main/res/values/strings.xml | 12 +++++++ .../sdk/bookmarks/data/Metadata.java | 4 ++- .../app/organicmaps/sdk/util/DateUtils.java | 31 +++++++++++++++++++ 7 files changed, 98 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java b/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java index 26832ee96..bd29be8e0 100644 --- a/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java +++ b/android/app/src/main/java/app/organicmaps/widget/placepage/PlacePageView.java @@ -106,7 +106,6 @@ public class PlacePageView extends Fragment Arrays.asList(CoordinatesFormat.LatLonDMS, CoordinatesFormat.LatLonDecimal, CoordinatesFormat.OLCFull, CoordinatesFormat.UTM, CoordinatesFormat.MGRS, CoordinatesFormat.OSMLink); private View mFrame; - private Context mContext; // Preview. private ViewGroup mPreview; @@ -144,6 +143,7 @@ public class PlacePageView extends Fragment private MaterialTextView mTvOutdoorSeating; private View mEntrance; private MaterialTextView mTvEntrance; + private MaterialTextView mTvLastChecked; private View mEditPlace; private View mAddOrganisation; private View mAddPlace; @@ -308,6 +308,7 @@ public class PlacePageView extends Fragment mTvCuisine = mFrame.findViewById(R.id.tv__place_cuisine); mEntrance = mFrame.findViewById(R.id.ll__place_entrance); mTvEntrance = mEntrance.findViewById(R.id.tv__place_entrance); + mTvLastChecked = mFrame.findViewById(R.id.place_page_last_checked); mEditPlace = mFrame.findViewById(R.id.ll__place_editor); mEditPlace.setOnClickListener(this); mAddOrganisation = mFrame.findViewById(R.id.ll__add_organisation); @@ -662,7 +663,14 @@ public class PlacePageView extends Fragment refreshMetadataOrHide(outdoorSeating.equals("yes") ? getString(R.string.outdoor_seating) : "", mOutdoorSeating, mTvOutdoorSeating); - // showTaxiOffer(mapObject); + final String lastChecked = mMapObject.getMetadata(Metadata.MetadataType.FMD_CHECK_DATE); + if (!lastChecked.isEmpty()) + { + String periodSinceCheck = DateUtils.getRelativePeriodString(getResources(), lastChecked); + UiUtils.setTextAndShow(mTvLastChecked, requireContext().getString(R.string.existence_confirmed_time_ago, periodSinceCheck)); + } + else + UiUtils.hide(mTvLastChecked); if (RoutingController.get().isNavigating() || RoutingController.get().isPlanning()) { diff --git a/android/app/src/main/java/app/organicmaps/widget/placepage/sections/PlacePageOpeningHoursFragment.java b/android/app/src/main/java/app/organicmaps/widget/placepage/sections/PlacePageOpeningHoursFragment.java index 4cc4898d3..feba8b7ee 100644 --- a/android/app/src/main/java/app/organicmaps/widget/placepage/sections/PlacePageOpeningHoursFragment.java +++ b/android/app/src/main/java/app/organicmaps/widget/placepage/sections/PlacePageOpeningHoursFragment.java @@ -5,6 +5,7 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -20,6 +21,8 @@ import app.organicmaps.sdk.bookmarks.data.Metadata; import app.organicmaps.sdk.editor.OpeningHours; import app.organicmaps.sdk.editor.data.Timespan; import app.organicmaps.sdk.editor.data.Timetable; +import app.organicmaps.sdk.util.DateUtils; +import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.UiUtils; import app.organicmaps.util.Utils; @@ -36,6 +39,7 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer< private MaterialTextView mTodayOpenTime; private MaterialTextView mTodayNonBusinessTime; private RecyclerView mFullWeekOpeningHours; + private MaterialTextView mLastCheckedDate; private PlaceOpeningHoursAdapter mOpeningHoursAdapter; private PlacePageViewModel mViewModel; @@ -58,10 +62,23 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer< mTodayOpenTime = view.findViewById(R.id.oh_today_open_time); mTodayNonBusinessTime = view.findViewById(R.id.oh_nonbusiness_time); mFullWeekOpeningHours = view.findViewById(R.id.rw__full_opening_hours); + mLastCheckedDate = view.findViewById(R.id.oh_check_date); mOpeningHoursAdapter = new PlaceOpeningHoursAdapter(); mFullWeekOpeningHours.setAdapter(mOpeningHoursAdapter); } + private static void setOrHideLastCheckedDate(MapObject mapObject, Resources resources, TextView checkDateView) + { + final String checkDate = mapObject.getMetadata(Metadata.MetadataType.FMD_CHECK_DATE_OPEN_HOURS); + if (!checkDate.isEmpty()) + { + String periodSinceCheck = DateUtils.getRelativePeriodString(resources, checkDate); + UiUtils.setTextAndShow(checkDateView, resources.getString(R.string.hours_confirmed_time_ago, periodSinceCheck)); + } + else + UiUtils.hide(checkDateView); + } + private void refreshTodayNonBusinessTime(Timespan[] closedTimespans) { final String hoursClosedLabel = getResources().getString(R.string.editor_hours_closed); @@ -102,6 +119,9 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer< final boolean isEmptyTT = (timetables == null || timetables.length == 0); final int color = ThemeUtils.getColor(requireContext(), android.R.attr.textColorPrimary); + final Resources resources = getResources(); + + setOrHideLastCheckedDate(mapObject, resources, mLastCheckedDate); if (isEmptyTT) { @@ -119,7 +139,6 @@ public class PlacePageOpeningHoursFragment extends Fragment implements Observer< else { UiUtils.show(mFrame); - final Resources resources = getResources(); if (timetables[0].isFullWeek()) { final Timetable tt = timetables[0]; diff --git a/android/app/src/main/res/layout/place_page_details.xml b/android/app/src/main/res/layout/place_page_details.xml index 6df9ea63a..a3d1e9e88 100644 --- a/android/app/src/main/res/layout/place_page_details.xml +++ b/android/app/src/main/res/layout/place_page_details.xml @@ -74,6 +74,15 @@ android:layout_width="match_parent" android:layout_height="wrap_content"/> + + diff --git a/android/app/src/main/res/layout/place_page_opening_hours_fragment.xml b/android/app/src/main/res/layout/place_page_opening_hours_fragment.xml index 31031b661..79bac0a53 100644 --- a/android/app/src/main/res/layout/place_page_opening_hours_fragment.xml +++ b/android/app/src/main/res/layout/place_page_opening_hours_fragment.xml @@ -63,4 +63,17 @@ tools:listitem="@layout/place_page_opening_hours_item" android:layout_marginTop="8dp"/> + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index fada3a08f..baf8593c8 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -466,6 +466,18 @@ Opens in %s Closes in %s Closed + + Confirmed %s + + Existence confirmed %s + Yesterday + %s days ago + %s week ago + %s weeks ago + %s month ago + %s months ago + %s year ago + %s years ago Edit business hours Don\'t have an OpenStreetMap account? Register at OpenStreetMap diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java b/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java index 6ba2c3354..84d607478 100644 --- a/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java +++ b/android/sdk/src/main/java/app/organicmaps/sdk/bookmarks/data/Metadata.java @@ -68,7 +68,9 @@ public class Metadata implements Parcelable FMD_NETWORK(49), FMD_CONTACT_FEDIVERSE(50), FMD_CONTACT_BLUESKY(51), - FMD_PANORAMAX(52); + FMD_PANORAMAX(52), + FMD_CHECK_DATE(53), + FMD_CHECK_DATE_OPEN_HOURS(54); private final int mMetaType; MetadataType(int metadataType) diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/util/DateUtils.java b/android/sdk/src/main/java/app/organicmaps/sdk/util/DateUtils.java index 028c9015f..bc445cb63 100644 --- a/android/sdk/src/main/java/app/organicmaps/sdk/util/DateUtils.java +++ b/android/sdk/src/main/java/app/organicmaps/sdk/util/DateUtils.java @@ -1,11 +1,17 @@ package app.organicmaps.sdk.util; import android.content.Context; +import android.content.res.Resources; + import androidx.annotation.Keep; import androidx.annotation.NonNull; import java.text.DateFormat; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.Locale; +import app.organicmaps.R; + public final class DateUtils { private DateUtils() {} @@ -23,4 +29,29 @@ public final class DateUtils { return android.text.format.DateFormat.is24HourFormat(context); } + + /*** + * @param dateString Date string in the yyyy-MM-dd format + * @return Human-readable string of the time that's passed since the date + */ + public static String getRelativePeriodString(Resources resources, String dateString) + { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + int days = (int) (LocalDate.now().toEpochDay() - LocalDate.parse(dateString, formatter).toEpochDay()); + + if (days == 0) + return resources.getString(R.string.today); + if (days == 1) + return resources.getString(R.string.yesterday); + if (days < 7) + return resources.getString(R.string.days_ago, Integer.toString(days)); + if (days < 30) + return resources.getString(days < 14 ? R.string.week_ago : R.string.weeks_ago, Integer.toString(days / 7)); + if (days < 365) + return resources.getString(days < 60 ? R.string.month_ago : R.string.months_ago, Integer.toString(days / 30)); + if (days > 365) + return resources.getString(days < 730 ? R.string.year_ago : R.string.years_ago, Integer.toString(days / 365)); + else + return ""; + } }