@@ -116,12 +116,33 @@ plugin.fromBackground = function( no )
116116 plugin . onStart ( this . foreground ) ;
117117}
118118
119- plugin . copyConsoleLog = function ( ) {
120- const consoleLog = $ ( '#tskcmdlog' ) . text ( ) ;
119+ plugin . readConsoleLog = function ( ) {
120+ const consoleLog = $ ( '#tskcmdlog' ) [ 0 ] . innerText ;
121121 if ( consoleLog !== "" ) {
122- copyToClipboard ( consoleLog ) ;
122+ return consoleLog ;
123123 } else {
124- log ( "Console log is empty." ) ;
124+ log ( theUILang . tskLogEmpty ) ;
125+ return ;
126+ }
127+ }
128+
129+ plugin . copyConsoleLog = function ( ) {
130+ const consoleLog = plugin . readConsoleLog ( ) ;
131+ if ( ! ! consoleLog ) {
132+ copyToClipboard ( consoleLog ) ;
133+ }
134+ }
135+
136+ plugin . saveConsoleLog = function ( ) {
137+ const consoleLog = plugin . readConsoleLog ( ) ;
138+ if ( ! ! consoleLog ) {
139+ const blob = new Blob ( [ consoleLog ] , { type :"text/plain" } ) ;
140+ const fileUrl = URL . createObjectURL ( blob ) ;
141+ const link = document . createElement ( "a" ) ;
142+ link . href = fileUrl ;
143+ link . download = "log.txt" ;
144+ link . click ( ) ;
145+ URL . revokeObjectURL ( fileUrl ) ; // revoke object url to prevent memory leaks
125146 }
126147}
127148
@@ -232,7 +253,9 @@ plugin.setConsoleControls = function(errPresent) {
232253 $ ( "#tskConsole-header" ) . html ( theUILang . tskCommandDone ) ;
233254 if ( $ ( '#tskcmdlog' ) . text ( ) === "" ) {
234255 // hide copy log button if log output is empty
235- $ ( "#tskCopy" ) . hide ( ) ;
256+ $ ( "#tskCopy, #tskSaveLog" ) . hide ( ) ;
257+ } else {
258+ $ ( "#tskCopy, #tskSaveLog" ) . show ( ) ;
236259 } ;
237260 }
238261 else
@@ -579,9 +602,16 @@ plugin.onLangLoaded = function() {
579602 ) ,
580603 ) ;
581604 const tskConsoleButtons = $ ( "<div>" ) . attr ( { id :"tsk_btns" } ) . addClass ( "buttons-list" ) . append (
582- $ ( "<button>" ) . attr ( { type :"button" , id :"tskCopy" } )
605+ $ ( "<button>" )
606+ . attr ( { type :"button" , id :"tskCopy" } )
583607 . on ( "click" , plugin . copyConsoleLog )
584- . text ( theUILang . tskCopy ) ,
608+ . text ( theUILang . tskCopy )
609+ . hide ( ) ,
610+ $ ( "<button>" )
611+ . attr ( { type :"button" , id :"tskSaveLog" } )
612+ . on ( "click" , plugin . saveConsoleLog )
613+ . text ( theUILang . tskSaveLog )
614+ . hide ( ) ,
585615 $ ( "<button>" ) . attr ( { type :"button" , id :"tskBackground" } )
586616 . on ( "click" , plugin . toBackground )
587617 . text ( theUILang . tskBackground ) ,
@@ -594,19 +624,17 @@ plugin.onLangLoaded = function() {
594624 true ,
595625 ) ;
596626
597- theDialogManager . setHandler ( 'tskConsole' , 'afterHide' , function ( )
598- {
599- if ( plugin . foreground . no )
600- {
601- if ( ! plugin . isInBackground ( ) )
627+ theDialogManager . setHandler ( 'tskConsole' , 'afterHide' , function ( ) {
628+ if ( plugin . foreground . no ) {
629+ if ( ! plugin . isInBackground ( ) )
602630 plugin . shutdown ( ) ;
603631 else
604632 theWebUI . getTable ( 'tasks' ) . tasksRemovePrim ( ) ;
605633 }
634+ $ ( "#tskCopy, #tskSaveLog" ) . hide ( ) ;
606635 } ) ;
607- theDialogManager . setHandler ( 'tskConsole' , 'afterShow' , function ( )
608- {
609- if ( ! plugin . cHeight )
636+ theDialogManager . setHandler ( 'tskConsole' , 'afterShow' , function ( ) {
637+ if ( ! plugin . cHeight )
610638 plugin . cHeight = $ ( '#tskcmderrors' ) . parent ( ) . height ( ) ;
611639 } ) ;
612640 $ ( ".tskconsole" ) . enableSysMenu ( ) ;
0 commit comments