feat(file-explorer): add file download with share sheet support
This commit is contained in:
Generated
+28
-34
@@ -148,7 +148,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
|
||||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.27.1",
|
"@babel/code-frame": "^7.27.1",
|
||||||
"@babel/generator": "^7.28.5",
|
"@babel/generator": "^7.28.5",
|
||||||
@@ -1530,7 +1529,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
||||||
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
@@ -5147,6 +5145,7 @@
|
|||||||
"integrity": "sha512-6rqTdFt67AAAzln3NOKsXRmv5ZzPkgbfaebKBqUbts7vK1GZudqnrun5a8d3M/h955cam9RHZ6Jb4Y1XhnmFPg==",
|
"integrity": "sha512-6rqTdFt67AAAzln3NOKsXRmv5ZzPkgbfaebKBqUbts7vK1GZudqnrun5a8d3M/h955cam9RHZ6Jb4Y1XhnmFPg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.6",
|
"ajv": "^6.12.6",
|
||||||
"content-type": "^1.0.5",
|
"content-type": "^1.0.5",
|
||||||
@@ -5171,6 +5170,7 @@
|
|||||||
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
|
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mime-types": "^3.0.0",
|
"mime-types": "^3.0.0",
|
||||||
"negotiator": "^1.0.0"
|
"negotiator": "^1.0.0"
|
||||||
@@ -5185,6 +5185,7 @@
|
|||||||
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
|
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bytes": "^3.1.2",
|
"bytes": "^3.1.2",
|
||||||
"content-type": "^1.0.5",
|
"content-type": "^1.0.5",
|
||||||
@@ -5206,6 +5207,7 @@
|
|||||||
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
|
"integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "5.2.1"
|
"safe-buffer": "5.2.1"
|
||||||
},
|
},
|
||||||
@@ -5219,6 +5221,7 @@
|
|||||||
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
|
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.6.0"
|
"node": ">=6.6.0"
|
||||||
}
|
}
|
||||||
@@ -5229,6 +5232,7 @@
|
|||||||
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
|
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "^2.0.0",
|
"accepts": "^2.0.0",
|
||||||
"body-parser": "^2.2.0",
|
"body-parser": "^2.2.0",
|
||||||
@@ -5272,6 +5276,7 @@
|
|||||||
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
|
"integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"encodeurl": "^2.0.0",
|
"encodeurl": "^2.0.0",
|
||||||
@@ -5290,6 +5295,7 @@
|
|||||||
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
|
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
@@ -5300,6 +5306,7 @@
|
|||||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
},
|
},
|
||||||
@@ -5313,6 +5320,7 @@
|
|||||||
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
|
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
@@ -5323,6 +5331,7 @@
|
|||||||
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
|
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
@@ -5336,6 +5345,7 @@
|
|||||||
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"mime-db": "^1.54.0"
|
"mime-db": "^1.54.0"
|
||||||
},
|
},
|
||||||
@@ -5349,6 +5359,7 @@
|
|||||||
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
|
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
@@ -5359,6 +5370,7 @@
|
|||||||
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"side-channel": "^1.1.0"
|
"side-channel": "^1.1.0"
|
||||||
},
|
},
|
||||||
@@ -5375,6 +5387,7 @@
|
|||||||
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
|
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": "^4.3.5",
|
"debug": "^4.3.5",
|
||||||
"encodeurl": "^2.0.0",
|
"encodeurl": "^2.0.0",
|
||||||
@@ -5398,6 +5411,7 @@
|
|||||||
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
|
"integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"encodeurl": "^2.0.0",
|
"encodeurl": "^2.0.0",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
@@ -5414,6 +5428,7 @@
|
|||||||
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
|
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"content-type": "^1.0.5",
|
"content-type": "^1.0.5",
|
||||||
"media-typer": "^1.1.0",
|
"media-typer": "^1.1.0",
|
||||||
@@ -6583,7 +6598,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.18.tgz",
|
||||||
"integrity": "sha512-DZgd6860dxcq3YX7UzIXeBr6m3UgXvo9acxp5jiJyIZXdR00Br9JwVkO7e0bUeTA2d3Z8dsmtAR84Y86NnH64Q==",
|
"integrity": "sha512-DZgd6860dxcq3YX7UzIXeBr6m3UgXvo9acxp5jiJyIZXdR00Br9JwVkO7e0bUeTA2d3Z8dsmtAR84Y86NnH64Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^7.12.4",
|
"@react-navigation/core": "^7.12.4",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
@@ -7273,7 +7287,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz",
|
||||||
"integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==",
|
"integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
@@ -7308,7 +7321,6 @@
|
|||||||
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
|
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.2"
|
"csstype": "^3.0.2"
|
||||||
}
|
}
|
||||||
@@ -7430,7 +7442,6 @@
|
|||||||
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
|
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.46.2",
|
"@typescript-eslint/scope-manager": "8.46.2",
|
||||||
"@typescript-eslint/types": "8.46.2",
|
"@typescript-eslint/types": "8.46.2",
|
||||||
@@ -8119,7 +8130,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -8180,7 +8190,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ai/-/ai-5.0.78.tgz",
|
"resolved": "https://registry.npmjs.org/ai/-/ai-5.0.78.tgz",
|
||||||
"integrity": "sha512-ec77fmQwJGLduswMrW4AAUGSOiu8dZaIwMmWHHGKsrMUFFS6ugfkTyx0srtuKYHNRRLRC2dT7cPirnUl98VnxA==",
|
"integrity": "sha512-ec77fmQwJGLduswMrW4AAUGSOiu8dZaIwMmWHHGKsrMUFFS6ugfkTyx0srtuKYHNRRLRC2dT7cPirnUl98VnxA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/gateway": "2.0.1",
|
"@ai-sdk/gateway": "2.0.1",
|
||||||
"@ai-sdk/provider": "2.0.0",
|
"@ai-sdk/provider": "2.0.0",
|
||||||
@@ -9069,7 +9078,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.8.19",
|
"baseline-browser-mapping": "^2.8.19",
|
||||||
"caniuse-lite": "^1.0.30001751",
|
"caniuse-lite": "^1.0.30001751",
|
||||||
@@ -10554,7 +10562,6 @@
|
|||||||
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"json-schema-traverse": "^1.0.0",
|
"json-schema-traverse": "^1.0.0",
|
||||||
@@ -11119,7 +11126,6 @@
|
|||||||
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
|
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -11316,7 +11322,6 @@
|
|||||||
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
|
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rtsao/scc": "^1.1.0",
|
"@rtsao/scc": "^1.1.0",
|
||||||
"array-includes": "^3.1.9",
|
"array-includes": "^3.1.9",
|
||||||
@@ -11687,7 +11692,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.20.tgz",
|
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.20.tgz",
|
||||||
"integrity": "sha512-mWHky+H63W60P5Oo+VbtqzF2sLvdaoSSwG57H9rlq1DrgIla++QJZuwJkXXo55lYPymVmkVhwG6FjWYKKylwpw==",
|
"integrity": "sha512-mWHky+H63W60P5Oo+VbtqzF2sLvdaoSSwG57H9rlq1DrgIla++QJZuwJkXXo55lYPymVmkVhwG6FjWYKKylwpw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.0",
|
"@babel/runtime": "^7.20.0",
|
||||||
"@expo/cli": "54.0.13",
|
"@expo/cli": "54.0.13",
|
||||||
@@ -11860,7 +11864,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.10.tgz",
|
||||||
"integrity": "sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw==",
|
"integrity": "sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/config": "~12.0.10",
|
"@expo/config": "~12.0.10",
|
||||||
"@expo/env": "~2.0.7"
|
"@expo/env": "~2.0.7"
|
||||||
@@ -11941,7 +11944,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz",
|
||||||
"integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==",
|
"integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fontfaceobserver": "^2.1.0"
|
"fontfaceobserver": "^2.1.0"
|
||||||
},
|
},
|
||||||
@@ -12019,7 +12021,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.8.tgz",
|
||||||
"integrity": "sha512-MyeMcbFDKhXh4sDD1EHwd0uxFQNAc6VCrwBkNvvvufUsTYFq3glTA9Y8a+x78CPpjNqwNAamu74yIaIz7IEJyg==",
|
"integrity": "sha512-MyeMcbFDKhXh4sDD1EHwd0uxFQNAc6VCrwBkNvvvufUsTYFq3glTA9Y8a+x78CPpjNqwNAamu74yIaIz7IEJyg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"expo-constants": "~18.0.8",
|
"expo-constants": "~18.0.8",
|
||||||
"invariant": "^2.2.4"
|
"invariant": "^2.2.4"
|
||||||
@@ -12164,6 +12165,15 @@
|
|||||||
"node": ">=20.16.0"
|
"node": ">=20.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-sharing": {
|
||||||
|
"version": "14.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-14.0.8.tgz",
|
||||||
|
"integrity": "sha512-A1pPr2iBrxypFDCWVAESk532HK+db7MFXbvO2sCV9ienaFXAk7lIBm6bkqgE6vzRd9O3RGdEGzYx80cYlc089Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-splash-screen": {
|
"node_modules/expo-splash-screen": {
|
||||||
"version": "31.0.10",
|
"version": "31.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-31.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-31.0.10.tgz",
|
||||||
@@ -13325,7 +13335,6 @@
|
|||||||
"integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
|
"integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
|
||||||
}
|
}
|
||||||
@@ -14849,7 +14858,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
||||||
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
"integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-libc": "^2.0.3"
|
"detect-libc": "^2.0.3"
|
||||||
},
|
},
|
||||||
@@ -17315,7 +17323,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
||||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -17356,7 +17363,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
},
|
},
|
||||||
@@ -17393,7 +17399,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
|
||||||
"integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
|
"integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/create-cache-key-function": "^29.7.0",
|
"@jest/create-cache-key-function": "^29.7.0",
|
||||||
"@react-native/assets-registry": "0.81.5",
|
"@react-native/assets-registry": "0.81.5",
|
||||||
@@ -17483,7 +17488,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-edge-to-edge/-/react-native-edge-to-edge-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-edge-to-edge/-/react-native-edge-to-edge-1.7.0.tgz",
|
||||||
"integrity": "sha512-ERegbsq28yoMndn/Uq49i4h6aAhMvTEjOfkFh50yX9H/dMjjCr/Tix/es/9JcPRvC+q7VzCMWfxWDUb6Jrq1OQ==",
|
"integrity": "sha512-ERegbsq28yoMndn/Uq49i4h6aAhMvTEjOfkFh50yX9H/dMjjCr/Tix/es/9JcPRvC+q7VzCMWfxWDUb6Jrq1OQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
@@ -17503,7 +17507,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz",
|
||||||
"integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==",
|
"integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@egjs/hammerjs": "^2.0.17",
|
"@egjs/hammerjs": "^2.0.17",
|
||||||
"hoist-non-react-statics": "^3.3.0",
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
@@ -17560,7 +17563,6 @@
|
|||||||
"integrity": "sha512-+/uVS7FQwOiKYZQERMIvBRv5/X3CVHrFG6Nr/kIhVfVxGeUimHnBz7cgA97lJKIn7AKDRWL+UjLedW8pGOt0dg==",
|
"integrity": "sha512-+/uVS7FQwOiKYZQERMIvBRv5/X3CVHrFG6Nr/kIhVfVxGeUimHnBz7cgA97lJKIn7AKDRWL+UjLedW8pGOt0dg==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
@@ -17587,7 +17589,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.3.tgz",
|
||||||
"integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==",
|
"integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-native-is-edge-to-edge": "^1.2.1",
|
"react-native-is-edge-to-edge": "^1.2.1",
|
||||||
"semver": "7.7.2"
|
"semver": "7.7.2"
|
||||||
@@ -17616,7 +17617,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.1.tgz",
|
||||||
"integrity": "sha512-/wJE58HLEAkATzhhX1xSr+fostLsK8Q97EfpfMDKo8jlOc1QKESSX/FQrhk7HhQH/2uSaox4Y86sNaI02kteiA==",
|
"integrity": "sha512-/wJE58HLEAkATzhhX1xSr+fostLsK8Q97EfpfMDKo8jlOc1QKESSX/FQrhk7HhQH/2uSaox4Y86sNaI02kteiA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
@@ -17627,7 +17627,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
|
||||||
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
|
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-freeze": "^1.0.0",
|
"react-freeze": "^1.0.0",
|
||||||
"react-native-is-edge-to-edge": "^1.2.1",
|
"react-native-is-edge-to-edge": "^1.2.1",
|
||||||
@@ -17643,7 +17642,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.14.0.tgz",
|
||||||
"integrity": "sha512-B3gYc7WztcOT4N54AtUutbe0Nuqqh/nkresY0fAXzUHYLsWuIu/yGiCCD3DKfAs6GLv5LFtWTu7N333Q+e3bkg==",
|
"integrity": "sha512-B3gYc7WztcOT4N54AtUutbe0Nuqqh/nkresY0fAXzUHYLsWuIu/yGiCCD3DKfAs6GLv5LFtWTu7N333Q+e3bkg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"css-select": "^5.1.0",
|
"css-select": "^5.1.0",
|
||||||
"css-tree": "^1.1.3",
|
"css-tree": "^1.1.3",
|
||||||
@@ -17686,7 +17684,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz",
|
||||||
"integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==",
|
"integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.18.6",
|
"@babel/runtime": "^7.18.6",
|
||||||
"@react-native/normalize-colors": "^0.74.1",
|
"@react-native/normalize-colors": "^0.74.1",
|
||||||
@@ -17719,7 +17716,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz",
|
||||||
"integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==",
|
"integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
|
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
|
||||||
"@babel/plugin-transform-class-properties": "^7.0.0-0",
|
"@babel/plugin-transform-class-properties": "^7.0.0-0",
|
||||||
@@ -17835,7 +17831,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||||
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
|
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -19874,6 +19869,7 @@
|
|||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
],
|
],
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
}
|
}
|
||||||
@@ -20032,7 +20028,6 @@
|
|||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -20389,7 +20384,6 @@
|
|||||||
"integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==",
|
"integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -21106,7 +21100,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
@@ -21177,6 +21170,7 @@
|
|||||||
"expo-keep-awake": "^15.0.7",
|
"expo-keep-awake": "^15.0.7",
|
||||||
"expo-linking": "~8.0.8",
|
"expo-linking": "~8.0.8",
|
||||||
"expo-router": "~6.0.13",
|
"expo-router": "~6.0.13",
|
||||||
|
"expo-sharing": "^14.0.8",
|
||||||
"expo-splash-screen": "~31.0.10",
|
"expo-splash-screen": "~31.0.10",
|
||||||
"expo-symbols": "~1.0.7",
|
"expo-symbols": "~1.0.7",
|
||||||
"expo-system-ui": "~6.0.7",
|
"expo-system-ui": "~6.0.7",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
"expo-keep-awake": "^15.0.7",
|
"expo-keep-awake": "^15.0.7",
|
||||||
"expo-linking": "~8.0.8",
|
"expo-linking": "~8.0.8",
|
||||||
"expo-router": "~6.0.13",
|
"expo-router": "~6.0.13",
|
||||||
|
"expo-sharing": "^14.0.8",
|
||||||
"expo-splash-screen": "~31.0.10",
|
"expo-splash-screen": "~31.0.10",
|
||||||
"expo-symbols": "~1.0.7",
|
"expo-symbols": "~1.0.7",
|
||||||
"expo-system-ui": "~6.0.7",
|
"expo-system-ui": "~6.0.7",
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
|
Alert,
|
||||||
FlatList,
|
FlatList,
|
||||||
Image as RNImage,
|
Image as RNImage,
|
||||||
|
LayoutChangeEvent,
|
||||||
ListRenderItemInfo,
|
ListRenderItemInfo,
|
||||||
ViewToken,
|
ViewToken,
|
||||||
NativeScrollEvent,
|
NativeScrollEvent,
|
||||||
NativeSyntheticEvent,
|
NativeSyntheticEvent,
|
||||||
|
Modal,
|
||||||
|
Platform,
|
||||||
Pressable,
|
Pressable,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
Text,
|
Text,
|
||||||
@@ -17,21 +21,23 @@ import {
|
|||||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import * as Clipboard from "expo-clipboard";
|
import * as Clipboard from "expo-clipboard";
|
||||||
|
import * as FileSystem from "expo-file-system";
|
||||||
|
import * as Sharing from "expo-sharing";
|
||||||
import {
|
import {
|
||||||
Copy,
|
|
||||||
Check,
|
|
||||||
File,
|
File,
|
||||||
FileText,
|
FileText,
|
||||||
Folder,
|
Folder,
|
||||||
Image as ImageIcon,
|
Image as ImageIcon,
|
||||||
LayoutGrid,
|
LayoutGrid,
|
||||||
List as ListIcon,
|
List as ListIcon,
|
||||||
|
MoreVertical,
|
||||||
X,
|
X,
|
||||||
} from "lucide-react-native";
|
} from "lucide-react-native";
|
||||||
import { BackHeader } from "@/components/headers/back-header";
|
import { BackHeader } from "@/components/headers/back-header";
|
||||||
import type { ExplorerEntry } from "@/stores/session-store";
|
import type { ExplorerEntry } from "@/stores/session-store";
|
||||||
import type { ConnectionStatus } from "@/contexts/daemon-connections-context";
|
import type { ConnectionStatus } from "@/contexts/daemon-connections-context";
|
||||||
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
|
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
|
||||||
|
import type { DaemonProfile } from "@/contexts/daemon-registry-context";
|
||||||
import { formatConnectionStatus } from "@/utils/daemons";
|
import { formatConnectionStatus } from "@/utils/daemons";
|
||||||
import { useSessionStore } from "@/stores/session-store";
|
import { useSessionStore } from "@/stores/session-store";
|
||||||
|
|
||||||
@@ -109,6 +115,8 @@ function FileExplorerContent({
|
|||||||
fileParamRaw,
|
fileParamRaw,
|
||||||
}: FileExplorerContentProps) {
|
}: FileExplorerContentProps) {
|
||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
|
const { connectionStates } = useDaemonConnections();
|
||||||
|
const daemonProfile = connectionStates.get(serverId)?.daemon;
|
||||||
|
|
||||||
const agent = useSessionStore((state) =>
|
const agent = useSessionStore((state) =>
|
||||||
agentId && state.sessions[serverId]
|
agentId && state.sessions[serverId]
|
||||||
@@ -125,18 +133,17 @@ function FileExplorerContent({
|
|||||||
const methods = useSessionStore((state) => state.sessions[serverId]?.methods);
|
const methods = useSessionStore((state) => state.sessions[serverId]?.methods);
|
||||||
const requestDirectoryListing = methods?.requestDirectoryListing;
|
const requestDirectoryListing = methods?.requestDirectoryListing;
|
||||||
const requestFilePreview = methods?.requestFilePreview;
|
const requestFilePreview = methods?.requestFilePreview;
|
||||||
|
const requestFileDownloadToken = methods?.requestFileDownloadToken;
|
||||||
const navigateExplorerBack = methods?.navigateExplorerBack;
|
const navigateExplorerBack = methods?.navigateExplorerBack;
|
||||||
const [viewMode, setViewMode] = useState<"list" | "grid">("list");
|
const [viewMode, setViewMode] = useState<"list" | "grid">("list");
|
||||||
const [selectedEntryPath, setSelectedEntryPath] = useState<string | null>(null);
|
const [selectedEntryPath, setSelectedEntryPath] = useState<string | null>(null);
|
||||||
const pendingPathParamRef = useRef<string | null>(null);
|
const pendingPathParamRef = useRef<string | null>(null);
|
||||||
const pendingFileParamRef = useRef<string | null>(null);
|
const pendingFileParamRef = useRef<string | null>(null);
|
||||||
const [copiedPath, setCopiedPath] = useState<string | null>(null);
|
|
||||||
const copyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
||||||
const listScrollRef = useRef<FlatList<ExplorerEntry> | null>(null);
|
const listScrollRef = useRef<FlatList<ExplorerEntry> | null>(null);
|
||||||
const listScrollOffsetRef = useRef(0);
|
const listScrollOffsetRef = useRef(0);
|
||||||
const scrollOffsetsByPathRef = useRef<Map<string, number>>(new Map());
|
const scrollOffsetsByPathRef = useRef<Map<string, number>>(new Map());
|
||||||
const pendingScrollRestoreRef = useRef<number | null>(null);
|
const pendingScrollRestoreRef = useRef<number | null>(null);
|
||||||
const { width: windowWidth } = useWindowDimensions();
|
const { width: windowWidth, height: windowHeight } = useWindowDimensions();
|
||||||
|
|
||||||
const normalizedPathParam = normalizePathParam(getFirstParam(pathParamRaw));
|
const normalizedPathParam = normalizePathParam(getFirstParam(pathParamRaw));
|
||||||
const normalizedFileParam = normalizeFileParam(getFirstParam(fileParamRaw));
|
const normalizedFileParam = normalizeFileParam(getFirstParam(fileParamRaw));
|
||||||
@@ -196,6 +203,60 @@ function FileExplorerContent({
|
|||||||
}, [windowWidth]);
|
}, [windowWidth]);
|
||||||
const listColumns = viewMode === "grid" ? gridColumnCount : 1;
|
const listColumns = viewMode === "grid" ? gridColumnCount : 1;
|
||||||
const listKey = viewMode === "grid" ? `grid-${gridColumnCount}` : "list";
|
const listKey = viewMode === "grid" ? `grid-${gridColumnCount}` : "list";
|
||||||
|
const [menuEntry, setMenuEntry] = useState<ExplorerEntry | null>(null);
|
||||||
|
const [menuAnchor, setMenuAnchor] = useState({ top: 0, left: 0 });
|
||||||
|
const [menuHeight, setMenuHeight] = useState(0);
|
||||||
|
const agentIdRef = useRef(agentId);
|
||||||
|
const viewModeRef = useRef(viewMode);
|
||||||
|
const requestFilePreviewRef = useRef(requestFilePreview);
|
||||||
|
const explorerFilesRef = useRef(explorerState?.files);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
agentIdRef.current = agentId;
|
||||||
|
}, [agentId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
viewModeRef.current = viewMode;
|
||||||
|
}, [viewMode]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
requestFilePreviewRef.current = requestFilePreview;
|
||||||
|
}, [requestFilePreview]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
explorerFilesRef.current = explorerState?.files;
|
||||||
|
}, [explorerState?.files]);
|
||||||
|
|
||||||
|
const handleViewableItemsChangedRef = useRef(
|
||||||
|
({ viewableItems }: { viewableItems: Array<ViewToken> }) => {
|
||||||
|
const currentAgentId = agentIdRef.current;
|
||||||
|
const currentViewMode = viewModeRef.current;
|
||||||
|
const currentRequestFilePreview = requestFilePreviewRef.current;
|
||||||
|
if (!currentAgentId || currentViewMode !== "grid" || !currentRequestFilePreview) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewableItems.forEach((token) => {
|
||||||
|
const item = token.item as ExplorerEntry | undefined;
|
||||||
|
if (!item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getEntryDisplayKind(item) !== "image") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasPreview = explorerFilesRef.current?.get(item.path);
|
||||||
|
if (hasPreview || pendingThumbnailPathsRef.current.has(item.path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingThumbnailPathsRef.current.add(item.path);
|
||||||
|
setThumbnailLoadingMap((prev) => ({ ...prev, [item.path]: true }));
|
||||||
|
currentRequestFilePreview(currentAgentId, item.path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const restoreQueuedScrollOffset = useCallback(() => {
|
const restoreQueuedScrollOffset = useCallback(() => {
|
||||||
if (pendingScrollRestoreRef.current === null) {
|
if (pendingScrollRestoreRef.current === null) {
|
||||||
@@ -236,10 +297,6 @@ function FileExplorerContent({
|
|||||||
queueScrollRestore(savedOffset);
|
queueScrollRestore(savedOffset);
|
||||||
}, [activePath, queueScrollRestore]);
|
}, [activePath, queueScrollRestore]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setCopiedPath(null);
|
|
||||||
}, [activePath]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!agentId || !initialTargetDirectory || !requestDirectoryListing) {
|
if (!agentId || !initialTargetDirectory || !requestDirectoryListing) {
|
||||||
pendingPathParamRef.current = null;
|
pendingPathParamRef.current = null;
|
||||||
@@ -303,24 +360,103 @@ function FileExplorerContent({
|
|||||||
|
|
||||||
const handleCopyPath = useCallback(async (path: string) => {
|
const handleCopyPath = useCallback(async (path: string) => {
|
||||||
await Clipboard.setStringAsync(path);
|
await Clipboard.setStringAsync(path);
|
||||||
setCopiedPath(path);
|
|
||||||
if (copyTimeoutRef.current) {
|
|
||||||
clearTimeout(copyTimeoutRef.current);
|
|
||||||
}
|
|
||||||
copyTimeoutRef.current = setTimeout(() => {
|
|
||||||
setCopiedPath(null);
|
|
||||||
copyTimeoutRef.current = null;
|
|
||||||
}, 1500);
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
const handleOpenMenu = useCallback((entry: ExplorerEntry, event: any) => {
|
||||||
return () => {
|
event.stopPropagation();
|
||||||
if (copyTimeoutRef.current) {
|
const { pageX, pageY } = event.nativeEvent ?? {};
|
||||||
clearTimeout(copyTimeoutRef.current);
|
setMenuAnchor({
|
||||||
}
|
left: typeof pageX === "number" ? pageX : 0,
|
||||||
};
|
top: typeof pageY === "number" ? pageY : 0,
|
||||||
|
});
|
||||||
|
setMenuEntry(entry);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleCloseMenu = useCallback(() => {
|
||||||
|
setMenuEntry(null);
|
||||||
|
setMenuHeight(0);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleMenuLayout = useCallback((event: LayoutChangeEvent) => {
|
||||||
|
const { height } = event.nativeEvent.layout;
|
||||||
|
setMenuHeight((current) => (current === height ? current : height));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDownloadEntry = useCallback(
|
||||||
|
async (entry: ExplorerEntry) => {
|
||||||
|
if (!agentId || !requestFileDownloadToken || entry.kind !== "file") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tokenResponse = await requestFileDownloadToken(agentId, entry.path);
|
||||||
|
if (tokenResponse.error || !tokenResponse.token) {
|
||||||
|
throw new Error(tokenResponse.error ?? "Failed to request download token.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const downloadTarget = resolveDaemonDownloadTarget(daemonProfile);
|
||||||
|
if (!downloadTarget.baseUrl) {
|
||||||
|
throw new Error("Download host is unavailable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileName = tokenResponse.fileName ?? entry.name;
|
||||||
|
const downloadUrl = buildDownloadUrl(
|
||||||
|
downloadTarget.baseUrl,
|
||||||
|
tokenResponse.token,
|
||||||
|
Platform.OS === "web" ? downloadTarget.authCredentials : null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Platform.OS === "web") {
|
||||||
|
triggerBrowserDownload(downloadUrl, fileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetUri = await resolveDownloadTargetUri(fileName);
|
||||||
|
const downloadResult = await FileSystem.downloadAsync(
|
||||||
|
downloadUrl,
|
||||||
|
targetUri,
|
||||||
|
downloadTarget.authHeader
|
||||||
|
? { headers: { Authorization: downloadTarget.authHeader } }
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
if (await Sharing.isAvailableAsync()) {
|
||||||
|
await Sharing.shareAsync(downloadResult.uri, {
|
||||||
|
mimeType: tokenResponse.mimeType ?? undefined,
|
||||||
|
dialogTitle: fileName ? `Share ${fileName}` : "Share file",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Alert.alert("Download complete", `Saved to ${downloadResult.uri}`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const message =
|
||||||
|
error instanceof Error ? error.message : "Failed to download file.";
|
||||||
|
if (Platform.OS === "web") {
|
||||||
|
console.warn("[FileExplorer] Download failed:", message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Alert.alert("Download failed", message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[agentId, daemonProfile, requestFileDownloadToken]
|
||||||
|
);
|
||||||
|
|
||||||
|
const menuPosition = useMemo(() => {
|
||||||
|
if (!menuEntry) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const menuWidth = 180;
|
||||||
|
const horizontalPadding = theme.spacing[2];
|
||||||
|
const verticalPadding = theme.spacing[2];
|
||||||
|
const maxLeft = Math.max(horizontalPadding, windowWidth - menuWidth - horizontalPadding);
|
||||||
|
const maxTop = Math.max(verticalPadding, windowHeight - menuHeight - verticalPadding);
|
||||||
|
const left = Math.min(
|
||||||
|
Math.max(menuAnchor.left - menuWidth + horizontalPadding, horizontalPadding),
|
||||||
|
maxLeft
|
||||||
|
);
|
||||||
|
const top = Math.min(Math.max(menuAnchor.top + verticalPadding, verticalPadding), maxTop);
|
||||||
|
return { top, left, width: menuWidth };
|
||||||
|
}, [menuEntry, menuAnchor.left, menuAnchor.top, menuHeight, theme.spacing, windowHeight, windowWidth]);
|
||||||
|
|
||||||
const handleListScroll = useCallback(
|
const handleListScroll = useCallback(
|
||||||
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
const offset = event.nativeEvent.contentOffset.y;
|
const offset = event.nativeEvent.contentOffset.y;
|
||||||
@@ -342,6 +478,13 @@ function FileExplorerContent({
|
|||||||
router.back();
|
router.back();
|
||||||
}, [agentId, serverId]);
|
}, [agentId, serverId]);
|
||||||
|
|
||||||
|
const handleRetryDirectory = useCallback(() => {
|
||||||
|
if (!agentId || !requestDirectoryListing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
requestDirectoryListing(agentId, activePath);
|
||||||
|
}, [agentId, requestDirectoryListing, activePath]);
|
||||||
|
|
||||||
const handleBackNavigation = useCallback(() => {
|
const handleBackNavigation = useCallback(() => {
|
||||||
if (!agentId) {
|
if (!agentId) {
|
||||||
router.back();
|
router.back();
|
||||||
@@ -429,27 +572,19 @@ function FileExplorerContent({
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={(event) => {
|
onPress={(event) => handleOpenMenu(item, event)}
|
||||||
event.stopPropagation();
|
|
||||||
handleCopyPath(item.path);
|
|
||||||
}}
|
|
||||||
hitSlop={8}
|
hitSlop={8}
|
||||||
style={styles.copyButton}
|
style={styles.menuButton}
|
||||||
>
|
>
|
||||||
{copiedPath === item.path ? (
|
<MoreVertical size={16} color={theme.colors.foreground} />
|
||||||
<Check size={16} color={theme.colors.primary} />
|
|
||||||
) : (
|
|
||||||
<Copy size={16} color={theme.colors.foreground} />
|
|
||||||
)}
|
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
copiedPath,
|
|
||||||
explorerState?.files,
|
explorerState?.files,
|
||||||
handleCopyPath,
|
|
||||||
handleEntryPress,
|
handleEntryPress,
|
||||||
|
handleOpenMenu,
|
||||||
theme.colors,
|
theme.colors,
|
||||||
thumbnailLoadingMap,
|
thumbnailLoadingMap,
|
||||||
viewMode,
|
viewMode,
|
||||||
@@ -474,35 +609,6 @@ function FileExplorerContent({
|
|||||||
);
|
);
|
||||||
}, [activePath, showListLoadingBanner, viewMode]);
|
}, [activePath, showListLoadingBanner, viewMode]);
|
||||||
|
|
||||||
const handleViewableItemsChanged = useCallback(
|
|
||||||
({ viewableItems }: { viewableItems: Array<ViewToken> }) => {
|
|
||||||
if (!agentId || viewMode !== "grid" || !requestFilePreview) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
viewableItems.forEach((token) => {
|
|
||||||
const item = token.item as ExplorerEntry | undefined;
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getEntryDisplayKind(item) !== "image") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasPreview = explorerState?.files.get(item.path);
|
|
||||||
if (hasPreview || pendingThumbnailPathsRef.current.has(item.path)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pendingThumbnailPathsRef.current.add(item.path);
|
|
||||||
setThumbnailLoadingMap((prev) => ({ ...prev, [item.path]: true }));
|
|
||||||
requestFilePreview(agentId, item.path);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[agentId, explorerState?.files, requestFilePreview, viewMode]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!explorerState) {
|
if (!explorerState) {
|
||||||
return;
|
return;
|
||||||
@@ -607,6 +713,9 @@ function FileExplorerContent({
|
|||||||
{error ? (
|
{error ? (
|
||||||
<View style={styles.centerState}>
|
<View style={styles.centerState}>
|
||||||
<Text style={styles.errorText}>{error}</Text>
|
<Text style={styles.errorText}>{error}</Text>
|
||||||
|
<Pressable style={styles.retryButton} onPress={handleRetryDirectory}>
|
||||||
|
<Text style={styles.retryButtonText}>Retry</Text>
|
||||||
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
) : showInitialListLoading ? (
|
) : showInitialListLoading ? (
|
||||||
<View style={styles.centerState}>
|
<View style={styles.centerState}>
|
||||||
@@ -638,17 +747,63 @@ function FileExplorerContent({
|
|||||||
onLayout={restoreQueuedScrollOffset}
|
onLayout={restoreQueuedScrollOffset}
|
||||||
onContentSizeChange={restoreQueuedScrollOffset}
|
onContentSizeChange={restoreQueuedScrollOffset}
|
||||||
ListHeaderComponent={listHeaderComponent}
|
ListHeaderComponent={listHeaderComponent}
|
||||||
extraData={{ copiedPath, viewMode, thumbnailLoadingMap }}
|
extraData={{ viewMode, thumbnailLoadingMap }}
|
||||||
initialNumToRender={20}
|
initialNumToRender={20}
|
||||||
maxToRenderPerBatch={30}
|
maxToRenderPerBatch={30}
|
||||||
windowSize={10}
|
windowSize={10}
|
||||||
onViewableItemsChanged={handleViewableItemsChanged}
|
onViewableItemsChanged={handleViewableItemsChangedRef.current}
|
||||||
viewabilityConfig={viewabilityConfigRef.current}
|
viewabilityConfig={viewabilityConfigRef.current}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
visible={Boolean(menuEntry)}
|
||||||
|
animationType="fade"
|
||||||
|
transparent={true}
|
||||||
|
onRequestClose={handleCloseMenu}
|
||||||
|
>
|
||||||
|
<View style={styles.menuOverlay}>
|
||||||
|
<Pressable style={styles.menuBackdrop} onPress={handleCloseMenu} />
|
||||||
|
{menuEntry && menuPosition ? (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.entryMenu,
|
||||||
|
{
|
||||||
|
position: "absolute",
|
||||||
|
top: menuPosition.top,
|
||||||
|
left: menuPosition.left,
|
||||||
|
width: menuPosition.width,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onLayout={handleMenuLayout}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
|
style={styles.entryMenuItem}
|
||||||
|
onPress={() => {
|
||||||
|
handleCopyPath(menuEntry.path);
|
||||||
|
handleCloseMenu();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={styles.entryMenuText}>Copy Path</Text>
|
||||||
|
</Pressable>
|
||||||
|
{menuEntry.kind === "file" ? (
|
||||||
|
<Pressable
|
||||||
|
style={styles.entryMenuItem}
|
||||||
|
onPress={async () => {
|
||||||
|
handleCloseMenu();
|
||||||
|
await handleDownloadEntry(menuEntry);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={styles.entryMenuText}>Download</Text>
|
||||||
|
</Pressable>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -898,6 +1053,120 @@ function getExtension(name: string): string | null {
|
|||||||
return name.slice(index + 1).toLowerCase();
|
return name.slice(index + 1).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DownloadTarget = {
|
||||||
|
baseUrl: string | null;
|
||||||
|
authHeader: string | null;
|
||||||
|
authCredentials: { username: string; password: string } | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function resolveDaemonDownloadTarget(daemon?: DaemonProfile): DownloadTarget {
|
||||||
|
const rawUrl = daemon?.restUrl ?? daemon?.wsUrl;
|
||||||
|
if (!rawUrl) {
|
||||||
|
return { baseUrl: null, authHeader: null, authCredentials: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsed: URL;
|
||||||
|
try {
|
||||||
|
parsed = new URL(rawUrl);
|
||||||
|
} catch {
|
||||||
|
return { baseUrl: null, authHeader: null, authCredentials: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed.protocol === "ws:") {
|
||||||
|
parsed.protocol = "http:";
|
||||||
|
} else if (parsed.protocol === "wss:") {
|
||||||
|
parsed.protocol = "https:";
|
||||||
|
}
|
||||||
|
|
||||||
|
let authCredentials: { username: string; password: string } | null = null;
|
||||||
|
if (parsed.username || parsed.password) {
|
||||||
|
authCredentials = {
|
||||||
|
username: decodeURIComponent(parsed.username),
|
||||||
|
password: decodeURIComponent(parsed.password),
|
||||||
|
};
|
||||||
|
parsed.username = "";
|
||||||
|
parsed.password = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed.pathname = parsed.pathname.replace(/\/ws\/?$/, "/");
|
||||||
|
|
||||||
|
const baseUrl = parsed.origin;
|
||||||
|
const authHeader = authCredentials
|
||||||
|
? `Basic ${btoa(`${authCredentials.username}:${authCredentials.password}`)}`
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return { baseUrl, authHeader, authCredentials };
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildDownloadUrl(
|
||||||
|
baseUrl: string,
|
||||||
|
token: string,
|
||||||
|
authCredentials: { username: string; password: string } | null
|
||||||
|
): string {
|
||||||
|
const url = new URL("/api/files/download", baseUrl);
|
||||||
|
url.searchParams.set("token", token);
|
||||||
|
if (authCredentials) {
|
||||||
|
url.username = authCredentials.username;
|
||||||
|
url.password = authCredentials.password;
|
||||||
|
}
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function triggerBrowserDownload(url: string, fileName: string) {
|
||||||
|
if (typeof document === "undefined") {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
window.open(url, "_blank", "noopener");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.href = url;
|
||||||
|
link.download = fileName;
|
||||||
|
link.rel = "noopener";
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
link.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveDownloadTargetUri(fileName: string): Promise<string> {
|
||||||
|
const directory = FileSystem.Paths.cache?.uri ?? FileSystem.Paths.document?.uri;
|
||||||
|
if (!directory) {
|
||||||
|
throw new Error("No download directory available.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const safeName = sanitizeDownloadFileName(fileName);
|
||||||
|
const split = splitFileName(safeName);
|
||||||
|
let targetUri = `${directory}${safeName}`;
|
||||||
|
let suffix = 1;
|
||||||
|
|
||||||
|
while ((await FileSystem.getInfoAsync(targetUri)).exists) {
|
||||||
|
targetUri = `${directory}${split.base} (${suffix})${split.ext}`;
|
||||||
|
suffix += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitizeDownloadFileName(fileName: string): string {
|
||||||
|
const trimmed = fileName.trim();
|
||||||
|
if (!trimmed) {
|
||||||
|
return "download";
|
||||||
|
}
|
||||||
|
return trimmed.replace(/[\\/:*?"<>|]+/g, "_");
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitFileName(fileName: string): { base: string; ext: string } {
|
||||||
|
const lastDot = fileName.lastIndexOf(".");
|
||||||
|
if (lastDot <= 0) {
|
||||||
|
return { base: fileName, ext: "" };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
base: fileName.slice(0, lastDot),
|
||||||
|
ext: fileName.slice(lastDot),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create((theme) => ({
|
const styles = StyleSheet.create((theme) => ({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -962,6 +1231,18 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontSize: theme.fontSize.base,
|
fontSize: theme.fontSize.base,
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
},
|
},
|
||||||
|
retryButton: {
|
||||||
|
borderRadius: theme.borderRadius.full,
|
||||||
|
borderWidth: theme.borderWidth[1],
|
||||||
|
borderColor: theme.colors.primary,
|
||||||
|
paddingHorizontal: theme.spacing[3],
|
||||||
|
paddingVertical: theme.spacing[1],
|
||||||
|
},
|
||||||
|
retryButtonText: {
|
||||||
|
color: theme.colors.primary,
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
fontWeight: theme.fontWeight.semibold,
|
||||||
|
},
|
||||||
statusText: {
|
statusText: {
|
||||||
color: theme.colors.mutedForeground,
|
color: theme.colors.mutedForeground,
|
||||||
fontSize: theme.fontSize.sm,
|
fontSize: theme.fontSize.sm,
|
||||||
@@ -1037,13 +1318,37 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
marginTop: theme.spacing[1],
|
marginTop: theme.spacing[1],
|
||||||
},
|
},
|
||||||
copyButton: {
|
menuButton: {
|
||||||
width: 36,
|
width: 36,
|
||||||
height: 36,
|
height: 36,
|
||||||
borderRadius: theme.borderRadius.full,
|
borderRadius: theme.borderRadius.full,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
|
menuOverlay: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
menuBackdrop: {
|
||||||
|
...StyleSheet.absoluteFillObject,
|
||||||
|
backgroundColor: "rgba(0, 0, 0, 0.2)",
|
||||||
|
},
|
||||||
|
entryMenu: {
|
||||||
|
borderRadius: theme.borderRadius.md,
|
||||||
|
borderWidth: theme.borderWidth[1],
|
||||||
|
borderColor: theme.colors.border,
|
||||||
|
backgroundColor: theme.colors.card,
|
||||||
|
padding: theme.spacing[1],
|
||||||
|
},
|
||||||
|
entryMenuItem: {
|
||||||
|
paddingVertical: theme.spacing[2],
|
||||||
|
paddingHorizontal: theme.spacing[3],
|
||||||
|
borderRadius: theme.borderRadius.md,
|
||||||
|
},
|
||||||
|
entryMenuText: {
|
||||||
|
color: theme.colors.foreground,
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
fontWeight: theme.fontWeight.semibold,
|
||||||
|
},
|
||||||
viewToggleContainer: {
|
viewToggleContainer: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
borderRadius: theme.borderRadius.full,
|
borderRadius: theme.borderRadius.full,
|
||||||
|
|||||||
@@ -60,6 +60,11 @@ type FileExplorerResponseMessage = Extract<
|
|||||||
{ type: "file_explorer_response" }
|
{ type: "file_explorer_response" }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
type FileDownloadTokenResponseMessage = Extract<
|
||||||
|
SessionOutboundMessage,
|
||||||
|
{ type: "file_download_token_response" }
|
||||||
|
>;
|
||||||
|
|
||||||
type StatusMessage = Extract<SessionOutboundMessage, { type: "status" }>;
|
type StatusMessage = Extract<SessionOutboundMessage, { type: "status" }>;
|
||||||
|
|
||||||
const SESSION_SNAPSHOT_STORAGE_PREFIX = "@paseo:session-snapshot:";
|
const SESSION_SNAPSHOT_STORAGE_PREFIX = "@paseo:session-snapshot:";
|
||||||
@@ -173,6 +178,7 @@ export interface SessionContextValue {
|
|||||||
requestGitDiff: (agentId: string) => void;
|
requestGitDiff: (agentId: string) => void;
|
||||||
requestDirectoryListing: (agentId: string, path: string, options?: { recordHistory?: boolean }) => void;
|
requestDirectoryListing: (agentId: string, path: string, options?: { recordHistory?: boolean }) => void;
|
||||||
requestFilePreview: (agentId: string, path: string) => void;
|
requestFilePreview: (agentId: string, path: string) => void;
|
||||||
|
requestFileDownloadToken: (agentId: string, path: string) => Promise<FileDownloadTokenResponseMessage["payload"]>;
|
||||||
navigateExplorerBack: (agentId: string) => string | null;
|
navigateExplorerBack: (agentId: string) => string | null;
|
||||||
requestProviderModels: (provider: any, options?: { cwd?: string }) => void;
|
requestProviderModels: (provider: any, options?: { cwd?: string }) => void;
|
||||||
restartServer: (reason?: string) => void;
|
restartServer: (reason?: string) => void;
|
||||||
@@ -503,6 +509,40 @@ export function SessionProvider({ children, serverUrl, serverId }: SessionProvid
|
|||||||
keepPreviousData: false,
|
keepPreviousData: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fileDownloadTokenRequest = useDaemonRequest<
|
||||||
|
{ agentId: string; path: string },
|
||||||
|
FileDownloadTokenResponseMessage["payload"],
|
||||||
|
FileDownloadTokenResponseMessage
|
||||||
|
>({
|
||||||
|
ws,
|
||||||
|
responseType: "file_download_token_response",
|
||||||
|
buildRequest: ({ params, requestId }) => ({
|
||||||
|
type: "session",
|
||||||
|
message: {
|
||||||
|
type: "file_download_token_request",
|
||||||
|
agentId: params?.agentId ?? "",
|
||||||
|
path: params?.path ?? "",
|
||||||
|
requestId,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
matchResponse: (message, context) => {
|
||||||
|
if (message.payload.requestId) {
|
||||||
|
return message.payload.requestId === context.requestId;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
message.payload.agentId === context.params?.agentId &&
|
||||||
|
message.payload.path === context.params?.path
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getRequestKey: (params) =>
|
||||||
|
params ? `${params.agentId}:download:${params.path}` : "default",
|
||||||
|
selectData: (message) => message.payload,
|
||||||
|
extractError: (message) =>
|
||||||
|
message.payload.error ? new Error(message.payload.error) : null,
|
||||||
|
timeoutMs: 10000,
|
||||||
|
keepPreviousData: false,
|
||||||
|
});
|
||||||
|
|
||||||
const initializeAgentRpc = useSessionRpc({
|
const initializeAgentRpc = useSessionRpc({
|
||||||
ws,
|
ws,
|
||||||
requestType: "initialize_agent_request",
|
requestType: "initialize_agent_request",
|
||||||
@@ -1635,6 +1675,13 @@ export function SessionProvider({ children, serverUrl, serverId }: SessionProvid
|
|||||||
});
|
});
|
||||||
}, [filePreviewRequest, updateExplorerState]);
|
}, [filePreviewRequest, updateExplorerState]);
|
||||||
|
|
||||||
|
const requestFileDownloadToken = useCallback(
|
||||||
|
(agentId: string, path: string) => {
|
||||||
|
return fileDownloadTokenRequest.execute({ agentId, path });
|
||||||
|
},
|
||||||
|
[fileDownloadTokenRequest]
|
||||||
|
);
|
||||||
|
|
||||||
const navigateExplorerBack = useCallback((agentId: string) => {
|
const navigateExplorerBack = useCallback((agentId: string) => {
|
||||||
let targetPath: string | null = null;
|
let targetPath: string | null = null;
|
||||||
|
|
||||||
@@ -1721,6 +1768,7 @@ export function SessionProvider({ children, serverUrl, serverId }: SessionProvid
|
|||||||
requestGitDiff,
|
requestGitDiff,
|
||||||
requestDirectoryListing,
|
requestDirectoryListing,
|
||||||
requestFilePreview,
|
requestFilePreview,
|
||||||
|
requestFileDownloadToken,
|
||||||
navigateExplorerBack,
|
navigateExplorerBack,
|
||||||
requestProviderModels,
|
requestProviderModels,
|
||||||
restartServer,
|
restartServer,
|
||||||
@@ -1744,6 +1792,7 @@ export function SessionProvider({ children, serverUrl, serverId }: SessionProvid
|
|||||||
requestGitDiff,
|
requestGitDiff,
|
||||||
requestDirectoryListing,
|
requestDirectoryListing,
|
||||||
requestFilePreview,
|
requestFilePreview,
|
||||||
|
requestFileDownloadToken,
|
||||||
navigateExplorerBack,
|
navigateExplorerBack,
|
||||||
requestProviderModels,
|
requestProviderModels,
|
||||||
restartServer,
|
restartServer,
|
||||||
@@ -1769,6 +1818,7 @@ export function SessionProvider({ children, serverUrl, serverId }: SessionProvid
|
|||||||
requestGitDiff,
|
requestGitDiff,
|
||||||
requestDirectoryListing,
|
requestDirectoryListing,
|
||||||
requestFilePreview,
|
requestFilePreview,
|
||||||
|
requestFileDownloadToken,
|
||||||
navigateExplorerBack,
|
navigateExplorerBack,
|
||||||
requestProviderModels,
|
requestProviderModels,
|
||||||
restartServer,
|
restartServer,
|
||||||
@@ -1788,6 +1838,7 @@ export function SessionProvider({ children, serverUrl, serverId }: SessionProvid
|
|||||||
requestGitDiff,
|
requestGitDiff,
|
||||||
requestDirectoryListing,
|
requestDirectoryListing,
|
||||||
requestFilePreview,
|
requestFilePreview,
|
||||||
|
requestFileDownloadToken,
|
||||||
navigateExplorerBack,
|
navigateExplorerBack,
|
||||||
requestProviderModels,
|
requestProviderModels,
|
||||||
restartServer,
|
restartServer,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import type {
|
|||||||
AgentUsage,
|
AgentUsage,
|
||||||
AgentPersistenceHandle,
|
AgentPersistenceHandle,
|
||||||
} from "@server/server/agent/agent-sdk-types";
|
} from "@server/server/agent/agent-sdk-types";
|
||||||
import type { GitSetupOptions } from "@server/server/messages";
|
import type { FileDownloadTokenResponse, GitSetupOptions } from "@server/server/messages";
|
||||||
import { isPerfLoggingEnabled, measurePayload, perfLog } from "@/utils/perf";
|
import { isPerfLoggingEnabled, measurePayload, perfLog } from "@/utils/perf";
|
||||||
|
|
||||||
// Re-export types that were in session-context
|
// Re-export types that were in session-context
|
||||||
@@ -177,6 +177,7 @@ export interface SessionState {
|
|||||||
requestGitDiff: (agentId: string) => void;
|
requestGitDiff: (agentId: string) => void;
|
||||||
requestDirectoryListing: (agentId: string, path: string, options?: { recordHistory?: boolean }) => void;
|
requestDirectoryListing: (agentId: string, path: string, options?: { recordHistory?: boolean }) => void;
|
||||||
requestFilePreview: (agentId: string, path: string) => void;
|
requestFilePreview: (agentId: string, path: string) => void;
|
||||||
|
requestFileDownloadToken: (agentId: string, path: string) => Promise<FileDownloadTokenResponse["payload"]>;
|
||||||
navigateExplorerBack: (agentId: string) => string | null;
|
navigateExplorerBack: (agentId: string) => string | null;
|
||||||
requestProviderModels: (provider: any, options?: { cwd?: string }) => void;
|
requestProviderModels: (provider: any, options?: { cwd?: string }) => void;
|
||||||
restartServer: (reason?: string) => void;
|
restartServer: (reason?: string) => void;
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ export async function createPaseoDaemon(
|
|||||||
realm: authRealm,
|
realm: authRealm,
|
||||||
});
|
});
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
|
if (req.path === "/api/files/download") {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
if (agentMcpBearerToken && req.path.startsWith(agentMcpRoute)) {
|
if (agentMcpBearerToken && req.path.startsWith(agentMcpRoute)) {
|
||||||
const authHeader = req.header("authorization") ?? "";
|
const authHeader = req.header("authorization") ?? "";
|
||||||
if (authHeader.startsWith("Bearer ")) {
|
if (authHeader.startsWith("Bearer ")) {
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ const TEXT_EXTENSIONS = new Set([
|
|||||||
".sh",
|
".sh",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const TEXT_MIME_TYPES: Record<string, string> = {
|
||||||
|
".json": "application/json",
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_TEXT_MIME_TYPE = "text/plain";
|
||||||
|
|
||||||
const IMAGE_MIME_TYPES: Record<string, string> = {
|
const IMAGE_MIME_TYPES: Record<string, string> = {
|
||||||
".png": "image/png",
|
".png": "image/png",
|
||||||
".jpg": "image/jpeg",
|
".jpg": "image/jpeg",
|
||||||
@@ -140,7 +146,7 @@ export async function readExplorerFile({
|
|||||||
kind: "text",
|
kind: "text",
|
||||||
encoding: "utf-8",
|
encoding: "utf-8",
|
||||||
content,
|
content,
|
||||||
mimeType: "text/plain",
|
mimeType: TEXT_MIME_TYPES[ext] ?? DEFAULT_TEXT_MIME_TYPE,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +188,7 @@ export async function getDownloadableFileInfo({
|
|||||||
|
|
||||||
const ext = path.extname(filePath).toLowerCase();
|
const ext = path.extname(filePath).toLowerCase();
|
||||||
const mimeType = TEXT_EXTENSIONS.has(ext)
|
const mimeType = TEXT_EXTENSIONS.has(ext)
|
||||||
? "text/plain"
|
? TEXT_MIME_TYPES[ext] ?? DEFAULT_TEXT_MIME_TYPE
|
||||||
: ext in IMAGE_MIME_TYPES
|
: ext in IMAGE_MIME_TYPES
|
||||||
? IMAGE_MIME_TYPES[ext]
|
? IMAGE_MIME_TYPES[ext]
|
||||||
: "application/octet-stream";
|
: "application/octet-stream";
|
||||||
|
|||||||
@@ -487,6 +487,7 @@ export const FileDownloadTokenRequestSchema = z.object({
|
|||||||
type: z.literal("file_download_token_request"),
|
type: z.literal("file_download_token_request"),
|
||||||
agentId: z.string(),
|
agentId: z.string(),
|
||||||
path: z.string(),
|
path: z.string(),
|
||||||
|
requestId: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ClearAgentAttentionMessageSchema = z.object({
|
export const ClearAgentAttentionMessageSchema = z.object({
|
||||||
@@ -761,6 +762,7 @@ export const FileDownloadTokenResponseSchema = z.object({
|
|||||||
mimeType: z.string().nullable(),
|
mimeType: z.string().nullable(),
|
||||||
size: z.number().nullable(),
|
size: z.number().nullable(),
|
||||||
error: z.string().nullable(),
|
error: z.string().nullable(),
|
||||||
|
requestId: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2098,7 +2098,7 @@ export class Session {
|
|||||||
private async handleFileDownloadTokenRequest(
|
private async handleFileDownloadTokenRequest(
|
||||||
request: FileDownloadTokenRequest
|
request: FileDownloadTokenRequest
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { agentId, path: requestedPath } = request;
|
const { agentId, path: requestedPath, requestId } = request;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`[Session ${this.clientId}] Handling file download token request for agent ${agentId} (${requestedPath})`
|
`[Session ${this.clientId}] Handling file download token request for agent ${agentId} (${requestedPath})`
|
||||||
@@ -2119,6 +2119,7 @@ export class Session {
|
|||||||
mimeType: null,
|
mimeType: null,
|
||||||
size: null,
|
size: null,
|
||||||
error: `Agent not found: ${agentId}`,
|
error: `Agent not found: ${agentId}`,
|
||||||
|
...(requestId ? { requestId } : {}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -2148,6 +2149,7 @@ export class Session {
|
|||||||
mimeType: entry.mimeType,
|
mimeType: entry.mimeType,
|
||||||
size: entry.size,
|
size: entry.size,
|
||||||
error: null,
|
error: null,
|
||||||
|
...(requestId ? { requestId } : {}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -2165,6 +2167,7 @@ export class Session {
|
|||||||
mimeType: null,
|
mimeType: null,
|
||||||
size: null,
|
size: null,
|
||||||
error: error.message,
|
error: error.message,
|
||||||
|
...(requestId ? { requestId } : {}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user