Bimba.git

commit 27d3f584a603ed80f82a34db6c1e48352cbf1fda

Author: Adam Evyčędo <git@apiote.xyz>

add landscape layout to journey searching

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt
index d70dc1c6f78dde7051b5797e069dd7b5dc29c6e0..2f9db1a9daa4e9aa6d4126759e6a47710a0d0450 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/journey/JourneyFragment.kt
@@ -6,6 +6,7 @@ package xyz.apiote.bimba.czwek.dashboard.ui.journey
 
 import android.annotation.SuppressLint
 import android.content.Context
+import android.content.res.Configuration
 import android.graphics.RectF
 import android.graphics.drawable.LayerDrawable
 import android.location.Location
@@ -89,8 +90,6 @@ 		savedInstanceState: Bundle?
 	): View {
 		viewModel = ViewModelProvider(this)[JourneyViewModel::class.java]
 
-		// TODO separate layout: two columns for horizontal
-
 		_binding = FragmentJourneyBinding.inflate(inflater, container, false)
 		val root: View = binding.root
 
@@ -102,8 +101,16 @@
 		dashboard.viewModel.suggestions[DashboardViewModel.ORIGIN_KEY] = binding.originSuggestions
 		dashboard.viewModel.suggestions[DashboardViewModel.DEST_KEY] = binding.destinationSuggestions
 
+		// TODO test upside down
 		ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
 			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+
+			binding.chipsParamsTime.updateLayoutParams<ViewGroup.MarginLayoutParams> {
+				if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+					topMargin = insets.top + dpToPixelI(16f)
+				}
+			}
+
 			binding.originInput.updatePadding(left = insets.left, right = insets.right)
 			binding.originInput.updateLayoutParams<ViewGroup.MarginLayoutParams> {
 				topMargin = insets.top + dpToPixelI(16f)




diff --git a/app/src/main/res/layout-land/fragment_journey.xml b/app/src/main/res/layout-land/fragment_journey.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6d61f4ad266345f85b9bd2dc53b958c0531b3902
--- /dev/null
+++ b/app/src/main/res/layout-land/fragment_journey.xml
@@ -0,0 +1,369 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+SPDX-FileCopyrightText: Adam Evyčędo
+
+SPDX-License-Identifier: GPL-3.0-or-later
+-->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	tool:context="xyz.apiote.bimba.czwek.dashboard.ui.journey.JourneyFragment">
+
+	<androidx.constraintlayout.widget.Guideline
+		android:id="@+id/middle"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:orientation="vertical"
+		app:layout_constraintGuide_percent=".5" />
+
+	<com.google.android.material.textfield.TextInputLayout
+		android:id="@+id/origin_input"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginLeft="16dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginRight="16dp"
+		android:hint="@string/origin_input_hint"
+		app:layout_constraintEnd_toEndOf="@+id/middle"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		app:startIconDrawable="@drawable/origin">
+
+		<com.google.android.material.textfield.TextInputEditText
+			android:id="@+id/origin"
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content"
+			android:imeOptions="actionSearch"
+			android:inputType="text" />
+	</com.google.android.material.textfield.TextInputLayout>
+
+	<com.google.android.material.chip.ChipGroup
+		android:id="@+id/origin_suggestions"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginLeft="16dp"
+		android:layout_marginTop="4dp"
+		android:layout_marginRight="16dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@id/origin_input" />
+
+	<!--  via
+				required: false
+					List of via stops to visit (only stop IDs, no coordinates allowed for now).
+					maxItems: 2
+
+				viaMinimumStay
+				required: false
+					Optional. If not set, the default is `0,0` - no stay required.
+					For each `via` stop a minimum stay duration in minutes.
+
+					The value `0` signals that it's allowed to stay in the same trip.
+					This enables via stays without counting a transfer and can lead
+					to better connections with less transfers. Transfer connections can
+					still be found with `viaMinimumStay=0`.
+					default: [ 0, 0 ]
+					type: array
+					maxItems: 2
+				-->
+
+	<com.google.android.material.textfield.TextInputLayout
+		android:id="@+id/destination_input"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginLeft="16dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginRight="16dp"
+		android:hint="@string/destination_input_hint"
+		app:layout_constraintEnd_toEndOf="@id/middle"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@id/origin_suggestions"
+		app:startIconDrawable="@drawable/destination">
+
+		<com.google.android.material.textfield.TextInputEditText
+			android:id="@+id/destination"
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content"
+			android:imeOptions="actionSearch"
+			android:inputType="text" />
+	</com.google.android.material.textfield.TextInputLayout>
+
+	<com.google.android.material.chip.ChipGroup
+		android:id="@+id/destination_suggestions"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginLeft="16dp"
+		android:layout_marginTop="4dp"
+		android:layout_marginRight="16dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@id/destination_input" />
+
+
+	<com.google.android.material.chip.ChipGroup
+		android:id="@+id/chips_params_time"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="16dp"
+		android:paddingStart="16dp"
+		android:paddingEnd="16dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="@id/middle"
+		app:layout_constraintTop_toTopOf="parent">
+
+		<com.google.android.material.chip.Chip
+			android:id="@+id/chip_time_reference"
+			style="@style/Widget.Material3.Chip.Filter"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:checkable="false"
+			android:text="@string/depart_after"
+			app:checkedIconEnabled="false"
+			app:closeIcon="@drawable/dropdown"
+			app:closeIconEnabled="true"
+			tool:ignore="MissingConstraints" />
+
+		<com.google.android.material.chip.Chip
+			android:id="@+id/chip_date"
+			style="@style/Widget.Material3.Chip.Filter"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:checkable="false"
+			android:text="@string/today"
+			app:checkedIconEnabled="false"
+			app:closeIcon="@drawable/dropdown"
+			app:closeIconEnabled="true"
+			tool:ignore="MissingConstraints" />
+
+		<com.google.android.material.chip.Chip
+			android:id="@+id/chip_time"
+			style="@style/Widget.Material3.Chip.Filter"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:checkable="false"
+			android:text="@string/now"
+			app:checkedIconEnabled="false"
+			app:closeIcon="@drawable/dropdown"
+			app:closeIconEnabled="true"
+			tool:ignore="MissingConstraints" />
+
+	</com.google.android.material.chip.ChipGroup>
+
+	<com.google.android.material.chip.ChipGroup
+		android:id="@+id/chips_params_accessible"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="8dp"
+		android:paddingStart="16dp"
+		android:paddingEnd="16dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="@id/middle"
+		app:layout_constraintTop_toBottomOf="@id/chips_params_time">
+
+		<com.google.android.material.chip.Chip
+			android:id="@+id/chip_wheelchair"
+			style="@style/Widget.Material3.Chip.Filter"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:text="@string/wheelchair_accessible"
+			app:chipIcon="@drawable/wheelchair"
+			app:chipIconEnabled="true"
+			tool:ignore="MissingConstraints" />
+
+		<com.google.android.material.chip.Chip
+			android:id="@+id/chip_bike"
+			style="@style/Widget.Material3.Chip.Filter"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:text="@string/bike_transport"
+			app:chipIcon="@drawable/bike"
+			app:chipIconEnabled="true"
+			tool:ignore="MissingConstraints" />
+
+		<!--<com.google.android.material.chip.Chip
+			android:id="@+id/chip_options"
+			style="@style/Widget.Material3.Chip.Filter"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:text="@string/other_options"
+			app:chipIcon="@drawable/options"
+			app:chipIconEnabled="true"
+			tool:ignore="MissingConstraints" />-->
+
+	</com.google.android.material.chip.ChipGroup>
+
+	<Button
+		android:id="@+id/goButton"
+		style="@style/Widget.Material3.Button.Icon"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_margin="16dp"
+		android:text="@string/go"
+		app:icon="@drawable/journey_outline"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="@id/middle" />
+
+	<!--
+			- name: maxTransfers
+				required: false
+					The maximum number of allowed transfers.
+					If not provided, the routing uses the server-side default value
+					which is hardcoded and very high to cover all use cases.
+				schema:
+					type: integer
+
+			- name: maxHours
+				required: false
+					The maximum travel time in hours.
+					If not provided, the routing to uses the value
+					hardcoded in the server which is usually quite high.
+				schema:
+					type: number
+
+			- name: minTransferTime
+				required: false
+					Minimum transfer time for each transfer in minutes.
+				schema:
+					type: integer
+					default: 0
+
+			- name: additionalTransferTime
+				required: false
+					Additional transfer time reserved for each transfer in minutes.
+				schema:
+					type: integer
+					default: 0
+
+			- name: transferTimeFactor
+				required: false
+					Factor to multiply minimum required transfer times with.
+					Values smaller than 1.0 are not supported.
+				schema:
+					type: number
+					default: 1.0
+
+			- name: maxMatchingDistance
+				required: true
+					Maximum matching distance in meters to match geo coordinates to the street network.
+				schema:
+					type: number
+					default: 25
+
+			- name: transitModes
+				required: false
+					Optional. Default is `TRANSIT` which allows all transit modes (no restriction).
+					Allowed modes for the transit part. If empty, no transit connections will be computed.
+					For example, this can be used to allow only `METRO,SUBWAY,TRAM`.
+				schema:
+					default:
+						- TRANSIT
+					type: array
+
+			- name: directModes
+				required: false
+					Optional. Default is `WALK` which will compute walking routes as direct connections.
+					Modes used for direction connections from start to destination without using transit.
+					Results will be returned on the `direct` key.
+					Note: Direct connections will only be returned on the first call. For paging calls, they can be omitted.
+					Note: Transit connections that are slower than the fastest direct connection will not show up.
+					This is being used as a cut-off during transit routing to speed up the search.
+					To prevent this, it's possible to send two separate requests (one with only `transitModes` and one with only `directModes`).
+					Only non-transit modes such as `WALK`, `BIKE`, `CAR`, `BIKE_SHARING`, etc. can be used.
+				schema:
+					default:
+						- WALK
+					type: array
+
+			- name: preTransitModes
+				required: false
+					Optional. Default is `WALK`. Only applies if the `from` place is a coordinate (not a transit stop). Does not apply to direct connections (see `directModes`).
+					A list of modes that are allowed to be used from the `from` coordinate to the first transit stop. Example: `WALK,BIKE_SHARING`.
+				schema:
+					default:
+						- WALK
+					type: array
+
+			- name: postTransitModes
+				required: false
+					Optional. Default is `WALK`. Only applies if the `to` place is a coordinate (not a transit stop). Does not apply to direct connections (see `directModes`).
+					A list of modes that are allowed to be used from the last transit stop to the `to` coordinate. Example: `WALK,BIKE_SHARING`.
+				schema:
+					default:
+						- WALK
+					type: array
+
+			- name: numItineraries
+				required: false
+					The minimum number of itineraries to compute.
+					This is only relevant if `timetableView=true`.
+				schema:
+					type: integer
+					default: 5
+
+			- name: pageCursor
+				required: false
+					Use the cursor to go to the next "page" of itineraries.
+					Copy the cursor from the last response and keep the original request as is.
+					This will enable you to search for itineraries in the next or previous time-window.
+
+			- name: timetableView
+				required: false
+					Search for the best trip options within a time window.
+					If true two itineraries are considered optimal
+					if one is better on arrival time (earliest wins)
+					and the other is better on departure time (latest wins).
+					In combination with arriveBy this parameter cover the following use cases:
+					`timetable=false` = waiting for the first transit departure/arrival is considered travel time:
+						- `arriveBy=true`: event (e.g. a meeting) starts at 10:00 am,
+							compute the best journeys that arrive by that time (maximizes departure time)
+						- `arriveBy=false`: event (e.g. a meeting) ends at 11:00 am,
+							compute the best journeys that depart after that time
+					`timetable=true` = optimize "later departure" + "earlier arrival" and give all options over a time window:
+						- `arriveBy=true`: the time window around `date` and `time` refers to the arrival time window
+						- `arriveBy=false`: the time window around `date` and `time` refers to the departure time window
+				schema:
+					type: boolean
+					default: true
+
+			- name: searchWindow
+				required: false
+					Optional. Default is 2 hours which is `7200`.
+					The length of the search-window in seconds. Default value two hours.
+						- `arriveBy=true`: number of seconds between the earliest departure time and latest departure time
+						- `arriveBy=false`: number of seconds between the earliest arrival time and the latest arrival time
+				schema:
+					type: integer
+					default: 7200
+					minium: 0
+
+			- name: maxPreTransitTime
+				required: false
+					Maximum time in seconds for the first street leg.
+				schema:
+					type: integer
+					default: 900
+					minimum: 0
+
+			- name: maxPostTransitTime
+				required: false
+					Maximum time in seconds for the last street leg.
+				schema:
+					type: integer
+					default: 900
+					minimum: 0
+
+			- name: maxDirectTime
+				required: false
+					Maximum time in seconds for direct connections.
+				schema:
+					type: integer
+					default: 1800
+					minimum: 0
+					-->
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file