@gjsify/file-chooser 0.0.0-stage → 0.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,60 @@
1
- # Temporary Holding Version
1
+ # @gjsify/file-chooser
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `Gtk.FileDialog`, `Gtk.FileFilter` and `Gio.File` as one import on GJS, the browser and
4
+ NativeScript ([ADR 0100](../../../docs/adr/0100-file-dialog-and-gio-file-run-on-the-browser-and-nativescript.md)).
5
+
6
+ ```ts
7
+ import { FileDialog, FileFilter, File, ListStore, promisify } from '@gjsify/file-chooser';
8
+
9
+ promisify(FileDialog.prototype, 'open', 'open_finish');
10
+ promisify(File.prototype, 'load_contents_async', 'load_contents_finish');
11
+
12
+ const filter = FileFilter.new();
13
+ filter.set_name('Assembly');
14
+ filter.add_suffix('asm');
15
+ const filters = new ListStore({ item_type: FileFilter.$gtype });
16
+ filters.append(filter);
17
+
18
+ const file = await new FileDialog({ filters }).open(window, null);
19
+ const [contents] = await file.load_contents_async(null);
20
+ ```
21
+
22
+ | Target | What you get |
23
+ |---|---|
24
+ | GJS | the native `gi://` classes, by identity; the xdg portal is the dialog |
25
+ | browser | File System Access where `showSaveFilePicker` exists, otherwise a self-drawn Adwaita dialog over the Origin Private File System |
26
+ | NativeScript (Android) | the Storage Access Framework (`ACTION_OPEN_DOCUMENT` / `ACTION_CREATE_DOCUMENT`) |
27
+
28
+ The package is a strict SUBSET of the GJS API: the same names and semantics, and anything outside
29
+ the subset (`File.new_for_uri`, `get_parent`, `query_exists`, non-modal dialogs, `open_multiple`,
30
+ glob patterns other than `*.ext` and `*`, …) throws `UnsupportedGObjectError` rather than guessing.
31
+
32
+ ## Recommended import path
33
+
34
+ - An app written against `gi://` that you build with `gjsify build --gi-renderer` needs nothing
35
+ from here: `gi://Gtk` and `gi://Gio` already resolve to the renderer, which carries the same
36
+ subset.
37
+ - Code that imports `@gjsify/file-chooser` gets the right door per target through gjsify's
38
+ platform files (`platform.gtk.ts` / `platform.web.ts` / `platform.native.ts`). A bundler
39
+ without those chains gets the base, which has no driver: every `open`/`save` rejects
40
+ `Gtk.DialogError.FAILED` until you call `registerFileChooserDriver()`.
41
+
42
+ ## Behaviour you should know about
43
+
44
+ - **A save is not atomic on the ports.** `replace_async` truncates and writes in place; GJS writes
45
+ a temporary file and renames it. A crash mid-write leaves a partial file on the web and Android.
46
+ - **OPFS is invisible to the file manager.** On a browser without File System Access, files live
47
+ in the origin's private storage. The dialog's "Upload…" copies a picked file in; nothing is ever
48
+ saved as a download.
49
+ - **Persistence is the app's call.** The browser may evict OPFS under storage pressure; call
50
+ `navigator.storage.persist()` yourself if your files must survive that.
51
+ - **Android filters by MIME type.** An extension-only filter (`add_suffix('asm')`) opens `*/*`
52
+ and accepts any pick: the filter is a hint, as is usual on Android.
53
+ - **`etag` is `null` on the ports**; the browser has no user activation outside a gesture, so a
54
+ dialog opened then rejects `Gtk.DialogError.FAILED`.
55
+ - **iOS has no picker yet**: `open`/`save` reject `FAILED`.
56
+
57
+ ## Conformance
58
+
59
+ `@gjsify/file-chooser/conformance` exports `FILE_CHOOSER_VECTORS` and `driveFileChooserVectors`,
60
+ the same vectors that run against real GJS, for anyone writing a driver of their own.
@@ -0,0 +1 @@
1
+ var e=Object.defineProperty,__name=(t,n)=>e(t,`name`,{value:n,configurable:!0});export{__name};
@@ -0,0 +1 @@
1
+ import{FILE_CHOOSER_ROWS as e,FILE_CHOOSER_VECTORS as t,driveFileChooserVectors as n,promisifyFileChooser as r}from"@gjsify/adwaita-core/conformance";export{e as FILE_CHOOSER_ROWS,t as FILE_CHOOSER_VECTORS,n as driveFileChooserVectors,r as promisifyFileChooser};
@@ -0,0 +1 @@
1
+ import{Bytes as e,DialogError as t,File as n,FileCreateFlags as r,FileDialog as i,FileFilter as a,FileOutputStream as o,GLibError as s,IOErrorEnum as c,ListStore as l,OutputStream as u,promisify as d,registerFileChooserDriver as f}from"./platform.js";export{e as Bytes,t as DialogError,n as File,r as FileCreateFlags,i as FileDialog,a as FileFilter,o as FileOutputStream,s as GLibError,c as IOErrorEnum,l as ListStore,u as OutputStream,d as promisify,f as registerFileChooserDriver};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import e from"gi://Gio?version=2.0";import t from"gi://GLib?version=2.0";import n from"gi://Gtk?version=4.0";const r=n.FileDialog,i=n.FileFilter,a=n.DialogError,o=e.File,s=e.ListStore,c=e.OutputStream,l=e.FileOutputStream,u=e.FileCreateFlags,d=e.IOErrorEnum,f=e._promisify,p=t.Bytes,m=t.Error;function registerFileChooserDriver(e){throw Error(`registerFileChooserDriver() has no effect on GJS: Gtk.FileDialog is native there and the xdg portal is its driver (ADR 0101).`)}export{p as Bytes,a as DialogError,o as File,u as FileCreateFlags,r as FileDialog,i as FileFilter,l as FileOutputStream,m as GLibError,d as IOErrorEnum,s as ListStore,c as OutputStream,f as promisify,registerFileChooserDriver};
@@ -0,0 +1 @@
1
+ import{DialogError as e,FileCreateFlags as t,GLibBytes as n,GLibError as r,GioFile as i,GioFileOutputStream as a,GioListStore as o,GioOutputStream as s,GtkFileDialog as c,GtkFileFilter as l,IOErrorEnum as u,promisify as d,registerFileChooserDriver as f}from"@gjsify/adwaita-core";export{n as Bytes,e as DialogError,i as File,t as FileCreateFlags,c as FileDialog,l as FileFilter,a as FileOutputStream,r as GLibError,u as IOErrorEnum,o as ListStore,s as OutputStream,d as promisify,f as registerFileChooserDriver};
@@ -0,0 +1 @@
1
+ import{registerFileChooserDriver as e}from"@gjsify/adwaita-core";import{GLib as t,Gio as n,Gtk as r}from"@gjsify/adwaita-nativescript";const i=r.FileDialog,a=r.FileFilter,o=r.DialogError,s=n.File,c=n.ListStore,l=n.OutputStream,u=n.FileOutputStream,d=n.FileCreateFlags,f=n.IOErrorEnum,p=n._promisify,m=t.Bytes,h=t.Error;export{m as Bytes,o as DialogError,s as File,d as FileCreateFlags,i as FileDialog,a as FileFilter,u as FileOutputStream,h as GLibError,f as IOErrorEnum,c as ListStore,l as OutputStream,p as promisify,e as registerFileChooserDriver};
@@ -0,0 +1 @@
1
+ import{registerFileChooserDriver as e}from"@gjsify/adwaita-core";import{GLib as t,Gio as n,Gtk as r}from"@gjsify/adwaita-web";const i=r.FileDialog,a=r.FileFilter,o=r.DialogError,s=n.File,c=n.ListStore,l=n.OutputStream,u=n.FileOutputStream,d=n.FileCreateFlags,f=n.IOErrorEnum,p=n._promisify,m=t.Bytes,h=t.Error;export{m as Bytes,o as DialogError,s as File,d as FileCreateFlags,i as FileDialog,a as FileFilter,u as FileOutputStream,h as GLibError,f as IOErrorEnum,c as ListStore,l as OutputStream,p as promisify,e as registerFileChooserDriver};
@@ -0,0 +1,2 @@
1
+ export { FILE_CHOOSER_ROWS, FILE_CHOOSER_VECTORS, driveFileChooserVectors, promisifyFileChooser, } from '@gjsify/adwaita-core/conformance';
2
+ export type { FileChooserNamespaces, FileChooserRow, FileChooserSubject, FileChooserVector, ScriptedPick, } from '@gjsify/adwaita-core/conformance';
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ export { FileDialog, FileFilter, File, ListStore, OutputStream, FileOutputStream, FileCreateFlags, IOErrorEnum, DialogError, Bytes, GLibError, promisify, registerFileChooserDriver, } from './platform.js';
2
+ export type { FileChooserDriver, FileChooserHandle, FileChooserRequest, FileChooserWriter } from '@gjsify/adwaita-core';
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -0,0 +1 @@
1
+ export { GtkFileDialog as FileDialog, GtkFileFilter as FileFilter, GioFile as File, GioListStore as ListStore, GioOutputStream as OutputStream, GioFileOutputStream as FileOutputStream, FileCreateFlags, IOErrorEnum, DialogError, GLibBytes as Bytes, GLibError, promisify, registerFileChooserDriver, } from '@gjsify/adwaita-core';
@@ -0,0 +1,17 @@
1
+ import Gio from 'gi://Gio?version=2.0';
2
+ import GLib from 'gi://GLib?version=2.0';
3
+ import Gtk from 'gi://Gtk?version=4.0';
4
+ import type { FileChooserDriver } from '@gjsify/adwaita-core';
5
+ export declare const FileDialog: typeof Gtk.FileDialog;
6
+ export declare const FileFilter: typeof Gtk.FileFilter;
7
+ export declare const DialogError: typeof Gtk.DialogError;
8
+ export declare const File: Gio.FileNamespace & (new () => Gio.File);
9
+ export declare const ListStore: typeof Gio.ListStore;
10
+ export declare const OutputStream: typeof Gio.OutputStream;
11
+ export declare const FileOutputStream: typeof Gio.FileOutputStream;
12
+ export declare const FileCreateFlags: typeof Gio.FileCreateFlags;
13
+ export declare const IOErrorEnum: typeof Gio.IOErrorEnum;
14
+ export declare const promisify: typeof Gio._promisify;
15
+ export declare const Bytes: typeof GLib.Bytes;
16
+ export declare const GLibError: typeof GLib.Error;
17
+ export declare function registerFileChooserDriver(_next: FileChooserDriver | null): FileChooserDriver | null;
@@ -0,0 +1,30 @@
1
+ import { Gio, GLib, Gtk } from '@gjsify/adwaita-nativescript';
2
+ import { registerFileChooserDriver } from '@gjsify/adwaita-core';
3
+ export declare const FileDialog: typeof Gtk.FileDialog;
4
+ export declare const FileFilter: typeof Gtk.FileFilter;
5
+ export declare const DialogError: Readonly<{
6
+ FAILED: number;
7
+ CANCELLED: number;
8
+ DISMISSED: number;
9
+ }>;
10
+ export declare const File: typeof Gio.File;
11
+ export declare const ListStore: typeof Gio.ListStore;
12
+ export declare const OutputStream: typeof Gio.OutputStream;
13
+ export declare const FileOutputStream: typeof Gio.FileOutputStream;
14
+ export declare const FileCreateFlags: Readonly<{
15
+ NONE: 0;
16
+ PRIVATE: 1;
17
+ REPLACE_DESTINATION: 2;
18
+ }>;
19
+ export declare const IOErrorEnum: Readonly<{
20
+ FAILED: number;
21
+ NOT_FOUND: number;
22
+ NOT_SUPPORTED: number;
23
+ CLOSED: number;
24
+ CANCELLED: number;
25
+ PENDING: number;
26
+ }>;
27
+ export declare const promisify: typeof Gio._promisify;
28
+ export declare const Bytes: typeof GLib.Bytes;
29
+ export declare const GLibError: typeof GLib.Error;
30
+ export { registerFileChooserDriver };
@@ -0,0 +1,30 @@
1
+ import { Gio, GLib, Gtk } from '@gjsify/adwaita-web';
2
+ import { registerFileChooserDriver } from '@gjsify/adwaita-core';
3
+ export declare const FileDialog: typeof Gtk.FileDialog;
4
+ export declare const FileFilter: typeof Gtk.FileFilter;
5
+ export declare const DialogError: Readonly<{
6
+ FAILED: number;
7
+ CANCELLED: number;
8
+ DISMISSED: number;
9
+ }>;
10
+ export declare const File: typeof Gio.File;
11
+ export declare const ListStore: typeof Gio.ListStore;
12
+ export declare const OutputStream: typeof Gio.OutputStream;
13
+ export declare const FileOutputStream: typeof Gio.FileOutputStream;
14
+ export declare const FileCreateFlags: Readonly<{
15
+ NONE: 0;
16
+ PRIVATE: 1;
17
+ REPLACE_DESTINATION: 2;
18
+ }>;
19
+ export declare const IOErrorEnum: Readonly<{
20
+ FAILED: number;
21
+ NOT_FOUND: number;
22
+ NOT_SUPPORTED: number;
23
+ CLOSED: number;
24
+ CANCELLED: number;
25
+ PENDING: number;
26
+ }>;
27
+ export declare const promisify: typeof Gio._promisify;
28
+ export declare const Bytes: typeof GLib.Bytes;
29
+ export declare const GLibError: typeof GLib.Error;
30
+ export { registerFileChooserDriver };
package/package.json CHANGED
@@ -1,6 +1,82 @@
1
1
  {
2
- "name": "@gjsify/file-chooser",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "@gjsify/file-chooser",
3
+ "version": "0.61.0",
4
+ "description": "Gtk.FileDialog, Gtk.FileFilter and Gio.File as one import on GJS, the browser and NativeScript: the native classes on GJS, File System Access or a self-drawn OPFS dialog on the web, the Storage Access Framework on Android",
5
+ "keywords": [
6
+ "gjs",
7
+ "gtk",
8
+ "gio",
9
+ "file-dialog",
10
+ "file-system-access",
11
+ "opfs",
12
+ "nativescript",
13
+ "storage-access-framework"
14
+ ],
15
+ "type": "module",
16
+ "main": "lib/esm/index.js",
17
+ "module": "lib/esm/index.js",
18
+ "types": "lib/types/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./lib/types/index.d.ts",
22
+ "default": "./lib/esm/index.js"
23
+ },
24
+ "./conformance": {
25
+ "types": "./lib/types/conformance.d.ts",
26
+ "default": "./lib/esm/conformance.js"
27
+ },
28
+ "./package.json": "./package.json"
29
+ },
30
+ "files": [
31
+ "lib",
32
+ "!lib/types/**/*.spec.d.ts",
33
+ "!lib/types/test.d.mts"
34
+ ],
35
+ "scripts": {
36
+ "clear": "gjsify clear lib tmp tsconfig.tsbuildinfo test.gjs.mjs dist",
37
+ "check": "gjsify tsc --noEmit",
38
+ "build": "gjsify run build:gjsify && gjsify run build:types",
39
+ "build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}' 'src/test.browser.{mts,ts}'",
40
+ "build:types": "gjsify tsc",
41
+ "build:test": "gjsify run build:test:gjs",
42
+ "build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
43
+ "build:test:browser": "gjsify build src/test.browser.mts --app browser --outfile dist/test.browser.mjs",
44
+ "test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
45
+ "test:gjs": "gjsify run test.gjs.mjs"
46
+ },
47
+ "gjsify": {
48
+ "runtimes": {
49
+ "gjs": "polyfill",
50
+ "node": "none",
51
+ "browser": "polyfill",
52
+ "nativescript": "polyfill"
53
+ },
54
+ "tier": 3
55
+ },
56
+ "dependencies": {
57
+ "@gjsify/adwaita-core": "^0.61.0",
58
+ "@gjsify/adwaita-nativescript": "^0.61.0",
59
+ "@gjsify/adwaita-web": "^0.61.0"
60
+ },
61
+ "devDependencies": {
62
+ "@girs/gio-2.0": "5.4.0",
63
+ "@girs/gjs": "5.4.0",
64
+ "@girs/glib-2.0": "5.4.0",
65
+ "@girs/gtk-4.0": "5.4.0",
66
+ "@gjsify/cli": "^0.61.0",
67
+ "@gjsify/unit": "^0.61.0",
68
+ "@types/node": "^25.9.2",
69
+ "typescript": "^6.0.3"
70
+ },
71
+ "author": "Pascal Garber <pascal@artandcode.studio>",
72
+ "license": "MIT",
73
+ "repository": {
74
+ "type": "git",
75
+ "url": "git+https://github.com/gjsify/gjsify.git",
76
+ "directory": "packages/framework/file-chooser"
77
+ },
78
+ "bugs": {
79
+ "url": "https://github.com/gjsify/gjsify/issues"
80
+ },
81
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/framework/file-chooser#readme"
82
+ }