From 151142fa9bdc580e243b66359115229510fdd440 Mon Sep 17 00:00:00 2001 From: John Costa Date: Sat, 26 Apr 2025 16:12:48 +0100 Subject: [PATCH] feat: linux screenshots --- frontend/bun.lockb | Bin 164224 -> 165491 bytes frontend/package.json | 1 + frontend/src-tauri/Cargo.lock | 1 + frontend/src-tauri/Cargo.toml | 1 + frontend/src-tauri/src/commands.rs | 6 +++ frontend/src-tauri/src/lib.rs | 2 + frontend/src-tauri/src/screenshot.rs | 68 +++++++++++++++++++++---- frontend/src-tauri/~/tmp/bruhhhhhhhhhh | Bin 0 -> 72 bytes frontend/src/App.tsx | 58 ++++++++++++--------- 9 files changed, 101 insertions(+), 36 deletions(-) create mode 100644 frontend/src-tauri/~/tmp/bruhhhhhhhhhh diff --git a/frontend/bun.lockb b/frontend/bun.lockb index 85f294736a9c124c5e8388508bb92cca2c593fb6..a26f712d876e5b92dafa27675cf335cb76672786 100755 GIT binary patch delta 31514 zcmeIbd3;UR_y2#+O+qe0%u|pc<{%MCBwV!AaLp}2O+gT1j4?`LDAh@ImqX3kDyb}e#^7`)V7~rcWH8bI3>P> z>&vNAh6kq&&^0Yc)6(an&IPwaE(k{=XNRl#TJk(NCvvxxl*E*7nihn< zReqWlfV{~^)3U++68iN|>aJ;Xk=@8668a`f(}9!=M0Q#ArKR7+Kq?-Tn9@IaXrfld zU(-q;hr&`(L0Iy8C8YEp)=$%ts7)H$o7Ku6kkn&@RJ;Z`ANpVI`cA5`axSh0ZSNv0thnCbYX+T0s%IoMQ)Ha2!vY*4! zHLuzFdPS_ZqG74CYEjGH2bQipW%D8Or7Mz|fime5U}^6I^5L}f*2Sy}K8B^>|Er?Y z#Vtpkswn*$ogxnZ082xif;A1F(_e&XD}5I%`pPgdr1wr5oTO>$SD!pdjW{8s--h-` zN>0=?Ev%HL;Z1rzSbPtLCC2QqG%2uy$0kDp(e#Y2nCk z!$g>#4AV*Jb*fknwm_Ekqb4jBSA(S+a#AP+{-CPm*j?4qFFNfc5@Vje9hUz8IMTA3 z2ur8-fu*+QHh+elj7to%aEQ%spcgOSiMCqnp4fFrPdc@4igYcj4pB&V?T@iqUt@7v z`T`R9$avT0G+1W;fLNB=Qow_FuP3}K{bHaA`>51~Z zfp-SloJeUj=*%Ez<~TFUnNjoVS`j)k#+e~cPYh>5I1|8`D9!}9%Mi&>I}<>LK1~$P z%y7omnG4R?J9EOB15b~=Ggq7$SCXETwV}t5l*G!tQ?zc$DZ^zBxY5fTyF*%r@U-kJ zGIrmfkaK7$ECz4d@|(?65&z<8Ia^p$Bn6f^Hl?{Wq<$@}8GjeOjGzX~2>wWZ2%OYP z(^!7eo5K=k6*w3^OupEid)eyPJvOg`#f@#RSZ=Jt4tLVhd$qP2o{vKOZG?Z);LxPO zvH)p`DP4yoC3n}xw6h%Q2j?ZfJuGv(p{Ih(Kz3N{{%C78d;yj<<`699HoygB zjxMwnlVNdSgqcAP!%{&jJHHMr6;!h201Dc&nk4ur%;BEcwfAc@8Y)2lY=* z9x_1FBD%2($Q&&|LY9GtoLbVAKf=ha5edo3NhyQ1SpzKxkCImaJFejpk`uZo zeuFFytb}EVJ{?5=%d8(w0qK%tI1jv=2BgbY!ZK^;!=hKPIMy?TSj{4i@pz6Q&X=7Xi4tgtvRAYo8SA_WuE`VD6DO-yNINBHdsYZ9)9#q*DB zE>9y8`G|x;JyS?e9cgvp1UMJ^R9FJ(mYg&siTn}aG5sK|7J6AOoXfl(-IIu2(^8TX zQhLE@RWT5cg5f||F0{JRXt1v}t9zt`v6l}@aM?X25zDo~pQ9~@0_}24Skr-F>6Syu zusBR_nGOyaYxPhYSbDZP%n+uf7bGEFe|L;EYmdUg$g5#7oB_+EdJUGdqAM(2S`U_T z)Nc++n~7F_99$HANw_ea4K4)Vo?!7QxFGUQxPTU+r7trRtekC@-)=N!sCMRI%deCA z6h1mPG`&*A*Au(;eeY7E=|0~q95HQRz3kgu(^j?!=#sTi;;S!BPxeWBr}F-XduBFV zcd@{+ABL>2IW=VEwtU0=+=i}cQ8c2f?M0*Y6KX_}+5!1pn$`uKIIJtZY(-VIh`)Or z+E}zMwY_w-dovOTxagRjEZi`a`w8Xl-{@E~T4c=&QzH zINDFe26ep%T8C8A zDW>05HG*rqOEdLap!1bx{01Y{Q=5y%`K=@6k(B!nNnw%2j3Y9;N)7S22QzV`DtaL( z+O<5pdJy9AyN~h(HR`3BdJdIZ(&I|cp*EECxHmBC#U&p#CM4Q@4@pX9m6GlknAj4f zpVCW4yC)+_Pm>oMqX(!5r95swrl-~Wb&E&4YUfm`r9G}0In{>J9`^zA#5F%fc&_ZZ zRBWin)iIY!4fVK}a?aHuk3K3Etv^!tLuZxWd+oRiXQhvlrNz)r>kFcPOBHp zQJq3c;-r0s;b)`>(@JJdeojV9+D^AND5PS;Jg&usRBD*VeSthFmsRPZG5(yrGB$2i zw@kD<5y@(bv2?93Ea!szk!`}@hef+yDWV=!_PD1NvC8?&lybLcEwD!&X)cn?k1Xbl z_{Em2`4JLijVb+FCfaWtQX4av6Qm?^e>o@J1zCfvei$<##veiY(k0comKIZ~;U4#I zD5XVz=_z;V;?9f|sf#UTG4p02$t*HwnEN**nGTxFDR*VoJ`a*xZ66flZws6y^ygmOWwLcu zm!`^>v?M>X!{U)-*iAQFCrYXZ)jjUU+zfR!>*FkQEh(i^qde|kQNCa)!=wGmmBuSo zt4y4`E2(Jo*`#szCrA>cIdR;-AVnfEV`#Z>=#!Hd%ce+G%{&IqH7Zo4#&}$7L)C^D zkKbeR%n?w2ZAbHm4+jboAOQaqbE45yH6PdOLQg=yNG zBI!v<&^`MT&{V8X#HG!ng?~&w`W-|(n_RCt0VN{!o z#kr$NS%WQWb04H9^|`-6YVXwU-icX;A62+AlG$cP>z;zt#gwG2TTdkMu_dcqnx|}KNc6ho(NI|yqKv8X6Owd|*|+Yf8c!qw zdlN}In3Fm(+I`ZNtO2hOt2VskagU?Rn_mq*%?Id-nCHC1XukGoJUXFb*HM!Op$VI@_wB2B2JVjFqvcSi zh%a2VP;LfE=~K({B9ffvX1BZRQ+=x^lJOtXWhAN7yt;7Lt>>JdW2kcqQgia~Iyl*miw}G>a zOSzFqa&}k~^B9sf-Pl;%73mNwPo#-Ra;{jB-a?Wyz>*p?vgQ&kFe3AjGFsOgXD-(V zDI;$mQbsKy-ptZ4q^?g|IDsUS-I@XAS#M;zSyCbrCmq|joLn=JSZwf&Iq%xnM5VU& zxC=AVGQ7A;&Z=~t;MQsbw7j)?0NrV=Vmol1K!;2JaGte}cJ+)`8#;LWR6D6}bB8#;W29a( zQ^i;(8=9#^QdaKbC%RjtnwYt@UUf>0Bh}c{9Ux_u$juD0YH3HxD)Gq^-8E9p%o1@O zo!p6}EDsKlvdZS?9JA_cN6OO8CuP-ljg(cQT4%?DQKT%poun+g+{`@N7gA<@t|eVm zY&VZz^KP2Se}s$?%s>ujdRJV~7+WtFIv;?atT7TEjForbx8w-99Qd$>Z`%R;fuIzdp%KN;N7e z&Tj{)_GYS5UoM|it)w{DjJ_(hx5w|Wqwp)kI#bik>e^4m_VKuvp@?NhnP;QlWuzA* z+a1~8TG6>0y?q;#oq{MNSTb7;6 zNK!e=EoWz`K~L^5IJw&mQnCG*(I}bzvU;+CHb{AL6Tm%YT8etm&*SmM~rG2df9@{~oMj2YCEC50QDq`Q`qE6zd49086dkEhLW_ah0Jeb|Cjc zL!WGZWujekhN=w%J+8XL)PsQ@znR123Qj7|I$Wg=^7wTeZeG%rigPa`B^wEA3-@8S zkR;Bm=DHI)!g8A{yvS%*#}R5nipTF)lr7ALqf%AuV2^uzs_jfAbn}F_NqaTtZUOiPu!>P>;L7 zC}&t@qiBI-FB`0x=}1zXD^S+4FOeiJ>%!tLk}O5$a_p)(T0I!X_2_74*OUTVkZNGU zPR#X1&NS;%-P%ixRU7WtZEElu=9J z*PWeHEc+r^`fTsMJv&zm$n`dXE|v=eM6!Ycmz{hNiVNQ-eq~ zH&ff6qyi@~6HHx4QeH{97EMyAX|ZX=H1jPfO^1sEIfO+nAp(c6$ibihhypG^&znbP z_C-?@_<-7G?msd^^^~DhTo*`1^?_8>5Xh04#i2$(nEly2ghgimH;;c}v1`J6yJi9Q zaq|!s2e`g64`Gp8TB6BPuoVzyk2RSU#XO$He&n!EnuoBIV=kEWc98g`flfd&Is-W} zv*^2slA{ao2fctC!jjMGZXUuSv!0vvvPNrJ0qdN3WM=8vL>4Er01J`H!%Z_ydlqLQ zZ?v5+ERLt!vanP*4u}Ixc=Iq>U3<5z=^^vg%zeY=NtTf&EVaF5%fiyy6d<*J0HoHb zKn`KiPZxnBGwbS$u_e;PdXAZAu~^Ty<$q$a`xuBf3vK)V35(ZDc+c3JzsnKCkrj4D z!cy@{TNakl*9EYDk8S-YwtlfKe+J8(*=Xyx!ZK{yHeQ6c z^CAuIuz4pebK!f*wAn|^Rt3YQxeI8;?TfG&T(Yg6#ky)bv7ouuT(zyQ!P3?ZyOgjb zZ`yndmfm{+i`_$;AKPpy(F>!}bXe?sc#+=sx8-a$=WubZi$P9awh%(Kh974e|nhVfLy-xw(bA7IPHI{ zqG#13L)Zt0WoGt=#rJ`B05+$Y3elzTBBySuZ6GXDc@!)ajke`6cD}I8l?k>iEOrxZ zSy+;jc#%0V9Txl9qO@6;y=IQB5Ef4tz|!z1w*G&@QhqVzr0C~%d0|O@Vau60t6T%E zB11f1Z5yt&4WGqgx6aNNmWbq`rs%iWycOn8+s=!uJqO^dDqwm+6*Rq&IpI!7Hixj3 zJZa0BS-RkitrwP-eu72+i>()y(!MxXTUy}wpRjaVT_CfpK9G7E0y#3X3~3`E{PgWbnir)U|HM+T2@w8Y zzP(73cQDLDSSHnT?=Q%ch&ussq%)8sGmE~9C^@T^j~911O#b)&!s?8F?=Swnzo^6cDyQtf_ZOM(E9CqTS$gK*`wQs}wgu@79hM#9 z-}{T_-r)Rue<3#-GD-fuzxen5;(z77L#{EOfBO(jF30l?Ru-92O0U!4$hl6}&(Hnp zq`P0Dv9HnjE0NJjUsZ2+d9|m?>A}ZJ4!F|iWRD9Kjoz*QoH=#lU%!91?R?K8J92NG z_-@78c`me!IHpE@SV(oe;?@0B_=oW-W@dnz`k`0Ps?H-_LaIO0tGm^dnel4+tN`^p z63?J!#jA$11Joz8ynH_M7ScVW*0a5OE;WC4yjnCTK>5w_>bX_RIq|CP+yJ#2DX-G! z#w-7M0V;8>SI@6jAgx2nKhLWdR0;FqRj>I0Y9~@*m3w}?DzqR#4VmxNi>mENyOBZ{ zc=cjx;DUHH{G$N%JyHo3@=?4h_i=!F{Ufg)q7EY+N2>m@S1+Z;d>pUd_#{C6f)uL4 zKOw$_#P^9;FRRWYT|%nA(5shMQx+26r^JU;QPusF_!bf0r(Qiw-9oyD)OwLuucGEJ zBEH4Mx7e$PtCow2?=#{9XS1XX#A?5$vt4FJZ&xvmd@gdbvxt9>% z7sR*3tH-JBNV}0jzwqj{)W9!@Zz=I1)m9-(iEkP4E%oYk)nTOLNY$5l^%vEcWyH6f z_>k(W@a4p}g7}tu^#K4*Hq}D6F zdUG{@CGo8yzExhmrE0l~_*N4i(#uL;O?+#JZ?#u%tyUndL(0F#tH-N^HN>};_>kJE z+-r$%9r3O8>aVKpNV}0j*Ln4hYT!EJTTgsQomI$s;@d!c>%Dq{I*fE2srm-5-c60! zKztjC4=GWFZzR4=#JAC__f+SRE+N(5h!06AeIN1dC%%1NeX3f4v<@l%ey?t* zg#E;KfcTJRsN4sL?;!CV@ai+wcBI`%p$EPCY&Gy8@qJ5tNOM)lx5Rgd_`db(^VMOb z<4DyHdG(Lfm_x*OnD~%BQQ?P)?+Ec7_UfOi^GKJF>L2myi`A4P#P=QXA$_juen)&q ziSIkF{)M`QbPuWZQLnyC%|A+f-xJ^WUVVjX`91OdKzv9mmHq?q9V5OUy!vXj0%;vm z{$pN!tx7mXe8-6oX}!vQocK-<-*KIc*-#Owt=hY9Zmgk7?Jng{4;TMVT67gO1>KD~{q)SNkFM0LLYRVNnK<--z!D@m=vYy=Coj=Bw}IO`qpHa$v@i zvA#dAN!>FnY38GMLT{f~{IF`om3>1i{XX^VGQZ#-XZ+r+&$yeZt_C*(#@)&{uGs2} zzrEY?cKa`*Dwa@9uNG3PsZ}1IIfrlg!z;JkjL8$=Gco6gYFVr0Uw5lY(Y)W(?Y~3Y zdbnczv@LIZ<8yRZ@svp)lD3>V%NR;Un=Q3{f%@0>5(dYgZ{o5phn&B z>VK;}Nabz?sIZ$}m#(YSn{Cu_#4|U&x{oS$-xhW6#_IuU2Cq5QEnah}M!(1FfoeXlxz&AM^Qe}8 z#Iq4E<~5(v|BPoFZpUi@wSw1z%6%_hFQgK9Ev(k_T14f(AI}Dy#A}e+&TBDM_(8m0 zTn*&4gxbSvunPGro~?HTuO-!CUQ4O+599UHY7DQT>IAQ4RQRKKHr+|QmQ&|>Ew5@k zj@K)wDZExxmwBzE>i!+ib~}UD%IX%cRi-x5D3eMGr7W`RQ!7#vW0W z%Zef_3yQkNh%6|Mi{gwZUNp*QMe&9|ig&W2sBfGQMT{FoEq@dZj7k0|E{WorC>j|x z+$g4JLowTp!fRX>MZ@eUnr1`M)R>VC#XV6x5=C>PQFauIa-jGkJBpUZeNnUxK+!P= zikFSWIZ*iLL=g~xqP5X30L3~{Y!*el;m*lRuUshl=0wrXSTBk~fhdaQLh-7Rlncdf zQ5+CON272cis89Yj0!~2+1MkBa(PgM5Zy>GNE2`OW-&2R^S^2lU!!yxy{+qL*0rO{=tq3~ z;_~yDSTZL|X270;*1su!2M4Z2Jaqxgeyg`~uP?*6`YT6(jOR{hq7Ogte9H>F+j^c;3%*bE^2jhbCrNoUNvD_9G1s`pV_+6W_@YqzolxQ+e-NyfE3ONx&k@In1qieQ)dDuyxE~v)e^2pVZ*b{0v{5Bsku* zbxdmW(>u}|&L=qvkv;=NC!gw&9+jco2Be45H z6|c5+GJ7Z6x;3`0g?$!PnrC>X>2JzcFqn=>?>xrazraHv9?8SqzriE$0NesMz+G?~ z+yQ@po8WhF5Bv$_X|X&>z636V-@p}c71X3^50EqPD;J}?gM^%VyNtfm^@3^D$O{G) zKnRc+Dg%kDBq$H$46F*OfN&57B0zN@9VQ(VNtIPV7?4ku$R|ungHTWglm+F0d?e;J zxC8FW)5YIO`~m(1_ket+W+N4D0-He>i#wNuVw040-^0qkAe);C*0#X<#yV7rY0ifOo(L^6?`1 z_{ZDeP4E`j1U7(;Ko&6h*hn&v&oKQBN|Me80zpoY8{`GPzz^s^mJV4eWNDC3mdOGq zpEQ&0K$d@5?qzjPk&luMCUKNLlEqE-kd~kocp0?oK< z+5oSD_Mjn{4;Fxrz-wRxNCm^eC?M-n3hiry!4Qy6MWey%U^%kPFPfW*is~=7C7?DOdzP1G0H`2WN4VizE5$yL{T; z{3L2LM!Ec;ASen-fFN*?yt!aD$oU~JZDqD_bXX#LM#;1(h_3^gG}+P1hd8sq z1a6L@jHNhs4~S#G17C0#+yS@2EpQWvqt}7VlTqMnAZO7);0JsF)tPlm9ki2XE?xZ* z`hj2|PUHhMK@_M2DuN22Gzb7CK?zVC6a#V*lLzDm*+5p{2L2!riSUZ6gx2WkTks0CgCFM>LtE)cmTXbt4_ zZw?xOmp~(s){vK`pb2OUyr3D7LM_0{;1v)L*&Xz%Vcf3UhEWO$|fhk(^UhIAEJDKp_q5-Y$O zunlYi8^L<84y1!oHa0vXy%pUSuo-*>wgb^gJ&xXy#b!sQ{LQrggJnf+2mhD(Aw0gi(MKJu9$?Kt^FmhsPQAYNsbGpD8de4l|o(8;_IWC0IB zcAXs%_yU>CvhV&4Jpf|&m(6KnEQ-hAkqsx)he9qO7bVWje;#MWM$VWlupf{{#a8N& z`ki`2cIrT%sQKFljxrnaW(o*52faZv&;-;59w7U;R4Nyl<$zphW=D<&lGo2>Ne7ZP zLKfAvIScid(xmpr;6+deNQ*DPb#1vG z+z^OO1Mm_MJDHjFVaXG{=md>G0C`g0(I+AI23~YcL02GAQ%9P4YbtjrU4T>|g*pRi zNE(-hrIAjcBj^BHfLDQB{J#R^?ndg6JDhf)ErK^hK@ZR!bOT~6`b0aOWXs~LTqY+2xz!RI2a*>>-DBWUK%96DP6Z=C5#-@=J2M3I z2Qs*F@0J4O9_>|Rxv3in3bu?Kw{DdDTyNqk$s4|(>k&mO(Naz< z3ud1=vGd0DbzFLmpL|`Mi?`W}Ezv`aBcJJcf`+)PmLu_%PD*clZ%?w{ zjgMXl)bsint(NFNL^)re9A5k5(AUQ0E<(-KDp!-Hov&CP9+Y(G{2QHalM_)nTyhrq z7@fY*3k5k}-h8F+*E8E*Y`G7MNaCu_#_3}myr~y*?eZ~}h^6zj%yTAed~wmEoC~px z!je8dDRJ!oLTGbPx_gDRF&48@2ala|JxZ;3XZByPIz_G5tpw~c`0R` zueT1WmM13kQ0duNRJXb>m{mD1aW}ueWA!HAt{;*k9)@$R?`yoaRF81Y^EH+W&-F1b zEY*9s@Vv<~Ja)cXyW;mB4LaQC%MQ{iby_9Um+28f&UasbGHG6^3e6UH?7H!IZ&u^r zGRD84zY(;Yxi)rsO(*yKXx3_u&!n8jCd#@F`4~T} zz|${%jBH=xhx5hS2XZt$+J5zo@-AH*W$2$#mrQoaS&++k`%CJ&p37MHrT*bFX2ob3 zSY}13+(w6$SpMo`3|*;5M17IlyoF5f{`Q(SNvG#rxBbKOXZD9VPQ!8-XQ?CT`7`T> zJVxMkJ-;6fUdv-tTBS$me;A!t=}lc(^BPN6(f&d9rq$Hpe9w2QNk1$t-nMZz+PCM? zuX&A!tMm%ls^l|oT+^)*5kbzka&IdVnq_0>F6Su0C`oLu=Ql=EXO#0j->(ODNKPKF z&%%O{mce$uHN0@1Jjt(=%5~H(OSFsg8~eo{=X=Ckj85Kkdd12mSjb4S9`qwLBNqhx*gfRgo2Vqp*H9X1Y` zVD}!3?DbXK4?c0}r_sp5>QmH6rfg8jqSjK?z1@zl=H!~^=h6ev$f8`es4-7!Z;H%{ zpB|p=)|Cn`<@0svHPF!S&R3VGH>>j1g2H=ue*FSX5G zQcgixfUt1B7QMYb>(ons&K+R-Y%URaR&yPmC9v|!;(4`u`_^Y_ZmWld#7)`cAY%X) zQO-A}cO6)|R-Np*Vz4k5c<$zkS?wNf``MvJcjx}XCcy|-WEzgp*Nef% zyHZ!DV58Y@dV%7R+AeHm9J(~>mc8Vp)-q-?QHjp76`Q#wtuHNo=TO!ca&_qG)Q8R5 zl1AVLqS%3jjLrN{2BmIXSS(OlBnYZGRMM!off<>-l(BpxE$1s`c(zg^xRh05eCx@* ze$QI|E3;j*SHnsf=cv=Me8RTg7=BPMVszQ4H+#BH*NoD}g^hX-{f6P)q&L;?82VRN>xK%Ig%2w7mxQS|$${NiM>4l!kO(|>i+d}TRvPO%|bguKA?GN+)RjKTRzpmh( z3@ITy-}*jyWA3f3_nmo6PIW71TUlccWnDFR4E+_{teg=nb#^OfblDDnSI!9hCPVKy zX7`B8alw&?RWNQ!@$nUmO~Oy>ot|{Q6u->*hq)eA_$ggnWwqt7Es8$h!tR?Lm5jHy z>P?C|-y{Cg=VOy64&SviV^C~Er%mU3!1sp~u2XDR--f24IcuH@GRXO=@|2xpFMheK zF=s7v@ju2nIn3B{g!tYLGn(yymxUQ;x4};LIb5fTQAxVdk)3XJ%G>4aZZ&po*CSnT zR5dysrHtiOen0lfr$^_5sz&jzG5M^jaZX0Zt~O{pV_ldjJ@7)^bK7RF$zeNA4JWG_ z`x#&TuCaM16Kh-9Y2vo+Mo>;HLMZpgt~Jg3ggnj^@Y4Z0UFCRS2WA}Hp%;02vbZdx z4;{UP=NOq`Ilbak77}UH+?gq?m`G!Q$WE{QXAn`&7r(FXT_IPxHa63;|Kuy;2X=oU zAnov?i~*b&Y2?_I5xMK*NTZI(PMl7Bj%!ZS|6To4BjSYqB!s8ydCER>7yZ{+^G>w! z+HQ7yYmsnHu76mT(qfFqyNS+TA%dJ=Gnha6bjb#zePzkBSBM2MMw2}(arO@&qz@bR zTDu|d{E;=oVtQ0ZfqPxkcCIO8CeQO<859KF$} zX`Q$7JIi!fJW z!TY$7mA9y67wxzuPm`&q-cGR_XOGM0G5YOeqFV)moZnwK_3@Y0zxgzg52Tr1VrW<8 z)Qr>F_H(hg-eY+7KPm5W)HX*wr+=z(rHJ?9QuFn5Ru%dFl_Xke}bGJiMU?7`kvu_s}qRP-bZkEtdww^ zVIw%ijuqtmzR1cl1@pf>vzuJ?*%vWSSw1Q0=sEL}4^xBl`x8+O{`~0J{StD`Y0p{C z(Ro7qW~6KwHD%4V&5V9W^de54)2Ou|Mg%=$udsW&T9}dJ zJKS=9#$s>D(|^qR`h(&bZnX$A>R=&D%4^bjPrK)glcRS6eSVFOrR7~ljn+;PVK3tm z&szSS3jj6>*;DMcWM#g33^`}GQ5hejp5ONKyWfs4$oZ|7uVWfDE3W@qI-@7->BFYe z_c&9{34;OHc7nO$IFU(jj^ER=W9N*o6NDq%gXUswZ$VH&AzZ4;8oF5z6H`i}n=bZ0;ol$3>NF!Kgo!uQppWhw-wHwTE zou-}++i~{)N50v;&nx#Fy?rVei%#mzjMFE%UX>Tuo6U@SCs{qFG&j1OVx~AhHuA>a z!@1WQ14_^l)hcst@OY!Sb@6d+WX+$xsc^fbnPcA89&TK1sEsg!BDebUXIwHvV$(2jq69W#M`RSV3oEb#(Rz|Zk6i8}i)cg^)_n+r+kn`g# zwH6$0G&0Ul=0#PygZD|A#2LwFnPbk+xcv0>sV3zvuUKO`$1LLk!pp`yEdHTef@@kc zxkBf;RTo#v5=7Z3>m8jct&Hnu>5ixT{fEe$9d+9)#+Dx`=|tA6wNd6A?^ig#CbO^2 zv;#+uj_qtl!s^bO;9ofGAx`Q-TC~bq>h7X zmz|Z7Gr6r1bOFy6QdX`^DwO@Hg>`56`)+8Qmeh;n|}r)z0`Ro9H1$acn6@yz)J zqV2y-S(LY6gFiDY+P5=;f1!5gH;eppdn&HeKiHpP;ryymRFnN{=D)uxH6!PI7o*=V zEDP7Wn4hyq-v=PBW+xb)Un#o@3*KW$e{1riS!+w> z{w>4eEIGWFkbbYzjM0&^_Wqrbqjxplrfg7&uI6Vw(mU=MSifH5QH;0K?u%WGZBlzT zEJCOww8!{P<4)c9Cc|R9UH1JkLG4Bl{k>d9&Z4eH&Wn`Yg@v4RwX?SDG3bpw-7_qH zB!~BZ(u<`w*ME8K`}B;Qhh2>hlnruzb1BzPhr=s9-1jiUBBGn|-bKAa>5ZJfrK!XD zZK5l^M^13ZM$L8BjVP^0ALA@_xyJS}x?Ixp896TL#a+Am7?m!e{JD>D`r4DsLat(c zjd@q}e8JT#*U+5bKWe=C?{jB6oNH}W$(pFO>0>OF(xduL`wcIhA5MCqdF$p)-%(pE zLvBtqr_I32dQ8ys>$B>4;vv?){~-h|>}P%~DE-o+H*@{)Ll$`x&b~x+o+LPdJgX|} zeO%{FttPIp0mdx+c6r(uYkt#*XPYpe+)J)jdD<`2&pW)E?#hhLhG~%h%W58+e)!BdmuM&aXVROZ|BB@A=Ozb;hBpc5#4F z^D3St544uFT|s#t&%T_ikYf>}jUH$W5DVwO0{Tz?HrMDkniysWM#wHauaNQaRUR#T zI>>s1y4w5QQn$~ZH_D}dh(;Fom4l2N%#k4HXQ|c}+IjlWp~tfE$OT+@4ejV4qs}$9 zIp^WX)2#*So)l{UGtV#QSExFjxLLW`ydsko8-nFVa(dkMiDxomWfFG1LEmNeX;fchIi;dL8eu&`%<+ExS8|U( z-oW)_dv$(ztJW_6axeRTvpOT^+Y!cN%1V7rl@{nIkvw z8gKabqpZB)EpNcPcoToYZT6sNJnNBFf@=<*_1u&acA!SdJG?v0BfUX)xZ3`6v~ltd zz2HhSa^A(r<{;;{!(tlmy&f^M2%9a7j`>h^)&Y+mheVJ zR4(yVULUzmm$$uf$v#(HYqA<=@8W#DG1lhSX?~?E3r^kW=*t5$n&Wb+>lmZb@6`1g z7P4JLWV>@N|FC!2NF0k9V~j3XM6Jf61Qsv%ZI_;M`@Ih`ERK>BOwNHNeuXQY$$mE@ z=k6F|sgx}^)@r|7)32r`1O?22xZT#d?|1HycK6=w}GkM9$0@b(w(d@9V9$vYIT(fG<51r+@V@xaI`F37L&g}`t zXesObG}_^)l`m{Pc)L@Eh4bTSo0l}K9TXokHzOx*qOqT{b)BDEYdyKn*rknsDwSbz z?}1M1+)4dqakiS)e^OPh&u_vG>X(rG^58*9{dyWD|J2Lqn$hr2y{dk|81biG!qv>j z`0!6QQFsF!J3NndoqVeG$dBVc4=y|oS!Vs1f~|A@oiFn2WaL2Poi#eYTzhEju}gN7 zr(XXw&plmt^++-F`mVf2p8I-1pXB~MEvfu{{gt4>2}1@Yg$+m^(le=FSW2&iL5YL; zX}!e3VF?40j8XUXg)N_-UnQ){KNSy?i5OLRaL-gvE%Qb^tSgmQjxx4)a0MAv>$$QU zlj^xD8=D^J{%gxW(7QA?0_wZ6=EFg1wp~I9V-^}A)m$Z|OdexzJy+vAJyJ4E_-Q^i QGUMC`SJ+xANU8b%0fMh?zW@LL delta 31077 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 diff --git a/frontend/package.json b/frontend/package.json index 9002825..d6c9ebb 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,6 +22,7 @@ "@tauri-apps/plugin-dialog": "~2", "@tauri-apps/plugin-fs": "~2", "@tauri-apps/plugin-http": "~2", + "@tauri-apps/plugin-log": "~2", "@tauri-apps/plugin-opener": "^2", "clsx": "^2.1.1", "fuse.js": "^7.1.0", diff --git a/frontend/src-tauri/Cargo.lock b/frontend/src-tauri/Cargo.lock index ce6331d..31e14e0 100644 --- a/frontend/src-tauri/Cargo.lock +++ b/frontend/src-tauri/Cargo.lock @@ -9,6 +9,7 @@ dependencies = [ "base64 0.21.7", "chrono", "cocoa", + "log", "notify", "serde", "serde_json", diff --git a/frontend/src-tauri/Cargo.toml b/frontend/src-tauri/Cargo.toml index 66abbcd..4827672 100644 --- a/frontend/src-tauri/Cargo.toml +++ b/frontend/src-tauri/Cargo.toml @@ -27,6 +27,7 @@ tokio = { version = "1.36.0", features = ["full"] } tauri-plugin-store = "2.0.0-beta.12" tauri-plugin-http = "2.0.0-beta.12" chrono = "0.4" +log = "0.4" tauri-plugin-log = "2" tauri-plugin-sharetarget = "0.1.6" tauri-plugin-fs = "2" diff --git a/frontend/src-tauri/src/commands.rs b/frontend/src-tauri/src/commands.rs index ec471e6..0b4b645 100644 --- a/frontend/src-tauri/src/commands.rs +++ b/frontend/src-tauri/src/commands.rs @@ -1,3 +1,4 @@ +use crate::screenshot::take_area_screenshot; use crate::state::SharedWatcherState; use crate::utils::process_png_file; use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher}; @@ -69,3 +70,8 @@ pub async fn handle_selected_folder( Ok(format!("Now watching directory: {}", path)) } + +#[tauri::command] +pub fn take_screenshot(app: AppHandle) -> Result { + take_area_screenshot(&app) +} diff --git a/frontend/src-tauri/src/lib.rs b/frontend/src-tauri/src/lib.rs index 480344e..c3fec08 100644 --- a/frontend/src-tauri/src/lib.rs +++ b/frontend/src-tauri/src/lib.rs @@ -15,6 +15,7 @@ pub fn desktop() { let watcher_state = new_shared_watcher_state(); tauri::Builder::default() + .plugin(tauri_plugin_log::Builder::new().build()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_http::init()) @@ -24,6 +25,7 @@ pub fn desktop() { .manage(watcher_state) .invoke_handler(tauri::generate_handler![ commands::handle_selected_folder, + commands::take_screenshot, shortcut::change_shortcut, shortcut::unregister_shortcut, shortcut::get_current_shortcut, diff --git a/frontend/src-tauri/src/screenshot.rs b/frontend/src-tauri/src/screenshot.rs index 1b78861..a20f1e1 100644 --- a/frontend/src-tauri/src/screenshot.rs +++ b/frontend/src-tauri/src/screenshot.rs @@ -1,8 +1,55 @@ use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _}; -use std::fs; -use std::process::Command; +use std::process::{Command, Output}; +use std::{fs, path::PathBuf}; use tauri::{AppHandle, Emitter, Runtime}; +#[cfg(target_os = "macos")] +fn screenshot(path: &PathBuf) -> Result { + Command::new("screencapture") + .arg("-i") // interactive selection + .arg("-x") // don't play sound + .arg("-o") // don't show cursor + .arg("-r") // don't add shadow + .arg(path.to_str().unwrap()) + .output() + .map_err(|e| format!("Failed to execute screencapture: {}", e)) +} + +#[cfg(target_os = "linux")] +fn screenshot(path: &PathBuf) -> Result { + let slurp_output = Command::new("slurp") + .output() + .map_err(|e| format!("Failed to execute screencapture: {}", e))?; + + if !slurp_output.status.success() { + let stderr = String::from_utf8_lossy(&slurp_output.stderr); + if slurp_output.status.code() == Some(1) && stderr.is_empty() { + log::warn!("slurp cancelled by user."); + return Err("Screenshot cancelled by user.".to_string()); + } + return Err(format!( + "slurp failed. Status: {:?}, Stderr: {}", + slurp_output.status, stderr + )); + } + + let geometry = String::from_utf8(slurp_output.stdout) + .map_err(|e| format!("slurp output is not valid UTF-8: {}", e))? + .trim() + .to_string(); + + if geometry.is_empty() { + return Err("slurp succeeded but returned empty geometry".to_string()); + } + + Command::new("grim") + .arg("-g") + .arg(&geometry) + .arg(path.to_str().unwrap()) + .output() + .map_err(|e| format!("Failed to execute screencapture: {}", e)) +} + /// Takes a screenshot of a selected area and returns the image data as base64 pub fn take_area_screenshot(app: &AppHandle) -> Result { // Create a temporary file path @@ -10,15 +57,10 @@ pub fn take_area_screenshot(app: &AppHandle) -> Result(app: &AppHandle) -> ResultgTe~DWM4f5bqJx literal 0 HcmV?d00001 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e5f0447..28af921 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -9,6 +9,7 @@ import { ImageViewer } from "./components/ImageViewer"; import { ShareTarget } from "./components/share-target/ShareTarget"; import type { sendImage } from "./network"; import { ImageStatus } from "./components/image-status/ImageStatus"; +import { invoke } from "@tauri-apps/api/core"; export const App = () => { const [processingImage, setProcessingImage] = @@ -25,34 +26,41 @@ export const App = () => { }); }); - createEffect(() => { - let listener: PluginListener; - const setupListener = async () => { - listener = await listenForShareEvents( - async (intent: ShareEvent) => { - const contents = await readFile(intent.stream).catch( - (error: Error) => { - console.warn("fetching shared content failed:"); - throw error; - }, - ); - setFile( - new File([contents], intent.name ?? "no-name", { - type: intent.content_type, - }), - ); - setLogs((l) => [...l, intent.uri]); - }, - ); - }; - setupListener(); - return () => { - listener?.unregister(); - }; - }); + // createEffect(() => { + // let listener: PluginListener; + // const setupListener = async () => { + // listener = await listenForShareEvents( + // async (intent: ShareEvent) => { + // const contents = await readFile(intent.stream ?? "").catch( + // (error: Error) => { + // console.warn("fetching shared content failed:"); + // throw error; + // }, + // ); + // setFile( + // new File([contents], intent.name ?? "no-name", { + // type: intent.content_type, + // }), + // ); + // setLogs((l) => [...l, intent.uri]); + // }, + // ); + // }; + // setupListener(); + // return () => { + // listener?.unregister(); + // }; + // }); + + const onTakeScreenshot = () => { + invoke("take_screenshot"); + }; return ( <> +