@@ -8,8 +8,6 @@ import "@material/web/icon/icon.js";
88import { ArgoArchiveList } from "./argo-archive-list" ;
99import { Downloader } from "./sw/downloader" ;
1010
11- import wrRec from "./assets/icons/recLogo.svg" ;
12-
1311import {
1412 getLocalOption ,
1513 // removeLocalOption,
@@ -128,6 +126,35 @@ class ArgoViewer extends LitElement {
128126 filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.6));
129127 }
130128
129+ /* Fade overlay styles */
130+ .tabs-wrapper {
131+ position: relative;
132+ }
133+
134+ .tabs-overlay {
135+ transition: opacity 0.3s ease;
136+ }
137+ .tabs-overlay.inactive {
138+ opacity: 0;
139+ pointer-events: none;
140+ }
141+
142+ .actions-overlay {
143+ position: absolute;
144+ top: 0;
145+ left: 0;
146+ width: 100%;
147+ transition: opacity 0.3s ease;
148+ opacity: 0;
149+ pointer-events: none;
150+ background: white;
151+ z-index: 1;
152+ }
153+ .actions-overlay.active {
154+ opacity: 1;
155+ pointer-events: auto;
156+ }
157+
131158 md-icon[filled] {
132159 font-variation-settings: "FILL" 1;
133160 }
@@ -137,6 +164,8 @@ class ArgoViewer extends LitElement {
137164 private archiveList ! : ArgoArchiveList ;
138165 constructor ( ) {
139166 super ( ) ;
167+ // @ts -expect-error - TS2339 - Property 'selectedCount' does not exist on type 'ArgoViewer'.
168+ this . selectedCount = 0 ;
140169 // @ts -expect-error - TS2339 - Property 'searchQuery' does not exist on type 'ArgoViewer'.
141170 this . searchQuery = "" ;
142171 // @ts -expect-error - TS2339 - Property 'collections' does not exist on type 'ArgoViewer'.
@@ -193,6 +222,7 @@ class ArgoViewer extends LitElement {
193222 static get properties ( ) {
194223 return {
195224 searchQuery : { type : String } ,
225+ selectedCount : { type : Number } ,
196226 collections : { type : Array } ,
197227 collId : { type : String } ,
198228 collTitle : { type : String } ,
@@ -250,6 +280,16 @@ class ArgoViewer extends LitElement {
250280 } ) [ 0 ] ;
251281 }
252282
283+ onDeleteSelected ( ) {
284+ const pages = this . archiveList . getSelectedPages ( ) ;
285+ const ids = pages . map ( ( p ) => p . id ) ;
286+ this . sendMessage ( { type : "deletePages" , pageIds : ids } ) ;
287+ // then clear UI
288+ this . archiveList . clearSelection ( ) ;
289+ // @ts -expect-error - TS2339 - Property 'selectedCount' does not exist on type 'ArgoViewer'.
290+ this . selectedCount = 0 ;
291+ }
292+
253293 private async onDownload ( ) {
254294 const selectedPages = this . archiveList ?. getSelectedPages ?.( ) || [ ] ;
255295 if ( ! selectedPages . length ) {
@@ -389,7 +429,7 @@ class ArgoViewer extends LitElement {
389429 }
390430
391431 firstUpdated ( ) {
392- this . archiveList = this . shadowRoot ? .getElementById (
432+ this . archiveList = this . shadowRoot ! . getElementById (
393433 "archive-list" ,
394434 ) as ArgoArchiveList ;
395435
@@ -416,29 +456,54 @@ class ArgoViewer extends LitElement {
416456 } ) ;
417457 }
418458
419- registerMessages ( ) {
420- // @ts -expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'.
459+ private connectPort ( ) {
460+ // if already connected, do nothing
461+ // @ts -expect-error
462+ if ( this . port ) return ;
463+ // @ts -expect-error
421464 this . port = chrome . runtime . connect ( { name : "sidepanel-port" } ) ;
465+ // @ts -expect-error
466+ this . port . onMessage . addListener ( ( msg ) => this . onMessage ( msg ) ) ;
467+ // @ts -expect-error
468+ this . port . onDisconnect . addListener ( ( ) => {
469+ // clear so next sendMessage() will reconnect
470+ console . warn ( "Port disconnected, will reconnect on next send." ) ;
471+ // @ts -expect-error
472+ this . port = null ;
473+ } ) ;
474+ }
422475
476+ registerMessages ( ) {
477+ this . connectPort ( ) ;
423478 this . updateTabInfo ( ) ;
424-
425- // @ts -expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'.
426- this . port . onMessage . addListener ( ( message ) => {
427- this . onMessage ( message ) ;
428- } ) ;
429479 }
430480
431- // @ts -expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type.
432- sendMessage ( message ) {
433- // @ts -expect-error - TS2339 - Property 'port' does not exist on type 'ArgoViewer'.
434- this . port . postMessage ( message ) ;
481+ private sendMessage ( message : any ) {
482+ // reconnect if needed
483+ // @ts -expect-error
484+ if ( ! this . port ) this . connectPort ( ) ;
485+ try {
486+ // @ts -expect-error
487+ this . port ! . postMessage ( message ) ;
488+ } catch ( e ) {
489+ console . warn (
490+ "Port died while sending, retrying via chrome.runtime.sendMessage" ,
491+ e ,
492+ ) ;
493+ chrome . runtime . sendMessage ( message ) ;
494+ }
435495 }
436496 // @ts -expect-error - TS7006 - Parameter 'message' implicitly has an 'any' type.
437497 async onMessage ( message ) {
438498 switch ( message . type ) {
439499 case "update" :
440500 this . updateTabInfo ( ) ;
441501 break ;
502+
503+ case "pages" :
504+ // @ts -expect-error — pages is internal to the list
505+ this . archiveList . pages = message . pages ;
506+ break ;
442507 case "status" :
443508 // @ts -expect-error - TS2339 - Property 'tabId' does not exist on type 'ArgoViewer'.
444509 if ( this . tabId !== message . tabId ) {
@@ -704,7 +769,7 @@ class ArgoViewer extends LitElement {
704769 style ="color: white; border-radius: 9999px; align-self: flex-end; "
705770 @click =${ this . onShareCurrent }
706771 >
707- < md-icon slot ="icon " style ="color:white "> share</ md-icon >
772+ < md-icon slot ="icon " style ="color:#444 "> share</ md-icon >
708773 Share Current Page
709774 </ md-filled-button > `
710775 : ""
@@ -816,25 +881,86 @@ class ArgoViewer extends LitElement {
816881
817882 renderTabs ( ) {
818883 return html `
819- < md-tabs id ="tabs " aria-label ="Archive tabs ">
820- < md-primary-tab class ="md-typescale-label-large "
821- > My Archives</ md-primary-tab
884+ < div class ="tabs-wrapper ">
885+ <!-- Original tabs overlay -->
886+ < div
887+ class ="tabs-overlay ${
888+ //@ts -expect-error
889+ this . selectedCount > 0 ? "inactive" : ""
890+ } "
822891 >
823- < md-primary-tab class ="md-typescale-label-large "
824- > My Shared Archives</ md-primary-tab
892+ < md-tabs id ="tabs " aria-label ="Archive tabs ">
893+ < md-primary-tab class ="md-typescale-label-large "
894+ > My Archives</ md-primary-tab
895+ >
896+ < md-primary-tab class ="md-typescale-label-large "
897+ > My Shared Archives</ md-primary-tab
898+ >
899+ </ md-tabs >
900+ </ div >
901+
902+ <!-- Actions overlay on selection -->
903+ < div
904+ class ="actions-overlay ${
905+ //@ts -expect-error
906+ this . selectedCount > 0 ? "active" : ""
907+ } "
825908 >
826- </ md-tabs >
909+ < div
910+ style ="display:flex; align-items:center; justify-content:space-between; padding: 0.25rem 1rem; "
911+ >
912+ < div style ="display:flex; align-items:center; gap: 0.5rem; ">
913+ < md-icon-button
914+ aria-label ="Deselect All "
915+ @click =${ ( ) => {
916+ this . archiveList . clearSelection ( ) ;
917+ //@ts -expect-error
918+ this . selectedCount = 0 ;
919+ } }
920+ >
921+ < md-icon style ="color: gray "> clear</ md-icon >
922+ </ md-icon-button >
923+ < span class ="md-typescale-body-small "
924+ > ${
925+ //@ts -expect-error
926+ this . selectedCount
927+ }
928+ selected</ span
929+ >
930+ </ div >
931+
932+ < div style ="display:flex; align-items:center; gap: 0.5rem; ">
933+ < md-icon-button aria-label ="Download " @click =${ this . onDownload }
934+ > < md-icon > download</ md-icon > </ md-icon-button
935+ >
936+ < md-icon-button aria-label ="Share " @click =${ this . onShareSelected }
937+ > < md-icon > share</ md-icon > </ md-icon-button
938+ >
939+ < md-icon-button
940+ aria-label ="Delete "
941+ @click =${ this . onDeleteSelected }
942+ > < md-icon > delete</ md-icon > </ md-icon-button
943+ >
944+ </ div >
945+ </ div >
946+ < md-divider > </ md-divider >
947+ </ div >
948+ </ div >
827949
950+ <!-- Panels remain unchanged -->
828951 < div
829952 class ="tab-panels "
830- style ="flex: 1; overflow-y: auto; position: relative; flex-grow: 1; "
953+ style ="flex:1; overflow-y:auto; position:relative; flex-grow:1; "
954+ @selection-change =${ ( e : CustomEvent ) =>
955+ // @ts -expect-error
956+ ( this . selectedCount = e . detail . count ) }
831957 >
832958 < div id ="my-archives " class ="tab-panel " active >
833959 ${ this . renderStatusCard ( ) }
834960 < argo-archive-list
835961 id ="archive-list "
836962 .filterQuery =${
837- //@ts -expect-error - TS2339 - Property 'searchQuery' does not exist on type 'ArgoViewer'.
963+ // @ts -expect-error
838964 this . searchQuery
839965 }
840966 > </ argo-archive-list >
@@ -868,19 +994,6 @@ class ArgoViewer extends LitElement {
868994 < md-icon slot ="icon " style ="color:white "> public</ md-icon >
869995 Resume Archiving
870996 </ md-filled-button >
871- < md-icon-button
872- aria-label ="Download "
873- @click =${ this . onDownload }
874- >
875- < md-icon style ="color: gray; "> download</ md-icon >
876- </ md-icon-button >
877-
878- < md-icon-button
879- aria-label ="Share "
880- @click =${ this . onShareSelected }
881- >
882- < md-icon style ="color: gray; "> share</ md-icon >
883- </ md-icon-button >
884997 `
885998 : html `
886999 < md-outlined-button
0 commit comments