-
-
Notifications
You must be signed in to change notification settings - Fork 671
Fix Android style file selection #1806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import { isAndroid } from "./is-mobile"; | ||
|
|
||
| export interface FileDialogFilter { | ||
| name: string; | ||
| extensions: string[]; | ||
| } | ||
|
|
||
| /** | ||
| * Select native file-dialog filters for the current platform. | ||
| * | ||
| * Android's document picker filters by MIME type and cannot reliably map | ||
| * uncommon filename extensions. Callers can therefore provide a separate | ||
| * Android filter set while retaining precise extension filters on desktop and | ||
| * iOS. | ||
| * | ||
| * @param filters - Default file filters used outside Android. | ||
| * @param androidFilters - Android-specific filters, when required. | ||
| * @param userAgent - Override for testing; defaults to `navigator.userAgent`. | ||
| * @returns The filters appropriate for the current platform. | ||
| */ | ||
| export function nativeFileDialogFilters( | ||
| filters: FileDialogFilter[], | ||
| androidFilters: FileDialogFilter[] | undefined, | ||
| userAgent: string = typeof navigator !== "undefined" ? navigator.userAgent : "", | ||
| ): FileDialogFilter[] { | ||
| return isAndroid(userAgent) && androidFilters !== undefined ? androidFilters : filters; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,22 @@ import { isIpadDesktopUserAgent } from "@geolibre/core"; | |
| * @returns True on Android/iOS (including desktop-UA iPadOS). | ||
| */ | ||
| const MOBILE_UA_PATTERN = /Android|iPhone|iPad|iPod/i; | ||
| const ANDROID_UA_PATTERN = /Android/i; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor readability nit: the pre-existing JSDoc block just above this line documents |
||
|
|
||
| /** | ||
| * Whether the app is running on Android. | ||
| * | ||
| * This narrower check is used for platform APIs whose Android behavior differs | ||
| * from iOS, such as native document-picker MIME filtering. | ||
| * | ||
| * @param userAgent - Override for testing; defaults to `navigator.userAgent`. | ||
| * @returns True when the user agent identifies Android. | ||
| */ | ||
| export function isAndroid( | ||
| userAgent: string = typeof navigator !== "undefined" ? navigator.userAgent : "", | ||
| ): boolean { | ||
| return ANDROID_UA_PATTERN.test(userAgent); | ||
| } | ||
|
|
||
| export function isMobile( | ||
| userAgent: string = typeof navigator !== "undefined" ? navigator.userAgent : "", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import assert from "node:assert/strict"; | ||
| import { describe, it } from "node:test"; | ||
| import { | ||
| nativeFileDialogFilters, | ||
| type FileDialogFilter, | ||
| } from "../apps/geolibre-desktop/src/lib/file-dialog-filters"; | ||
|
|
||
| const styleFilters: FileDialogFilter[] = [ | ||
| { | ||
| name: "Style", | ||
| extensions: ["json", "sld", "qml", "xml"], | ||
| }, | ||
| ]; | ||
|
|
||
| describe("nativeFileDialogFilters", () => { | ||
| it("uses the Android override even when it intentionally has no filters", () => { | ||
| assert.deepEqual( | ||
| nativeFileDialogFilters(styleFilters, [], "Mozilla/5.0 (Linux; Android 16; Mobile)"), | ||
| [], | ||
| ); | ||
| }); | ||
|
|
||
| it("keeps extension filters on desktop and iOS", () => { | ||
| assert.equal( | ||
| nativeFileDialogFilters(styleFilters, [], "Mozilla/5.0 (X11; Linux x86_64)"), | ||
| styleFilters, | ||
| ); | ||
| assert.equal( | ||
| nativeFileDialogFilters(styleFilters, [], "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0)"), | ||
| styleFilters, | ||
| ); | ||
| }); | ||
|
|
||
| it("keeps the default filters on Android when no override is supplied", () => { | ||
| assert.equal( | ||
| nativeFileDialogFilters(styleFilters, undefined, "Mozilla/5.0 (Linux; Android 16)"), | ||
| styleFilters, | ||
| ); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing an explicit empty array (
androidFilters: []) rather than omitting the property is the crux of this fix, and it relies on the Tauri Android dialog plugin treating a zero-length filter list the same as "no filters" (i.e. same asundefined) — showing all documents rather than, say, matching nothing. That's native (Kotlin/Rust) plugin behavior I can't verify from the JS side. The PR description says the author manually tested SLD/QML import on device, so this is presumably already confirmed in practice — flagging only as a low-confidence note in case this assumption needs re-checking on a future@tauri-apps/plugin-dialogupgrade.