11import Dismiss from 'solid-dismiss' ;
22import { Icon } from 'solid-heroicons' ;
33import { Component , onCleanup , createSignal , Show } from 'solid-js' ;
4- import { download , xCircle , menu , moon , sun } from 'solid-heroicons/outline' ;
4+ import { share , link , download , xCircle , menu , moon , sun } from 'solid-heroicons/outline' ;
55import { exportToZip } from '../utils/exportFiles' ;
66import { ZoomDropdown } from './zoomDropdown' ;
77import { API , useAppContext } from '../context' ;
8+ import { compressToURL } from '@amoutonbrady/lz-string' ;
9+
810import logo from '../assets/logo.svg?url' ;
911
10- export const Header : Component < {
11- dark : boolean ;
12- toggleDark : ( ) => void ;
13- } > = ( props ) => {
12+ export const Header : Component = ( ) => {
13+ const [ copy , setCopy ] = createSignal ( false ) ;
1414 const context = useAppContext ( ) ! ;
1515 const [ showMenu , setShowMenu ] = createSignal ( false ) ;
1616 let menuBtnEl ! : HTMLButtonElement ;
1717
18+ function shareLink ( ) {
19+ let url = new URL ( location . origin ) ;
20+ url . hash = compressToURL ( JSON . stringify ( context . tabs ( ) ) ) ;
21+ console . log ( 'Shareable url:' , url . href ) ;
22+
23+ fetch ( '/' , { method : 'PUT' , body : `{"url":"${ url . href } "}` } )
24+ . then ( ( response ) => {
25+ if ( response . status >= 400 ) {
26+ throw new Error ( response . statusText ) ;
27+ }
28+
29+ return response . text ( ) ;
30+ } )
31+ . then ( ( hash ) => {
32+ const tinyUrl = new URL ( location . origin ) ;
33+ tinyUrl . searchParams . set ( 'hash' , hash ) ;
34+
35+ navigator . clipboard . writeText ( tinyUrl . toString ( ) ) . then ( ( ) => {
36+ setCopy ( true ) ;
37+ setTimeout ( setCopy , 750 , false ) ;
38+ } ) ;
39+ } )
40+ . catch ( ( ) => {
41+ navigator . clipboard . writeText ( url . href ) . then ( ( ) => {
42+ setCopy ( true ) ;
43+ setTimeout ( setCopy , 750 , false ) ;
44+ } ) ;
45+ } ) ;
46+ }
47+
1848 window . addEventListener ( 'resize' , closeMobileMenu ) ;
1949 onCleanup ( ( ) => {
2050 window . removeEventListener ( 'resize' , closeMobileMenu ) ;
@@ -53,17 +83,17 @@ export const Header: Component<{
5383 >
5484 < button
5585 type = "button"
56- onClick = { props . toggleDark }
86+ onClick = { context . toggleDark }
5787 class = "flex flex-row space-x-2 items-center md:px-1 px-2 py-2 rounded opacity-80 hover:opacity-100"
5888 classList = { {
5989 'rounded-none active:bg-gray-300 hover:bg-gray-300 dark:hover:text-black' : showMenu ( ) ,
6090 } }
6191 title = "Toggle dark mode"
6292 >
63- < Show when = { props . dark } fallback = { < Icon path = { moon } class = "h-6" /> } >
93+ < Show when = { context . dark ( ) } fallback = { < Icon path = { moon } class = "h-6" /> } >
6494 < Icon path = { sun } class = "h-6" />
6595 </ Show >
66- < span class = "text-xs md:sr-only" > { props . dark ? 'Light' : 'Dark' } mode</ span >
96+ < span class = "text-xs md:sr-only" > { context . dark ( ) ? 'Light' : 'Dark' } mode</ span >
6797 </ button >
6898
6999 < Show when = { context . tabs ( ) } >
@@ -82,6 +112,21 @@ export const Header: Component<{
82112 </ Show >
83113
84114 < ZoomDropdown showMenu = { showMenu ( ) } />
115+
116+ < button
117+ type = "button"
118+ onClick = { shareLink }
119+ class = "flex flex-row space-x-2 items-center md:px-1 px-2 py-2 rounded"
120+ classList = { {
121+ 'opacity-80 hover:opacity-100' : ! copy ( ) ,
122+ 'text-green-100' : copy ( ) && ! showMenu ( ) ,
123+ 'rounded-none active:bg-gray-300 hover:bg-gray-300 dark:hover:text-black' : showMenu ( ) ,
124+ } }
125+ title = "Share with a minified link"
126+ >
127+ < Icon class = "h-6" path = { copy ( ) ? link : share } />
128+ < span class = "text-xs md:sr-only" > { copy ( ) ? 'Copied to clipboard' : 'Share' } </ span >
129+ </ button >
85130 </ div >
86131 </ Dismiss >
87132 < button
0 commit comments