From f81c0b448eca105f899954c3bf2a5850bc054f15 Mon Sep 17 00:00:00 2001 From: alex-signal Date: Fri, 6 Sep 2019 13:28:54 -0300 Subject: [PATCH] Add CameraXFlashToggleView and selfie flash. --- res/drawable-hdpi/flash_auto_32.webp | Bin 0 -> 1402 bytes res/drawable-hdpi/flash_off_32.webp | Bin 0 -> 1178 bytes res/drawable-hdpi/flash_on_32.webp | Bin 0 -> 920 bytes res/drawable-mdpi/flash_auto_32.webp | Bin 0 -> 926 bytes res/drawable-mdpi/flash_off_32.webp | Bin 0 -> 776 bytes res/drawable-mdpi/flash_on_32.webp | Bin 0 -> 588 bytes res/drawable-xhdpi/flash_auto_32.webp | Bin 0 -> 2024 bytes res/drawable-xhdpi/flash_off_32.webp | Bin 0 -> 1652 bytes res/drawable-xhdpi/flash_on_32.webp | Bin 0 -> 1230 bytes res/drawable-xxhdpi/flash_auto_32.webp | Bin 0 -> 3466 bytes res/drawable-xxhdpi/flash_off_32.webp | Bin 0 -> 2806 bytes res/drawable-xxhdpi/flash_on_32.webp | Bin 0 -> 1846 bytes res/drawable-xxxhdpi/flash_auto_32.webp | Bin 0 -> 4334 bytes res/drawable-xxxhdpi/flash_off_32.webp | Bin 0 -> 3400 bytes res/drawable-xxxhdpi/flash_on_32.webp | Bin 0 -> 2156 bytes res/drawable/camerax_flash_toggle.xml | 6 + res/layout/camera_controls_landscape.xml | 21 +++ res/layout/camera_controls_portrait.xml | 21 +++ res/values/attrs.xml | 6 + .../securesms/mediasend/CameraXFragment.java | 31 ++++- .../mediasend/CameraXSelfieFlashHelper.java | 72 ++++++++++ .../camerax/CameraXFlashToggleView.java | 131 ++++++++++++++++++ .../mediasend/camerax/CameraXModule.java | 10 ++ .../mediasend/camerax/CameraXView.java | 4 + 24 files changed, 298 insertions(+), 4 deletions(-) create mode 100644 res/drawable-hdpi/flash_auto_32.webp create mode 100644 res/drawable-hdpi/flash_off_32.webp create mode 100644 res/drawable-hdpi/flash_on_32.webp create mode 100644 res/drawable-mdpi/flash_auto_32.webp create mode 100644 res/drawable-mdpi/flash_off_32.webp create mode 100644 res/drawable-mdpi/flash_on_32.webp create mode 100644 res/drawable-xhdpi/flash_auto_32.webp create mode 100644 res/drawable-xhdpi/flash_off_32.webp create mode 100644 res/drawable-xhdpi/flash_on_32.webp create mode 100644 res/drawable-xxhdpi/flash_auto_32.webp create mode 100644 res/drawable-xxhdpi/flash_off_32.webp create mode 100644 res/drawable-xxhdpi/flash_on_32.webp create mode 100644 res/drawable-xxxhdpi/flash_auto_32.webp create mode 100644 res/drawable-xxxhdpi/flash_off_32.webp create mode 100644 res/drawable-xxxhdpi/flash_on_32.webp create mode 100644 res/drawable/camerax_flash_toggle.xml create mode 100644 src/org/thoughtcrime/securesms/mediasend/CameraXSelfieFlashHelper.java create mode 100644 src/org/thoughtcrime/securesms/mediasend/camerax/CameraXFlashToggleView.java diff --git a/res/drawable-hdpi/flash_auto_32.webp b/res/drawable-hdpi/flash_auto_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..b2f9129a9ac97444b0eede481359953a287d2fd0 GIT binary patch literal 1402 zcmV-=1%>)jNk&F;1pok7MM6+kP&iCw1pojqFTe{BwNQe#|BxiTYa2J4r@?jY-IH;$ zZQHhO+cw9x&9=M$5!qFd*%`a{W=@pi->Chvwo4Hb001l->C3CewzIdx?491WZQHhO z+qP}nHqN&3Vc@oHBO6IN-1J7rA6oyd1Of&DQ(!~?V8NjgBkGX#(c0Hi|25{yXk<`< zUls}>`Y{^~n7AJkB2d39fJXD`NK>tEHep2q=9fXDxS&~Gz5%*!0=6EXoFxoyH+RW* z1JqQtMH?az2L2crV$9Po8BkZI#R=5M0PV{#paKGPKQEQ39{yIt?+}X`!VfqZP(9wO zsX{;Bnf62PY{3T)9{KFErvJAyj#w78?i@ ziksUulxY5kb?f6>EmT*aH&^2eAwZ%DY`s0Q&BN~%s7O#%_I~Yg6LCcc19alZY$sAg zkwn;+>86tsxMi+I}Pz+B_fKL|BFF_xEDh(gcycwGC*H$ zBZv+T?esIM$ot~l566E$`1ig@{<;5;14H(HI2lU}+%-501obOJO_ioRARZHvK2()I z?mcCi|e!+)iHiF5yA4fiIC^w)oW2-on zc{kWD*qvM@UsYdv`T(3oNDwfXB4%tWaIJ8N8$Y$zZ9nb30gaVckHrq_wkDf5!?g1T z=!IoOqeqknOF<%x!FPAV!M0|K7zqqNV}L%`N(c?KizEzS(0#X9`uz&c@L?!6Kb}*H z#UWE*5Qr1+PcuLh?oty|JD6KcbwAOivBH4y@7C^5Yii-c?YzAs!`6We8Z1boxVlwC zu>s5fZrAjG_t6$|u(2jpHAR0tnek=br|6HH%r1Gkr41G$pBd;a`=$EglltN;I$2!t zQcbzC$Zh1Xaw=7bq$-oqKkCe5PWS1)vQWYRnCE(@#C1hYy9D{NBhoigevQ{X@P)k5KTyw z-^^BB@v2P-uI8KnSWQ*8Par_lH7#YT7ys7RYp}w$;1IEC)RT{C_B)zV`}dvFS33#y zV)}8emL|M$P*d*{M3uJQ0gZ9_2mNr0)^|@cRhs&UnpjXIW}erOJEzT2RSvZhFd&{0 zv~OZFKk(-TSJ*n>w~ogrxY0M{p}6Vz{zudsG;-pHjQ@584Z2iSfyc?iNz2Hhs=*Ztg@`n&wqJ#{3`=0vZ>$ixx;4rOTMbQNDF>! z-k1oa;6WDCvd@wv>G%PjZxu(mjjO3bsxCOZ7Y=v`;Glhgv#C;(UXHjq`r61FH3fQS z9WFRNr zA7Dmb)V6Kgwr$(iXXC-Dy5IBGecn^u`8^S`Xxla&sdJwdr(@$qZQHhO+h4YA+qP}n zwvBStX5hAwqV|?~ci`U8{a;CgLSt%2Q!tDaTiW}nd*wB@N89X=8K>Xv$ihH ziY1`Y+jIvT7nIt0%m@${@9*&p2szB(jIhbj`Vj3Q@sA7lovoc`%a z@bq+kQi+~47&`tvYApF0%zC@a;9+)fdb<)Mn@(h|b&LLeJLvsCXu!#nf&A8iflb>q}|aZ@n+p(JC0o(P^A})ZJH%VDQW>@= zHTy}>PdTYMU-KGxMjlalFIIJ;W=%Pn{= zNKfHV;M-$Cy?dxI!x%z>CUZSC@Pn0&K#WSp+iPFj`23DVzk+Y}iLkIqJ~=a}A8!_C z8ONLGwmb^N`VFDMhUaY9g@=)CVU8y?@h7%RjxuZ}>+*Co?S62n~wfUksk`@B_A6NUcGohTq!O+KA@R*5t^QID?IaAu=HOr^U-ESIf!NaAcE)IsN5hk zsLOsIT9=2?2uKl-cu(mP)MQ^ZNQfR&$g82qd@oE3>RT(snHvEq1QOSGYlFYfubPLA sP|S%pw)>{)zb-$h02`^G&qos(m>D`u!G8(_jm2S5O{apSsoj5w0MDj9!2kdN literal 0 HcmV?d00001 diff --git a/res/drawable-hdpi/flash_on_32.webp b/res/drawable-hdpi/flash_on_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..65a6ee20927eae32cea9f8542186c05f72c6053b GIT binary patch literal 920 zcmV;J184kFNk&GH0{{S5MM6+kP&iD30{{RoFTe{Bm*qH;Bu6QP|Gwb}zf&;Xg?eFu zqehY(DcA7lc0}&CzN^wvBT0^wYxr|JBKKS0RSC(qZPV5Djcuo_MyQldrw8V@ZR0>_ zLrfyM0}z1xFM#@)1oYbgr;Y&zxGlX+6@XMp{eO1=0k4Ak(N?LfG7wZH@C#7ezqbEv z2{3I*6>agfESs4rtC+;8bXt~!B(|*r{(w`ptBSUi#J8m+cv_b8nbB&l?UTv?s1h)$ zRApPKN#K9J<5%N44~L0f0hx^#Fi|< zBm{00bnGJ{8mUWg8Boh^zTWTHUT&fUsHSS4PbTN3LQMh?@$xSV$l3QgTZPDgn?+q4 z$aPLrN?}n0*YjG>ko($dn@5JROvAk~9!JV;!95Wn6cov-H?zp|eoc15JsvkTfe;K7 zyY$CW@*MlKyQ!|$y}C5V5*P@$SjcA57nPv;OFx2hhJbNrKHivx>ZNj98w^k1$_ z2w)P5O#4R1j=HppOhVA|dlnMW$nP8tnT%+Zd>tT~{<6U2AO*K7?-C8)F0&P2a>OeS u5*@2b31pI3CCh0=Z6=0HQq(h7{(i{l9Ap7uB-3$?1CtgNRTUiA{~7>&1I0`L literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/flash_auto_32.webp b/res/drawable-mdpi/flash_auto_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..b92093f095f9a566075625c8eceb2b8b444e8a26 GIT binary patch literal 926 zcmV;P17ZA9Nk&GN0{{S5MM6+kP&iDA0{{RoAHW9?=LWg9ZQIa7{&@*N7PP(~ts^$RvRv`ccunGd8f&d1%6$+q$ zRe1pWMF2hk08=Fa8o(+C@GGM7Di`p8P$dEmU{;9=1@zg)0KGy00l)x4{Q@9hRE5d` z%nAjBN~$!#1@sC46p#W0^}32xKeHQ~UAOYpiz-rKfTreDMg@QZsMTK;1hR+Ag;E!Q zQ57q@Vk#71fJapYT9u)q0A4w2v|?vhRR7g$6;vN;TrC51MeK7nYHfDK3I#UD>y>~1 z|LaQ8)_4}1nQC+PW0Vq7b-ycBR z=Ok5A)vM&1!DrVv-|yAy^Z9&vJVuac+qSVc-*@hJKm4|>*f=q3rnYU{ZvWJ_ZQHip zzD<5VK}7#2fJt?haKI)51g$|%lECuj_x=9TByjrNxwuzI98qN+#ImP+!a(l7UemRg zjV202$Mf#v$IQ@^1hLfoeQc`-Wvi8tAfnA)il;8)F_B3uDASJMg5s@}uldA)*!mWUfvB^# z;c}y(xws!FE`j-PKU#r`(Z%an{tRII3Kp}|1RisI9*P& zf)_3Mv&;5r2@_rUV`%;MEzRL@xOwfof4nMV7cMkYHkM}{Fvb&V|JBNo-xL&L;0^xt zjP&&M^qi7a4L`jvnz}vlyG#;915OYnNs?ri!a*Z4e@&=5pS^D4s55-D=*0Y`YFW{G z+z`y~v7~m50^*|18+i6Y*;JS3F`gbbSx@2;0tfJZyFM>9{-gM4Q)fGkhm~h79zDI` zl1h=evP23L({fC>TXh|H@eg%ho z7J(QJ;YnZitWKJEIMbdscNM^ZWVEOxwbdX(93V5kk`snufKp%y<$#Hk1_PwOblga`Z0Hvh>8lY4F0Qgq{Kmeu+0Z?(31{hVK{;QZO zQ5UKZ-~l`pR1(0_vH<~bPODVkz`x1>nzTQa0N$zuP^Kk;&Fo@nNkBQfSlUA;4XLqt3$EFke?AF!({r@IF zwO!W*NX#w==q$$pX^(35{{L!Px2j7^r+uh~w1t{6bpkbW>*Q23i`mU}GOU@v?B=iU zW0vEvU*C7D8GhPb%~1FM8?W!1rsbx6?)NPQ>?+jEUnj=%eRsgH6UlzxIu(Eyz|5{t zeRuK$EbDnjAknrhLy{t1B+F*oMpWCjZQFMD*tTtZey~@^is~G(uV-JLYUx>zH zR=^LSeN%hNO!$EkI83iO1#Vb$Y*F6_E8#{=7c(nc6Ai!%^iRsW2PUIb%n8(QZTSy< zCqpE}7t8K(df^7W>k;{2(RPB)r7UE8u@XMScsr-#M{HM1l1-zks;bBWFoEt>b=ixc zKe_X%@ljDxQPEMMW{CxqzkTU9gN>IdW8q6J1D2e#bT?8jpPpD;Us+jM-`UP+`Nblb z&!&wg+7(If2nY=D284fXD1GLZjso5NqQ=h&!Cr4bpvR(-bRk2&E1_CAO88ory}!4y za(L#dL2)e6)o24j3=aw@<2}3eQbzx8i+~tG>yC(yii(PgNuJ947x1*A>a|P4EEq&Z zJ**FF?oImHnRzEj1;kZ)pShVbO%Eb;fVg7KIeP25Z!FG45MMAZ)5j%EpBy6QMC>E& zgL#hv6hNHCfchGGK1>UUxBNDXuEiP&;;x*bJ>RV&;xGR%e(sjAABf?dRRQEjOhf|c GxB~!6g>%0E literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/flash_on_32.webp b/res/drawable-mdpi/flash_on_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..386de74f1c5722b272126639cec2ecb7caf0a0e7 GIT binary patch literal 588 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/flash_auto_32.webp b/res/drawable-xxhdpi/flash_auto_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..39aeefa3b9dfa5e7d3de12dcd66cbc65826674bd GIT binary patch literal 3466 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/flash_off_32.webp b/res/drawable-xxhdpi/flash_off_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..9147665a9fb1ea576279d60e8ca32689111744cb GIT binary patch literal 2806 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 IrpW)D4ynCbmH+?% literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/flash_on_32.webp b/res/drawable-xxhdpi/flash_on_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..d1d8424b83b7b9cb641cf6353afc04df0110b18e GIT binary patch literal 1846 zcmV-62g&$SNk&F42LJ$9MM6+kP&iB?2LJ#sU%(d-HF%=7-L!4nww__zwrx9R+YH&Z zZQHhO+aA+420BYhCFhb$MV<(j963 z2q4F$76OIF5r`cg3+A|lfH)G3!DP_MI1rJa3Jeb7C`>MYh1^Y(lekO@4hiI@0t1jZ z3Y#yx=g5dJD)hGpC-xXbG#sWWD~DjoY#GsvU4MJ6LZ!U0jRXaQ$W90}NnBc4&!@N4 zDIXroqhT{sC?YVVM0#&OE~MPN6<-X8%t_%G3P8+uWO?XKmFRs=szau6fge4w~X%0{W&5}_y{K37=ly|PID>2z9Ox6SjUu59+QxYjR?yJBdqcb@Z zMnK_fp!Mvx)98OvT7O!WMFcZZR79#2Um@>PTyKyA`_~k$vObN*~SsSrZeW>nfrv|1QeiY z_)Y*l)6AbfNT>YeEp;u7EN(gpppATVe@n{8H|8>FH-J_$aMx*VDR&>HjZ4Xa>L$>7 z588RmKdst*nJha8suMu3uSB6Od5kL{6{PVxNZ_Kud}AU3z!`df@)!OH)<(3_Pm8 z%bGyz-gb+TzgK7o{^7d~rsOyjY=7J(fSzOiUp}eO5IpwZ)3+5#g|Yfm6X?$#sn9U| z;W5w;o>QS=_}lxn3neI6B+!?l{$I0#o+Ec3^IwIA;J<&k(4ah*hC}r^ ztJc3oW^2{H=JM~quh0-Y>i4}@DN6QT)OBIaQ=EM8x35-c2(D&t*k47ON$j&I2t{CO zQG4&|3Jt?=U#Tu&lQ9SYrm0VXM3&&Htt&JP|Mta6I%PT3XoNlm5Bl=b3Jt;Ef4kna z0*{VI!TZ0X0U&`X{n+jm8obB+d(zfQd@HATT5b zPpG6_w>|>~+ib{)3G*$t(e|%A+f%-}Hvx42g27Q(GK0ex$SP=S?HfeO=IS$HnazLy zc`y0f2lEXK0O*7O1c)V4#KhU0uC?#c%oi%_H8aDevH$mwk-zP>JO+AT?G_vfVsQi_ zsl98XGPpu@V+S43L#o+p_f}2-J(#85Kp;^)^qgociOE+na_>bw=&j582D*oh0_!@U z2g6Y~x}>s^j~{8zZ=Y)cdYFbGuyiREV}Jd;HQ#@|=41^tE&_Vkh9U6`8SV2fsv2z> z^UrZxi4s5$+b|T7CDe7|KCSCVj&A^+K?(qpIr91*y{Ii;+|>j+2f@)4p2+YQkGJHn z@6FyHfX*XPC12I}KfX$5}fX=}{sMLM>0qOPY7pn_c zG0-_Us#MVb)Md&1`kC=NWI4Hv&~>4bT33GcbSnS;YPE?7=xjcnG%8aM_+$P)YV!be zE+ceZsAS4$UvX7x{opaGTEt1&jL>yarL6Ar4oT#*JG2Ygp(q;_039lyy{ehNyghSY zMnFd{a152FWcb_X8X57+c8hDE@fj6$aiyB^?|+C>H7?yfE1-iLmFul;tY5uQEe1NH zG;Ru)9~$RZPc?zgNCf~%Y+2o}UKQovU#vKm7tq1+m2$d%{cOnSzmMD~lFAC`$Uzda zI!62y^w8ldnE@R+?63rTPlbGWql$nX-pu6nK`)5Fkh*qtoxi^}M^(U~#z1G~65g}0 zXAS;xe}#Vfc%Oc030eR;v&3&g=xpBh(Nrm}I2E7i=Vla^NTD;tXe1mMfX>bZh`z>m kT|uMr{M=unW*aP}L%=isyF%ARe}>5S?-r#r-a7yPX;|QfI{*Lx literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/flash_auto_32.webp b/res/drawable-xxxhdpi/flash_auto_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..f59bc3055686e816d6071cf44ec7a22055d9a384 GIT binary patch literal 4334 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/flash_off_32.webp b/res/drawable-xxxhdpi/flash_off_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..ab1edbeef0146a192539fb8f60beeb185b553dce GIT binary patch literal 3400 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 literal 0 HcmV?d00001 diff --git a/res/drawable-xxxhdpi/flash_on_32.webp b/res/drawable-xxxhdpi/flash_on_32.webp new file mode 100644 index 0000000000000000000000000000000000000000..a2d36e2258d87de8063d94d21c1b539c82473728 GIT binary patch literal 2156 zcmV-y2$T0xNk&Fw2mk+PzFJ0rjdB)BC<{S}{wrw+H zr|N5tZB=XfIJRxuwv(03mF;BZ`~Y)lHDcRl^#l~mZ+$w+<`79!kcPvg#Q~LJRzt)B z3>9W%K%o#ZGy$RrgfRvYLlQKT)G!=JA_4~l2vAZVD(@V;+NJMO3XO=sK>A3AcEmk%v4@AgNffZN@WDWaEd7=r}bj;=dDr}1qDMH5u}=O|Eh(O zDepE)c?1OyLqMRWa-ryMgP0sowMq#R#1H@x1#E7_J#;ElfAIW${^F%LA~6gErh3K* zrhnNg8j1{JG*k6C&79#AX3+tR0SF?-7)`k`S=N#n&ocfkSe%T$3nWQQJiv4L@yxjF z_YtqG?QEvy?6?Cg@O@#4hT|BHs$U=mDzv%?v1oW3R1w{LnZa}QOx-jyC@ne z(QgqEnhDQu$-JL6OA!&I#|;uS(VNN3n$7hVqv((!{Vq;S5As}U9P=*xf8w3rD`KAs zqM5iVdhs;o{?4QCBnoec*kd53DyQ~i{x4d;hYT@#EF{$=A6BE}TKK4WwxNdfcA%O{ zUNXLAA6k6ltx}3uoC48T0Z6LJ7W_S@(BjX(J?leB7c7W<)pY7kl*h_+#s+>B2mcMKlO+myKiZg>Q5kd;Xgh$mb$+kXj{RIj}X*(cd zf=eM#DGci6k{kA0gh0gWWRgSNchBE0qS z*`^}46vRY`AUYKgjU+kBck&n(@g>iTlA6+fjKnxXL?LLEuh|6TVAIZ7XCeE zS*cyZ6cCI~1WZWr_`orv=*3gFzrJ>;gz8iN1Csy|}Hu4p%eNRHTzaLYlm`3%$5O`tV@ZbRwNq z61{i%LXBQnGjL+IX3dl?3#u0k?KPG@T!}kO&6=s&Ey4BSQS<1<-O6ib1HsNH2Psdtu$!@$sxR)q=Vo@zalMM0#LV_pzif1vFE-9t4HHVE<(Yuf#7o z_baKjrqZxWK`?R)d%ty;nz}(rVVBsp`kHJlkZCH?=^!Fvy!O=>Z}{#5SJX_~F>5Vc z5sG;J5y`hKScDC-=VeVN()D1BF~*3IAg~o6)p`*^`^*2Hkgl1T()}Qa<~TAEv?MC& z;qoH9c1vbW)$Rc!5o3%*KuDX0V(P9+dmlS_kz=($rXtueQIRxNX<1Rpt>xA>m$wsZ zrm0HzMF3S6Ayo2`aoS!deq20jt!hC_QxH&~EhB;Cf?8Xvd5$ABHI=0+$Yfi=P+>o% zB@fhVt!dJ5i7d7tqT4AgZC|n`TQes~Un|I}Xv0D~8{`i1XH7Mgz7|lpN}5*J3Z9h7 zru4cXa*Ec@5o*nvsy!yA3VSK7>|R=HW-5Svg{a6jQX5++TZx%zsz`53PFMrh%eJs? z;`nH-1yZHg1vB9qIp#nAxI)cr(DSM(C#&=2K_#`;R2ue|6BG83=i9zyRmh2m^t-0A zl|0u*xkCaqQ%$AUCDmkoSS>xzTA>qC*O6av)|#mz z*lU83z;5y!Td120nNy_q6=7>>w)K+7Me4NPH!=jb;1=RDt?oU(P#ek+8VPbOiCOa? zz1B>nVb2)?86Ks~v}5V2kc~v7_eBiZMV@7&{C@t-G)ZL;72!KiW>_nHVzM@57>x|X zo%jVhZ581twKh_RfeZnzsW5%7(pocB1cv}bIb4~xrM3x|Q;-1^#2|LjrmUYhHc~Su z$S}&p*g~7My6=R1t(nTu#=-6qo=^|bEszZX2PEP;Iumy)F{^1JGMoW%SjmJRKD+Yn zQp+?^8PbS|?J66~f8KvlsaZS)rOKd2SZKt;ua$hjo0h%3T9L`jfeB+I#s{vyLBsVL zmVY1KcneZAQ$TPy2pD60=i5S0 literal 0 HcmV?d00001 diff --git a/res/drawable/camerax_flash_toggle.xml b/res/drawable/camerax_flash_toggle.xml new file mode 100644 index 000000000..483102991 --- /dev/null +++ b/res/drawable/camerax_flash_toggle.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/camera_controls_landscape.xml b/res/layout/camera_controls_landscape.xml index bb044eb72..8cf4313c6 100644 --- a/res/layout/camera_controls_landscape.xml +++ b/res/layout/camera_controls_landscape.xml @@ -17,6 +17,16 @@ app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> + + + + diff --git a/res/layout/camera_controls_portrait.xml b/res/layout/camera_controls_portrait.xml index e49f3b1a1..e2af5dada 100644 --- a/res/layout/camera_controls_portrait.xml +++ b/res/layout/camera_controls_portrait.xml @@ -17,6 +17,16 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> + + + + diff --git a/res/values/attrs.xml b/res/values/attrs.xml index c2ed44653..1dd75c9ab 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -362,4 +362,10 @@ + + + + + + diff --git a/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java b/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java index 129d7951c..5220df679 100644 --- a/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java +++ b/src/org/thoughtcrime/securesms/mediasend/CameraXFragment.java @@ -29,6 +29,7 @@ import com.bumptech.glide.Glide; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.mediasend.camerax.CameraXFlashToggleView; import org.thoughtcrime.securesms.mediasend.camerax.CameraXUtil; import org.thoughtcrime.securesms.mediasend.camerax.CameraXView; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; @@ -52,6 +53,7 @@ public class CameraXFragment extends Fragment implements CameraFragment { private ViewGroup controlsContainer; private Controller controller; private MediaSendViewModel viewModel; + private View selfieFlash; public static CameraXFragment newInstance() { return new CameraXFragment(); @@ -160,14 +162,18 @@ public class CameraXFragment extends Fragment implements CameraFragment { @SuppressLint({"ClickableViewAccessibility", "MissingPermission"}) private void initControls() { - View flipButton = requireView().findViewById(R.id.camera_flip_button); - View captureButton = requireView().findViewById(R.id.camera_capture_button); - View galleryButton = requireView().findViewById(R.id.camera_gallery_button); - View countButton = requireView().findViewById(R.id.camera_count_button); + View flipButton = requireView().findViewById(R.id.camera_flip_button); + View captureButton = requireView().findViewById(R.id.camera_capture_button); + View galleryButton = requireView().findViewById(R.id.camera_gallery_button); + View countButton = requireView().findViewById(R.id.camera_count_button); + CameraXFlashToggleView flashButton = requireView().findViewById(R.id.camera_flash_button); + + selfieFlash = requireView().findViewById(R.id.camera_selfie_flash); captureButton.setOnClickListener(v -> { captureButton.setEnabled(false); flipButton.setEnabled(false); + flashButton.setEnabled(false); onCaptureClicked(); }); @@ -181,6 +187,8 @@ public class CameraXFragment extends Fragment implements CameraFragment { animation.setDuration(200); animation.setInterpolator(new DecelerateInterpolator()); flipButton.startAnimation(animation); + flashButton.setAutoFlashEnabled(camera.hasFlash()); + flashButton.setFlash(camera.getFlash()); }); GestureDetector gestureDetector = new GestureDetector(requireContext(), new GestureDetector.SimpleOnGestureListener() { @@ -199,6 +207,10 @@ public class CameraXFragment extends Fragment implements CameraFragment { flipButton.setVisibility(View.GONE); } + flashButton.setAutoFlashEnabled(camera.hasFlash()); + flashButton.setFlash(camera.getFlash()); + flashButton.setOnFlashModeChangedListener(camera::setFlash); + galleryButton.setOnClickListener(v -> controller.onGalleryClicked()); countButton.setOnClickListener(v -> controller.onCameraCountButtonClicked()); @@ -208,9 +220,17 @@ public class CameraXFragment extends Fragment implements CameraFragment { private void onCaptureClicked() { Stopwatch stopwatch = new Stopwatch("Capture"); + CameraXSelfieFlashHelper flashHelper = new CameraXSelfieFlashHelper( + requireActivity().getWindow(), + camera, + selfieFlash + ); + camera.takePicture(new ImageCapture.OnImageCapturedListener() { @Override public void onCaptureSuccess(ImageProxy image, int rotationDegrees) { + flashHelper.endFlash(); + SimpleTask.run(CameraXFragment.this.getLifecycle(), () -> { stopwatch.split("captured"); try { @@ -234,8 +254,11 @@ public class CameraXFragment extends Fragment implements CameraFragment { @Override public void onError(ImageCapture.UseCaseError useCaseError, String message, @Nullable Throwable cause) { + flashHelper.endFlash(); controller.onCameraError(); } }); + + flashHelper.startFlash(); } } diff --git a/src/org/thoughtcrime/securesms/mediasend/CameraXSelfieFlashHelper.java b/src/org/thoughtcrime/securesms/mediasend/CameraXSelfieFlashHelper.java new file mode 100644 index 000000000..aa88dfb3b --- /dev/null +++ b/src/org/thoughtcrime/securesms/mediasend/CameraXSelfieFlashHelper.java @@ -0,0 +1,72 @@ +package org.thoughtcrime.securesms.mediasend; + +import android.view.View; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.camera.core.CameraX; +import androidx.camera.core.FlashMode; + +import org.thoughtcrime.securesms.mediasend.camerax.CameraXView; + +@RequiresApi(21) +final class CameraXSelfieFlashHelper { + + private static final float MAX_SCREEN_BRIGHTNESS = 1f; + private static final float MAX_SELFIE_FLASH_ALPHA = 0.75f; + private static final long SELFIE_FLASH_DURATION_MS = 250; + + private final Window window; + private final CameraXView camera; + private final View selfieFlash; + + private float brightnessBeforeFlash; + private boolean inFlash; + + CameraXSelfieFlashHelper(@NonNull Window window, + @NonNull CameraXView camera, + @NonNull View selfieFlash) + { + this.window = window; + this.camera = camera; + this.selfieFlash = selfieFlash; + } + + void startFlash() { + if (inFlash || !shouldUseViewBasedFlash()) return; + inFlash = true; + + WindowManager.LayoutParams params = window.getAttributes(); + + brightnessBeforeFlash = params.screenBrightness; + params.screenBrightness = MAX_SCREEN_BRIGHTNESS; + window.setAttributes(params); + + selfieFlash.animate() + .alpha(MAX_SELFIE_FLASH_ALPHA) + .setDuration(SELFIE_FLASH_DURATION_MS); + } + + void endFlash() { + if (!inFlash) return; + + WindowManager.LayoutParams params = window.getAttributes(); + + params.screenBrightness = brightnessBeforeFlash; + window.setAttributes(params); + + selfieFlash.animate() + .alpha(0f) + .setDuration(SELFIE_FLASH_DURATION_MS); + + inFlash = false; + } + + private boolean shouldUseViewBasedFlash() { + return camera.getFlash() == FlashMode.ON && + !camera.hasFlash() && + camera.getCameraLensFacing() == CameraX.LensFacing.FRONT; + } +} diff --git a/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXFlashToggleView.java b/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXFlashToggleView.java new file mode 100644 index 000000000..588b44e45 --- /dev/null +++ b/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXFlashToggleView.java @@ -0,0 +1,131 @@ +package org.thoughtcrime.securesms.mediasend.camerax; + +import android.content.Context; +import android.os.Bundle; +import android.os.Parcelable; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.camera.core.FlashMode; + +import org.thoughtcrime.securesms.R; + +import java.util.Arrays; +import java.util.List; + +public final class CameraXFlashToggleView extends AppCompatImageView { + + private static final String STATE_FLASH_INDEX = "flash.toggle.state.flash.index"; + private static final String STATE_SUPPORT_AUTO = "flash.toggle.state.support.auto"; + private static final String STATE_PARENT = "flash.toggle.state.parent"; + + private static final int[] FLASH_AUTO = { R.attr.state_flash_auto }; + private static final int[] FLASH_OFF = { R.attr.state_flash_off }; + private static final int[] FLASH_ON = { R.attr.state_flash_on }; + private static final int[][] FLASH_ENUM = { FLASH_AUTO, FLASH_OFF, FLASH_ON }; + private static final List FLASH_MODES = Arrays.asList(FlashMode.AUTO, FlashMode.OFF, FlashMode.ON); + private static final FlashMode FLASH_FALLBACK = FlashMode.OFF; + + private boolean supportsFlashModeAuto = true; + private int flashIndex; + private OnFlashModeChangedListener flashModeChangedListener; + + public CameraXFlashToggleView(Context context) { + this(context, null); + } + + public CameraXFlashToggleView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public CameraXFlashToggleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + super.setOnClickListener((v) -> setFlash(FLASH_MODES.get((flashIndex + 1) % FLASH_ENUM.length))); + } + + @Override + public int[] onCreateDrawableState(int extraSpace) { + final int[] extra = FLASH_ENUM[flashIndex]; + final int[] drawableState = super.onCreateDrawableState(extraSpace + extra.length); + mergeDrawableStates(drawableState, extra); + return drawableState; + } + + @Override + public void setOnClickListener(@Nullable OnClickListener l) { + throw new IllegalStateException("This View does not support custom click listeners."); + } + + public void setAutoFlashEnabled(boolean isAutoEnabled) { + supportsFlashModeAuto = isAutoEnabled; + setFlash(FLASH_MODES.get(flashIndex)); + } + + public void setFlash(@NonNull FlashMode flashMode) { + flashIndex = resolveFlashIndex(FLASH_MODES.indexOf(flashMode), supportsFlashModeAuto); + refreshDrawableState(); + notifyListener(); + } + + public void setOnFlashModeChangedListener(@Nullable OnFlashModeChangedListener listener) { + this.flashModeChangedListener = listener; + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable parentState = super.onSaveInstanceState(); + Bundle bundle = new Bundle(); + + bundle.putParcelable(STATE_PARENT, parentState); + bundle.putInt(STATE_FLASH_INDEX, flashIndex); + bundle.putBoolean(STATE_SUPPORT_AUTO, supportsFlashModeAuto); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle savedState = (Bundle) state; + + supportsFlashModeAuto = savedState.getBoolean(STATE_SUPPORT_AUTO); + setFlash(FLASH_MODES.get( + resolveFlashIndex(savedState.getInt(STATE_FLASH_INDEX), supportsFlashModeAuto)) + ); + + super.onRestoreInstanceState(savedState.getParcelable(STATE_PARENT)); + } else { + super.onRestoreInstanceState(state); + } + } + + private void notifyListener() { + if (flashModeChangedListener == null) return; + + flashModeChangedListener.flashModeChanged(FLASH_MODES.get(flashIndex)); + } + + private static int resolveFlashIndex(int desiredFlashIndex, boolean supportsFlashModeAuto) { + if (isIllegalFlashIndex(desiredFlashIndex)) { + throw new IllegalArgumentException("Unsupported index: " + desiredFlashIndex); + } + if (isUnsupportedFlashMode(desiredFlashIndex, supportsFlashModeAuto)) { + return FLASH_MODES.indexOf(FLASH_FALLBACK); + } + return desiredFlashIndex; + } + + private static boolean isIllegalFlashIndex(int desiredFlashIndex) { + return desiredFlashIndex < 0 || desiredFlashIndex > FLASH_ENUM.length; + } + + private static boolean isUnsupportedFlashMode(int desiredFlashIndex, boolean supportsFlashModeAuto) { + return FLASH_MODES.get(desiredFlashIndex) == FlashMode.AUTO && !supportsFlashModeAuto; + } + + public interface OnFlashModeChangedListener { + void flashModeChanged(FlashMode flashMode); + } +} diff --git a/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXModule.java b/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXModule.java index e486a506a..465535035 100644 --- a/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXModule.java +++ b/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXModule.java @@ -686,6 +686,16 @@ final class CameraXModule { mImageCapture.setFlashMode(flash); } + public boolean hasFlash() { + try { + Boolean flashInfoAvailable = mCameraManager.getCameraCharacteristics(getActiveCamera()) + .get(CameraCharacteristics.FLASH_INFO_AVAILABLE); + return flashInfoAvailable == Boolean.TRUE; + } catch (CameraInfoUnavailableException | CameraAccessException e) { + return false; + } + } + public void enableTorch(boolean torch) { if (mPreview == null) { return; diff --git a/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXView.java b/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXView.java index 9a6d74c53..1b69c7046 100644 --- a/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXView.java +++ b/src/org/thoughtcrime/securesms/mediasend/camerax/CameraXView.java @@ -683,6 +683,10 @@ public final class CameraXView extends ViewGroup { mCameraModule.setFlash(flashMode); } + public boolean hasFlash() { + return mCameraModule.hasFlash(); + } + private int getRelativeCameraOrientation(boolean compensateForMirroring) { return mCameraModule.getRelativeCameraOrientation(compensateForMirroring); }