Skip to content

Commit

Permalink
add landscape mode support to trip status
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigohpalmeirim committed Sep 22, 2024
1 parent 5770d18 commit 1580953
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 28 deletions.
1 change: 1 addition & 0 deletions android/app/capacitor.build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dependencies {
implementation project(':capacitor-keyboard')
implementation project(':capacitor-local-notifications')
implementation project(':capacitor-preferences')
implementation project(':capacitor-screen-orientation')
implementation project(':capacitor-status-bar')
implementation project(':capacitor-toast')
implementation project(':mauricewegner-capacitor-navigation-bar')
Expand Down
3 changes: 3 additions & 0 deletions android/capacitor.settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ project(':capacitor-local-notifications').projectDir = new File('../node_modules
include ':capacitor-preferences'
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')

include ':capacitor-screen-orientation'
project(':capacitor-screen-orientation').projectDir = new File('../node_modules/@capacitor/screen-orientation/android')

include ':capacitor-status-bar'
project(':capacitor-status-bar').projectDir = new File('../node_modules/@capacitor/status-bar/android')

Expand Down
1 change: 1 addition & 0 deletions ios/App/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def capacitor_pods
pod 'CapacitorKeyboard', :path => '../../node_modules/@capacitor/keyboard'
pod 'CapacitorLocalNotifications', :path => '../../node_modules/@capacitor/local-notifications'
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
pod 'CapacitorScreenOrientation', :path => '../../node_modules/@capacitor/screen-orientation'
pod 'CapacitorStatusBar', :path => '../../node_modules/@capacitor/status-bar'
pod 'CapacitorToast', :path => '../../node_modules/@capacitor/toast'
pod 'MauricewegnerCapacitorNavigationBar', :path => '../../node_modules/@mauricewegner/capacitor-navigation-bar'
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@capacitor/keyboard": "^5.0.7",
"@capacitor/local-notifications": "^5.0.6",
"@capacitor/preferences": "^5.0.6",
"@capacitor/screen-orientation": "^5.0.8",
"@capacitor/status-bar": "^5.0.6",
"@capacitor/toast": "^5.0.6",
"@fontsource-variable/inter": "^5.0.16",
Expand All @@ -66,4 +67,4 @@
"@sveltejs/kit",
"svelte-preprocess"
]
}
}
14 changes: 7 additions & 7 deletions src/lib/components/Map.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
import { pulsingDot } from '$lib/pulsing-dot';
import { currentPos, bearingNorth, bearing } from '$lib/location';
import type { Unsubscriber } from 'svelte/motion';
import { getMapStyle } from '$lib/mapStyle';
import { getCssVariable } from '$lib/utils';
import { getMapStyle } from '$lib/mapStyle';
import { getCssVariable } from '$lib/utils';
export let loading = true;
export let bottomPadding = 0;
export let topPadding = 0;
export let leftPadding = 0;
let mapElem: HTMLDivElement;
let map : maplibregl.Map;
Expand Down Expand Up @@ -148,7 +149,7 @@
await tick();
map.flyTo({
center: feature.geometry.coordinates as [number, number],
padding: { top: topPadding, bottom: Math.min(bottomPadding, window.innerHeight / 2) },
padding: { top: topPadding, bottom: Math.min(bottomPadding, window.innerHeight / 2), left: leftPadding },
curve: 0,
});
});
Expand All @@ -174,7 +175,7 @@
map.addImage('bike_inactive_selected', await loadSvg('./assets/bike_marker_inactive_selected.svg'));
map.addImage('dock_inactive', await loadSvg('./assets/dock_marker_inactive.svg'));
map.addImage('dock_inactive_selected', await loadSvg('./assets/dock_marker_inactive_selected.svg'));
const primaryColor = getCssVariable('--color-primary');
const imgs = [['bike', './assets/bike_marker.svg', primaryColor], ['bike_selected', './assets/bike_marker_selected.svg', '#fff'], ['dock', './assets/dock_marker.svg', primaryColor], ['dock_selected', './assets/dock_marker_selected.svg', '#fff']];
const canvas = document.createElement('canvas');
Expand Down Expand Up @@ -212,7 +213,7 @@
function centerMap(pos: Position) {
map.flyTo({
center: [pos.coords.longitude, pos.coords.latitude],
padding: { top: topPadding, bottom: Math.min(bottomPadding, window.innerHeight / 2) },
padding: { top: topPadding, bottom: Math.min(bottomPadding, window.innerHeight / 2), left: leftPadding },
zoom: 16,
});
}
Expand Down Expand Up @@ -245,7 +246,6 @@
}
onMount(() => {
const mode = $appSettings.theme === 'system' ? window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' : $appSettings.theme;
map = new Map({
container: mapElem,
Expand Down Expand Up @@ -292,7 +292,7 @@
}
});
$: if ($following && !blurred && $currentPos && topPadding !== null && bottomPadding !== null) centerMap($currentPos);
$: if ($following && !blurred && $currentPos && topPadding !== null && bottomPadding !== null && leftPadding !== null) centerMap($currentPos);
$: if ($selectedStation == null) bottomPadding = 0;
</script>
Expand Down
42 changes: 27 additions & 15 deletions src/lib/components/TripStatus.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
import { following, safeInsets, currentTrip as t } from '$lib/state';
import { onMount } from 'svelte';
import { KeepAwake } from '@capacitor-community/keep-awake';
import { ScreenOrientation } from '@capacitor/screen-orientation';
let height:number;
export { height as posBottom };
export let height:number;
export let width:number;
let portrait = true;
$: if ($t) {
height = ($t.destination ? 216 : 160) + Math.max(12, $safeInsets.top);
height = portrait ? ($t.destination ? 216 : 160) + Math.max(12, $safeInsets.top) : 0;
width = portrait ? 0 : ($t.destination ? 238 : 190) + $safeInsets.top;
ScreenOrientation.unlock();
} else {
height = 0;
width = 0;
ScreenOrientation.lock({ orientation: 'portrait' });
}
let seconds = 0;
Expand All @@ -20,14 +27,15 @@
onMount(() => {
seconds = 0;
let startTime = Date.now();
inter = setInterval(() => {
seconds = (Date.now() - startTime) / 1000;
}, 1000);
inter = setInterval(() => seconds = (Date.now() - startTime) / 1000, 1000);
$following = true;
KeepAwake.keepAwake();
ScreenOrientation.orientation().then(o => portrait = o.type === 'portrait-primary');
ScreenOrientation.addListener('screenOrientationChange', o => portrait = o.type === 'portrait-primary');
return () => {
clearInterval(inter);
KeepAwake.allowSleep();
ScreenOrientation.removeAllListeners();
};
});
Expand All @@ -37,39 +45,43 @@
let minutes = Math.floor(seconds / 60).toString().padStart(2, '0');
return `${minutes}:${displaySeconds}`;
}
function formatTime(date: Date) {
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
}
</script>

<div transition:fly={{ y: -172 }} class="absolute top-0 bg-background w-full transition-all" style:height="{height}px" style:box-shadow="0px 0px 20px 0px var(--color-shadow)">
<div transition:fly={portrait ? { y: -172 } : { x: -172 }} class="absolute bg-background top-0 left-0 transition-all" style:height={portrait ? `${height}px` : '100%'} style:width={portrait ? '100%' : `${width}px`} style:box-shadow="0px 0px 20px 0px var(--color-shadow)">
{#key seconds}
{#if $t != null}
{@const deltaSeconds = Date.now() - $t.startDate.getTime()}
<div class="flex flex-col items-center gap-2 relative" style:margin-top="{Math.max(12, $safeInsets.top)}px">
<div class="flex flex-col items-center gap-2 relative {$t.destination ? 'h-64' : 'h-52'} {portrait ? '' : 'top-1/2 -translate-y-1/2'}" style={`margin-${portrait ? 'top' : 'left'}: ${portrait ? Math.max(12, $safeInsets.top) : $safeInsets.top}px`}>
{#if $t.bikePlate}
<span class="font-semibold text-label text-lg">{$t.bikePlate}</span>
{/if}
<span class="text-5xl text-primary font-bold">{msToMinuteSeconds(deltaSeconds)}</span>
<div class="absolute top-[92px] transition-all {$t.destination ? 'left-12' : 'left-20'}">
<div class="absolute top-[92px] transition-all {portrait ? $t.destination ? 'left-12' : 'left-20' : $t.destination ? 'left-4' : 'right-1/2 translate-x-1/2'}">
<Metric value={$t.traveledDistanceKm >= 1 ? $t.traveledDistanceKm : Math.round($t.traveledDistanceKm * 1000)} unit={$t.traveledDistanceKm >= 1 ? 'km' : 'm'} label="Distância Percorrida" />
</div>
<div class="absolute top-[92px] transition-all {$t.destination ? 'right-1/2 translate-x-1/2' : 'right-20 translate-x-0'}">
<div class="absolute transition-all {portrait ? $t.destination ? 'top-[92px] right-1/2 translate-x-1/2' : 'top-[92px] right-20 translate-x-0' : $t.destination ? 'top-[92px] right-4' : 'top-[150px] right-1/2 translate-x-1/2'}">
<Metric value={$t.speed < 0 ? 0 : $t.speed} unit="km/h" label="Velocidade Média" />
</div>
{#if $t.destination}
<div transition:fly={{ x: 64, duration: 150, easing: cubicInOut }} class="absolute top-[92px] transition-all right-12">
{#if $t.distanceLeft}
<div transition:fly={{ x: 64, duration: 150, easing: cubicInOut }} class="absolute transition-all {portrait ? 'top-[92px] right-12' : 'top-[150px] left-4'}">
{#if $t.distanceLeft != null}
<Metric value={$t.distanceLeft} unit="km" label="Distância em Falta" />
{/if}
</div>
<div transition:fade={{ duration: 150 }}>
<div class="absolute top-[160px] transition-all left-24">
<div class="absolute top-[150px] transition-all {portrait ? 'left-24' : 'right-4'}">
{#if $t.arrivalTime}
{@const timeLeft = $t.arrivalTime.getTime() - Date.now()}
<Metric value={msToMinuteSeconds(timeLeft)} unit="min" label="Tempo em Falta" />
{/if}
</div>
<div class="absolute top-[160px] transition-all right-24">
<div class="absolute transition-all {portrait ? 'top-[150px] right-24' : 'top-[208px] right-1/2 translate-x-1/2'}">
{#if $t.arrivalTime}
<Metric value={`${$t.arrivalTime.getHours()}:${$t.arrivalTime.getMinutes()}`} label="Hora de Chegada" />
<Metric value={formatTime($t.arrivalTime)} label="Hora de Chegada" />
{/if}
</div>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import { refreshToken } from '$lib/auth';
import { updateActiveTripInfo } from '$lib/state/helper';
import { initAnalytics } from '$lib/analytics';
import { ScreenOrientation } from '@capacitor/screen-orientation';
if (Capacitor.getPlatform() === 'android' || Capacitor.getPlatform() === 'ios') {
StatusBar.setOverlaysWebView({ overlay: true });
Expand All @@ -35,6 +36,8 @@
updateActiveTripInfo();
});
ScreenOrientation.lock({ orientation: 'portrait' });
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const updateTheme = () => {
document.documentElement.setAttribute('data-theme', $appSettings.theme === 'system' ? mediaQuery.matches ? 'dark' : 'light' : $appSettings.theme);
Expand Down
11 changes: 6 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
let menuHeight = 0;
let stationMenuPos:number|undefined = 0;
let tripStatusPos:number = 0;
let tripStatusHeight:number = 0;
let tripStatusWidth:number = 0;
let profileOpen = false;
let locationPermission = false;
Expand Down Expand Up @@ -57,10 +58,10 @@
<Login />
</div>
{/if}
<Map loading={!$token} bind:bottomPadding={menuHeight} bind:topPadding={tripStatusPos} />
<Map loading={!$token} bind:bottomPadding={menuHeight} bind:topPadding={tripStatusHeight} bind:leftPadding={tripStatusWidth} />

{#if $currentTrip !== null}
<TripStatus bind:posBottom={tripStatusPos} />
<TripStatus bind:height={tripStatusHeight} bind:width={tripStatusWidth} />
{:else}
<StationMenu bind:posTop={stationMenuPos} bind:bikeListHeight={menuHeight} />
{#if $tripRating.currentRating != null}
Expand All @@ -72,11 +73,11 @@
<LocationButton bind:locationPermission />
</Floating>

<Floating right={16} y={tripStatusPos} offset={16}>
<Floating right={16} y={tripStatusHeight} offset={16}>
<ProfileButton on:click={() => profileOpen = true}/>
</Floating>

<Floating right={20} y={Math.max(tripStatusPos + 16, $safeInsets.top)} offset={70}>
<Floating right={20} y={Math.max(tripStatusHeight + 16, $safeInsets.top)} offset={70}>
<Compass />
</Floating>

Expand Down

0 comments on commit 1580953

Please sign in to comment.