@brftech/filex-core 0.42.1 → 0.43.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 +14 -2
- package/dist/ArchiveViewer-BqU761Wk.js +149 -0
- package/dist/ArchiveViewer-BqU761Wk.js.map +1 -0
- package/dist/CsvViewer-ByHVK5ga.js +172 -0
- package/dist/CsvViewer-ByHVK5ga.js.map +1 -0
- package/dist/{DrawioViewer-BuhZOAx6.js → DrawioViewer-Bgrj8-zG.js} +45 -44
- package/dist/DrawioViewer-Bgrj8-zG.js.map +1 -0
- package/dist/{EpubViewer-DS3mb3k8.js → EpubViewer-DJwUKlHW.js} +50 -50
- package/dist/EpubViewer-DJwUKlHW.js.map +1 -0
- package/dist/IpynbViewer-Bz0eJ4NS.js +184 -0
- package/dist/IpynbViewer-Bz0eJ4NS.js.map +1 -0
- package/dist/MermaidViewer-CEDTD_pp.js +136 -0
- package/dist/MermaidViewer-CEDTD_pp.js.map +1 -0
- package/dist/PsdViewer-CZcxUpZO.js +121 -0
- package/dist/PsdViewer-CZcxUpZO.js.map +1 -0
- package/dist/TiffViewer-BwI62CbQ.js +141 -0
- package/dist/TiffViewer-BwI62CbQ.js.map +1 -0
- package/dist/{Viewer3D-CIrOn63I.js → Viewer3D-DoeZcuMm.js} +16 -16
- package/dist/Viewer3D-DoeZcuMm.js.map +1 -0
- package/dist/filex-core.js +475 -219
- package/dist/filex-core.umd.cjs +165 -108
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/fonts/caveat-latin-ext.woff2 +0 -0
- package/dist/fonts/caveat-latin.woff2 +0 -0
- package/dist/fonts/dancing-script-latin-ext.woff2 +0 -0
- package/dist/fonts/dancing-script-latin.woff2 +0 -0
- package/dist/fonts/homemade-apple-latin.woff2 +0 -0
- package/dist/fonts/source-serif-4-latin-ext.woff2 +0 -0
- package/dist/fonts/source-serif-4-latin.woff2 +0 -0
- package/dist/index-DuWnGuv5.js +35901 -0
- package/dist/index-DuWnGuv5.js.map +1 -0
- package/dist/index.d.ts +5241 -553
- package/dist/pdf-CaPYsOUo.js +21302 -0
- package/dist/pdf-CaPYsOUo.js.map +1 -0
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/FileExplorer.vue +1207 -343
- package/src/assets/fonts/LICENSE-Apache-2.0.txt +202 -0
- package/src/assets/fonts/LICENSE-OFL-1.1.txt +93 -0
- package/src/assets/fonts/README.md +58 -0
- package/src/assets/fonts/caveat-latin-ext.woff2 +0 -0
- package/src/assets/fonts/caveat-latin.woff2 +0 -0
- package/src/assets/fonts/dancing-script-latin-ext.woff2 +0 -0
- package/src/assets/fonts/dancing-script-latin.woff2 +0 -0
- package/src/assets/fonts/homemade-apple-latin.woff2 +0 -0
- package/src/assets/fonts/source-serif-4-latin-ext.woff2 +0 -0
- package/src/assets/fonts/source-serif-4-latin.woff2 +0 -0
- package/src/components/AdvancedSearch.vue +49 -0
- package/src/components/Breadcrumb.vue +5 -5
- package/src/components/ChoiceButtons.vue +152 -0
- package/src/components/CommandPalette.vue +5 -5
- package/src/components/ConnectionGuideView.vue +1 -1
- package/src/components/ConnectionNotice.vue +59 -0
- package/src/components/ConnectionsPanel.vue +30 -568
- package/src/components/ContextMenu.vue +31 -5
- package/src/components/DataTable.vue +1331 -0
- package/src/components/FilePane.vue +3 -0
- package/src/components/FilterBar.vue +12 -5
- package/src/components/GalleryView.vue +50 -2
- package/src/components/GridView.vue +51 -3
- package/src/components/HomeView.vue +18 -6
- package/src/components/InspectorPanel.vue +134 -17
- package/src/components/ListView.vue +366 -900
- package/src/components/LogoMark.vue +57 -0
- package/src/components/NFSExportsPanel.vue +76 -28
- package/src/components/OnboardingTour.vue +19 -7
- package/src/components/OperationsCenter.vue +77 -1
- package/src/components/PendingOpsTray.vue +59 -5
- package/src/components/PresenceBar.vue +7 -7
- package/src/components/ProductVersion.vue +31 -0
- package/src/components/QuickLook.vue +10 -14
- package/src/components/RecentlyOpened.vue +47 -17
- package/src/components/RecoveryKeyModal.vue +1 -1
- package/src/components/RowActions.vue +134 -0
- package/src/components/S3KeysPanel.vue +98 -56
- package/src/components/SSHKeysPanel.vue +79 -26
- package/src/components/SideNav.vue +260 -96
- package/src/components/StarButton.vue +1 -0
- package/src/components/StorageFields.vue +74 -6
- package/src/components/StorageTags.vue +62 -0
- package/src/components/TabBar.vue +1 -1
- package/src/components/TagKindIcon.vue +56 -0
- package/src/components/TagPicker.vue +226 -40
- package/src/components/ThemePalette.vue +4 -4
- package/src/components/TimeZonePicker.vue +29 -10
- package/src/components/TokensPanel.vue +82 -27
- package/src/components/Toolbar.vue +28 -6
- package/src/components/plugin/PluginConfirmModal.vue +54 -0
- package/src/components/plugin/PluginInspectorSection.vue +149 -0
- package/src/components/plugin/PluginPageView.vue +339 -0
- package/src/components/plugin/PluginViewModal.vue +159 -0
- package/src/components/plugin/SurfaceConversation.vue +76 -0
- package/src/components/plugin/SurfaceFooterButtons.vue +73 -0
- package/src/components/plugin/SurfaceRenderer.vue +299 -0
- package/src/components/plugin/SurfaceSections.vue +91 -0
- package/src/components/plugin/nodes/PdfFieldEditor.vue +509 -0
- package/src/components/plugin/nodes/SurfaceFileChooser.vue +94 -0
- package/src/components/plugin/nodes/SurfaceForm.vue +82 -0
- package/src/components/plugin/nodes/SurfaceList.vue +127 -0
- package/src/components/plugin/nodes/SurfacePdfFields.vue +1285 -0
- package/src/components/plugin/nodes/SurfacePeoplePicker.vue +213 -0
- package/src/components/plugin/nodes/SurfacePinInput.vue +57 -0
- package/src/components/plugin/nodes/SurfacePreview.vue +119 -0
- package/src/components/plugin/nodes/SurfaceProgress.vue +48 -0
- package/src/components/plugin/nodes/SurfaceSignaturePad.vue +472 -0
- package/src/components/plugin/nodes/SurfaceSteps.vue +53 -0
- package/src/components/public/PublicLanguagePicker.vue +58 -0
- package/src/components/public/PublicLinkPage.vue +286 -0
- package/src/components/public/PublicLinkPreview.vue +85 -0
- package/src/components/public/PublicPinGate.vue +108 -0
- package/src/components/public/PublicRequestBody.vue +204 -0
- package/src/components/public/PublicShareBody.vue +188 -0
- package/src/components/public/PublicShell.vue +332 -0
- package/src/composables/useConnections.ts +8 -2
- package/src/composables/useFileApi.ts +183 -44
- package/src/composables/useLocale.ts +277 -41
- package/src/composables/useNFSExports.ts +8 -10
- package/src/composables/useOperations.ts +44 -3
- package/src/composables/usePendingOps.ts +59 -8
- package/src/composables/usePluginActions.ts +121 -0
- package/src/composables/usePluginSurface.ts +223 -0
- package/src/composables/usePublicBranding.ts +172 -0
- package/src/composables/usePublicLink.ts +573 -0
- package/src/composables/usePublicPage.ts +61 -0
- package/src/composables/useS3Keys.ts +17 -12
- package/src/composables/useSSHKeys.ts +8 -10
- package/src/composables/useTokens.ts +8 -12
- package/src/composables/useUploadChunked.ts +18 -8
- package/src/composables/useViewerFetch.ts +6 -3
- package/src/index.ts +404 -8
- package/src/lib/actionIcons.ts +46 -1
- package/src/lib/advSearch.ts +14 -7
- package/src/lib/appLock.ts +130 -0
- package/src/lib/connection.ts +110 -0
- package/src/lib/destinationTree.ts +19 -3
- package/src/lib/direction.ts +353 -0
- package/src/lib/dragGhost.ts +6 -0
- package/src/lib/dropLimits.ts +69 -0
- package/src/lib/errorWords.ts +394 -0
- package/src/lib/externalReach.ts +5 -1
- package/src/lib/fileFilters.ts +7 -2
- package/src/lib/fileIcons.ts +4 -0
- package/src/lib/internalPaths.ts +77 -0
- package/src/lib/listInput.ts +64 -0
- package/src/lib/listing.ts +58 -23
- package/src/lib/modalStack.ts +26 -0
- package/src/lib/nodeRow.ts +121 -0
- package/src/lib/pdfFieldRules.ts +126 -0
- package/src/lib/pdfFields.ts +589 -0
- package/src/lib/pdfFieldsGeom.ts +203 -0
- package/src/lib/pdfjsLoader.ts +51 -0
- package/src/lib/personName.ts +47 -0
- package/src/lib/pluginApplies.ts +123 -0
- package/src/lib/pluginLabel.ts +72 -0
- package/src/lib/pluginMenu.ts +253 -0
- package/src/lib/pluginPage.ts +58 -0
- package/src/lib/plural.ts +181 -0
- package/src/lib/popupLayer.ts +103 -0
- package/src/lib/prefs.ts +563 -0
- package/src/lib/productVersion.ts +35 -0
- package/src/lib/publicLayout.ts +39 -0
- package/src/lib/serviceGate.ts +104 -0
- package/src/lib/shareTtl.ts +25 -11
- package/src/lib/signFonts.ts +85 -0
- package/src/lib/signaturePad.ts +111 -0
- package/src/lib/sortOrder.ts +100 -38
- package/src/lib/star.ts +7 -1
- package/src/lib/surfaceCell.ts +41 -0
- package/src/lib/surfaceConditions.ts +156 -0
- package/src/lib/surfaceOpen.ts +106 -0
- package/src/lib/surfaceSteps.ts +68 -0
- package/src/lib/surfaceValues.ts +191 -0
- package/src/lib/symlink.ts +150 -0
- package/src/lib/tableColumns.ts +493 -0
- package/src/lib/tableEnv.ts +34 -0
- package/src/lib/tablePrefs.ts +84 -0
- package/src/lib/tags.ts +121 -12
- package/src/lib/themes.ts +286 -18
- package/src/lib/tour.ts +152 -0
- package/src/lib/trashEmpty.ts +111 -0
- package/src/lib/trashTimeLeft.ts +23 -0
- package/src/lib/uiLocales.ts +460 -0
- package/src/lib/viewPrefs.ts +696 -660
- package/src/lib/viewPrefsHttp.ts +78 -0
- package/src/locales/en.ts +522 -119
- package/src/locales/resolve.ts +17 -8
- package/src/locales/tr.ts +539 -155
- package/src/modals/ConvertModal.vue +62 -11
- package/src/modals/DestinationPickerModal.vue +59 -16
- package/src/modals/Modal.vue +113 -23
- package/src/modals/NewDocumentModal.vue +16 -6
- package/src/modals/NewFolderModal.vue +8 -0
- package/src/modals/PermissionsModal.vue +272 -163
- package/src/modals/PreviewModal.vue +119 -20
- package/src/modals/RenameModal.vue +37 -1
- package/src/styles/base.css +2895 -241
- package/src/styles/sign-fonts.css +118 -0
- package/src/styles/variables.css +60 -0
- package/src/types/Connections.ts +17 -0
- package/src/types/ExplorerConfig.ts +117 -1
- package/src/types/FileNode.ts +58 -0
- package/src/types/Plugins.ts +494 -0
- package/src/types/Public.ts +212 -0
- package/src/viewers/ArchiveViewer.vue +93 -48
- package/src/viewers/CsvViewer.vue +99 -53
- package/src/viewers/DrawioViewer.vue +35 -9
- package/src/viewers/EpubViewer.vue +7 -8
- package/src/viewers/IpynbViewer.vue +3 -1
- package/src/viewers/MermaidViewer.vue +4 -5
- package/src/viewers/PdfViewer.vue +8 -17
- package/src/viewers/PsdViewer.vue +2 -4
- package/src/viewers/TiffViewer.vue +4 -5
- package/src/viewers/Viewer3D.vue +1 -1
- package/LICENSE +0 -21
- package/dist/ArchiveViewer-CLNevfPE.js +0 -124
- package/dist/ArchiveViewer-CLNevfPE.js.map +0 -1
- package/dist/CsvViewer-K8XA3z7N.js +0 -141
- package/dist/CsvViewer-K8XA3z7N.js.map +0 -1
- package/dist/DrawioViewer-BuhZOAx6.js.map +0 -1
- package/dist/EpubViewer-DS3mb3k8.js.map +0 -1
- package/dist/IpynbViewer-BTk7p4Dn.js +0 -184
- package/dist/IpynbViewer-BTk7p4Dn.js.map +0 -1
- package/dist/MermaidViewer-DqucH_io.js +0 -137
- package/dist/MermaidViewer-DqucH_io.js.map +0 -1
- package/dist/PsdViewer-CwiVENmq.js +0 -122
- package/dist/PsdViewer-CwiVENmq.js.map +0 -1
- package/dist/TiffViewer-CpewSVmQ.js +0 -142
- package/dist/TiffViewer-CpewSVmQ.js.map +0 -1
- package/dist/Viewer3D-CIrOn63I.js.map +0 -1
- package/dist/index-Dx0IbBcI.js +0 -26831
- package/dist/index-Dx0IbBcI.js.map +0 -1
- package/dist/useViewerFetch-czqbd2Lj.js +0 -25
- package/dist/useViewerFetch-czqbd2Lj.js.map +0 -1
|
@@ -17,6 +17,7 @@ import type { ExplorerConfig } from '../types/ExplorerConfig';
|
|
|
17
17
|
import type { S3AccessKey, S3Connection, S3KeyCreated, S3KeyRequest } from '../types/S3Keys';
|
|
18
18
|
import { connectionsBase } from './useConnections';
|
|
19
19
|
import { useFileApi } from './useFileApi';
|
|
20
|
+
import { serverWords } from '../lib/errorWords';
|
|
20
21
|
|
|
21
22
|
export function useS3Keys(config: ExplorerConfig) {
|
|
22
23
|
const api = useFileApi(config);
|
|
@@ -28,6 +29,9 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
28
29
|
const loading = ref(false);
|
|
29
30
|
const loaded = ref(false);
|
|
30
31
|
const error = ref<string | null>(null);
|
|
32
|
+
/** The fix, when the server told THIS caller one (`admin_hint`: only an
|
|
33
|
+
* administrator who can act on it is sent it). */
|
|
34
|
+
const errorHint = ref<string | null>(null);
|
|
31
35
|
/**
|
|
32
36
|
* null until the first load answers. False means the caller may not mint
|
|
33
37
|
* keys (anonymous, or a token without the right to) — the guide is still
|
|
@@ -38,19 +42,15 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
38
42
|
/** The secret, held in memory for exactly as long as the user is looking. */
|
|
39
43
|
const revealed = ref<S3KeyCreated | null>(null);
|
|
40
44
|
|
|
45
|
+
/** A refusal, said — lib/errorWords `serverWords`, the one rule every
|
|
46
|
+
* connection panel shares (it used to print the server's `error` field as
|
|
47
|
+
* it came: an environment variable, to a regular user). ⚠ The locale is
|
|
48
|
+
* passed because what comes back may be the SERVER's own sentence: it
|
|
49
|
+
* never met a translator, and an Arabic panel needs its machine runs
|
|
50
|
+
* isolated (lib/direction `foreignText`). */
|
|
41
51
|
function messageOf(e: unknown): string {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// available on this install" tells an operator what to fix; "503" does not.
|
|
45
|
-
if (err?.detail) {
|
|
46
|
-
try {
|
|
47
|
-
const parsed = JSON.parse(err.detail) as { error?: string };
|
|
48
|
-
if (parsed?.error) return parsed.error;
|
|
49
|
-
} catch {
|
|
50
|
-
/* not JSON — fall through */
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return err?.message || String(e);
|
|
52
|
+
errorHint.value = (e as { hint?: string } | null)?.hint ?? null;
|
|
53
|
+
return serverWords(e, config.locale);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function statusOf(e: unknown): number | undefined {
|
|
@@ -60,6 +60,7 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
60
60
|
async function load(): Promise<void> {
|
|
61
61
|
loading.value = true;
|
|
62
62
|
error.value = null;
|
|
63
|
+
errorHint.value = null;
|
|
63
64
|
try {
|
|
64
65
|
const body = await api.jsonFetch<{ keys: S3AccessKey[] } & S3Connection>(
|
|
65
66
|
url('/api/auth/s3-keys'),
|
|
@@ -93,6 +94,7 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
93
94
|
*/
|
|
94
95
|
async function create(req: S3KeyRequest): Promise<S3KeyCreated | null> {
|
|
95
96
|
error.value = null;
|
|
97
|
+
errorHint.value = null;
|
|
96
98
|
try {
|
|
97
99
|
const body = await api.jsonFetch<S3KeyCreated>(url('/api/auth/s3-keys'), {
|
|
98
100
|
method: 'POST',
|
|
@@ -117,6 +119,7 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
117
119
|
|
|
118
120
|
async function setDisabled(id: number, disabled: boolean): Promise<void> {
|
|
119
121
|
error.value = null;
|
|
122
|
+
errorHint.value = null;
|
|
120
123
|
try {
|
|
121
124
|
await api.jsonFetch(url(`/api/auth/s3-keys/${id}/state`), {
|
|
122
125
|
method: 'POST',
|
|
@@ -131,6 +134,7 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
131
134
|
|
|
132
135
|
async function remove(id: number): Promise<void> {
|
|
133
136
|
error.value = null;
|
|
137
|
+
errorHint.value = null;
|
|
134
138
|
try {
|
|
135
139
|
await api.jsonFetch(url(`/api/auth/s3-keys/${id}`), { method: 'DELETE' });
|
|
136
140
|
// A revealed secret belonging to the key just revoked must go with it.
|
|
@@ -163,6 +167,7 @@ export function useS3Keys(config: ExplorerConfig) {
|
|
|
163
167
|
loading,
|
|
164
168
|
loaded,
|
|
165
169
|
error,
|
|
170
|
+
errorHint,
|
|
166
171
|
canMint,
|
|
167
172
|
revealed,
|
|
168
173
|
guideKey,
|
|
@@ -16,6 +16,7 @@ import type { ExplorerConfig } from '../types/ExplorerConfig';
|
|
|
16
16
|
import type { SSHConnection, SSHPublicKey } from '../types/SSHKeys';
|
|
17
17
|
import { connectionsBase } from './useConnections';
|
|
18
18
|
import { useFileApi } from './useFileApi';
|
|
19
|
+
import { serverWords } from '../lib/errorWords';
|
|
19
20
|
|
|
20
21
|
export function useSSHKeys(config: ExplorerConfig) {
|
|
21
22
|
const api = useFileApi(config);
|
|
@@ -29,17 +30,14 @@ export function useSSHKeys(config: ExplorerConfig) {
|
|
|
29
30
|
const error = ref<string | null>(null);
|
|
30
31
|
const canAdd = ref<boolean | null>(null);
|
|
31
32
|
|
|
33
|
+
/** A refusal, said — lib/errorWords `serverWords`, the one rule every
|
|
34
|
+
* connection panel shares (it used to print the server's `error` field as
|
|
35
|
+
* it came: an environment variable, to a regular user). ⚠ The locale is
|
|
36
|
+
* passed because what comes back may be the SERVER's own sentence: it
|
|
37
|
+
* never met a translator, and an Arabic panel needs its machine runs
|
|
38
|
+
* isolated (lib/direction `foreignText`). */
|
|
32
39
|
function messageOf(e: unknown): string {
|
|
33
|
-
|
|
34
|
-
if (err?.detail) {
|
|
35
|
-
try {
|
|
36
|
-
const parsed = JSON.parse(err.detail) as { error?: string };
|
|
37
|
-
if (parsed?.error) return parsed.error;
|
|
38
|
-
} catch {
|
|
39
|
-
/* not JSON */
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return err?.message || String(e);
|
|
40
|
+
return serverWords(e, config.locale);
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
function statusOf(e: unknown): number | undefined {
|
|
@@ -20,6 +20,7 @@ import type { ExplorerConfig } from '../types/ExplorerConfig';
|
|
|
20
20
|
import type { ApiToken, ApiTokenCreated, ApiTokenRequest } from '../types/Tokens';
|
|
21
21
|
import { connectionsBase } from './useConnections';
|
|
22
22
|
import { useFileApi } from './useFileApi';
|
|
23
|
+
import { serverWords } from '../lib/errorWords';
|
|
23
24
|
|
|
24
25
|
export function useTokens(config: ExplorerConfig) {
|
|
25
26
|
const api = useFileApi(config);
|
|
@@ -40,19 +41,14 @@ export function useTokens(config: ExplorerConfig) {
|
|
|
40
41
|
/** The secret, held in memory for exactly as long as the user is looking. */
|
|
41
42
|
const revealed = ref<ApiTokenCreated | null>(null);
|
|
42
43
|
|
|
44
|
+
/** A refusal, said — lib/errorWords `serverWords`, the one rule every
|
|
45
|
+
* connection panel shares (it used to print the server's `error` field as
|
|
46
|
+
* it came: an environment variable, to a regular user). ⚠ The locale is
|
|
47
|
+
* passed because what comes back may be the SERVER's own sentence: it
|
|
48
|
+
* never met a translator, and an Arabic panel needs its machine runs
|
|
49
|
+
* isolated (lib/direction `foreignText`). */
|
|
43
50
|
function messageOf(e: unknown): string {
|
|
44
|
-
|
|
45
|
-
// The backend's own words beat a status line: "scope 'admin' is not
|
|
46
|
-
// available here" tells the user what to change; "403" does not.
|
|
47
|
-
if (err?.detail) {
|
|
48
|
-
try {
|
|
49
|
-
const parsed = JSON.parse(err.detail) as { error?: string };
|
|
50
|
-
if (parsed?.error) return parsed.error;
|
|
51
|
-
} catch {
|
|
52
|
-
/* not JSON — fall through */
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return err?.message || String(e);
|
|
51
|
+
return serverWords(e, config.locale);
|
|
56
52
|
}
|
|
57
53
|
|
|
58
54
|
function statusOf(e: unknown): number | undefined {
|
|
@@ -36,6 +36,12 @@
|
|
|
36
36
|
|
|
37
37
|
import type { ExplorerConfig } from '../types/ExplorerConfig';
|
|
38
38
|
import type { FileApi } from './useFileApi';
|
|
39
|
+
import { networkFailure, requestFailure, wordsIn } from '../lib/errorWords';
|
|
40
|
+
// ⚠ An upload is an ACTION: it is never folded into the shared "no
|
|
41
|
+
// connection" notice, because the person is waiting to be told whether their
|
|
42
|
+
// file went (lib/connection).
|
|
43
|
+
import { noteRequestFailed, noteRequestSucceeded } from '../lib/connection';
|
|
44
|
+
import { resolveLocale } from '../locales/resolve';
|
|
39
45
|
import {
|
|
40
46
|
clearResume,
|
|
41
47
|
defaultResumeStorage,
|
|
@@ -367,7 +373,12 @@ export function useUploadChunked(
|
|
|
367
373
|
}
|
|
368
374
|
if (next === -2) continue; // offset moved under us; re-slice
|
|
369
375
|
if (next < 0) throw lastErr ?? new Error('chunk upload failed');
|
|
370
|
-
|
|
376
|
+
// Said, not "upload stalled at byte 8388608": the row is read by a
|
|
377
|
+
// person, and the byte count is only for whoever is debugging.
|
|
378
|
+
if (next <= acked) {
|
|
379
|
+
console.warn('[filex] upload stalled at byte', acked);
|
|
380
|
+
throw new Error(wordsIn(resolveLocale(config.locale))('err.upload_stalled'));
|
|
381
|
+
}
|
|
371
382
|
acked = next;
|
|
372
383
|
report();
|
|
373
384
|
saveResume(storage, key, {
|
|
@@ -455,6 +466,7 @@ export function useUploadChunked(
|
|
|
455
466
|
};
|
|
456
467
|
xhr.onload = () => {
|
|
457
468
|
inFlight = null;
|
|
469
|
+
noteRequestSucceeded();
|
|
458
470
|
if (xhr.status >= 200 && xhr.status < 300) {
|
|
459
471
|
try {
|
|
460
472
|
const body = JSON.parse(xhr.responseText) as StatusResponse;
|
|
@@ -466,16 +478,14 @@ export function useUploadChunked(
|
|
|
466
478
|
}
|
|
467
479
|
return;
|
|
468
480
|
}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
err.status = xhr.status;
|
|
473
|
-
err.detail = xhr.responseText.slice(0, 200);
|
|
474
|
-
reject(err);
|
|
481
|
+
// Said (lib/errorWords): the upload row used to read
|
|
482
|
+
// "chunk 0-8388607 → 500". Status and body still ride along.
|
|
483
|
+
reject(requestFailure(xhr.status, xhr.responseText || '', resolveLocale(config.locale)));
|
|
475
484
|
};
|
|
476
485
|
xhr.onerror = () => {
|
|
477
486
|
inFlight = null;
|
|
478
|
-
|
|
487
|
+
noteRequestFailed('action');
|
|
488
|
+
reject(networkFailure(resolveLocale(config.locale)));
|
|
479
489
|
};
|
|
480
490
|
xhr.onabort = () => {
|
|
481
491
|
inFlight = null;
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* doesn't reject the request when the viewer fetches the file body
|
|
13
13
|
* directly (instead of letting the browser do it via `<img src>` etc).
|
|
14
14
|
*/
|
|
15
|
+
import { requestFailure } from '../lib/errorWords';
|
|
16
|
+
|
|
15
17
|
export interface ViewerFetchOptions {
|
|
16
18
|
url: string;
|
|
17
19
|
headers?: Record<string, string>;
|
|
@@ -26,10 +28,11 @@ async function fetchOk(opts: ViewerFetchOptions): Promise<Response> {
|
|
|
26
28
|
signal: opts.signal,
|
|
27
29
|
});
|
|
28
30
|
if (!res.ok) {
|
|
31
|
+
// Said, not printed (lib/errorWords): the viewers used to show
|
|
32
|
+
// "404 Not Found — {…}" in the pane. The viewer re-says it in its own
|
|
33
|
+
// language through `sayFailure(err, …, { t })`.
|
|
29
34
|
const text = await res.text().catch(() => '');
|
|
30
|
-
throw
|
|
31
|
-
`${res.status} ${res.statusText}${text ? ' — ' + text.slice(0, 200) : ''}`,
|
|
32
|
-
);
|
|
35
|
+
throw requestFailure(res.status, text, undefined);
|
|
33
36
|
}
|
|
34
37
|
return res;
|
|
35
38
|
}
|