mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-14 00:01:03 +00:00
feat(native): the apps load the server's own UI
The apps ship only an address screen now. Once a server is picked, the native side points the WebView at it: TrekBridgeViewController on iOS and a config copy with server.url on Android. The UI then comes from that server, in the version it runs and on its own origin, so the session cookie, uploads, /ws and plugins work exactly as in a browser and no app release has to keep pace with the servers out there. The address screen (native-shell/, built into native-dist/) probes /api/health/features through native HTTP, tries https before http when no scheme was typed, and refuses servers without the nativeApp flag. It also serves as the error page when the remembered server does not load: retry, change server, or on iOS the stored copy of the server's start page. TrekShell is the app's own plugin for all of that: remember, change and reload the server, sign in through ASWebAuthenticationSession or a Custom Tab, and on iOS keep and open the offline copy of the start page, because WKWebView runs no service worker for a domain the app does not list. Plugins the frame does not use are gone (push, camera, geolocation, calendar, file transfer, in-app browser and more): the WebView covers the camera and location itself, and push needs a relay before it is worth shipping. With them go the push entitlement, the calendar usage strings and the Firebase bits. The iOS scheme falls back to capacitor://, since Capacitor drops an iosScheme of https, and the arm64 capability replaces armv7.
This commit is contained in:
@@ -24,16 +24,17 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Deep links (@capacitor/app appUrlOpen).
|
||||
<!-- Deep links.
|
||||
|
||||
The scheme is @string/custom_url_scheme (com.liketrek.trek).
|
||||
launchMode is singleTask above, so a link delivers into the
|
||||
running task via onNewIntent rather than starting a second copy
|
||||
of the app on top of the first.
|
||||
|
||||
This is the return path for native OIDC/OAuth login: the flow
|
||||
opens in a Custom Tab and the provider redirects back to
|
||||
com.liketrek.trek://… , which lands here.
|
||||
This is the return path for SSO and passkey sign-in: TrekShell
|
||||
opens the server's login page in a Custom Tab, and after the
|
||||
hand-off it redirects to com.liketrek.trek://auth?code=…, which
|
||||
lands here and in TrekShellPlugin.handleOnNewIntent.
|
||||
|
||||
Not an App Link (autoVerify + https). App Links are verified
|
||||
against a specific domain via assetlinks.json, and TREK is
|
||||
@@ -59,101 +60,21 @@
|
||||
android:resource="@xml/file_paths"></meta-data>
|
||||
</provider>
|
||||
|
||||
<!-- Notification icon, shared by @capacitor/push-notifications (via this
|
||||
FCM meta-data) and @capacitor/local-notifications (via the smallIcon
|
||||
option in capacitor.config.ts).
|
||||
|
||||
It must be a white silhouette on transparency; the launcher icon is a
|
||||
full-colour square and Android would render it as a white blob.
|
||||
notification_icon is generated from public/icons/icon-white.svg by
|
||||
scripts/generate-native-icons.mjs.
|
||||
|
||||
default_notification_channel_id names the channel FCM uses for any
|
||||
message that does not carry its own. The channel itself still has to
|
||||
be created at runtime with PushNotifications.createChannel() using
|
||||
this exact id — Android drops notifications for a channel that was
|
||||
never created, and FCM silently falls back to its own channel.
|
||||
|
||||
No default_notification_color on purpose. TREK's palette is neutral
|
||||
and user-selectable, so there is no one brand colour to tint with;
|
||||
left unset, Android tints the small icon with the system accent,
|
||||
which stays legible in both the light and dark shade. -->
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_icon"
|
||||
android:resource="@drawable/notification_icon" />
|
||||
<meta-data
|
||||
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||
android:value="@string/default_notification_channel_id" />
|
||||
|
||||
<!-- Asks Play services to install the backported Android photo picker on
|
||||
Android 11/12 devices, so @capacitor/camera gets the modern picker
|
||||
instead of falling back to ACTION_OPEN_DOCUMENT. Disabled by design:
|
||||
it is a dependency declaration, not a service that runs.
|
||||
|
||||
Drop this block if TREK ever ships a Play-services-free build
|
||||
(F-Droid); the fallback picker keeps working without it. -->
|
||||
<service
|
||||
android:name="com.google.android.gms.metadata.ModuleDependencies"
|
||||
android:enabled="false"
|
||||
android:exported="false"
|
||||
tools:ignore="MissingClass">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="photopicker_activity:0:required" android:value="" />
|
||||
</service>
|
||||
</application>
|
||||
|
||||
<!-- Permissions.
|
||||
|
||||
Declared here only where the app itself needs them. Plugins that ship
|
||||
their own manifest contribute theirs through the merge and are NOT
|
||||
repeated: @capacitor/haptics (VIBRATE), @capacitor/calendar
|
||||
(READ_CALENDAR, WRITE_CALENDAR) and @capacitor/local-notifications
|
||||
(RECEIVE_BOOT_COMPLETED, WAKE_LOCK, SCHEDULE_EXACT_ALARM). -->
|
||||
<!-- Permissions. Only what the WebView itself needs: the file picker's
|
||||
camera option and navigator.geolocation for "locate me" on the map,
|
||||
both granted at runtime through Capacitor's WebChromeClient. -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<!-- Reachability: connectivity.ts probes the server on an interval, and on
|
||||
native we want to skip the probe entirely when there is no transport.
|
||||
@capacitor/network declares this too; kept explicit because
|
||||
connectivity.ts depends on it directly. -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<!-- Android 13+ gates notifications behind a runtime grant. firebase-messaging
|
||||
and @capacitor/local-notifications declare this too, but relying on a
|
||||
transitive manifest merge for a permission the app must request by hand is
|
||||
a silent-failure waiting to happen — it must be requested via
|
||||
requestPermissions() before register()/schedule(). -->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<!-- @capacitor/geolocation. Declares no permissions of its own, so both are
|
||||
required here. COARSE is listed first because it is the weaker grant and
|
||||
is enough for "what city am I in" — request FINE only where the map
|
||||
genuinely needs it. -->
|
||||
<!-- COARSE is listed first because it is the weaker grant and is enough
|
||||
for "what city am I in". -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<!-- required="false" on purpose: TREK is a planner, and everything except
|
||||
"locate me" works without GPS hardware. Marking it required would have
|
||||
Play hide the app from tablets and other GPS-less devices. -->
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
|
||||
|
||||
<!-- @capacitor/camera. Not strictly required — the plugin launches the system
|
||||
camera activity, which carries its own permission — but io.ionic.libs's
|
||||
inappbrowser transitively declares CAMERA anyway, and once it is declared
|
||||
Android routes the plugin through the runtime-grant path. Declared here
|
||||
explicitly so it is a decision rather than something inherited. -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<!-- Stripped from the merge. io.ionic.libs:ioninappbrowser-android declares
|
||||
RECORD_AUDIO and MODIFY_AUDIO_SETTINGS so that pages opened in its WebView
|
||||
mode can use getUserMedia for microphone capture. TREK records no audio
|
||||
anywhere, and shipping these would put "Microphone" on the store listing
|
||||
and in the app's permission screen for a capability that does not exist.
|
||||
|
||||
Revisit only if a feature genuinely needs mic input in an embedded page. -->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" tools:node="remove" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" tools:node="remove" />
|
||||
|
||||
<!-- Deliberately NOT declared: READ/WRITE_EXTERNAL_STORAGE.
|
||||
@capacitor/camera needs storage permissions only for saveToGallery, and
|
||||
TREK uploads photos to the server rather than writing them to the device
|
||||
gallery. Add them the day a feature actually needs them. -->
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
</manifest>
|
||||
|
||||
Reference in New Issue
Block a user