phirepass-widgets 0.0.53 → 0.0.55
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/dist/cjs/{index-DqslB2R4.js → index-YW0ts9D0.js} +0 -37
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/phirepass-sftp-client.cjs.entry.js +462 -83
- package/dist/cjs/phirepass-terminal.cjs.entry.js +3 -3
- package/dist/cjs/phirepass-widgets.cjs.js +2 -2
- package/dist/cjs/{protocol-D_0VKXs_.js → protocol-DPi8rcp9.js} +5 -1
- package/dist/collection/common/protocol.js +4 -0
- package/dist/collection/components/phirepass-sftp-client/phirepass-sftp-client.css +53 -40
- package/dist/collection/components/phirepass-sftp-client/phirepass-sftp-client.js +462 -81
- package/dist/collection/components/phirepass-terminal/phirepass-terminal.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/p-D7u6YzKp.js +1 -0
- package/dist/components/phirepass-sftp-client.js +1 -1
- package/dist/components/phirepass-terminal.js +2 -2
- package/dist/esm/{index-jdexunMF.js → index-PKnTMZa7.js} +0 -37
- package/dist/esm/loader.js +3 -3
- package/dist/esm/phirepass-sftp-client.entry.js +462 -83
- package/dist/esm/phirepass-terminal.entry.js +3 -3
- package/dist/esm/phirepass-widgets.js +3 -3
- package/dist/esm/{protocol-BYaVbj9C.js → protocol-D7u6YzKp.js} +4 -0
- package/dist/phirepass-widgets/p-21fb3b58.entry.js +1 -0
- package/dist/phirepass-widgets/p-D7u6YzKp.js +1 -0
- package/dist/phirepass-widgets/p-PKnTMZa7.js +2 -0
- package/dist/phirepass-widgets/{p-a6553a86.entry.js → p-fec100bd.entry.js} +2 -2
- package/dist/phirepass-widgets/phirepass-widgets.esm.js +1 -1
- package/dist/types/common/protocol.d.ts +37 -2
- package/dist/types/components/phirepass-sftp-client/phirepass-sftp-client.d.ts +28 -5
- package/package.json +1 -1
- package/dist/components/p-BYaVbj9C.js +0 -1
- package/dist/phirepass-widgets/p-BYaVbj9C.js +0 -1
- package/dist/phirepass-widgets/p-ba7d75c5.entry.js +0 -1
- package/dist/phirepass-widgets/p-jdexunMF.js +0 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
4
|
-
var protocol = require('./protocol-
|
|
3
|
+
var index = require('./index-YW0ts9D0.js');
|
|
4
|
+
var protocol = require('./protocol-DPi8rcp9.js');
|
|
5
5
|
|
|
6
6
|
const phirepassSftpClientLogoSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIgogICAgc3Ryb2tlPSJyZ2IoNDYsIDE4NCwgMTM4KSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiCiAgICBjbGFzcz0ibHVjaWRlIGx1Y2lkZS10ZXJtaW5hbCB3LTMuNSBoLTMuNSB0ZXh0LXByaW1hcnkiPgogICAgPHBvbHlsaW5lIHBvaW50cz0iNCAxNyAxMCAxMSA0IDUiPjwvcG9seWxpbmU+CiAgICA8bGluZSB4MT0iMTIiIHgyPSIyMCIgeTE9IjE5IiB5Mj0iMTkiPjwvbGluZT4KPC9zdmc+Cg==';
|
|
7
7
|
|
|
@@ -19,7 +19,7 @@ const phirepassSftpClientRefreshSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0
|
|
|
19
19
|
|
|
20
20
|
const phirepassSftpClientUploadSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIgogICAgc3Ryb2tlPSJyZ2IoMTg5LCAyMTksIDIwOSkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIgogICAgY2xhc3M9Imx1Y2lkZSBsdWNpZGUtdXBsb2FkIHctMy41IGgtMy41Ij4KICAgIDxwYXRoIGQ9Ik0yMSAxNXY0YTIgMiAwIDAgMS0yIDJINWEyIDIgMCAwIDEtMi0ydi00Ij48L3BhdGg+CiAgICA8cG9seWxpbmUgcG9pbnRzPSIxNyA4IDEyIDMgNyA4Ij48L3BvbHlsaW5lPgogICAgPGxpbmUgeDE9IjEyIiB4Mj0iMTIiIHkxPSIzIiB5Mj0iMTUiPjwvbGluZT4KPC9zdmc+Cg==';
|
|
21
21
|
|
|
22
|
-
const phirepassSftpClientCss = () => `:host{--radius:0.375rem;--card:220 18% 10%;--border:220 15% 18%;--primary:160 60% 45%;--radius:0.375rem;--destructive:0 70% 50%;--muted:220 15% 13%;--muted-foreground:220 10% 50%;--primary-foreground:220 20% 7%;--scroll-track:220 16% 12%;--scroll-thumb:220 12% 34%;--scroll-thumb-hover:160 45% 44%;font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;height:100%;width:100%;border:1px solid hsl(var(--border));background-color:hsl(var(--card));border-radius:var(--radius);overflow:hidden;display:flex;flex-direction:column;position:relative;container-type:inline-size;.listing{height:100%;display:flex;flex-direction:column;justify-content:space-between;min-height:0;header{height:30px;background:rgba(28, 31, 38, 0.6);border-bottom:1px solid hsl(var(--border));display:flex;align-items:center;justify-content:space-between;.actions{display:flex;align-items:center;.action{cursor:pointer;padding:4px;display:flex;align-items:center;z-index:1;img{height:14px;padding:4px;border-radius:4px}&:hover{background-color:hsl(var(--border) / 0.6)}}}.title{color:hsl(var(--primary));height:14px;padding:0 12px;display:flex;align-items:center;font-size:0.75rem;line-height:1rem;img{height:14px;margin-right:5px}.text{display:flex;flex-direction:row;justify-content:center;margin-top:2px;.name{margin-right:10px}.description{color:hsl(var(--muted-foreground))}}}}main{flex:1;display:flex;flex-direction:column;position:relative;min-height:0;overflow:hidden;.loader{color:hsl(var(--muted-foreground));font-size:13px;animation:pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;text-align:center;display:flex;align-items:center;justify-content:center;position:absolute;height:100%;width:100%;background:rgba(28, 31, 38, 0);backdrop-filter:blur(4px)}.error{font-size:13px;text-align:center;color:hsl(var(--destructive));height:100%;display:flex;align-items:center;justify-content:center}.navigation{height:25px;padding:10px;font-size:0.75rem;line-height:1rem;background-color:hsl(var(--card));display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid hsl(var(--border));position:sticky;top:0;z-index:3;.breadcrumbs{display:flex;align-items:center;margin-right:10px;.breadcrumb{color:hsl(var(--primary));margin-right:4px;cursor:pointer;&:after{margin-left:4px}&:hover{color:rgb(189, 219, 209)}&:last-child{margin-right:0;color:rgb(189, 219, 209);cursor:default}}.arrow{height:12px;width:12px;opacity:0.6;top:2px;margin-right:4px;position:relative}}.actions{display:flex;align-items:center;gap:8px}.action{border:none;background:transparent;color:rgb(189, 219, 209);font-size:1.1rem;line-height:1;padding:2px 4px;border-radius:4px;cursor:pointer;&:hover{background-color:hsl(var(--border) / 0.6)}img{height:14px;width:14px;display:block}}.action.disconnect{color:#ff4d5f;font-size:0.65rem;letter-spacing:0.08em;padding:4px 8px;&:hover{color:#ff6b7a;background-color:hsl(var(--destructive) / 0.12)}}}.content{flex:1;min-height:0;overflow:auto;font-size:0.75rem;line-height:1rem;scrollbar-width:thin;scrollbar-color:hsl(var(--scroll-thumb)) hsl(var(--scroll-track));&::-webkit-scrollbar{width:10px;height:10px}&::-webkit-scrollbar-track{background:hsl(var(--scroll-track))}&::-webkit-scrollbar-thumb{background:hsl(var(--scroll-thumb));border-radius:999px;border:2px solid hsl(var(--scroll-track))}&::-webkit-scrollbar-thumb:hover{background:hsl(var(--scroll-thumb-hover))}table{width:100%;border-collapse:separate;border-spacing:0;table-layout:auto;thead{background-color:hsl(var(--muted));border-bottom:1px solid hsl(var(--border));th{padding:8px 10px;text-align:left;color:hsl(var(--muted-foreground));position:sticky;top:0;z-index:2;background-color:hsl(var(--muted));border-bottom:1px solid hsl(var(--border));line-height:0.95rem;&.action-col{width:58px;min-width:58px;padding:0 10px}&:first-child{width:30%;min-width:180px;max-width:195px}&:nth-child(2),&:nth-child(3),&:nth-child(4),&:nth-child(5){white-space:nowrap;width:1%}}}tbody{padding:10px 10px;tr{border-bottom:1px solid hsl(var(--border) / 0.4);td{padding:10px 10px 9px;color:hsl(var(--muted-foreground));&:first-child{min-width:180px;max-width:195px;white-space:nowrap;.name{display:inline-block;max-width:calc(100% - 26px);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}}&:nth-child(2),&:nth-child(3),&:nth-child(4),&:nth-child(5){white-space:nowrap}&.action-col{width:58px;min-width:58px;text-align:center;padding-left:1px;padding-right:1px;.file-actions{display:flex;align-items:center;justify-content:center;gap:8px}.file-action{border:none;background:transparent;color:hsl(var(--muted-foreground));width:16px;height:16px;border-radius:3px;cursor:pointer;opacity:0;visibility:hidden;pointer-events:none;transition:opacity 120ms ease;padding:0;svg{width:12px;height:12px;display:block;margin:0 auto}&:hover{color:hsl(var(--primary))}&.delete:hover{color:hsl(var(--destructive))}}}.name{&.file{color:rgb(189, 219, 209)}&.folder{color:hsl(var(--primary))}}.kind{height:14px;width:14px;margin-right:5px;top:3px;position:relative}}&:hover{cursor:pointer;background-color:hsl(var(--muted) / 0.4);td.action-col .file-action{opacity:1;visibility:visible;pointer-events:auto;color:hsl(var(--primary))}}&.selected{background-color:hsl(var(--primary) / 0.3);td.action-col .file-action{opacity:1;visibility:visible;pointer-events:auto}&:hover{background-color:hsl(var(--primary) / 0.4)}}}}}}}footer{height:25px;background:rgba(28, 31, 38, 0.6);border-top:1px solid hsl(var(--border));font-size:0.75rem;line-height:1rem;display:flex;align-items:center;justify-content:space-between;padding:0 10px;.status{font-size:0.65rem;color:hsl(var(--muted-foreground));.selected-item{margin-left:10px;color:hsl(var(--primary))}}.version{font-size:0.65rem;color:hsl(var(--muted-foreground))}}}.creds{position:absolute;top:0;left:0;height:100%;width:100%;display:flex;justify-content:center;align-items:center;;&.blurred{background:rgba(28, 31, 38, 0);backdrop-filter:blur(4px)}.auth{display:flex;flex-direction:column;background:hsl(var(--card));position:relative;background-color:rgba(21, 24, 30, 0.95);border:1px solid hsl(var(--border));padding:30px;box-shadow:rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.5) 0px 25px 50px -12px;border-radius:var(--radius);.title{margin-bottom:12px;color:hsl(var(--primary))}label{font-size:0.75rem;line-height:1rem;margin-bottom:1rem;color:hsl(var(--muted-foreground))}input{font-size:0.875rem;line-height:1.25rem;padding-top:0.5rem;padding-bottom:0.5rem;padding-left:0.75rem;padding-right:0.75rem;background-color:rgb(28, 31, 38);border-color:rgb(39, 44, 53);border-width:1px;border-radius:calc(var(--radius) - 2px);width:100%;margin-bottom:12px;color:rgb(189, 219, 209);box-sizing:border-box;&:focus{outline:none;border-color:hsl(var(--primary));box-shadow:0 0 0 1px hsl(var(--primary))}}button[type='submit']{margin-top:12px;width:100%;background-color:hsl(var(--primary));color:hsl(var(--primary-foreground));letter-spacing:0.05em;font-size:13px;font-weight:500;padding:0.5rem 1rem;border-radius:calc(var(--radius) - 2px);height:2rem;cursor:pointer;border:none;&:hover{background-color:hsl(var(--primary) / 0.9)}}}}.upload-modal,.download-modal,.delete-modal{position:absolute;inset:0;display:none;align-items:center;justify-content:center;background:rgba(28, 31, 38, 0);backdrop-filter:blur(4px);z-index:6;&.visible{display:flex}.upload-dialog,.download-dialog,.delete-dialog{width:min(360px, calc(100% - 24px));background-color:rgba(21, 24, 30, 0.96);border:1px solid hsl(var(--border));border-radius:var(--radius);padding:16px;box-shadow:rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.5) 0px 25px 50px -12px;.title{color:hsl(var(--primary));font-size:0.8rem;margin-bottom:8px}.file-name{color:rgb(189, 219, 209);font-size:0.72rem;line-height:1rem;margin-bottom:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.progress-track{width:100%;height:10px;border-radius:999px;background-color:hsl(var(--muted));overflow:hidden;border:1px solid hsl(var(--border));.progress-fill{height:100%;width:0;background:linear-gradient(90deg, hsl(var(--primary) / 0.7), hsl(var(--primary)));transition:width 140ms ease}}.progress-value{margin-top:8px;color:hsl(var(--muted-foreground));font-size:0.7rem;text-align:right}.cancel{margin-top:14px;width:100%;height:2rem;border:1px solid hsl(var(--border));border-radius:calc(var(--radius) - 2px);background:hsl(var(--muted));color:rgb(189, 219, 209);font-size:0.75rem;letter-spacing:0.03em;cursor:pointer;&:hover{border-color:hsl(var(--primary));color:hsl(var(--primary))}&.finished{background-color:hsl(var(--primary));border-color:hsl(var(--primary));color:hsl(var(--primary-foreground));&:hover{background-color:hsl(var(--primary) / 0.9);border-color:hsl(var(--primary) / 0.9);color:hsl(var(--primary-foreground))}}}.message{color:rgb(189, 219, 209);font-size:0.74rem;line-height:1rem;margin-bottom:8px}.modal-actions{margin-top:14px;display:grid;grid-template-columns:1fr 1fr;gap:8px;.btn{height:2rem;border:1px solid hsl(var(--border));border-radius:calc(var(--radius) - 2px);font-size:0.75rem;letter-spacing:0.03em;cursor:pointer;&:disabled{opacity:0.65;cursor:not-allowed}}.btn.secondary{background:hsl(var(--muted));color:rgb(189, 219, 209);&:hover{border-color:hsl(var(--primary));color:hsl(var(--primary))}}.btn.destructive{background:hsl(var(--destructive));border-color:hsl(var(--destructive));color:white;&:hover{background:hsl(var(--destructive) / 0.9);border-color:hsl(var(--destructive) / 0.9)}}}.delete-loading-bar{margin-top:2px;width:100%;height:8px;border-radius:999px;border:1px solid hsl(var(--border));background:linear-gradient(90deg, hsl(var(--muted)) 0%, hsl(var(--muted)) 100%), linear-gradient(90deg, hsl(var(--primary) / 0.3), hsl(var(--primary)), hsl(var(--primary) / 0.3));background-repeat:no-repeat;background-size:100% 100%, 40% 100%;animation:delete-loading 1s linear infinite}}}}@keyframes delete-loading{from{background-position:0 0, -45% 0}to{background-position:0 0, 145% 0}}:host(.max){height:100vh;width:100vw;position:fixed;top:0;left:0;z-index:9999}@container (max-width: 699px){:host .listing main .content table thead th:nth-child(4),:host .listing main .content table tbody td:nth-child(4){display:none}}@container (max-width: 635px){:host .listing main .content table thead th:nth-child(3),:host .listing main .content table tbody td:nth-child(3){display:none}}@container (max-width: 530px){:host .listing main .content table thead th:nth-child(5),:host .listing main .content table tbody td:nth-child(5){display:none}:host .listing footer .status{display:none}}@container (max-width: 370px){:host .listing main .content table thead th:nth-child(2),:host .listing main .content table tbody td:nth-child(2){display:none}:host .listing main .content table thead th:first-child,:host .listing main .content table tbody td:first-child{width:100%;min-width:0;max-width:none}:host .listing main .content table tbody td:first-child .name{max-width:100%}}@container (max-width: 295px){:host .listing main .content table tbody td:first-child .name{max-width:120px}}`;
|
|
22
|
+
const phirepassSftpClientCss = () => `:host{--radius:0.375rem;--card:220 18% 10%;--border:220 15% 18%;--primary:160 60% 45%;--radius:0.375rem;--destructive:0 70% 50%;--muted:220 15% 13%;--muted-foreground:220 10% 50%;--primary-foreground:220 20% 7%;--scroll-track:220 16% 12%;--scroll-thumb:220 12% 34%;--scroll-thumb-hover:160 45% 44%;font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;height:100%;width:100%;border:1px solid hsl(var(--border));background-color:hsl(var(--card));border-radius:var(--radius);overflow:hidden;display:flex;flex-direction:column;position:relative;container-type:inline-size;.listing{height:100%;display:flex;flex-direction:column;justify-content:space-between;min-height:0;header{height:30px;background:rgba(28, 31, 38, 0.6);border-bottom:1px solid hsl(var(--border));display:flex;align-items:center;justify-content:space-between;.actions{display:flex;align-items:center;.action{cursor:pointer;padding:4px;display:flex;align-items:center;z-index:1;img{height:14px;padding:4px;border-radius:4px}&:hover{background-color:hsl(var(--border) / 0.6)}}}.title{color:hsl(var(--primary));height:14px;padding:0 12px;display:flex;align-items:center;font-size:0.75rem;line-height:1rem;img{height:14px;margin-right:5px}.text{display:flex;flex-direction:row;justify-content:center;margin-top:2px;.name{margin-right:10px}.description{color:hsl(var(--muted-foreground))}}}}main{flex:1;display:flex;flex-direction:column;position:relative;min-height:0;overflow:hidden;.loader{color:hsl(var(--muted-foreground));font-size:13px;animation:pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;text-align:center;display:flex;align-items:center;justify-content:center;position:absolute;height:100%;width:100%;background:rgba(28, 31, 38, 0);backdrop-filter:blur(4px)}.error{font-size:13px;text-align:center;color:hsl(var(--destructive));height:100%;display:flex;align-items:center;justify-content:center}.navigation{height:25px;padding:10px;font-size:0.75rem;line-height:1rem;background-color:hsl(var(--card));display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid hsl(var(--border));position:sticky;top:0;z-index:3;.breadcrumbs{display:flex;align-items:center;margin-right:10px;.breadcrumb-container{white-space:nowrap;.breadcrumb{color:hsl(var(--primary));margin-right:4px;cursor:pointer;&:after{margin-left:4px}&:hover{color:rgb(189, 219, 209)}&:last-child{margin-right:0;color:rgb(189, 219, 209);cursor:default}}}.arrow{height:12px;width:12px;opacity:0.6;top:2px;margin-right:4px;position:relative}}.actions{display:flex;align-items:center;gap:8px}.action{border:none;background:transparent;color:rgb(189, 219, 209);font-size:1.1rem;line-height:1;padding:2px 4px;border-radius:4px;cursor:pointer;&:hover{background-color:hsl(var(--border) / 0.6)}img{height:14px;width:14px;display:block}}.action.disconnect{color:#ff4d5f;font-size:0.65rem;letter-spacing:0.08em;padding:4px 8px;&:hover{color:#ff6b7a;background-color:hsl(var(--destructive) / 0.12)}}}.content{flex:1;min-height:0;overflow:auto;font-size:0.75rem;line-height:1rem;scrollbar-width:thin;scrollbar-color:hsl(var(--scroll-thumb)) hsl(var(--scroll-track));&::-webkit-scrollbar{width:10px;height:10px}&::-webkit-scrollbar-track{background:hsl(var(--scroll-track))}&::-webkit-scrollbar-thumb{background:hsl(var(--scroll-thumb));border-radius:999px;border:2px solid hsl(var(--scroll-track))}&::-webkit-scrollbar-thumb:hover{background:hsl(var(--scroll-thumb-hover))}table{width:100%;border-collapse:separate;border-spacing:0;table-layout:auto;thead{background-color:hsl(var(--muted));border-bottom:1px solid hsl(var(--border));th{padding:8px 10px;text-align:left;color:hsl(var(--muted-foreground));position:sticky;top:0;z-index:2;background-color:hsl(var(--muted));border-bottom:1px solid hsl(var(--border));line-height:0.95rem;&.action-col{width:58px;min-width:58px;padding:0 10px}&:first-child{width:30%;min-width:180px;max-width:195px}&:nth-child(2),&:nth-child(3),&:nth-child(4),&:nth-child(5){white-space:nowrap;width:1%}}}tbody{padding:10px 10px;tr{border-bottom:1px solid hsl(var(--border) / 0.4);td{padding:10px 10px 9px;color:hsl(var(--muted-foreground));&:first-child{min-width:180px;max-width:195px;white-space:nowrap;.name{display:inline-block;max-width:calc(100% - 26px);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}}&:nth-child(2),&:nth-child(3),&:nth-child(4),&:nth-child(5){white-space:nowrap}&.action-col{width:58px;min-width:58px;text-align:center;padding-left:1px;padding-right:1px;.file-actions{display:flex;align-items:center;justify-content:center;gap:8px}.file-action{border:none;background:transparent;color:hsl(var(--muted-foreground));width:16px;height:16px;border-radius:3px;cursor:pointer;opacity:0;visibility:hidden;pointer-events:none;transition:opacity 120ms ease;padding:0;svg{width:12px;height:12px;display:block;margin:0 auto}&:hover{color:hsl(var(--primary))}&.delete:hover{color:hsl(var(--destructive))}}}.name{&.file{color:rgb(189, 219, 209)}&.folder{color:hsl(var(--primary))}}.kind{height:14px;width:14px;margin-right:5px;top:3px;position:relative}}&:hover{cursor:pointer;background-color:hsl(var(--muted) / 0.4);td.action-col .file-action{opacity:1;visibility:visible;pointer-events:auto;color:hsl(var(--primary))}}&.selected{background-color:hsl(var(--primary) / 0.3);td.action-col .file-action{opacity:1;visibility:visible;pointer-events:auto}&:hover{background-color:hsl(var(--primary) / 0.4)}}}}}}}footer{height:25px;background:rgba(28, 31, 38, 0.6);border-top:1px solid hsl(var(--border));font-size:0.75rem;line-height:1rem;display:flex;align-items:center;justify-content:space-between;padding:0 10px;.status{font-size:0.65rem;color:hsl(var(--muted-foreground));.selected-item{margin-left:10px;color:hsl(var(--primary))}}.version{font-size:0.65rem;color:hsl(var(--muted-foreground))}}}.creds{position:absolute;top:0;left:0;height:100%;width:100%;display:flex;justify-content:center;align-items:center;;&.blurred{background:rgba(28, 31, 38, 0);backdrop-filter:blur(4px)}.auth{display:flex;flex-direction:column;background:hsl(var(--card));position:relative;background-color:rgba(21, 24, 30, 0.95);border:1px solid hsl(var(--border));padding:30px;box-shadow:rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.5) 0px 25px 50px -12px;border-radius:var(--radius);.title{margin-bottom:12px;color:hsl(var(--primary))}label{font-size:0.75rem;line-height:1rem;margin-bottom:1rem;color:hsl(var(--muted-foreground))}input{font-size:0.875rem;line-height:1.25rem;padding-top:0.5rem;padding-bottom:0.5rem;padding-left:0.75rem;padding-right:0.75rem;background-color:rgb(28, 31, 38);border-color:rgb(39, 44, 53);border-width:1px;border-radius:calc(var(--radius) - 2px);width:100%;margin-bottom:12px;color:rgb(189, 219, 209);box-sizing:border-box;&:focus{outline:none;border-color:hsl(var(--primary));box-shadow:0 0 0 1px hsl(var(--primary))}}button[type='submit']{margin-top:12px;width:100%;background-color:hsl(var(--primary));color:hsl(var(--primary-foreground));letter-spacing:0.05em;font-size:13px;font-weight:500;padding:0.5rem 1rem;border-radius:calc(var(--radius) - 2px);height:2rem;cursor:pointer;border:none;&:hover{background-color:hsl(var(--primary) / 0.9)}}}}.upload-modal,.download-modal,.delete-modal{position:absolute;inset:0;display:none;align-items:center;justify-content:center;background:rgba(28, 31, 38, 0);backdrop-filter:blur(4px);z-index:6;&.visible{display:flex}.upload-dialog,.download-dialog,.delete-dialog{width:min(360px, calc(100% - 24px));background-color:rgba(21, 24, 30, 0.96);border:1px solid hsl(var(--border));border-radius:var(--radius);padding:16px;box-shadow:rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0) 0px 0px 0px 0px, rgba(0, 0, 0, 0.5) 0px 25px 50px -12px;.title{color:hsl(var(--primary));font-size:0.8rem;margin-bottom:8px}.file-name{color:rgb(189, 219, 209);font-size:0.72rem;line-height:1rem;margin-bottom:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.progress-track{width:100%;height:10px;border-radius:999px;background-color:hsl(var(--muted));overflow:hidden;border:1px solid hsl(var(--border));.progress-fill{height:100%;width:0;background:linear-gradient(90deg, hsl(var(--primary) / 0.7), hsl(var(--primary)));transition:width 140ms ease}}.progress-meta{margin-top:8px;margin-bottom:12px;display:flex;align-items:center;justify-content:space-between;gap:10px}.progress-speed{color:hsl(var(--muted-foreground));font-size:0.75rem;font-variant-numeric:tabular-nums;line-height:1.4;text-align:left}.progress-value{color:hsl(var(--muted-foreground));font-size:0.75rem;font-variant-numeric:tabular-nums;line-height:1.4;text-align:right}.cancel{margin-top:14px;width:100%;height:2rem;border:1px solid hsl(var(--border));border-radius:calc(var(--radius) - 2px);background:hsl(var(--muted));color:rgb(189, 219, 209);font-size:0.75rem;letter-spacing:0.03em;cursor:pointer;&:hover{border-color:hsl(var(--primary));color:hsl(var(--primary))}&.finished{background-color:hsl(var(--primary));border-color:hsl(var(--primary));color:hsl(var(--primary-foreground));&:hover{background-color:hsl(var(--primary) / 0.9);border-color:hsl(var(--primary) / 0.9);color:hsl(var(--primary-foreground))}}}.message{color:rgb(189, 219, 209);font-size:0.74rem;line-height:1rem;margin-bottom:8px}.modal-actions{margin-top:14px;display:grid;grid-template-columns:1fr 1fr;gap:8px;.btn{height:2rem;border:1px solid hsl(var(--border));border-radius:calc(var(--radius) - 2px);font-size:0.75rem;letter-spacing:0.03em;cursor:pointer;&:disabled{opacity:0.65;cursor:not-allowed}}.btn.secondary{background:hsl(var(--muted));color:rgb(189, 219, 209);&:hover{border-color:hsl(var(--primary));color:hsl(var(--primary))}}.btn.destructive{background:hsl(var(--destructive));border-color:hsl(var(--destructive));color:white;&:hover{background:hsl(var(--destructive) / 0.9);border-color:hsl(var(--destructive) / 0.9)}}}.delete-loader{margin-top:4px;display:flex;justify-content:center;.spinner{width:16px;height:16px;border:2px solid hsl(var(--muted-foreground) / 0.35);border-top-color:hsl(var(--primary));border-radius:50%;animation:spin 0.7s linear infinite}}}}}@keyframes spin{to{transform:rotate(360deg)}}:host(.max){height:100vh;width:100vw;position:fixed;top:0;left:0;z-index:9999}@container (max-width: 699px){:host .listing main .content table thead th:nth-child(4),:host .listing main .content table tbody td:nth-child(4){display:none}}@container (max-width: 635px){:host .listing main .content table thead th:nth-child(3),:host .listing main .content table tbody td:nth-child(3){display:none}}@container (max-width: 530px){:host .listing main .content table thead th:nth-child(5),:host .listing main .content table tbody td:nth-child(5){display:none}:host .listing footer .status{display:none}}@container (max-width: 370px){:host .listing main .content table thead th:nth-child(2),:host .listing main .content table tbody td:nth-child(2){display:none}:host .listing main .content table thead th:first-child,:host .listing main .content table tbody td:first-child{width:100%;min-width:0;max-width:none}:host .listing main .content table tbody td:first-child .name{max-width:100%}}@container (max-width: 295px){:host .listing main .content table tbody td:first-child .name{max-width:120px}}`;
|
|
23
23
|
|
|
24
24
|
const PhirepassSftpClient = class {
|
|
25
25
|
constructor(hostRef) {
|
|
@@ -32,9 +32,15 @@ const PhirepassSftpClient = class {
|
|
|
32
32
|
runtimeReady = false;
|
|
33
33
|
connected = false;
|
|
34
34
|
uploadInputEl;
|
|
35
|
-
uploadProgressHandle;
|
|
36
|
-
downloadProgressHandle;
|
|
37
35
|
deleteLoadingTimeout;
|
|
36
|
+
msgId = 1;
|
|
37
|
+
activeUploadToken = 0;
|
|
38
|
+
pendingUploadStarts = new Map();
|
|
39
|
+
pendingUploadAcks = new Map();
|
|
40
|
+
pendingDownloadStarts = new Map();
|
|
41
|
+
activeDownloads = new Map();
|
|
42
|
+
activeDownloadMsgId;
|
|
43
|
+
pendingDelete;
|
|
38
44
|
// private inputMode: InputMode = InputMode.Default;
|
|
39
45
|
session_id;
|
|
40
46
|
// private usernameBuffer = "";
|
|
@@ -95,10 +101,12 @@ const PhirepassSftpClient = class {
|
|
|
95
101
|
show_upload_modal = false;
|
|
96
102
|
upload_progress = 0;
|
|
97
103
|
upload_file_name = '';
|
|
104
|
+
upload_speed = '--';
|
|
98
105
|
upload_finished = false;
|
|
99
106
|
show_download_modal = false;
|
|
100
107
|
download_progress = 0;
|
|
101
108
|
download_file_name = '';
|
|
109
|
+
download_speed = '--';
|
|
102
110
|
download_finished = false;
|
|
103
111
|
show_delete_modal = false;
|
|
104
112
|
delete_file_name = '';
|
|
@@ -133,30 +141,120 @@ const PhirepassSftpClient = class {
|
|
|
133
141
|
this.connected = false;
|
|
134
142
|
this.domReady = false;
|
|
135
143
|
this.runtimeReady = false;
|
|
136
|
-
this.
|
|
137
|
-
this.
|
|
144
|
+
this.cancel_active_upload();
|
|
145
|
+
this.cancel_active_download();
|
|
146
|
+
this.clear_pending_operations();
|
|
138
147
|
this.clear_delete_loading_timeout();
|
|
139
148
|
this.close_comms();
|
|
140
149
|
// this.destroy_terminal();
|
|
141
150
|
}
|
|
142
|
-
clear_upload_progress() {
|
|
143
|
-
if (this.uploadProgressHandle !== undefined) {
|
|
144
|
-
window.clearInterval(this.uploadProgressHandle);
|
|
145
|
-
this.uploadProgressHandle = undefined;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
clear_download_progress() {
|
|
149
|
-
if (this.downloadProgressHandle !== undefined) {
|
|
150
|
-
window.clearInterval(this.downloadProgressHandle);
|
|
151
|
-
this.downloadProgressHandle = undefined;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
151
|
clear_delete_loading_timeout() {
|
|
155
152
|
if (this.deleteLoadingTimeout !== undefined) {
|
|
156
153
|
window.clearTimeout(this.deleteLoadingTimeout);
|
|
157
154
|
this.deleteLoadingTimeout = undefined;
|
|
158
155
|
}
|
|
159
156
|
}
|
|
157
|
+
next_msg_id() {
|
|
158
|
+
const id = this.msgId;
|
|
159
|
+
this.msgId += 1;
|
|
160
|
+
return id;
|
|
161
|
+
}
|
|
162
|
+
clear_pending_operations() {
|
|
163
|
+
this.pendingUploadStarts.forEach((pending) => {
|
|
164
|
+
window.clearTimeout(pending.timeout);
|
|
165
|
+
pending.reject(new Error('Upload start aborted'));
|
|
166
|
+
});
|
|
167
|
+
this.pendingUploadStarts.clear();
|
|
168
|
+
this.pendingUploadAcks.forEach((pending) => {
|
|
169
|
+
window.clearTimeout(pending.timeout);
|
|
170
|
+
pending.reject(new Error('Upload chunk aborted'));
|
|
171
|
+
});
|
|
172
|
+
this.pendingUploadAcks.clear();
|
|
173
|
+
this.pendingDownloadStarts.forEach((pending) => {
|
|
174
|
+
window.clearTimeout(pending.timeout);
|
|
175
|
+
pending.reject(new Error('Download start aborted'));
|
|
176
|
+
});
|
|
177
|
+
this.pendingDownloadStarts.clear();
|
|
178
|
+
this.stop_delete_polling();
|
|
179
|
+
this.activeDownloads.clear();
|
|
180
|
+
}
|
|
181
|
+
stop_delete_polling() {
|
|
182
|
+
if (this.pendingDelete?.interval !== undefined) {
|
|
183
|
+
window.clearInterval(this.pendingDelete.interval);
|
|
184
|
+
}
|
|
185
|
+
this.pendingDelete = undefined;
|
|
186
|
+
}
|
|
187
|
+
cancel_active_upload() {
|
|
188
|
+
this.activeUploadToken += 1;
|
|
189
|
+
this.upload_progress = 0;
|
|
190
|
+
this.upload_finished = false;
|
|
191
|
+
this.upload_speed = '--';
|
|
192
|
+
}
|
|
193
|
+
cancel_active_download() {
|
|
194
|
+
if (this.activeDownloadMsgId !== undefined) {
|
|
195
|
+
this.activeDownloads.delete(this.activeDownloadMsgId);
|
|
196
|
+
}
|
|
197
|
+
this.activeDownloadMsgId = undefined;
|
|
198
|
+
this.download_progress = 0;
|
|
199
|
+
this.download_finished = false;
|
|
200
|
+
this.download_speed = '--';
|
|
201
|
+
}
|
|
202
|
+
format_duration(seconds) {
|
|
203
|
+
if (!Number.isFinite(seconds) || seconds < 0) {
|
|
204
|
+
return '--';
|
|
205
|
+
}
|
|
206
|
+
if (seconds < 60) {
|
|
207
|
+
return `${seconds.toFixed(0)}s`;
|
|
208
|
+
}
|
|
209
|
+
const minutes = Math.floor(seconds / 60);
|
|
210
|
+
const remainderSeconds = Math.floor(seconds % 60);
|
|
211
|
+
if (minutes < 60) {
|
|
212
|
+
return `${minutes}m ${remainderSeconds}s`;
|
|
213
|
+
}
|
|
214
|
+
const hours = Math.floor(minutes / 60);
|
|
215
|
+
const remainderMinutes = minutes % 60;
|
|
216
|
+
return `${hours}h ${remainderMinutes}m`;
|
|
217
|
+
}
|
|
218
|
+
format_percent(value) {
|
|
219
|
+
const safe = Number.isFinite(value) ? value : 0;
|
|
220
|
+
return `${safe.toFixed(2)}%`;
|
|
221
|
+
}
|
|
222
|
+
format_transfer_rate(bytesPerSecond) {
|
|
223
|
+
if (!Number.isFinite(bytesPerSecond) || bytesPerSecond <= 0) {
|
|
224
|
+
return '--';
|
|
225
|
+
}
|
|
226
|
+
return `${this.format_size(bytesPerSecond)}/s`;
|
|
227
|
+
}
|
|
228
|
+
update_upload_progress(uploadedBytes, totalBytes, startTime) {
|
|
229
|
+
const progress = totalBytes > 0 ? (uploadedBytes / totalBytes) * 100 : 0;
|
|
230
|
+
this.upload_progress = Math.max(0, Math.min(100, progress));
|
|
231
|
+
if (uploadedBytes >= totalBytes) {
|
|
232
|
+
this.upload_finished = true;
|
|
233
|
+
this.upload_speed = '--';
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const elapsedSeconds = (performance.now() - startTime) / 1000;
|
|
237
|
+
const speed = elapsedSeconds > 0 ? uploadedBytes / elapsedSeconds : 0;
|
|
238
|
+
this.upload_speed = this.format_transfer_rate(speed);
|
|
239
|
+
const remaining = totalBytes - uploadedBytes;
|
|
240
|
+
const eta = speed > 0 ? remaining / speed : NaN;
|
|
241
|
+
this.status = `Uploading ${this.format_size(uploadedBytes)} / ${this.format_size(totalBytes)} (ETA ${this.format_duration(eta)})`;
|
|
242
|
+
}
|
|
243
|
+
update_download_progress(receivedBytes, totalBytes, startTime) {
|
|
244
|
+
const progress = totalBytes > 0 ? (receivedBytes / totalBytes) * 100 : 0;
|
|
245
|
+
this.download_progress = Math.max(0, Math.min(100, progress));
|
|
246
|
+
if (receivedBytes >= totalBytes) {
|
|
247
|
+
this.download_finished = true;
|
|
248
|
+
this.download_speed = '--';
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const elapsedSeconds = (Date.now() - startTime) / 1000;
|
|
252
|
+
const speed = elapsedSeconds > 0 ? receivedBytes / elapsedSeconds : 0;
|
|
253
|
+
this.download_speed = this.format_transfer_rate(speed);
|
|
254
|
+
const remaining = totalBytes - receivedBytes;
|
|
255
|
+
const eta = speed > 0 ? remaining / speed : NaN;
|
|
256
|
+
this.status = `Downloading ${this.format_size(receivedBytes)} / ${this.format_size(totalBytes)} (ETA ${this.format_duration(eta)})`;
|
|
257
|
+
}
|
|
160
258
|
connect() {
|
|
161
259
|
this.connected = true;
|
|
162
260
|
this.channel.connect();
|
|
@@ -195,10 +293,38 @@ const PhirepassSftpClient = class {
|
|
|
195
293
|
return `${protocol}://${this.serverHost}:${this.serverPort}`;
|
|
196
294
|
}
|
|
197
295
|
handle_error(error) {
|
|
296
|
+
if (error.msg_id !== undefined) {
|
|
297
|
+
const pendingUploadStart = this.pendingUploadStarts.get(error.msg_id);
|
|
298
|
+
if (pendingUploadStart) {
|
|
299
|
+
window.clearTimeout(pendingUploadStart.timeout);
|
|
300
|
+
pendingUploadStart.reject(new Error(error.message || 'Upload start failed'));
|
|
301
|
+
this.pendingUploadStarts.delete(error.msg_id);
|
|
302
|
+
}
|
|
303
|
+
const pendingDownloadStart = this.pendingDownloadStarts.get(error.msg_id);
|
|
304
|
+
if (pendingDownloadStart) {
|
|
305
|
+
window.clearTimeout(pendingDownloadStart.timeout);
|
|
306
|
+
pendingDownloadStart.reject(new Error(error.message || 'Download start failed'));
|
|
307
|
+
this.pendingDownloadStarts.delete(error.msg_id);
|
|
308
|
+
}
|
|
309
|
+
if (this.activeDownloads.has(error.msg_id)) {
|
|
310
|
+
this.activeDownloads.delete(error.msg_id);
|
|
311
|
+
if (this.activeDownloadMsgId === error.msg_id) {
|
|
312
|
+
this.activeDownloadMsgId = undefined;
|
|
313
|
+
}
|
|
314
|
+
this.download_finished = false;
|
|
315
|
+
}
|
|
316
|
+
if (this.pendingDelete?.msgId === error.msg_id) {
|
|
317
|
+
this.stop_delete_polling();
|
|
318
|
+
this.delete_loading = false;
|
|
319
|
+
this.show_delete_modal = false;
|
|
320
|
+
this.status = 'Connected';
|
|
321
|
+
}
|
|
322
|
+
}
|
|
198
323
|
switch (error.kind) {
|
|
199
324
|
case protocol.ErrorType.Generic:
|
|
200
325
|
case protocol.ErrorType.Authentication:
|
|
201
326
|
this.error_message = error.message || 'An unknown error occurred.';
|
|
327
|
+
this.show_error = true;
|
|
202
328
|
break;
|
|
203
329
|
case protocol.ErrorType.RequiresUsername:
|
|
204
330
|
this.show_login_screen_username = true;
|
|
@@ -248,8 +374,233 @@ const PhirepassSftpClient = class {
|
|
|
248
374
|
});
|
|
249
375
|
this.show_content = true;
|
|
250
376
|
this.show_navigation = true;
|
|
377
|
+
if (this.pendingDelete && web.path === this.current_dir) {
|
|
378
|
+
const fileStillExists = web.dir.items.some((item) => item.kind === 'File' && item.name === this.pendingDelete?.filename);
|
|
379
|
+
if (!fileStillExists) {
|
|
380
|
+
this.stop_delete_polling();
|
|
381
|
+
this.delete_loading = false;
|
|
382
|
+
this.show_delete_modal = false;
|
|
383
|
+
this.delete_file_name = '';
|
|
384
|
+
this.status = 'Connected';
|
|
385
|
+
}
|
|
386
|
+
}
|
|
251
387
|
console.log('Received SFTP list items:', web);
|
|
252
388
|
}
|
|
389
|
+
handle_upload_start_response(web) {
|
|
390
|
+
if (web.msg_id === undefined) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const pending = this.pendingUploadStarts.get(web.msg_id);
|
|
394
|
+
if (!pending) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
window.clearTimeout(pending.timeout);
|
|
398
|
+
pending.resolve(web.response.upload_id);
|
|
399
|
+
this.pendingUploadStarts.delete(web.msg_id);
|
|
400
|
+
}
|
|
401
|
+
handle_upload_chunk_ack(web) {
|
|
402
|
+
const key = `${web.upload_id}_${web.chunk_index}`;
|
|
403
|
+
const pending = this.pendingUploadAcks.get(key);
|
|
404
|
+
if (!pending) {
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
window.clearTimeout(pending.timeout);
|
|
408
|
+
pending.resolve();
|
|
409
|
+
this.pendingUploadAcks.delete(key);
|
|
410
|
+
}
|
|
411
|
+
handle_download_start_response(web) {
|
|
412
|
+
if (web.msg_id === undefined) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
const pending = this.pendingDownloadStarts.get(web.msg_id);
|
|
416
|
+
if (!pending) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
window.clearTimeout(pending.timeout);
|
|
420
|
+
pending.resolve({
|
|
421
|
+
download_id: web.response.download_id,
|
|
422
|
+
total_size: web.response.total_size,
|
|
423
|
+
total_chunks: web.response.total_chunks,
|
|
424
|
+
});
|
|
425
|
+
this.pendingDownloadStarts.delete(web.msg_id);
|
|
426
|
+
}
|
|
427
|
+
request_next_download_chunk(msgId) {
|
|
428
|
+
const download = this.activeDownloads.get(msgId);
|
|
429
|
+
if (!download || !this.session_id) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
this.channel.send_sftp_download_chunk(this.nodeId, this.session_id, download.download_id, download.nextChunkToRequest, msgId);
|
|
433
|
+
download.nextChunkToRequest += 1;
|
|
434
|
+
}
|
|
435
|
+
finalize_download(msgId) {
|
|
436
|
+
const download = this.activeDownloads.get(msgId);
|
|
437
|
+
if (!download) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const sortedChunks = Array.from(download.chunks.entries())
|
|
441
|
+
.sort((a, b) => a[0] - b[0])
|
|
442
|
+
.map(([, data]) => data);
|
|
443
|
+
// Normalize to fresh ArrayBuffer-backed views for BlobPart compatibility.
|
|
444
|
+
const blobParts = sortedChunks.map((chunk) => new Uint8Array(chunk));
|
|
445
|
+
const blob = new Blob(blobParts, { type: 'application/octet-stream' });
|
|
446
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
447
|
+
const anchor = document.createElement('a');
|
|
448
|
+
anchor.href = objectUrl;
|
|
449
|
+
anchor.download = download.filename;
|
|
450
|
+
document.body.appendChild(anchor);
|
|
451
|
+
anchor.click();
|
|
452
|
+
document.body.removeChild(anchor);
|
|
453
|
+
URL.revokeObjectURL(objectUrl);
|
|
454
|
+
this.activeDownloads.delete(msgId);
|
|
455
|
+
if (this.activeDownloadMsgId === msgId) {
|
|
456
|
+
this.activeDownloadMsgId = undefined;
|
|
457
|
+
}
|
|
458
|
+
this.download_finished = true;
|
|
459
|
+
this.status = 'Connected';
|
|
460
|
+
}
|
|
461
|
+
handle_download_chunk(web) {
|
|
462
|
+
if (web.msg_id === undefined) {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const download = this.activeDownloads.get(web.msg_id);
|
|
466
|
+
if (!download) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const chunkData = new Uint8Array(web.chunk.data);
|
|
470
|
+
download.chunks.set(web.chunk.chunk_index, chunkData);
|
|
471
|
+
const receivedBytes = Array.from(download.chunks.values()).reduce((sum, data) => sum + data.length, 0);
|
|
472
|
+
this.update_download_progress(receivedBytes, download.total_size, download.startTime);
|
|
473
|
+
if (download.chunks.size >= download.total_chunks) {
|
|
474
|
+
this.finalize_download(web.msg_id);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
this.request_next_download_chunk(web.msg_id);
|
|
478
|
+
}
|
|
479
|
+
async start_download(item) {
|
|
480
|
+
if (!this.session_id) {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
this.selected_item = item;
|
|
484
|
+
this.download_file_name = item.name;
|
|
485
|
+
this.download_progress = 0;
|
|
486
|
+
this.download_finished = false;
|
|
487
|
+
this.download_speed = '--';
|
|
488
|
+
this.show_download_modal = true;
|
|
489
|
+
this.show_error = false;
|
|
490
|
+
const msgId = this.next_msg_id();
|
|
491
|
+
this.activeDownloadMsgId = msgId;
|
|
492
|
+
this.activeDownloads.set(msgId, {
|
|
493
|
+
filename: item.name,
|
|
494
|
+
chunks: new Map(),
|
|
495
|
+
total_chunks: 0,
|
|
496
|
+
total_size: 0,
|
|
497
|
+
download_id: 0,
|
|
498
|
+
nextChunkToRequest: 0,
|
|
499
|
+
startTime: Date.now(),
|
|
500
|
+
});
|
|
501
|
+
const downloadStart = new Promise((resolve, reject) => {
|
|
502
|
+
const timeout = window.setTimeout(() => {
|
|
503
|
+
this.pendingDownloadStarts.delete(msgId);
|
|
504
|
+
reject(new Error('Download start timeout'));
|
|
505
|
+
}, 10_000);
|
|
506
|
+
this.pendingDownloadStarts.set(msgId, {
|
|
507
|
+
timeout,
|
|
508
|
+
resolve,
|
|
509
|
+
reject,
|
|
510
|
+
});
|
|
511
|
+
});
|
|
512
|
+
try {
|
|
513
|
+
this.channel.send_sftp_download_start(this.nodeId, this.session_id, item.path, item.name, msgId);
|
|
514
|
+
const { download_id, total_chunks, total_size } = await downloadStart;
|
|
515
|
+
const download = this.activeDownloads.get(msgId);
|
|
516
|
+
if (!download) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
download.download_id = download_id;
|
|
520
|
+
download.total_chunks = total_chunks;
|
|
521
|
+
download.total_size = total_size;
|
|
522
|
+
download.nextChunkToRequest = 0;
|
|
523
|
+
this.request_next_download_chunk(msgId);
|
|
524
|
+
}
|
|
525
|
+
catch (err) {
|
|
526
|
+
this.activeDownloads.delete(msgId);
|
|
527
|
+
if (this.activeDownloadMsgId === msgId) {
|
|
528
|
+
this.activeDownloadMsgId = undefined;
|
|
529
|
+
}
|
|
530
|
+
this.show_error = true;
|
|
531
|
+
this.error_message = err instanceof Error ? err.message : 'Failed to start download';
|
|
532
|
+
this.cancel_download();
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
async upload_file(fileToUpload) {
|
|
536
|
+
if (!this.session_id) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const uploadToken = this.activeUploadToken + 1;
|
|
540
|
+
this.activeUploadToken = uploadToken;
|
|
541
|
+
this.upload_file_name = fileToUpload.name;
|
|
542
|
+
this.upload_progress = 0;
|
|
543
|
+
this.upload_finished = false;
|
|
544
|
+
this.upload_speed = '--';
|
|
545
|
+
this.show_upload_modal = true;
|
|
546
|
+
this.show_error = false;
|
|
547
|
+
this.status = 'Uploading...';
|
|
548
|
+
const chunkSize = 64 * 1024;
|
|
549
|
+
const totalChunks = Math.max(1, Math.ceil(fileToUpload.size / chunkSize));
|
|
550
|
+
const msgId = this.next_msg_id();
|
|
551
|
+
const uploadStart = new Promise((resolve, reject) => {
|
|
552
|
+
const timeout = window.setTimeout(() => {
|
|
553
|
+
this.pendingUploadStarts.delete(msgId);
|
|
554
|
+
reject(new Error('Upload start timeout'));
|
|
555
|
+
}, 10_000);
|
|
556
|
+
this.pendingUploadStarts.set(msgId, {
|
|
557
|
+
timeout,
|
|
558
|
+
resolve,
|
|
559
|
+
reject,
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
try {
|
|
563
|
+
this.channel.send_sftp_upload_start(this.nodeId, this.session_id, fileToUpload.name, this.current_dir, totalChunks, BigInt(fileToUpload.size), msgId);
|
|
564
|
+
const uploadId = await uploadStart;
|
|
565
|
+
let uploadedBytes = 0;
|
|
566
|
+
const startedAt = performance.now();
|
|
567
|
+
for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex += 1) {
|
|
568
|
+
if (uploadToken !== this.activeUploadToken) {
|
|
569
|
+
throw new Error('Upload cancelled');
|
|
570
|
+
}
|
|
571
|
+
const start = chunkIndex * chunkSize;
|
|
572
|
+
const end = Math.min(start + chunkSize, fileToUpload.size);
|
|
573
|
+
const chunkBuffer = new Uint8Array(await fileToUpload.slice(start, end).arrayBuffer());
|
|
574
|
+
await new Promise((resolve, reject) => {
|
|
575
|
+
const key = `${uploadId}_${chunkIndex}`;
|
|
576
|
+
const timeout = window.setTimeout(() => {
|
|
577
|
+
this.pendingUploadAcks.delete(key);
|
|
578
|
+
reject(new Error(`Upload chunk ${chunkIndex + 1} timed out`));
|
|
579
|
+
}, 30_000);
|
|
580
|
+
this.pendingUploadAcks.set(key, {
|
|
581
|
+
timeout,
|
|
582
|
+
resolve,
|
|
583
|
+
reject,
|
|
584
|
+
});
|
|
585
|
+
this.channel.send_sftp_upload_chunk(this.nodeId, this.session_id, uploadId, chunkIndex, chunkBuffer.length, chunkBuffer, null);
|
|
586
|
+
});
|
|
587
|
+
uploadedBytes += chunkBuffer.length;
|
|
588
|
+
this.update_upload_progress(uploadedBytes, fileToUpload.size, startedAt);
|
|
589
|
+
}
|
|
590
|
+
this.upload_progress = 100;
|
|
591
|
+
this.upload_finished = true;
|
|
592
|
+
this.status = 'Connected';
|
|
593
|
+
this.refresh_directory();
|
|
594
|
+
}
|
|
595
|
+
catch (err) {
|
|
596
|
+
if (err.message !== 'Upload cancelled') {
|
|
597
|
+
this.show_error = true;
|
|
598
|
+
this.error_message = err instanceof Error ? err.message : 'Upload failed';
|
|
599
|
+
}
|
|
600
|
+
this.upload_finished = false;
|
|
601
|
+
this.status = 'Connected';
|
|
602
|
+
}
|
|
603
|
+
}
|
|
253
604
|
handle_tunnel_data(web) {
|
|
254
605
|
console.log('received tunnel data:', web);
|
|
255
606
|
}
|
|
@@ -305,12 +656,30 @@ const PhirepassSftpClient = class {
|
|
|
305
656
|
case protocol.ProtocolMessageType.SFTPListItems:
|
|
306
657
|
this.handle_sftp_list_items(web);
|
|
307
658
|
break;
|
|
659
|
+
case protocol.ProtocolMessageType.SFTPUploadStartResponse:
|
|
660
|
+
this.handle_upload_start_response(web);
|
|
661
|
+
break;
|
|
662
|
+
case protocol.ProtocolMessageType.SFTPUploadChunkAck:
|
|
663
|
+
this.handle_upload_chunk_ack(web);
|
|
664
|
+
break;
|
|
665
|
+
case protocol.ProtocolMessageType.SFTPDownloadStartResponse:
|
|
666
|
+
this.handle_download_start_response(web);
|
|
667
|
+
break;
|
|
668
|
+
case protocol.ProtocolMessageType.SFTPDownloadChunk:
|
|
669
|
+
this.handle_download_chunk(web);
|
|
670
|
+
break;
|
|
308
671
|
default:
|
|
309
672
|
console.warn('Unhandled protocol message type:', web);
|
|
310
673
|
}
|
|
311
674
|
});
|
|
312
675
|
}
|
|
313
676
|
close_comms() {
|
|
677
|
+
this.cancel_active_upload();
|
|
678
|
+
this.cancel_active_download();
|
|
679
|
+
this.clear_pending_operations();
|
|
680
|
+
if (!this.channel) {
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
314
683
|
this.channel.stop_heartbeat();
|
|
315
684
|
this.channel.disconnect();
|
|
316
685
|
}
|
|
@@ -356,26 +725,25 @@ const PhirepassSftpClient = class {
|
|
|
356
725
|
this.show_login_screen_username = false;
|
|
357
726
|
this.show_login_screen_password = false;
|
|
358
727
|
this.show_login_screen = false;
|
|
728
|
+
this.show_upload_modal = false;
|
|
729
|
+
this.show_download_modal = false;
|
|
730
|
+
this.show_delete_modal = false;
|
|
731
|
+
this.upload_progress = 0;
|
|
732
|
+
this.download_progress = 0;
|
|
733
|
+
this.upload_finished = false;
|
|
734
|
+
this.download_finished = false;
|
|
735
|
+
this.delete_loading = false;
|
|
736
|
+
this.delete_file_name = '';
|
|
359
737
|
this.version = '';
|
|
360
738
|
this.status = 'Disconnected';
|
|
361
739
|
}
|
|
362
740
|
on_file_row_action(item, event) {
|
|
363
741
|
event.preventDefault();
|
|
364
742
|
event.stopPropagation();
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
this.
|
|
369
|
-
this.show_download_modal = true;
|
|
370
|
-
this.clear_download_progress();
|
|
371
|
-
this.downloadProgressHandle = window.setInterval(() => {
|
|
372
|
-
if (this.download_progress >= 100) {
|
|
373
|
-
this.clear_download_progress();
|
|
374
|
-
this.download_finished = true;
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
this.download_progress = Math.min(100, this.download_progress + 5);
|
|
378
|
-
}, 180);
|
|
743
|
+
if (item.kind !== 'File') {
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
void this.start_download(item);
|
|
379
747
|
}
|
|
380
748
|
on_file_delete_action(item, event) {
|
|
381
749
|
event.preventDefault();
|
|
@@ -392,25 +760,48 @@ const PhirepassSftpClient = class {
|
|
|
392
760
|
this.show_delete_modal = false;
|
|
393
761
|
this.delete_file_name = '';
|
|
394
762
|
this.delete_loading = false;
|
|
763
|
+
this.refresh_directory();
|
|
395
764
|
}
|
|
396
765
|
confirm_delete() {
|
|
397
766
|
if (this.delete_loading) {
|
|
398
767
|
return;
|
|
399
768
|
}
|
|
400
|
-
this.
|
|
401
|
-
const deletingFileName = this.delete_file_name;
|
|
402
|
-
this.clear_delete_loading_timeout();
|
|
403
|
-
this.deleteLoadingTimeout = window.setTimeout(() => {
|
|
769
|
+
if (!this.session_id || !this.selected_item) {
|
|
404
770
|
this.show_delete_modal = false;
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
const fileToDelete = this.selected_item.name;
|
|
774
|
+
this.delete_loading = true;
|
|
775
|
+
this.status = 'Deleting...';
|
|
776
|
+
this.show_error = false;
|
|
777
|
+
this.stop_delete_polling();
|
|
778
|
+
const msgId = this.next_msg_id();
|
|
779
|
+
this.pendingDelete = {
|
|
780
|
+
filename: fileToDelete,
|
|
781
|
+
msgId,
|
|
782
|
+
startedAt: Date.now(),
|
|
783
|
+
};
|
|
784
|
+
const pollOnce = () => {
|
|
785
|
+
if (!this.pendingDelete) {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
const elapsed = Date.now() - this.pendingDelete.startedAt;
|
|
789
|
+
if (elapsed >= 30_000) {
|
|
790
|
+
this.stop_delete_polling();
|
|
791
|
+
this.delete_loading = false;
|
|
792
|
+
this.show_delete_modal = false;
|
|
793
|
+
this.show_error = true;
|
|
794
|
+
this.error_message = `Delete timed out for "${fileToDelete}".`;
|
|
795
|
+
this.status = 'Connected';
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
if (this.session_id) {
|
|
799
|
+
this.channel.send_sftp_list_data(this.nodeId, this.session_id, this.current_dir);
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
pollOnce();
|
|
803
|
+
this.pendingDelete.interval = window.setInterval(pollOnce, 2_500);
|
|
804
|
+
this.channel.send_sftp_delete(this.nodeId, this.session_id, this.current_dir, fileToDelete, msgId);
|
|
414
805
|
}
|
|
415
806
|
open_upload_picker() {
|
|
416
807
|
this.uploadInputEl?.click();
|
|
@@ -421,34 +812,24 @@ const PhirepassSftpClient = class {
|
|
|
421
812
|
if (!selectedFile) {
|
|
422
813
|
return;
|
|
423
814
|
}
|
|
424
|
-
this.
|
|
425
|
-
this.upload_progress = 0;
|
|
426
|
-
this.upload_finished = false;
|
|
427
|
-
this.show_upload_modal = true;
|
|
428
|
-
this.clear_upload_progress();
|
|
429
|
-
this.uploadProgressHandle = window.setInterval(() => {
|
|
430
|
-
if (this.upload_progress >= 100) {
|
|
431
|
-
this.clear_upload_progress();
|
|
432
|
-
this.upload_finished = true;
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
this.upload_progress = Math.min(100, this.upload_progress + 5);
|
|
436
|
-
}, 180);
|
|
815
|
+
void this.upload_file(selectedFile);
|
|
437
816
|
input.value = '';
|
|
438
817
|
}
|
|
439
818
|
cancel_upload() {
|
|
440
|
-
this.
|
|
819
|
+
this.cancel_active_upload();
|
|
441
820
|
this.show_upload_modal = false;
|
|
442
|
-
this.upload_progress = 0;
|
|
443
821
|
this.upload_file_name = '';
|
|
444
|
-
this.
|
|
822
|
+
this.upload_speed = '--';
|
|
823
|
+
this.status = 'Connected';
|
|
824
|
+
this.refresh_directory();
|
|
445
825
|
}
|
|
446
826
|
cancel_download() {
|
|
447
|
-
this.
|
|
827
|
+
this.cancel_active_download();
|
|
448
828
|
this.show_download_modal = false;
|
|
449
|
-
this.download_progress = 0;
|
|
450
829
|
this.download_file_name = '';
|
|
451
|
-
this.
|
|
830
|
+
this.download_speed = '--';
|
|
831
|
+
this.status = 'Connected';
|
|
832
|
+
this.refresh_directory();
|
|
452
833
|
}
|
|
453
834
|
is_selected(item) {
|
|
454
835
|
if (!this.selected_item) {
|
|
@@ -476,9 +857,6 @@ const PhirepassSftpClient = class {
|
|
|
476
857
|
this.selected_item = null;
|
|
477
858
|
this.channel.send_sftp_list_data(this.nodeId, this.session_id, path);
|
|
478
859
|
}
|
|
479
|
-
get_full_path(item) {
|
|
480
|
-
return [item.path, item.name].join('/');
|
|
481
|
-
}
|
|
482
860
|
format_size(size) {
|
|
483
861
|
if (size === undefined || Number.isNaN(size)) {
|
|
484
862
|
return '-';
|
|
@@ -555,18 +933,18 @@ const PhirepassSftpClient = class {
|
|
|
555
933
|
return `${typeChar}${chars.join('')}`;
|
|
556
934
|
}
|
|
557
935
|
render() {
|
|
558
|
-
return (index.h(index.Host, { key: '
|
|
936
|
+
return (index.h(index.Host, { key: '4a0c122426a92a92e3a7121d8adecbefe5eaf852', class: {
|
|
559
937
|
'default': !this.max,
|
|
560
938
|
'max': this.max,
|
|
561
|
-
} }, index.h("section", { key: '
|
|
562
|
-
index.h("header", { key: '
|
|
939
|
+
} }, index.h("section", { key: 'f408645cf18f728c09e7af174f5eb30b5d37ca3b', class: "listing" }, !this.hideHeader &&
|
|
940
|
+
index.h("header", { key: '42fbffd05631ab758d4a9647b4bda41cb5b77b0a' }, index.h("section", { key: '9b67a0e72219f287d8458bb8ce271789ec653dc7', class: "title" }, index.h("img", { key: '0eb4b3588b0631d4e93827f74111650d3bed26c4', src: phirepassSftpClientLogoSvg, alt: "SFTP Client" }), index.h("div", { key: '30945973ee86494b0b2c90ead1c178a1f48086fa', class: "text" }, index.h("div", { key: '716418d9af825dfd974ef96f7c9687f8e08cc4e7', class: "name" }, this.name), index.h("div", { key: 'eec1114d46f86c0f777b75a98dc21af1fe473f96', class: "description" }, this.description))), index.h("section", { key: '05aa545ba36f40adabe6d920514a00b50219744e', class: "actions" }, index.h("div", { key: '036d227279849911bd353ba879600d46d4cd1ab2', class: "action", onClick: () => this.toggle_max() }, index.h("img", { key: '3087b9252229f3dc401ea984c7e4576dc0bb74cb', src: phirepassSftpClientMaxSvg, alt: "Maximize" })))), index.h("main", { key: '5f2a69fb252b3df05742f8b74a15a0c9028f372f' }, this.show_navigation && index.h("nav", { key: '10612928faf505db3a3a2a00df51425540ea97ec', class: "navigation" }, index.h("div", { key: 'fdaa4662f45fad1b2fa31059f67df9344f7e7428', class: "breadcrumbs" }, this.breadcrumbs.map((crumb, index$1, breadcrumbs) => (index.h("span", { key: index$1, class: "breadcrumb-container" }, index.h("span", { key: index$1, onClick: () => this.list_breadcrumb(crumb.path), class: "breadcrumb" }, crumb.label), index$1 < breadcrumbs.length - 1 && index.h("img", { class: "arrow", src: phirepassSftpClientChevronSvg }))))), index.h("section", { key: '71356c63017f5c74eadeabec428a3b7b3809ade2', class: "actions", "aria-label": "SFTP actions" }, index.h("button", { key: 'eaf88ec4362509efd594f29a38531a8b158ece9f', type: "button", class: "action", onClick: () => this.go_to_parent_directory(), title: "Go to parent directory", "aria-label": "Go to parent directory" }, index.h("img", { key: 'b1d5c6a632e22d64f829dbbd7139b859006dbd7a', src: phirepassSftpClientGoUpSvg, alt: "Go up" })), index.h("button", { key: '94abac9e1a6984872c4c85e66aa448d11621e980', type: "button", class: "action", onClick: () => this.refresh_directory(), title: "Refresh", "aria-label": "Refresh" }, index.h("img", { key: 'd953e97de3411cd1a526c6e1fe042db0ddc673e5', src: phirepassSftpClientRefreshSvg, alt: "Refresh" })), index.h("button", { key: '03598d60ae17c54493b1572f53c267b765008766', type: "button", class: "action", onClick: () => this.open_upload_picker(), title: "Upload", "aria-label": "Upload" }, index.h("img", { key: 'c39ee38d8e584c35155035aeb37403d4a89372ba', src: phirepassSftpClientUploadSvg, alt: "Upload" })), index.h("button", { key: '7e017137f2588bb7a231ef76e874b85e3c1c112d', type: "button", class: "action disconnect", onClick: () => this.disconnect_session(), title: "Disconnect", "aria-label": "Disconnect" }, "DISCONNECT"))), index.h("input", { key: '2956f9ad2124f813d848ace2206312ee81a4e145', type: "file", ref: (el) => this.uploadInputEl = el, onChange: (event) => this.on_upload_selected(event), style: { display: 'none' } }), this.show_content && index.h("div", { key: '451d0758c8b71ac9c720f4ad07c5fa3a7011b43e', class: "content" }, index.h("table", { key: '27a87bfdc1e357a15ff578cae12f41fb768be576' }, index.h("thead", { key: 'c8161cd9ff7e2bdf0579b3aa9797bd2366b106e8' }, index.h("tr", { key: '23dc88a5b43a77bb1ab031f72e01996c0e16d4de' }, index.h("th", { key: '460827f1703d2c7165df2e07b2d873d71a842c6f' }, "Name"), index.h("th", { key: '6960f731ba9b30012d1772911899714ad6ea5e10' }, "Size"), index.h("th", { key: '71ae2e8bd6c7ba2110470b651aed9cda0ef2b88f' }, "Permissions"), index.h("th", { key: '6e8e87a11812570c5bbfebadf4793eafe15e6237' }, "Owner"), index.h("th", { key: 'b0001ae77eb5c4958434558c715aa5b23e336da2' }, "Modified"), index.h("th", { key: '3eb862c25e9734c1a2c99fe07ea804761d9578e9', class: "action-col", "aria-label": "Actions" }))), index.h("tbody", { key: 'b80916d2917e97c9e4058195c5d5d20e98702d60' }, this.listing.map((item, index$1) => (index.h("tr", { key: index$1, class: {
|
|
563
941
|
'selected': this.is_selected(item),
|
|
564
942
|
}, onClick: () => this.list_directory(item) }, index.h("td", null, item.kind === 'Folder' ? index.h("img", { class: "kind", src: phirepassSftpClientFolderSvg, alt: "Folder" }) : index.h("img", { class: "kind", src: phirepassSftpClientFileSvg, alt: "File" }), index.h("span", { class: `name ${item.kind.toLowerCase()}` }, item.name)), index.h("td", null, this.format_size(item.attributes.size)), index.h("td", null, this.format_permissions(item.attributes.permissions, item.kind)), index.h("td", null, item.attributes.user ?? '-'), index.h("td", null, new Date(item.attributes.modified * 1000).toLocaleString()), index.h("td", { class: "action-col" }, item.kind === 'File' &&
|
|
565
|
-
index.h("div", { class: "file-actions" }, index.h("button", { type: "button", class: "file-action", onClick: (event) => this.on_file_row_action(item, event), title: "Download", "aria-label": "Download" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), index.h("polyline", { points: "7 10 12 15 17 10" }), index.h("line", { x1: "12", x2: "12", y1: "15", y2: "3" }))), index.h("button", { type: "button", class: "file-action delete", onClick: (event) => this.on_file_delete_action(item, event), title: "Delete", "aria-label": "Delete" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("polyline", { points: "3 6 5 6 21 6" }), index.h("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), index.h("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), index.h("line", { x1: "10", x2: "10", y1: "11", y2: "17" }), index.h("line", { x1: "14", x2: "14", y1: "11", y2: "17" }))))))))))), this.show_loader && index.h("div", { key: '
|
|
566
|
-
index.h("section", { key: '
|
|
943
|
+
index.h("div", { class: "file-actions" }, index.h("button", { type: "button", class: "file-action", onClick: (event) => this.on_file_row_action(item, event), title: "Download", "aria-label": "Download" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), index.h("polyline", { points: "7 10 12 15 17 10" }), index.h("line", { x1: "12", x2: "12", y1: "15", y2: "3" }))), index.h("button", { type: "button", class: "file-action delete", onClick: (event) => this.on_file_delete_action(item, event), title: "Delete", "aria-label": "Delete" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("polyline", { points: "3 6 5 6 21 6" }), index.h("path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), index.h("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), index.h("line", { x1: "10", x2: "10", y1: "11", y2: "17" }), index.h("line", { x1: "14", x2: "14", y1: "11", y2: "17" }))))))))))), this.show_loader && index.h("div", { key: '6698d4f3a2f60efa264ac5d4a3e35da14c1b47d5', class: "loader" }, "Loading..."), this.show_error && index.h("div", { key: '411d74aa5574e444eb4f08d7ecec37fbe9c54a37', class: "error" }, this.error_message)), index.h("footer", { key: 'a58fb0f412a403f930cbdca15269678cf92037f9' }, index.h("section", { key: '8a989e00a03d5d3290599131989ddef872444e9b', class: "version" }, this.version ? `Version: ${this.version}` : ''))), this.show_login_screen &&
|
|
944
|
+
index.h("section", { key: '8f070e03986f073de9ca90ea2f46cd0d485a0a8c', class: {
|
|
567
945
|
'creds': true,
|
|
568
946
|
'blurred': this.show_login_screen,
|
|
569
|
-
} }, index.h("form", { key: '
|
|
947
|
+
} }, index.h("form", { key: 'f8d6b2455ecf15e6ef19f1058c86100d7fe36357', class: "auth", onSubmit: (event) => {
|
|
570
948
|
const formData = new FormData(event.target);
|
|
571
949
|
let username = undefined;
|
|
572
950
|
if (this.show_login_screen_username) {
|
|
@@ -583,27 +961,28 @@ const PhirepassSftpClient = class {
|
|
|
583
961
|
this.show_loader = true;
|
|
584
962
|
event.stopPropagation();
|
|
585
963
|
event.preventDefault();
|
|
586
|
-
} }, index.h("div", { key: '
|
|
587
|
-
index.h("div", { key: '
|
|
588
|
-
index.h("div", { key: '
|
|
589
|
-
index.h("section", { key: '
|
|
964
|
+
} }, index.h("div", { key: '870343a9f67b01ce620c88ab3af2d823e9c109da', class: "title" }, "SFTP Connection"), this.show_login_screen_username &&
|
|
965
|
+
index.h("div", { key: 'd32b19a3d0e89196247358ca846fd6108fe15128' }, index.h("label", { key: 'c60053d805db2357780bb986c71f6b839390ca20', htmlFor: "username" }, "Username"), index.h("input", { key: '73c368508cc63db7ff5d7c7ca1d3f12a6e409926', autocorrect: "off", autocapitalize: "none", autoComplete: "off", id: "username", name: "username", type: "text", placeholder: "" })), this.show_login_screen_password &&
|
|
966
|
+
index.h("div", { key: 'c5a91b121c0309e577ca63a5392dce7b982e6429' }, index.h("label", { key: 'b3adfc6963d418f9a7748092a661f87a77949f1d', htmlFor: "password" }, "Password"), index.h("input", { key: '0e6855eb8e7ef22e6981e5c7df429d4bc81e8d67', autocorrect: "off", autocapitalize: "none", autoComplete: "off", id: "password", name: "password", type: "password", placeholder: "" })), index.h("div", { key: '05377a2061e222afada603838feaac68b913be1b' }, index.h("button", { key: '4d28615b22f083ad8b7430a3babe2a5dbc9c4f90', type: "submit" }, "Connect")))), this.show_upload_modal &&
|
|
967
|
+
index.h("section", { key: '7979af0ec1f92bf78a94d5e1be2a7b7a79b780be', class: {
|
|
590
968
|
'upload-modal': true,
|
|
591
969
|
'visible': this.show_upload_modal,
|
|
592
|
-
} }, index.h("div", { key: '
|
|
970
|
+
} }, index.h("div", { key: '55132c16758312e55fd7bb5bb32dfcd557500838', class: "upload-dialog", role: "dialog", "aria-modal": "true", "aria-label": "Upload progress" }, index.h("div", { key: '7b808945f2123b5c1e8ed300cba85f3325be643e', class: "title" }, "Uploading File"), index.h("div", { key: '0c7065ccff128f524eee7da248eee97f78819bc0', class: "file-name", title: this.upload_file_name }, this.upload_file_name), index.h("div", { key: '848d3526b2cff55c6cc6eab0a4cb536264f14d80', class: "progress-track", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": this.upload_progress }, index.h("div", { key: 'a3f8d7c47971866243a5138ae1e5b84fe50fa008', class: "progress-fill", style: { width: `${this.upload_progress}%` } })), index.h("div", { key: '6675b28ce14fa0f3d84cbfcc602409f6ba650a13', class: "progress-meta" }, index.h("div", { key: '5205d72ab81c7bfc906fcfe827b05933440161b8', class: "progress-speed" }, this.upload_speed), index.h("div", { key: 'c3f59de705696ac1355629ac0397e1a9baf56a0a', class: "progress-value" }, this.format_percent(this.upload_progress))), index.h("button", { key: '06d9bc2f61d7f83361ad97b7bb23f2f45b11ec27', type: "button", class: {
|
|
593
971
|
'cancel': true,
|
|
594
972
|
'finished': this.upload_finished,
|
|
595
973
|
}, onClick: () => this.cancel_upload() }, this.upload_finished ? 'Close' : 'Cancel'))), this.show_download_modal &&
|
|
596
|
-
index.h("section", { key: '
|
|
974
|
+
index.h("section", { key: '7217722972f463d2893bd44ac5a4899c8fe545a7', class: {
|
|
597
975
|
'download-modal': true,
|
|
598
976
|
'visible': this.show_download_modal,
|
|
599
|
-
} }, index.h("div", { key: '
|
|
977
|
+
} }, index.h("div", { key: '493dddfad5d25411a3421641ef930eab561347b4', class: "download-dialog", role: "dialog", "aria-modal": "true", "aria-label": "Download progress" }, index.h("div", { key: '2115492e8360a19edf260c7c603bc44e736cccec', class: "title" }, "Downloading File"), index.h("div", { key: '5582b3ea56c9a184ff1b6de4ca89b93f07461847', class: "file-name", title: this.download_file_name }, this.download_file_name), index.h("div", { key: '90df12daa47066e7a212edeec5760cef2abc52c6', class: "progress-track", role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": this.download_progress }, index.h("div", { key: '2c3c6ef5b7091ea010c4fc9037d05db5845f4e23', class: "progress-fill", style: { width: `${this.download_progress}%` } })), index.h("div", { key: '9d963e08afe1e073f19fc9195cd66f67a874204f', class: "progress-meta" }, index.h("div", { key: '96508c5a2a95ce9889d947bc4786403785b15c75', class: "progress-speed" }, this.download_speed), index.h("div", { key: '3f0cab67e511efda1cf79111705525b9838eb410', class: "progress-value" }, this.format_percent(this.download_progress))), index.h("button", { key: 'cac13e01231ba4c1713b85e7b7ac661b1ec6f6e5', type: "button", class: {
|
|
600
978
|
'cancel': true,
|
|
601
979
|
'finished': this.download_finished,
|
|
602
980
|
}, onClick: () => this.cancel_download() }, this.download_finished ? 'Close' : 'Cancel'))), this.show_delete_modal &&
|
|
603
|
-
index.h("section", { key: '
|
|
981
|
+
index.h("section", { key: 'e66cc06cb588d7842a4557041a5fa617b2672b0b', class: {
|
|
604
982
|
'delete-modal': true,
|
|
605
983
|
'visible': this.show_delete_modal,
|
|
606
|
-
} }, index.h("div", { key: '
|
|
984
|
+
} }, index.h("div", { key: 'ac2298da9dde4e4043f29a8b2b137fe7f2e0f5dc', class: "delete-dialog", role: "dialog", "aria-modal": "true", "aria-label": "Delete confirmation" }, index.h("div", { key: 'ac53826a41c03e3cb94296c30e622f453bca0f40', class: "title" }, "Delete File"), index.h("div", { key: '9724627c77b3242f25e7d73b18bae820833cdb9f', class: "message" }, this.delete_loading ? 'Deleting file...' : 'Are you sure you want to delete this file?'), index.h("div", { key: '408ece6999a858d60baf7bd34b3133d07aba8806', class: "file-name", title: this.delete_file_name }, this.delete_file_name), this.delete_loading &&
|
|
985
|
+
index.h("div", { key: '6f157f39e1097a355c139af9ea0e35ee76a04117', class: "delete-loader", "aria-hidden": "true" }, index.h("span", { key: 'bd85fe1e6dfc09febebcd1c31fc99629d1f4429d', class: "spinner" })), index.h("div", { key: 'ad4f19824730b61e82e8ad205d5ea0cc2e715a7f', class: "modal-actions" }, index.h("button", { key: '9d95213a54aefc8064769796f235b4533fc5aa08', type: "button", class: "btn secondary", onClick: () => this.cancel_delete(), disabled: this.delete_loading }, "Cancel"), index.h("button", { key: 'd423c0537eb372ed491387c45e6a5c5f5a975259', type: "button", class: "btn destructive", onClick: () => this.confirm_delete(), disabled: this.delete_loading }, this.delete_loading ? 'Deleting...' : 'Delete'))))));
|
|
607
986
|
}
|
|
608
987
|
static get watchers() { return {
|
|
609
988
|
"nodeId": [{
|