From d436a19116e304c06803a9a7e2b237a0c92e6590 Mon Sep 17 00:00:00 2001 From: dank074 Date: Mon, 22 Nov 2021 23:41:46 -0600 Subject: [PATCH 01/17] added calendar view --- .../campaign/campaign_day_generic_bg.png | Bin 0 -> 36045 bytes .../images/campaign/campaign_opened.png | Bin 0 -> 744 bytes src/assets/images/campaign/locked.png | Bin 0 -> 220 bytes src/assets/images/campaign/unopened.png | Bin 0 -> 5731 bytes src/views/Styles.scss | 1 + src/views/campaign/CampaignView.scss | 1 + src/views/campaign/CampaignView.tsx | 60 ++++++++++++++++++ .../campaign/views/calendar/CalendarView.scss | 10 +++ .../campaign/views/calendar/CalendarView.tsx | 43 +++++++++++++ .../views/calendar/CalendarView.types.ts | 9 +++ src/views/main/MainView.tsx | 2 + 11 files changed, 126 insertions(+) create mode 100644 src/assets/images/campaign/campaign_day_generic_bg.png create mode 100644 src/assets/images/campaign/campaign_opened.png create mode 100644 src/assets/images/campaign/locked.png create mode 100644 src/assets/images/campaign/unopened.png create mode 100644 src/views/campaign/CampaignView.scss create mode 100644 src/views/campaign/CampaignView.tsx create mode 100644 src/views/campaign/views/calendar/CalendarView.scss create mode 100644 src/views/campaign/views/calendar/CalendarView.tsx create mode 100644 src/views/campaign/views/calendar/CalendarView.types.ts diff --git a/src/assets/images/campaign/campaign_day_generic_bg.png b/src/assets/images/campaign/campaign_day_generic_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..25b3c622dc9aa5aab2fc6469bf8d8e526c894ba6 GIT binary patch literal 36045 zcmY(pXEa>z8#Sy&j~*p@Cpw7|%qSyj)I|g|4>)kq^!9-RloP7dSoC z&3a5kXt+2J7;tmsCcnD8O#5WXGR>iOIw;H}r^IDL{KgX?r?hTEJbP4?aa}=$n8Fih z?|SpznZ_$Y85N@Vx7191Ie%i5__QbX&L8*N@(6!KJ? zK-M?qw!OP+!Y(z)1gCi)Zj&IPrM#TE>bvRwnm*~(T$)Hm^zp#(Q@_@|n30FTRn~K$ zfucpGBcQNTn=?o1el6U#sbwalhld-c#I+BqH)=BBZAu5JAitu%KD9{C$LxS?JwX0h zz%RYMIr>yZ#T2Am?oU7Nu)24x3W2{=y}8jFf)1AL{A`!?gr0RrX)b{~^InVt31!IhT39pcH z1hbRDrN!*gj8QL#R1(0KzC^qFncsc3=R@`{#h=Qpy)N}c80@Mqx$(GnNjOI#K_RB_ zhvxq>mNp7_Z5B58jB@31ek6n5pIX8D@xa}ly$67}IG=a1@muEle;uGdrlM4phzg|< zuwcoocm!jtL!b+KMm;60-ZV610<#Qs?!;Z~S!J+pXL_tW4cj%uT#Dk;go7VP^S8F} zkdtus$1Aa{6T!oxi{peBlNlkK!q+(d0zdDWorPgx>97ffqLcpnmtE3(`1>WN#Cy0z ztw6UO?j9ol8HHr1bF2`uui=Fk!TKL%ccdtl5OY&L$%Y2UoB!?+bn2*gqbxg*{fmMlyk1q)J@In z@Q3l7mFcS6Km{TxdevmkEXwDBH*Jw;KTJ2>!GvL6BeeOVYAkWm>&u5W?`9m_=>ABi z8_hs`Cc&@d9BjB{j95fVa|qj~Nda`s_4}jT%AhVgLOk15b8W~+1tFa^*f-lbhfR7U zVkP+}l%AY4{gcUQU`2b#fLqn8%mf;#`OE5FD<{HhByjkRi!UUVsZ9@ZYSrm3S&824 z229VBPZiKy&Z~dgFU@6KG!=;k$Mui%6VMRxH$ajZ_3O;M$5qL^#*vba+?ns!LygE*+}}Fx_;u zBEE6QW(~+YY);hO><};5QlcXKd!YU$E|8%8c@{e6*Jj%c4bF}FK)vB|$~rO|5gqX| z0@o#Pf{#!`$3aDHxSOtE3I8PTA^HN8K{C9yfAMf!VX71EH3Aua^JF$7pH%b6c+mEW zIV6oe8xXq#wV2or9nrbo3ZDc!1lj~$RPlPSDcf!5Jfv<1SpDl*RA;YrB5WxolJdPg zttInHKB+2*U$S}J>Wr@cmgw*sCH8Sw^Rcx(z9Z`UEace?!LT|xsB_Nof9hL%Y*c#Q zxy9OtZj*N#zH>~VGMC0`B;5N>{&sn5ii91d-)%gDgh>&bskRSZIF_9fNuptOg{0*% zNz)ZZcG+x%f&7@zWrHOHA!JMVYdLe@yw|n6vw_z#;klON-?I3{+~fbWKEb2P<$apT zhk5Nez0Hr_$W4M{^TpGxUa5SqYLIRW_1Vkq8`Ix%{&pi%{uptPKo--($z)WJH2tfD zM(u=J?S$;D81%cN6e^)NDM&3QP=t5@QL;4RKXT1cCEO+b_22f5o3e|x!X)t6{QnEj zk+7s3oUZs89t2ac8{*!ysH2wrOrDD{uKy8noI3_7Nn8i|CxzWQ!vC`L9aNpYV8y1f zE%SdVkGs44YA&P`(mTeWa`?o$zZ={2n-yuk;q|tmu_{DXIc<7m!u*Q`j%Y|yJBwk3 z(v|yu`CZ7nJTIipbT5+CAx?|p#QWd9LHV;%VK1-y^2PjHpz#f#LbAH5PgzQr=RW?G zC#B6Q8dyF3J(CqW&L?qpXV0>h?Sz(Oxg~AI9C%|zt|c?t7W!1?ngwpI)5DdhCBt*eLwjP zyU6ujbZ(CT)-=vHIT3a3?m?&vCeeY`4R7og?M;PxvxGkP2)R;pc4 zY3~=%EjGZ;HA2@`H*izvJ&x|;Tw-dmnhZI9?McV9vMGS z;gcBbghNeW+SR^%Cv#?Jk3{R$4y*o=-?_lR|UF1B|IjV`>^K=mP!%<)bM2korAcz{N!xcFvC-VJq2z>Xb zRiX7Ww8SDCBH?5UM-2d7ZZ&y~v&J?PNPoy-AMl^wR)V%xanw-h(<;{}Pi&X;5&k-% zoxzmzr`Pxe@9DB?7E~s?>mXO>T{&kTWHEj8xtl@3GNb=KonAITF85SRrdWnF767oq z8tJX_@LjTwA<^LO(OXPpqVZfBCmv8_E_A+5{;EKIovt;Xgm_sDCBmGuO-@tlxicUl z&F4VungRMiqxZl$Up|ni;u$YpstUO*Tu? zV%@S+H79bB?J)ng@~9f8M<584Nr{{4Hn?=tYtIx7Tx|$CD*QZi1z7|AfYWQEXS5`p zGrI)$W37L$wq_BY`zOn`ATF%18CIA9$Vswze5#8PIa~I9+n`0B1b^7OKBBRkF$u-w zTEb~j>7;2BjpxusP*ms@KZGX0(H~iht}u#6BA#1f{R$+Br4P0*SWo{Ml9n6L7s)g5 z?_>725@aa4tu=`a4F80hfeV_si_2wOMqQ+$LtS%_AcP{B&h1cF`vFKW=@ z{2w)(;7T&S$41UqWGnm*xw6G4dhawgt9-EwJPhN6DiV!Xy>k;1Hqb5n*t7W(&$@l1 zWEGF&N(l=)GCyyS<6jeTbXo?2E z-n-D1T0Q{ZY?5FzT904F)19r0ulY>wq5*qH_VnzBXf`S>_Di1aR;EWAy#l*c9J)bb zQNA;w2wl$3y=?epsnl^cYu>N-5!_^y?-6V4gt5WatAE)_tK)lI5hu4#Zj?zMHo7Q5 zPzNzLOw6(y5*)@$_vTs}3MA2BTcC@3lSdga`@bV$fR@A-UKd>ATywy8h-X{tU2yp5 zj2ydj8B#fRkv|*Jeu_BsYJ{Q-&M$-+&_EoZC<);u0q|zh{~4uL4{a7d`J0E!S|@k9 zaht%rDoHApmoRX<+a*s!98Xhv-@EKsd5?QnR-tJc3e`m@*biAL+P2aB^)7(3dq=_l zgrdW(&i*ODC;|SD1iL)v}{Z7<6G6Y~9%DIDs{edQ2ZJ&1@! ziy@0MPD0O^QR9Yq(QtMim1#qP9kg6lf{7&F^!vm-_k3rOB+U5Nbw{eR&Me}-99^#^ z1=(5QP^Xf7{kN5ry+J2W8PY6#K9_Jl0(q57(3Ludq~gR?_YFgGaYkKZXy^a}dfD(s z60Np`>NtG$z?r}_enX7%k{7A61Wh_!FNJ{?4FA^ZHIpN>5j9NWe=R0ZgakdfcY~(Eq7;9dp5}_blVgc3b zMAk)h3Xj?ezpfC$ba(zZy~axJos1i*+6_y?Tc|a}ktYyo30*~x{vW&=;f7uJtM*Q2 z-3OuLSEx1lH||0x9DkLXVscvQ;!8YLaGB%2O~l`ymjlhYAuQ|!-Mb_~ z``ywc9OX(#&-`bm1lHw~(CYq=$x$cxdKiu)DpXV?EG(DwpVO)Chs$~1tu)0?AX6;a z0bn|Qr6#UBmGHV_^!Y&4p&=dV6qL|aY>tn>K@Q8KuHLD=S>M%(F0wiAj@g&u~((vL69R6 z-^@ZZVbd4MA;7DC!1v78V#2B!G4INK8gglcSMi)n^H~;Sm$kmR@WbYA_}eDiEX+N>c-WmZ0-xM&&HorI`Hh?2|T z&T#0Z1U90c?T6R3W4ExX`pqNO9*wY=f>|^wojhfx$8}_7^_$M{D6Urs4O~Cb#o)Vg z=1hs2Hm{53?XQzP*5{p|?G~4^79XGyVnnjTAe5YOi9t@pon#+yaQE6kx zX9jC%?;cC6T>KDpJgsX3Y2N6()R0txe0pbUZh@Gkb&2?EW+A+7cG@s;*ZwuvCPu*? zBy9R0@d4QjCQR-yvUige+6^2ov3JLvFOzbwmW@AFuBr^C?){?rA5Ba-%vmJja|)40 zDK{>fXp{aVMWG`9=nm-%Q$u};8a+q%wQAgt&IhHld7YG5+=D-oU-XyA0RB0k+GtGO zB`ml=Z0t4^`tI^p_nD0{L)eV&4!;#Kr0CiQnf`&E+|&9~C6OpP$)Wsj`gbHn`E}{$�k3-p>X_y`} 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 VBLJ_-_G175002ovPDHLkV1hQ-?a2TD literal 0 HcmV?d00001 diff --git a/src/assets/images/campaign/campaign_opened.png b/src/assets/images/campaign/campaign_opened.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec1bb30bed39dec6fee41a5bdec960426270574 GIT binary patch literal 744 zcmVP)^wSkG>i$9xjvTgH~ zuz8V#zwdi+2{Kpp0pA74T-7)DE?@xs3e*SqE?@xs0@%wj1pzLm1%3i-@|c<^mq3J{ z02p#5C7|$~7byHxFUZu*hamX!GC<)E7)F+ray0zw{rRZpXQY7U8pmG_d|a_2uoW7A zIq;)JP~$HLzPE^8@s|VNDq>Xp<-lV_aK&E^d`*N@{N=#sK>U2Z991g*a^OE+pN<-T zUO|K^@VW126rmdY%py#IpGkyi@RmhP1>TZ~sljU(5q`hlj%sCc#Z-+V&UmMU+lg?A zz<{Sf$I9RmasK}^-a{|o5FrI#T0{nXelF-Of@7%BI5c6v4-r9`Tsh!F&xgx;$LEAZpLg$jUfjm%1@-LhyEVPy`W z?-jL(&xDY!Y=O%0XAJeKw5N3M8pl3 zjxYY402hc{!=>Y^c~WK+2x!igJHFay#d?9j=3Kern|WH23WA#K?j^!9_$Cpp;9Et^ z1Rf=#H+ZawnZbiZBpMzdJ2cMHDq;ojMG=LDX93?Ox=|8RBJO+Kw%GfFAPv3%PV6#3 zOSl)|Z(KxdlPPTRDE1a;aRC(x6+lS|8}3b7UMfQtdS{=56&$i$fC33FK=-`iMZvrw aR{j9$YQ}Hx9pRAx0000j_^|XUoodbBOldh^Av|0UeLaAs?KfJs}@0v!#O1sw06wfaxt-!-|7FE-m&Qu2iZyVZp!msfIR zF{e7NHM~-OSl{CHTAu2!`dgd@6&t6lDp}%XwDMNqsuNRJ9a}0V{bXMLDY+wY!f))> Un*QSa2Xrojr>mdKI;Vst04zgSJpcdz literal 0 HcmV?d00001 diff --git a/src/assets/images/campaign/unopened.png b/src/assets/images/campaign/unopened.png new file mode 100644 index 0000000000000000000000000000000000000000..71a754ff7cf3709548730eb6f52fc03816cd168c GIT binary patch literal 5731 zcmV-p7M$scP)U_khP26~Y}9>m)<=EtDm4=OAyjCMBE+}_%3eWbmu_UDqE=xnPy z-`QS!rL(=R<%^E`KS}bJ|L$yXLGU;Jhwr+6BmEZF;99hSw$P>uY0Qt#2r%f_v122e znyOZ|wAh}I06im#QwBQFg0^uF+za=_y#){(FWQ=n>`@MHT1c$v2wXez-oSaN`$nuw4qH+)%Q#Oy3ij0@>;LB zo@@BbwaNCOYpMjQ40NCcZQ~xeSFUtVKjV%U zr>+^*Z)ipUUxIt159o_eVn}1c*f2(u7`}-x*k-%BPI{Wkyeaj(^i)1t_uG(?z>~yF zeL~;P`>-4sBgTp`o5WC(p^FGbMY%KDTJ7(9Q{ujcJlAH)RO^ido@Ar#gRVY%8B;!BnquB*E_S6`PlgQ< zM8VijG+*{)E&dGMgnQ80Z54L!-W}2Ew7sFG412rX^{v{oVM_#2c1UBznALOv9YI&& z7F#G>#DxpzZt7^OEmc#%;iikO$yG=D4H;y?m=84-sFDJ@g3iLlg(zIa?@J07OQ}|y zTl&>m?|R5_w%-v!6zBlDP)SeQpgW_x5V_M}_E5W}G^4Yv&aLEp+F9yKwjA&GWRL~A zfKF73S=XRL=#q45C{lF02n@hs{rv+{p!9cfkVl#>nI!Na(2Yv4`FDr4;%kf)hKMT^ zWT>yb@~>($l6xC+P2hb9bfh+u3Y{8-6r2phY?iXGtC8XRb=fB1ehPG@Mhcsy{9mAB zJ(EH~25WW6Ry8;A?b=UGpnE8oG*fdQ(6L@gp&&zXaqhy7_PQ^{L716D-!c%jKoh#w z8z~go#F;Z$iCCa2c0SXz41JcJDwYDehR*epeJIGVef##YZ7p`UY3p5P%n&fyr4my> z=R0@qjMM`uWLJTXjA(AGIWBf~e?y)LWPoMA%5*w(4-5#4khqTS3Zx{%t(MY9^j>G^ z%f|?H3Sa;%goWA$ zF)=X_Z7q%>ac)9S<>+oe2Mp-7=#doAu{ieuEPx5iJT#9dc-%13R#W~1y{DJqN(fKs zC@=vw!H6dmalj0D%AovSF!&)M)rNB#ftPV5NsN~b^q-d71VDWH4NbpRu+ zT!+F{NHV6i*6=z|pE68{#by#|<36*C}Kf?J2t#l`2h zi!2Q0dlM!he82Z0;seZpT_CK4B9N41Y>U%cEWS}?#t!<5C7!C!5v+u@7}y0Oz~t5; z;@r7YcZlp;805FAOhWjUg(_A8*a5@7SP9WOMAp|;z8mV9Op_43n-K+ez_2e?LJ>P; zW@gUlY_Ge{Z-O_QO+x6C5Wq&5___`Z`w~lZXBO~3<>i+i7x!l{>byiKidCV|mAF3z zFr-+5XB<6p7sDurjcRVNT;z>oLyZ1fl{88P6BsEL(MT8qOIDZg+il410!$k7+)sWu zTU<^*JxDvZ7?lWmAOya2w-# z5?m@$O-aT#)Kz8kMt5qsf;wD@5GrDbE46_oFzrbSI*;fibVx9e}B7VrwU`xPYE5BDO zt_@5GV5ZpaS;7?9GPmK85Q^+VlGwHuM=Nhki|vAgrSyO-#Wx@!fSIr|yA{}~WE-l4 z7)IsI=ja4K9($jW;AKHdm+f;S=| zwD=f}5WtRO32cEeTVm(tHr(Qeg1qd1=Z(DFm~S{jX!$V`Ar3ZPP!OV^Am>S6afDod z=#C$xX!HMDmm;i~hT1r0&#zI=H6>JjXkn3Li zDdmg7HDzakF`Mji3oI1@r6g19YbzCdP_MSWZxTX7QfNsCV5e9xBVh}SJq4CLpp2kk zV_H*vwPJPkoSL`8k`R4*OUodHNVU8r>?dKV0mg)Ngcw+g8AgmG@lw9p!5fLIK57_3 z^cB=_BLrUe6KWBiz?iTeIfe?v=HJ{T^5JIj&bP>YHE+ZJ}sgVfb!DYyV;I)W> zszoVDl8hWwYF(!=+FXW*pfbr*aY`fvmRKdVI&EL@Mzq=;#%P2v;%ujwb^==>#1y{? z(O6ey<&B`Y5iW$#<06@07N&r0j|t(hRumh#bgjosLNBFjVB2FtR9?CKTO&_yX<4T* z8X= zg!retBw@#~{PibU&v{EbRSQ!uzx=|Ea9BcT62g569kBIPm~ty!r>EbxN)d>(+xtc7 zIviitaR?im0$X3DYq!ZQNm5&ytsUXA48Ok;LR^OLY^v!1w!S8}+@`-JxwYy_abCE+ zsMFsFA-<>sOo6Sh>2J3MGLoeHF8j>O;r1$@9#hU>zRCwofvrCaWE4y2BuU=4@0o|S ze%aR~gtmmp6JGY+zyCP|l*!(f(5Wu6m1Jggbo7$8R>w6hw*xQCl`Y013GilTfiHw-Zep&cQ_4MTt>FePlgF2h$#JrRY@IsMVQd$rtB$Rvbz zgb=qB`sjlbdx0ro>-9w)PnpK-&6_uD>TIw3U#&JBGYO#$A;e9`fFZC1rrt6Pk1zYm zfu$r1t<_~^T5U^c5<(k7h_CMfLtrTclpbI9RSPVq&;-c*4?cM70B`)WmI{*)Iwu4$ z;+O$LV991Vy>17fx?u>FH|NZockBB0R>$A8*xJ}6MBoV_Zfy+gfFZ>X3I1*vq83NQ zlh0XPQk?r6ev`coxh5fWN(f-Xu>y9$kg$yRcS|9+O~)u#oh8YFr+@s!x3xGP!7N<| zmJn*kBLF*KNLWto$zGL;Z3$_5G=WUbGMlxmn%@YAb(r%R`mzq<0V==@*fDo8+23sm z-8L>2-Nxa=FFd8y5liOArP>^^1kAj+3!fX8dU6{mbuJh(WXP&I$JGX{4q-F5HV*7W z7O(D<JfBY2>)}c?wG^(YbvX$tLB?b>3yw++_7OOfs>s_-fZ}y8r+Cq8A8gvX@D`qq; zr50c!#167`=+i;2YF2{B61PzFdfPo)Gai&&hvH1nQ_j+m9^)A7{j)&ZUfx9Y@kIz?CQO*H*;-TT5Ieg|qqoL`K@2?+0kTVY zi~FDZR+l=UdkQ2M5hgdWs^q9ZSqC*MF`UhD$N}aYDvzeGU%%!XO%2t55Idcz;n9v- z5JPW7P+LI_fv%x*aurJn3ptP+&)&HRn04?KU``iY$J!k`9{i3J;QTd|>1c0>p+_Qk zN-x`69e;(cp>x4iOb>J**&Ej(*Cr6*uHW;sXLfhA)&7rOErlmy=#2=TECX~49Yfco zbGhaqyNW0+T!lZbL#|E8S;u1XWp^ArxOb1Zd|xjyg~tUtI_sBO%mAIfba4M3=$Lf9 zm}M2b=AenI@W*w;&^&t*izjZEWS$TRY z%PKT=6(S)-*AXei6Z5E2hCpY-i!bimtL8pJS*OsusMQ&uL&@sygHB1e%ShKeZirNI z6`B%)TM7Bap3xLfOrpwIG6gu8Tv;Q@#^;}X>KU~_^R%eU$}7DI#wspu`RZ)Vb2-oz#SCg>h$CHdG6XGd@Rt-LJ&&lC*3XZK!%Ze zA%j|wIgF*FA}QumWPCg2(3>+d?#!&N{Jcg@G4h^PfqL&l4>GUjZMUWJTr5>3R_Fw} zAsyXLI#VNqoL&wKMG)B=QplEKG6g@$lqMl}UQJcDO@jvy-um|O*N=+J@x(X8j7$vl zU3{ZT$Rch)2has{Lb_Q^x|&D2lLJU@8FWboU!;%&%^8$4&!y_xZB&PckKD3m&FV)! zznoj>NokOM4S4~3>pU2OzV1_*uIBQ2(fJ~b9XcRgtR>wnCSA=U-SGfY_he8b1rIc% zC|90NRkc*Azpo%4c?X%vtv~wVV^3SH<#pbah`kT6Ax5A#KnsMRPw1PtKZ9EaA&n7Z z#h96kNGF{vBpoG@&L)u##Q;**Wbj6c2r8URq!Mcaiz}8=O@1AvR|uxI9XRm(0f()k z$(vH;J+ClnHY0@Oz`fB2aZe{T!I)k+@N;b5v5m&Mk;cA?bTOZFlR&zfNV)%iQI!6E67%15$R$U>1GP)Dw0(ob(Kx@mK40AIf|m=XsT*Xrv)9e>B(3^ z{&NkbTu|CwlHC2>@BZ79`4_Tt#hq-tNo|MS^@+2r>v#a1_i?}dv}>jHJ=bi@TU|$2 zM^znhjb?|-jjVjN>wowTzrk;D4X#BSXbWxndw=v5eMa9g1{%vI8rvEg>k=CKY~~_j zNk?NzXJQ4?aAZ&;1rIjmQujo`TBK6(Wf_^!wTu{es_vednD~wVeC?O7U9BjpQkzK) zwV+Sv8~TX85)rmABCMscEu*of3RYnvD@CgXkA@|Kx442^i}CbCOe4Q}3q{upsURZ~ zBZC65ZE0y~-+KMXFJ3J!%)RU_ZPi*Z`BYMz`#Ji8K2dzImHH|YVL6R$E{!#TS%vX} zRWM|{&|4S6t;IOw?OpImBm8_@qY%@K1UE~-$cI*S+`(EZ#@11z#c**6w zlE(U~KWIe&w2gbvKwD@NZPPvO7D%v>`m~n%xRUyu#)yzaW8?0@ zn^g!~GWfCTP8p3MCb!Cc#I*t zld%FhV#zm8qluuK$!E_bz!1#cO8$H<0Xm;#fgtk#=h1Id>Dm+qej?pt2HkTC^?{RM zEOQGZJh%pv2)!hRC#%890pC1<5hRYD)@k(Q%0x*ZKoiNTsEPc20s}st+L}sj%LJG} z_vR$6X5*!Qt?%|vQL20w}sU<`{3 zI0;N^5JX~da&XHroDpOc0TscB5=lVHgz+Zw?;;uS5!B`=Mu6dhB@jtq5+THHMYJHp z1)_{(gz+Z)w5 VX*XuF_RatR002ovPDHLkV1iW3ptAq~ literal 0 HcmV?d00001 diff --git a/src/views/Styles.scss b/src/views/Styles.scss index a727aa12..4a7438ed 100644 --- a/src/views/Styles.scss +++ b/src/views/Styles.scss @@ -24,3 +24,4 @@ @import './help/HelpView'; @import './floorplan-editor/FloorplanEditorView'; @import './nitropedia/NitropediaView'; +@import './campaign/CampaignView'; diff --git a/src/views/campaign/CampaignView.scss b/src/views/campaign/CampaignView.scss new file mode 100644 index 00000000..506d0169 --- /dev/null +++ b/src/views/campaign/CampaignView.scss @@ -0,0 +1 @@ +@import './views/calendar/CalendarView'; diff --git a/src/views/campaign/CampaignView.tsx b/src/views/campaign/CampaignView.tsx new file mode 100644 index 00000000..eb205f51 --- /dev/null +++ b/src/views/campaign/CampaignView.tsx @@ -0,0 +1,60 @@ +import { CampaignCalendarData, CampaignCalendarDataMessageEvent } from '@nitrots/nitro-renderer'; +import { FC, useCallback, useEffect, useState } from 'react'; +import { AddEventLinkTracker, RemoveLinkEventTracker } from '../../api'; +import { CreateMessageHook } from '../../hooks'; +import { CalendarView } from './views/calendar/CalendarView'; + +export const CampaignView: FC<{}> = props => +{ + const [ calendarData, setCalendarData ] = useState(null); + const [ isCalendarOpen, setCalendarOpen ] = useState(false); + + const onCampaignCalendarDataMessageEvent = useCallback((event: CampaignCalendarDataMessageEvent) => + { + const parser = event.getParser(); + + if(!parser) return; + + setCalendarData(parser.calendarData); + }, []); + + CreateMessageHook(CampaignCalendarDataMessageEvent, onCampaignCalendarDataMessageEvent); + + const onLinkReceived = useCallback((link: string) => + { + const value = link.split('/'); + + if(value.length < 2) return; + + switch(value[1]) + { + case 'calendar': + setCalendarOpen(true); + break; + } + }, []); + + useEffect(() => + { + const linkTracker = { linkReceived: onLinkReceived, eventUrlPrefix: 'openView/' }; + AddEventLinkTracker(linkTracker); + + return () => + { + RemoveLinkEventTracker(linkTracker); + } + }, [onLinkReceived]); + + const onCalendarClose = useCallback(() => + { + setCalendarOpen(false); + }, []); + + return ( + <> + {(calendarData && isCalendarOpen) && + + } + + ) +} diff --git a/src/views/campaign/views/calendar/CalendarView.scss b/src/views/campaign/views/calendar/CalendarView.scss new file mode 100644 index 00000000..7ef04128 --- /dev/null +++ b/src/views/campaign/views/calendar/CalendarView.scss @@ -0,0 +1,10 @@ +.nitro-campaign-calendar { + width: 800px; + height: 400px; + + .calendar-day { + background: url('../../../../assets/images/campaign/campaign_day_generic_bg.png'); + max-height: 100%; + min-width: 50px; + } +} diff --git a/src/views/campaign/views/calendar/CalendarView.tsx b/src/views/campaign/views/calendar/CalendarView.tsx new file mode 100644 index 00000000..72cc86fd --- /dev/null +++ b/src/views/campaign/views/calendar/CalendarView.tsx @@ -0,0 +1,43 @@ +import { FC, useCallback, useState } from 'react'; +import { LocalizeText } from '../../../../api'; +import { NitroCardContentView, NitroCardGridItemView, NitroCardGridView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { CalendarViewProps } from './CalendarView.types'; + +export const CalendarView: FC = props => +{ + const { close = null, campaignName = null, currentDay = null, numDays = null, missedDays = null, openedDays = null } = props; + const [ selectedDay, setSelectedDay ] = useState(currentDay); + + const dayMessage = useCallback((day: number) => + { + if(missedDays.includes(day)) + { + return LocalizeText('campaign.calendar.info.expired'); + } + + if(openedDays.includes(day)) + { + return LocalizeText('campaign.calendar.info.unlocked') + } + }, [missedDays, openedDays]); + + return ( + + + +
+

{LocalizeText('campaign.calendar.heading.day', ['number'], [selectedDay.toString()])}

+

{LocalizeText('')}

+
+ + { + [...Array(7)].map((e, i) => + { + return + }) + } + +
+
+ ) +} diff --git a/src/views/campaign/views/calendar/CalendarView.types.ts b/src/views/campaign/views/calendar/CalendarView.types.ts new file mode 100644 index 00000000..77539e8e --- /dev/null +++ b/src/views/campaign/views/calendar/CalendarView.types.ts @@ -0,0 +1,9 @@ +export interface CalendarViewProps +{ + close(): void; + campaignName: string; + currentDay: number; + numDays: number; + openedDays: number[]; + missedDays: number[]; +} diff --git a/src/views/main/MainView.tsx b/src/views/main/MainView.tsx index 5cd09f84..ca00b8dc 100644 --- a/src/views/main/MainView.tsx +++ b/src/views/main/MainView.tsx @@ -6,6 +6,7 @@ import { TransitionAnimation, TransitionAnimationTypes } from '../../layout'; import { AchievementsView } from '../achievements/AchievementsView'; import { AvatarEditorView } from '../avatar-editor/AvatarEditorView'; import { CameraWidgetView } from '../camera/CameraWidgetView'; +import { CampaignView } from '../campaign/CampaignView'; import { CatalogView } from '../catalog/CatalogView'; import { ChatHistoryView } from '../chat-history/ChatHistoryView'; import { FloorplanEditorView } from '../floorplan-editor/FloorplanEditorView'; @@ -77,6 +78,7 @@ export const MainView: FC = props => + ); } From 8b2cef7f93606cb0053d6803876e436ad1891478 Mon Sep 17 00:00:00 2001 From: Bill Date: Tue, 23 Nov 2021 01:06:00 -0500 Subject: [PATCH 02/17] Fixed --- .../views/calendar-item/CalendarItemView.tsx | 10 ++++++++++ .../calendar-item/CalendarItemView.types.ts | 4 ++++ .../campaign/views/calendar/CalendarView.tsx | 20 ++++++++----------- 3 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 src/views/campaign/views/calendar-item/CalendarItemView.tsx create mode 100644 src/views/campaign/views/calendar-item/CalendarItemView.types.ts diff --git a/src/views/campaign/views/calendar-item/CalendarItemView.tsx b/src/views/campaign/views/calendar-item/CalendarItemView.tsx new file mode 100644 index 00000000..172126ab --- /dev/null +++ b/src/views/campaign/views/calendar-item/CalendarItemView.tsx @@ -0,0 +1,10 @@ +import { FC } from 'react'; +import { NitroLayoutFlexColumn } from '../../../../layout'; +import { CalendarItemViewProps } from './CalendarItemView.types'; + +export const CalendarItemView: FC = props => +{ + return ( + + ); +} diff --git a/src/views/campaign/views/calendar-item/CalendarItemView.types.ts b/src/views/campaign/views/calendar-item/CalendarItemView.types.ts new file mode 100644 index 00000000..99f12758 --- /dev/null +++ b/src/views/campaign/views/calendar-item/CalendarItemView.types.ts @@ -0,0 +1,4 @@ +export interface CalendarItemViewProps +{ + +} diff --git a/src/views/campaign/views/calendar/CalendarView.tsx b/src/views/campaign/views/calendar/CalendarView.tsx index 72cc86fd..42a6a010 100644 --- a/src/views/campaign/views/calendar/CalendarView.tsx +++ b/src/views/campaign/views/calendar/CalendarView.tsx @@ -1,6 +1,7 @@ import { FC, useCallback, useState } from 'react'; import { LocalizeText } from '../../../../api'; -import { NitroCardContentView, NitroCardGridItemView, NitroCardGridView, NitroCardHeaderView, NitroCardView } from '../../../../layout'; +import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutFlex } from '../../../../layout'; +import { CalendarItemView } from '../calendar-item/CalendarItemView'; import { CalendarViewProps } from './CalendarView.types'; export const CalendarView: FC = props => @@ -23,20 +24,15 @@ export const CalendarView: FC = props => return ( - +
-

{LocalizeText('campaign.calendar.heading.day', ['number'], [selectedDay.toString()])}

-

{LocalizeText('')}

+

{ LocalizeText('campaign.calendar.heading.day', ['number'], [selectedDay.toString()]) }

+

{ LocalizeText('') }

- - { - [...Array(7)].map((e, i) => - { - return - }) - } - + + { [...Array(7)].map((e, i) => ) } +
) From a8eb8ecf228001a3dc16e908c764fa677772ec05 Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Fri, 26 Nov 2021 00:32:51 -0300 Subject: [PATCH 03/17] Sounds --- package-lock.json | 59 +++++++++++++++++-- public/renderer-config.json | 2 +- src/api/utils/PlaySound.ts | 7 +++ .../views/capture/CameraWidgetCaptureView.tsx | 3 +- src/views/catalog/CatalogView.tsx | 5 ++ .../views/messenger/FriendsMessengerView.tsx | 5 ++ .../mod-tools/ModToolsMessageHandler.tsx | 6 +- src/views/purse/PurseMessageHandler.tsx | 5 ++ 8 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 src/api/utils/PlaySound.ts diff --git a/package-lock.json b/package-lock.json index 0f2a0fe4..e6642ff6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1817,12 +1817,13 @@ "@nitrots/nitro-renderer": { "version": "file:../nitro-renderer", "requires": { - "@pixi/canvas-renderer": "^6.1.0", - "@pixi/extract": "^6.1.0", + "@pixi/canvas-renderer": "^6.1.3", + "@pixi/extract": "^6.1.3", "@pixi/filter-adjustment": "^4.1.3", + "@pixi/tilemap": "^3.2.2", "pako": "^2.0.4", - "pixi.js": "^6.1.0", - "tslib": "^2.3.0" + "pixi.js": "^6.1.3", + "tslib": "^2.3.1" }, "dependencies": { "@babel/code-frame": { @@ -2108,6 +2109,11 @@ "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-6.1.0.tgz", "integrity": "sha512-tCh1dhmriLKLMcxTJ9usm1UZEK2+M5nEwvyec9kouF4EMi/PiGup65+pwTHK4SvjXD+9vbtTDam39fWYXCpRxg==" }, + "@pixi/tilemap": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@pixi/tilemap/-/tilemap-3.2.2.tgz", + "integrity": "sha512-svdmMyJP63vdae3t66tCmE8IWeO/6lD1xXU+5gzfxqxJS5seTp2bm8mQok2c8PF0O6l/NYlLz6BRklOuEuHboQ==" + }, "@pixi/utils": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-6.1.0.tgz", @@ -11826,6 +11832,11 @@ } } }, + "load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=" + }, "loader-runner": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", @@ -15025,6 +15036,16 @@ "react-lifecycles-compat": "^3.0.4" } }, + "react-youtube": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-7.13.1.tgz", + "integrity": "sha512-b++TLHmHDpd0ZBS1wcbYabbuchU+W4jtx5A2MUQX0BINNKKsaIQX29sn/aLvZ9v5luwAoceia3VGtyz9blaB9w==", + "requires": { + "fast-deep-equal": "3.1.3", + "prop-types": "15.7.2", + "youtube-player": "5.5.2" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -16219,6 +16240,11 @@ } } }, + "sister": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz", + "integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA==" + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -19328,6 +19354,31 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "youtube-player": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz", + "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==", + "requires": { + "debug": "^2.6.6", + "load-script": "^1.0.0", + "sister": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } } } } diff --git a/public/renderer-config.json b/public/renderer-config.json index b6112627..40a50115 100644 --- a/public/renderer-config.json +++ b/public/renderer-config.json @@ -5,7 +5,7 @@ "hof.furni.url": "https://swf.nitrots.co/dcr/hof_furni", "images.url": "${asset.url}/images", "gamedata.url": "${asset.url}/gamedata", - "sounds.url": "${asset.url}/sounds", + "sounds.url": "${asset.url}/sounds/%sample%.mp3", "external.texts.url": [ "${gamedata.url}/ExternalTexts.json", "${gamedata.url}/UITexts.json" ], "external.samples.url": "${hof.furni.url}/mp3/sound_machine_sample_%sample%.mp3", "furnidata.url": "${gamedata.url}/FurnitureData.json", diff --git a/src/api/utils/PlaySound.ts b/src/api/utils/PlaySound.ts new file mode 100644 index 00000000..6dddb915 --- /dev/null +++ b/src/api/utils/PlaySound.ts @@ -0,0 +1,7 @@ +import { NitroSoundEvent } from '@nitrots/nitro-renderer/src/nitro/events/NitroSoundEvent'; +import { dispatchMainEvent } from '../../hooks'; + +export function PlaySound(sampleCode: string): void +{ + dispatchMainEvent(new NitroSoundEvent(NitroSoundEvent.PLAY_SOUND, sampleCode)); +} diff --git a/src/views/camera/views/capture/CameraWidgetCaptureView.tsx b/src/views/camera/views/capture/CameraWidgetCaptureView.tsx index 40407e3e..c24e936d 100644 --- a/src/views/camera/views/capture/CameraWidgetCaptureView.tsx +++ b/src/views/camera/views/capture/CameraWidgetCaptureView.tsx @@ -1,6 +1,7 @@ import { NitroRectangle, TextureUtils } from '@nitrots/nitro-renderer'; import { FC, useCallback, useRef } from 'react'; import { GetRoomEngine, GetRoomSession, LocalizeText } from '../../../../api'; +import { PlaySound } from '../../../../api/utils/PlaySound'; import { DraggableWindow } from '../../../../layout'; import { CameraPicture } from '../../common/CameraPicture'; import { useCameraWidgetContext } from '../../context/CameraWidgetContext'; @@ -30,7 +31,6 @@ export const CameraWidgetCaptureView: FC = props = if(selectedPictureIndex > -1) { setSelectedPictureIndex(-1); - return; } @@ -45,6 +45,7 @@ export const CameraWidgetCaptureView: FC = props = clone.pop(); } + PlaySound('camera_shutter'); clone.push(new CameraPicture(texture, TextureUtils.generateImageUrl(texture))); setCameraRoll(clone); diff --git a/src/views/catalog/CatalogView.tsx b/src/views/catalog/CatalogView.tsx index 403166bf..d1d9142d 100644 --- a/src/views/catalog/CatalogView.tsx +++ b/src/views/catalog/CatalogView.tsx @@ -1,6 +1,7 @@ import { GetCatalogIndexComposer, GetCatalogPageComposer, GetGiftWrappingConfigurationComposer, ILinkEventTracker, INodeData, RoomPreviewer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useReducer, useState } from 'react'; import { AddEventLinkTracker, GetRoomEngine, LocalizeText, RemoveLinkEventTracker } from '../../api'; +import { PlaySound } from '../../api/utils/PlaySound'; import { CatalogEvent } from '../../events'; import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../hooks/messages/message-event'; @@ -47,6 +48,9 @@ export const CatalogView: FC = props => save = true; setIsVisible(value => !value); return; + case CatalogEvent.PURCHASE_SUCCESS: + PlaySound('credits'); + return; } if(save) saveActivePages(); @@ -56,6 +60,7 @@ export const CatalogView: FC = props => useUiEvent(CatalogEvent.HIDE_CATALOG, onCatalogEvent); useUiEvent(CatalogEvent.TOGGLE_CATALOG, onCatalogEvent); useUiEvent(CatalogEvent.CATALOG_RESET, onCatalogEvent); + useUiEvent(CatalogEvent.PURCHASE_SUCCESS, onCatalogEvent); const linkReceived = useCallback((url: string) => { diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index 7faec597..5709f56a 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -1,6 +1,7 @@ import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer } from '@nitrots/nitro-renderer'; import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { AddEventLinkTracker, GetUserProfile, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; +import { PlaySound } from '../../../../api/utils/PlaySound'; import { FriendsMessengerIconEvent } from '../../../../events'; import { BatchUpdates, CreateMessageHook, dispatchUiEvent, SendMessageHook } from '../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutButton, NitroLayoutButtonGroup, NitroLayoutFlex, NitroLayoutFlexColumn } from '../../../../layout'; @@ -114,6 +115,8 @@ export const FriendsMessengerView: FC<{}> = props => SendMessageHook(new SendMessageComposer(thread.participant.id, messageText)); + if(messageThreads.length === 1 && thread.groups.length === 1) PlaySound('messenger_new_thread'); + thread.addMessage(0, messageText, 0, null, MessengerThreadChat.CHAT); BatchUpdates(() => @@ -227,6 +230,8 @@ export const FriendsMessengerView: FC<{}> = props => } } + if(isUnread) PlaySound('messenger_message_received'); + dispatchUiEvent(new FriendsMessengerIconEvent(FriendsMessengerIconEvent.UPDATE_ICON, isUnread ? FriendsMessengerIconEvent.UNREAD_ICON : FriendsMessengerIconEvent.SHOW_ICON)); }, [ visibleThreads, updateValue ]); diff --git a/src/views/mod-tools/ModToolsMessageHandler.tsx b/src/views/mod-tools/ModToolsMessageHandler.tsx index b810aa13..acf55120 100644 --- a/src/views/mod-tools/ModToolsMessageHandler.tsx +++ b/src/views/mod-tools/ModToolsMessageHandler.tsx @@ -1,5 +1,6 @@ import { CfhSanctionMessageEvent, CfhTopicsInitEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ModeratorActionResultMessageEvent, ModeratorInitMessageEvent, ModeratorToolPreferencesEvent, RoomEngineEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; +import { PlaySound } from '../../api/utils/PlaySound'; import { NotificationAlertEvent } from '../../events'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; import { ModToolsOpenRoomChatlogEvent } from '../../events/mod-tools/ModToolsOpenRoomChatlogEvent'; @@ -49,7 +50,7 @@ export const ModToolsMessageHandler: FC<{}> = props => const newTickets = tickets ? Array.from(tickets) : []; const existingIndex = newTickets.findIndex( entry => entry.issueId === parser.issueData.issueId) - + if(existingIndex > -1) { newTickets[existingIndex] = parser.issueData; @@ -57,6 +58,7 @@ export const ModToolsMessageHandler: FC<{}> = props => else { newTickets.push(parser.issueData); + PlaySound('modtools_new_ticket'); } dispatchModToolsState({ @@ -66,8 +68,6 @@ export const ModToolsMessageHandler: FC<{}> = props => } }); - //todo: play ticket sound - //GetNitroInstance().events.dispatchEvent(new NitroSoundEvent(NitroSoundEvent.PLAY_SOUND, sound) console.log(parser); }, [dispatchModToolsState, tickets]); diff --git a/src/views/purse/PurseMessageHandler.tsx b/src/views/purse/PurseMessageHandler.tsx index 5ff4558f..56941ae3 100644 --- a/src/views/purse/PurseMessageHandler.tsx +++ b/src/views/purse/PurseMessageHandler.tsx @@ -1,5 +1,6 @@ import { ActivityPointNotificationMessageEvent, UserCreditsEvent, UserCurrencyEvent, UserSubscriptionEvent, UserSubscriptionParser } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; +import { PlaySound } from '../../api/utils/PlaySound'; import { CreateMessageHook } from '../../hooks/messages/message-event'; import { usePurseContext } from './context/PurseContext'; import { PurseMessageHandlerProps } from './PurseMessageHandler.types'; @@ -12,6 +13,8 @@ export const PurseMessageHandler: FC = props => { const parser = event.getParser(); + if(purse.credits && purse.credits !== parseFloat(parser.credits)) PlaySound('credits'); + purse.credits = parseFloat(parser.credits); purse.notify(); @@ -32,6 +35,8 @@ export const PurseMessageHandler: FC = props => purse.activityPoints.set(parser.type, parser.amount); + if(parser.type === 0) PlaySound('duckets'); + purse.notify(); }, [ purse ]); From 02e3e04fe74257e809d29beb761173795cdc344e Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Fri, 26 Nov 2021 00:41:03 -0300 Subject: [PATCH 04/17] Add shutter sound to Thumbnail Camera --- src/layout/mini-camera/NitroLayoutMiniCameraView.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx b/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx index 7b5c6fc9..7bca0e0f 100644 --- a/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx +++ b/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx @@ -1,6 +1,7 @@ import { NitroRectangle } from '@nitrots/nitro-renderer'; import { FC, useCallback, useRef } from 'react'; import { GetRoomEngine, LocalizeText } from '../../api'; +import { PlaySound } from '../../api/utils/PlaySound'; import { DraggableWindow } from '../draggable-window'; import { NitroLayoutMiniCameraViewProps } from './NitroLayoutMiniCameraView.types'; @@ -20,6 +21,7 @@ export const NitroLayoutMiniCameraView: FC = pro const takePicture = useCallback(() => { + PlaySound('camera_shutter'); textureReceiver(GetRoomEngine().createTextureFromRoom(roomId, 1, getCameraBounds())); }, [ roomId, getCameraBounds, textureReceiver ]); From 74670f40cc926a865308e1489812cb73eb385238 Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Fri, 26 Nov 2021 01:07:00 -0300 Subject: [PATCH 05/17] Update Hall Of Fame --- .../hall-of-fame-item/HallOfFameItemView.tsx | 10 +++--- .../hall-of-fame/HallOfFameWidgetView.scss | 35 ++++++++++++------- .../hall-of-fame/HallOfFameWidgetView.tsx | 2 +- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/views/hotel-view/views/widgets/hall-of-fame-item/HallOfFameItemView.tsx b/src/views/hotel-view/views/widgets/hall-of-fame-item/HallOfFameItemView.tsx index 2aef86fe..4c6297b7 100644 --- a/src/views/hotel-view/views/widgets/hall-of-fame-item/HallOfFameItemView.tsx +++ b/src/views/hotel-view/views/widgets/hall-of-fame-item/HallOfFameItemView.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { LocalizeText } from '../../../../../api'; +import { LocalizeFormattedNumber, LocalizeText } from '../../../../../api'; import { UserProfileIconView } from '../../../../../layout'; import { AvatarImageView } from '../../../../shared/avatar-image/AvatarImageView'; import { HallOfFameItemViewProps } from './HallOfFameItemView.types'; @@ -9,12 +9,12 @@ export const HallOfFameItemView: FC = props => const { data = null, level = 0 } = props; return ( -
+
-
-
{ level }. { data.userName }
-
{ LocalizeText('landing.view.competition.hof.points', [ 'points' ], [ data.currentScore.toString() ])}
+
+ { level }. { data.userName }
+
{ LocalizeText('landing.view.competition.hof.points', [ 'points' ], [ LocalizeFormattedNumber(data.currentScore).toString() ])}
diff --git a/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.scss b/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.scss index 74fa0189..63033a46 100644 --- a/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.scss +++ b/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.scss @@ -1,7 +1,7 @@ .hall-of-fame { background-color: rgba($black,.3); border-radius: $border-radius; - display: inline-block; + justify-content: center; .hof-user-container { display:inline-flex; @@ -16,22 +16,31 @@ .hof-tooltip { position: absolute; - display: inline; - z-index: 2; display: none; - background-color: #1c323f; + width: 125px; + max-width: 125px; + padding: 2px; + background-color: $gable-green; border: 2px solid rgba($white, 0.5); border-radius: $border-radius; - bottom:calc(100% - 20px); - left: 0; - right: 0; - margin: auto; - padding:2px; - color: #fff; + font-size: $font-size-sm; + z-index: $context-menu-zindex; + pointer-events: all; + left: -15px; + bottom: calc(100% - 10px); - .hof-tooltip-content { - padding:3px; - background-color: #3d5f6e; + .hof-header { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + background-color: $william; + color: $white; + min-width: 117px; + height: 25px; + max-height: 25px; + font-size: 16px; + margin-bottom: 2px; } &:after { diff --git a/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.tsx b/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.tsx index 5676a9be..2cbfdc8c 100644 --- a/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.tsx +++ b/src/views/hotel-view/views/widgets/hall-of-fame/HallOfFameWidgetView.tsx @@ -26,7 +26,7 @@ export const HallOfFameWidgetView: FC = props => if(!data) return null; return ( -
+
{ data.hof && (data.hof.length > 0) && data.hof.map((entry, index) => { return ; From 8952e851b85cbf5595c4cf33c447d3edf369137c Mon Sep 17 00:00:00 2001 From: MyNameIsBatman Date: Fri, 26 Nov 2021 01:11:33 -0300 Subject: [PATCH 06/17] Fix Tooldbar Achievement Counter --- src/views/toolbar/me/ToolbarMeView.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/toolbar/me/ToolbarMeView.scss b/src/views/toolbar/me/ToolbarMeView.scss index 44cd37bf..491ffad6 100644 --- a/src/views/toolbar/me/ToolbarMeView.scss +++ b/src/views/toolbar/me/ToolbarMeView.scss @@ -17,6 +17,7 @@ } .navigation-item { + position: relative; display: flex; align-items: center; justify-content: center; From caf6fe4b18390ff9f4af302f370b9293d0839a45 Mon Sep 17 00:00:00 2001 From: dank074 Date: Thu, 25 Nov 2021 23:16:00 -0600 Subject: [PATCH 07/17] add constants --- src/api/utils/PlaySound.ts | 7 +++++++ src/layout/mini-camera/NitroLayoutMiniCameraView.tsx | 4 ++-- src/views/camera/views/capture/CameraWidgetCaptureView.tsx | 4 ++-- src/views/catalog/CatalogView.tsx | 4 ++-- src/views/friends/views/messenger/FriendsMessengerView.tsx | 6 +++--- src/views/mod-tools/ModToolsMessageHandler.tsx | 4 ++-- src/views/purse/PurseMessageHandler.tsx | 6 +++--- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/api/utils/PlaySound.ts b/src/api/utils/PlaySound.ts index 6dddb915..96bc8fc5 100644 --- a/src/api/utils/PlaySound.ts +++ b/src/api/utils/PlaySound.ts @@ -5,3 +5,10 @@ export function PlaySound(sampleCode: string): void { dispatchMainEvent(new NitroSoundEvent(NitroSoundEvent.PLAY_SOUND, sampleCode)); } + +export const CAMERA_SHUTTER = 'camera_shutter'; +export const CREDITS = 'credits'; +export const DUCKETS = 'duckets'; +export const MESSENGER_NEW_THREAD = 'messenger_new_thread'; +export const MESSENGER_MESSAGE_RECEIVED = 'messenger_message_received'; +export const MODTOOLS_NEW_TICKET = 'modtools_new_ticket'; diff --git a/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx b/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx index 7bca0e0f..261eebb3 100644 --- a/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx +++ b/src/layout/mini-camera/NitroLayoutMiniCameraView.tsx @@ -1,7 +1,7 @@ import { NitroRectangle } from '@nitrots/nitro-renderer'; import { FC, useCallback, useRef } from 'react'; import { GetRoomEngine, LocalizeText } from '../../api'; -import { PlaySound } from '../../api/utils/PlaySound'; +import { CAMERA_SHUTTER, PlaySound } from '../../api/utils/PlaySound'; import { DraggableWindow } from '../draggable-window'; import { NitroLayoutMiniCameraViewProps } from './NitroLayoutMiniCameraView.types'; @@ -21,7 +21,7 @@ export const NitroLayoutMiniCameraView: FC = pro const takePicture = useCallback(() => { - PlaySound('camera_shutter'); + PlaySound(CAMERA_SHUTTER); textureReceiver(GetRoomEngine().createTextureFromRoom(roomId, 1, getCameraBounds())); }, [ roomId, getCameraBounds, textureReceiver ]); diff --git a/src/views/camera/views/capture/CameraWidgetCaptureView.tsx b/src/views/camera/views/capture/CameraWidgetCaptureView.tsx index c24e936d..1c369a78 100644 --- a/src/views/camera/views/capture/CameraWidgetCaptureView.tsx +++ b/src/views/camera/views/capture/CameraWidgetCaptureView.tsx @@ -1,7 +1,7 @@ import { NitroRectangle, TextureUtils } from '@nitrots/nitro-renderer'; import { FC, useCallback, useRef } from 'react'; import { GetRoomEngine, GetRoomSession, LocalizeText } from '../../../../api'; -import { PlaySound } from '../../../../api/utils/PlaySound'; +import { CAMERA_SHUTTER, PlaySound } from '../../../../api/utils/PlaySound'; import { DraggableWindow } from '../../../../layout'; import { CameraPicture } from '../../common/CameraPicture'; import { useCameraWidgetContext } from '../../context/CameraWidgetContext'; @@ -45,7 +45,7 @@ export const CameraWidgetCaptureView: FC = props = clone.pop(); } - PlaySound('camera_shutter'); + PlaySound(CAMERA_SHUTTER); clone.push(new CameraPicture(texture, TextureUtils.generateImageUrl(texture))); setCameraRoll(clone); diff --git a/src/views/catalog/CatalogView.tsx b/src/views/catalog/CatalogView.tsx index d1d9142d..d45ed9e3 100644 --- a/src/views/catalog/CatalogView.tsx +++ b/src/views/catalog/CatalogView.tsx @@ -1,7 +1,7 @@ import { GetCatalogIndexComposer, GetCatalogPageComposer, GetGiftWrappingConfigurationComposer, ILinkEventTracker, INodeData, RoomPreviewer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useReducer, useState } from 'react'; import { AddEventLinkTracker, GetRoomEngine, LocalizeText, RemoveLinkEventTracker } from '../../api'; -import { PlaySound } from '../../api/utils/PlaySound'; +import { CREDITS, PlaySound } from '../../api/utils/PlaySound'; import { CatalogEvent } from '../../events'; import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../hooks/messages/message-event'; @@ -49,7 +49,7 @@ export const CatalogView: FC = props => setIsVisible(value => !value); return; case CatalogEvent.PURCHASE_SUCCESS: - PlaySound('credits'); + PlaySound(CREDITS); return; } diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index 5709f56a..0d5ad76c 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -1,7 +1,7 @@ import { FollowFriendMessageComposer, ILinkEventTracker, NewConsoleMessageEvent, SendMessageComposer } from '@nitrots/nitro-renderer'; import { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { AddEventLinkTracker, GetUserProfile, LocalizeText, RemoveLinkEventTracker } from '../../../../api'; -import { PlaySound } from '../../../../api/utils/PlaySound'; +import { MESSENGER_MESSAGE_RECEIVED, MESSENGER_NEW_THREAD, PlaySound } from '../../../../api/utils/PlaySound'; import { FriendsMessengerIconEvent } from '../../../../events'; import { BatchUpdates, CreateMessageHook, dispatchUiEvent, SendMessageHook } from '../../../../hooks'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutButton, NitroLayoutButtonGroup, NitroLayoutFlex, NitroLayoutFlexColumn } from '../../../../layout'; @@ -115,7 +115,7 @@ export const FriendsMessengerView: FC<{}> = props => SendMessageHook(new SendMessageComposer(thread.participant.id, messageText)); - if(messageThreads.length === 1 && thread.groups.length === 1) PlaySound('messenger_new_thread'); + if(messageThreads.length === 1 && thread.groups.length === 1) PlaySound(MESSENGER_NEW_THREAD); thread.addMessage(0, messageText, 0, null, MessengerThreadChat.CHAT); @@ -230,7 +230,7 @@ export const FriendsMessengerView: FC<{}> = props => } } - if(isUnread) PlaySound('messenger_message_received'); + if(isUnread) PlaySound(MESSENGER_MESSAGE_RECEIVED); dispatchUiEvent(new FriendsMessengerIconEvent(FriendsMessengerIconEvent.UPDATE_ICON, isUnread ? FriendsMessengerIconEvent.UNREAD_ICON : FriendsMessengerIconEvent.SHOW_ICON)); }, [ visibleThreads, updateValue ]); diff --git a/src/views/mod-tools/ModToolsMessageHandler.tsx b/src/views/mod-tools/ModToolsMessageHandler.tsx index acf55120..3357aef8 100644 --- a/src/views/mod-tools/ModToolsMessageHandler.tsx +++ b/src/views/mod-tools/ModToolsMessageHandler.tsx @@ -1,6 +1,6 @@ import { CfhSanctionMessageEvent, CfhTopicsInitEvent, IssueDeletedMessageEvent, IssueInfoMessageEvent, IssuePickFailedMessageEvent, ModeratorActionResultMessageEvent, ModeratorInitMessageEvent, ModeratorToolPreferencesEvent, RoomEngineEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; -import { PlaySound } from '../../api/utils/PlaySound'; +import { MODTOOLS_NEW_TICKET, PlaySound } from '../../api/utils/PlaySound'; import { NotificationAlertEvent } from '../../events'; import { ModToolsEvent } from '../../events/mod-tools/ModToolsEvent'; import { ModToolsOpenRoomChatlogEvent } from '../../events/mod-tools/ModToolsOpenRoomChatlogEvent'; @@ -58,7 +58,7 @@ export const ModToolsMessageHandler: FC<{}> = props => else { newTickets.push(parser.issueData); - PlaySound('modtools_new_ticket'); + PlaySound(MODTOOLS_NEW_TICKET); } dispatchModToolsState({ diff --git a/src/views/purse/PurseMessageHandler.tsx b/src/views/purse/PurseMessageHandler.tsx index 56941ae3..07ca8f09 100644 --- a/src/views/purse/PurseMessageHandler.tsx +++ b/src/views/purse/PurseMessageHandler.tsx @@ -1,6 +1,6 @@ import { ActivityPointNotificationMessageEvent, UserCreditsEvent, UserCurrencyEvent, UserSubscriptionEvent, UserSubscriptionParser } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; -import { PlaySound } from '../../api/utils/PlaySound'; +import { CREDITS, DUCKETS, PlaySound } from '../../api/utils/PlaySound'; import { CreateMessageHook } from '../../hooks/messages/message-event'; import { usePurseContext } from './context/PurseContext'; import { PurseMessageHandlerProps } from './PurseMessageHandler.types'; @@ -13,7 +13,7 @@ export const PurseMessageHandler: FC = props => { const parser = event.getParser(); - if(purse.credits && purse.credits !== parseFloat(parser.credits)) PlaySound('credits'); + if(purse.credits && purse.credits !== parseFloat(parser.credits)) PlaySound(CREDITS); purse.credits = parseFloat(parser.credits); @@ -35,7 +35,7 @@ export const PurseMessageHandler: FC = props => purse.activityPoints.set(parser.type, parser.amount); - if(parser.type === 0) PlaySound('duckets'); + if(parser.type === 0) PlaySound(DUCKETS); purse.notify(); }, [ purse ]); From 3eb4757d98c15b8858c7ce1877628f9ac4099b66 Mon Sep 17 00:00:00 2001 From: dank074 Date: Fri, 26 Nov 2021 01:31:06 -0600 Subject: [PATCH 08/17] changes --- src/assets/images/campaign/available.png | Bin 0 -> 1118 bytes src/assets/images/campaign/locked_bg.png | Bin 0 -> 5414 bytes src/assets/images/campaign/next.png | Bin 0 -> 244 bytes src/assets/images/campaign/prev.png | Bin 0 -> 235 bytes src/assets/images/campaign/unavailable.png | Bin 0 -> 448 bytes src/assets/images/campaign/unlocked_bg.png | Bin 0 -> 8798 bytes src/assets/images/campaign/unopened.png | Bin 5731 -> 0 bytes src/views/campaign/CampaignView.tsx | 2 +- .../campaign/common/CalendarItemState.ts | 7 ++ src/views/campaign/common/Utils.ts | 4 + .../views/calendar-item/CalendarItemView.tsx | 40 +++++++- .../calendar-item/CalendarItemView.types.ts | 6 +- .../campaign/views/calendar/CalendarView.scss | 67 ++++++++++++- .../campaign/views/calendar/CalendarView.tsx | 92 ++++++++++++++++-- .../widgets/word-quiz/WordQuizWidgetView.tsx | 7 +- 15 files changed, 206 insertions(+), 19 deletions(-) create mode 100644 src/assets/images/campaign/available.png create mode 100644 src/assets/images/campaign/locked_bg.png create mode 100644 src/assets/images/campaign/next.png create mode 100644 src/assets/images/campaign/prev.png create mode 100644 src/assets/images/campaign/unavailable.png create mode 100644 src/assets/images/campaign/unlocked_bg.png delete mode 100644 src/assets/images/campaign/unopened.png create mode 100644 src/views/campaign/common/CalendarItemState.ts create mode 100644 src/views/campaign/common/Utils.ts diff --git a/src/assets/images/campaign/available.png b/src/assets/images/campaign/available.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc8fa6219b2b4ff56e4c8885a945087f240321b GIT binary patch literal 1118 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 literal 0 HcmV?d00001 diff --git a/src/assets/images/campaign/unavailable.png b/src/assets/images/campaign/unavailable.png new file mode 100644 index 0000000000000000000000000000000000000000..dc134c3f12faa3d00aa4302bfa0ec7a5ca81608e GIT binary patch literal 448 zcmV;x0YCnUP)KNfDQ5dg1UGAYMfQUf;Uh)ngA-7Z1vq1^sisOZ0IbmyeMagsll2%NTpG!d;~iY!UQuJ;u6dX5T{`FFs4Erdhm98 zd&pnWSs3a`rOPPMJHIsJJ`u!aDPjtUXKN3lXl+514Uq02>IR4yr3{E^m97hj^`w>s zQEd-M=WiMH?KTEviGi8&^*jz_$#0nsS4IhtijzcbK*moYW{or2gQU&80|H2|p?msb z6(E50T)6`T5I_I{1Q0*~0R#|+?jInOWqy@qQn(Y&t|07)h{-GJL5OgffFj1rw576&cr68X_~ttRzGv$XS^2Nq0wK qQXw)y{>6S}9#bmFPwGU0V|fCdK~2vw4K_dk0000 literal 0 HcmV?d00001 diff --git a/src/assets/images/campaign/unlocked_bg.png b/src/assets/images/campaign/unlocked_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..31c35ba172146dd1af89db8539d582b033c9dde9 GIT binary patch literal 8798 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 UIckVaaR2}S07*qoM6N<$f)^J^t^fc4 literal 0 HcmV?d00001 diff --git a/src/assets/images/campaign/unopened.png b/src/assets/images/campaign/unopened.png deleted file mode 100644 index 71a754ff7cf3709548730eb6f52fc03816cd168c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5731 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 VX*XuF_RatR002ovPDHLkV1iW3ptAq~ diff --git a/src/views/campaign/CampaignView.tsx b/src/views/campaign/CampaignView.tsx index eb205f51..0f2307ee 100644 --- a/src/views/campaign/CampaignView.tsx +++ b/src/views/campaign/CampaignView.tsx @@ -14,7 +14,7 @@ export const CampaignView: FC<{}> = props => const parser = event.getParser(); if(!parser) return; - + console.log(parser); setCalendarData(parser.calendarData); }, []); diff --git a/src/views/campaign/common/CalendarItemState.ts b/src/views/campaign/common/CalendarItemState.ts new file mode 100644 index 00000000..1b91ca3f --- /dev/null +++ b/src/views/campaign/common/CalendarItemState.ts @@ -0,0 +1,7 @@ +export class CalendarItemState +{ + public static readonly STATE_UNLOCKED = 1; + public static readonly STATE_LOCKED_AVAILABLE = 2; + public static readonly STATE_LOCKED_EXPIRED = 3; + public static readonly STATE_LOCKED_FUTURE = 4; +} diff --git a/src/views/campaign/common/Utils.ts b/src/views/campaign/common/Utils.ts new file mode 100644 index 00000000..2695539e --- /dev/null +++ b/src/views/campaign/common/Utils.ts @@ -0,0 +1,4 @@ +export const getNumItemsDisplayed = (): number => +{ + return Math.max(Math.min(2, window.screen.width / 135), 7); +} diff --git a/src/views/campaign/views/calendar-item/CalendarItemView.tsx b/src/views/campaign/views/calendar-item/CalendarItemView.tsx index 172126ab..4841a67b 100644 --- a/src/views/campaign/views/calendar-item/CalendarItemView.tsx +++ b/src/views/campaign/views/calendar-item/CalendarItemView.tsx @@ -1,10 +1,46 @@ -import { FC } from 'react'; +import { FC, useCallback } from 'react'; +import { GetRoomEngine, GetSessionDataManager } from '../../../../api'; import { NitroLayoutFlexColumn } from '../../../../layout'; +import { CalendarItemState } from '../../common/CalendarItemState'; import { CalendarItemViewProps } from './CalendarItemView.types'; export const CalendarItemView: FC = props => { + const { state = null, productName = null, active = false, onClick = null, id = null } = props; + + const getFurnitureIcon = useCallback((name: string) => + { + + let furniData = GetSessionDataManager().getFloorItemDataByName(name); + let url = null; + if(furniData) url = GetRoomEngine().getFurnitureFloorIconUrl(furniData.id); + else + { + furniData = GetSessionDataManager().getWallItemDataByName(name); + if(furniData) url = GetRoomEngine().getFurnitureWallIconUrl(furniData.id); + } + + return url; + }, []); + return ( - + onClick(id)}> + { (state === CalendarItemState.STATE_UNLOCKED) && +
+ +
+ } + + { (state !== CalendarItemState.STATE_UNLOCKED) && +
+ { (state === CalendarItemState.STATE_LOCKED_AVAILABLE) && +
+ } + { (state === CalendarItemState.STATE_LOCKED_EXPIRED || state === CalendarItemState.STATE_LOCKED_FUTURE) && +
+ } +
+ } + ); } diff --git a/src/views/campaign/views/calendar-item/CalendarItemView.types.ts b/src/views/campaign/views/calendar-item/CalendarItemView.types.ts index 99f12758..038dc03c 100644 --- a/src/views/campaign/views/calendar-item/CalendarItemView.types.ts +++ b/src/views/campaign/views/calendar-item/CalendarItemView.types.ts @@ -1,4 +1,8 @@ export interface CalendarItemViewProps { - + id: number; + productName?: string; + state: number; + active?: boolean; + onClick(itemId: number): void; } diff --git a/src/views/campaign/views/calendar/CalendarView.scss b/src/views/campaign/views/calendar/CalendarView.scss index 7ef04128..f583ee0b 100644 --- a/src/views/campaign/views/calendar/CalendarView.scss +++ b/src/views/campaign/views/calendar/CalendarView.scss @@ -1,10 +1,69 @@ .nitro-campaign-calendar { - width: 800px; + width: 1010px; height: 400px; - .calendar-day { - background: url('../../../../assets/images/campaign/campaign_day_generic_bg.png'); + .calendar-item { + background: url("../../../../assets/images/campaign/campaign_day_generic_bg.png"); max-height: 100%; - min-width: 50px; + min-width: 135px; + filter: brightness(80%); + + &.active { + filter: brightness(100%); + } + + .unlocked-generic-bg { + background: url("../../../../assets/images/campaign/unlocked_bg.png"); + background-size: 132px 132px; + width: 132px; + height: 132px; + + //width: 190px; + //height: 189px; + } + + .locked-generic-bg { + background: url("../../../../assets/images/campaign/locked_bg.png"); + width: 132px; + height: 132px; + + .available { + background: url("../../../../assets/images/campaign/available.png"); + width: 69px; + height: 78px; + } + + .unavailable { + background: url("../../../../assets/images/campaign/unavailable.png"); + width: 68px; + height: 78px; + } + } + } + + .button-container { + position: relative; + width: 100%; + height: 0px; + + .calendar-prev { + background: url("../../../../assets/images/campaign/prev.png"); + width: 33px; + height: 34px; + position: absolute; + margin-top: 15%; + left: 5px; + z-index: 10; + } + + .calendar-next { + background: url("../../../../assets/images/campaign/next.png"); + width: 33px; + height: 34px; + position: absolute; + margin-top: 15%; + right: 5px; + z-index: 10; + } } } diff --git a/src/views/campaign/views/calendar/CalendarView.tsx b/src/views/campaign/views/calendar/CalendarView.tsx index 42a6a010..b89864dc 100644 --- a/src/views/campaign/views/calendar/CalendarView.tsx +++ b/src/views/campaign/views/calendar/CalendarView.tsx @@ -1,6 +1,8 @@ import { FC, useCallback, useState } from 'react'; import { LocalizeText } from '../../../../api'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutFlex } from '../../../../layout'; +import { CalendarItemState } from '../../common/CalendarItemState'; +import { getNumItemsDisplayed } from '../../common/Utils'; import { CalendarItemView } from '../calendar-item/CalendarItemView'; import { CalendarViewProps } from './CalendarView.types'; @@ -8,30 +10,104 @@ export const CalendarView: FC = props => { const { close = null, campaignName = null, currentDay = null, numDays = null, missedDays = null, openedDays = null } = props; const [ selectedDay, setSelectedDay ] = useState(currentDay); + const [ index, setIndex ] = useState(0); + + const getDayState = useCallback((day: number) => + { + if(openedDays.includes(day)) + { + return CalendarItemState.STATE_UNLOCKED; + } + if(day > currentDay) + { + return CalendarItemState.STATE_LOCKED_FUTURE; + } + + if(missedDays.includes(day)) + { + return CalendarItemState.STATE_LOCKED_EXPIRED; + } + + return CalendarItemState.STATE_LOCKED_AVAILABLE; + }, [currentDay, missedDays, openedDays]); const dayMessage = useCallback((day: number) => { - if(missedDays.includes(day)) + const state = getDayState(day); + + switch(state) { - return LocalizeText('campaign.calendar.info.expired'); + case CalendarItemState.STATE_UNLOCKED: + return LocalizeText('campaign.calendar.info.unlocked'); + case CalendarItemState.STATE_LOCKED_FUTURE: + return LocalizeText('campaign.calendar.info.future'); + case CalendarItemState.STATE_LOCKED_EXPIRED: + return LocalizeText('campaign.calendar.info.expired'); + default: return LocalizeText('campaign.calendar.info.available.desktop'); + } + }, [getDayState]); + + const onClickNext = useCallback(() => + { + const nextDay = selectedDay + 1; + + if( (nextDay) === numDays) return; + + setSelectedDay(nextDay); + + if( (index + getNumItemsDisplayed()) < nextDay + 1 ) + { + setIndex(index + 1); } - if(openedDays.includes(day)) + }, [index, numDays, selectedDay]); + + const onClickPrev = useCallback(() => + { + const prevDay = selectedDay - 1; + + if( (prevDay < 0)) return; + + setSelectedDay(prevDay); + + if( index > prevDay) { - return LocalizeText('campaign.calendar.info.unlocked') + setIndex(index - 1); } - }, [missedDays, openedDays]); + }, [index, selectedDay]); + + const onClickItem = useCallback((item: number) => + { + if(selectedDay === item) + { + //handle opening + } + else + { + setSelectedDay(item); + } + }, [selectedDay]); return (
-

{ LocalizeText('campaign.calendar.heading.day', ['number'], [selectedDay.toString()]) }

-

{ LocalizeText('') }

+

{ LocalizeText('campaign.calendar.heading.day', ['number'], [(selectedDay + 1).toString()]) }

+

{ dayMessage(selectedDay) }

+
+
+
+
- { [...Array(7)].map((e, i) => ) } + { + [...Array(getNumItemsDisplayed())].map((e, i) => + { + const day = index + i; + return + }) + } diff --git a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx index af258d59..271853e4 100644 --- a/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx +++ b/src/views/room/widgets/word-quiz/WordQuizWidgetView.tsx @@ -106,9 +106,8 @@ export const WordQuizWidgetView: FC<{}> = props => { setUserAnswers(prev => { - const copy = new Map(prev); const keysToRemove: number[] = []; - copy.forEach((value, key) => + prev.forEach((value, key) => { value.secondsLeft--; @@ -118,8 +117,10 @@ export const WordQuizWidgetView: FC<{}> = props => } }); - keysToRemove.forEach(key => copy.delete(key)); + if(keysToRemove.length === 0) return prev; + const copy = new Map(prev); + keysToRemove.forEach(key => copy.delete(key)); return copy; }) From d1128afd3deabfe8ba37bd27e55e990521794455 Mon Sep 17 00:00:00 2001 From: dank074 Date: Fri, 26 Nov 2021 22:13:30 -0600 Subject: [PATCH 09/17] fix some stuff --- src/views/help/HelpMessageHandler.tsx | 35 ++++++++++++++++++---- src/views/help/common/CallForHelpResult.ts | 5 ++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 src/views/help/common/CallForHelpResult.ts diff --git a/src/views/help/HelpMessageHandler.tsx b/src/views/help/HelpMessageHandler.tsx index 959abdb9..047dd512 100644 --- a/src/views/help/HelpMessageHandler.tsx +++ b/src/views/help/HelpMessageHandler.tsx @@ -1,9 +1,10 @@ -import { CallForHelpResultMessageEvent } from '@nitrots/nitro-renderer'; +import { CallForHelpResultMessageEvent, GetPendingCallsForHelpMessageComposer, IssueCloseNotificationMessageEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback } from 'react'; import { LocalizeText } from '../../api'; -import { CreateMessageHook } from '../../hooks/messages/message-event'; +import { CreateMessageHook, SendMessageHook } from '../../hooks/messages/message-event'; import { NotificationAlertType } from '../notification-center/common/NotificationAlertType'; import { NotificationUtilities } from '../notification-center/common/NotificationUtilities'; +import { CallForHelpResult } from './common/CallForHelpResult'; import { GetCloseReasonKey } from './common/GetCloseReasonKey'; export const HelpMessageHandler: FC<{}> = props => @@ -14,12 +15,36 @@ export const HelpMessageHandler: FC<{}> = props => let message = parser.messageText; - if(!message || !message.length) message = LocalizeText('help.cfh.closed.' + GetCloseReasonKey(parser.resultType)) - - NotificationUtilities.simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('mod.alert.title')); + switch(parser.resultType) + { + case CallForHelpResult.TOO_MANY_PENDING_CALLS_CODE: + SendMessageHook(new GetPendingCallsForHelpMessageComposer()); + NotificationUtilities.simpleAlert(LocalizeText('help.cfh.error.pending'), NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.error.title')); + break; + case CallForHelpResult.HAS_ABUSIVE_CALL_CODE: + NotificationUtilities.simpleAlert(LocalizeText('help.cfh.error.abusive'), NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.error.title')); + break; + default: + if(message.trim().length === 0) + { + message = LocalizeText('help.cfh.sent.text'); + } + NotificationUtilities.simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('help.cfh.sent.title')); + } }, []); CreateMessageHook(CallForHelpResultMessageEvent, onCallForHelpResultMessageEvent); + const onIssueCloseNotificationMessageEvent = useCallback((event: IssueCloseNotificationMessageEvent) => + { + const parser = event.getParser(); + + const message = LocalizeText('help.cfh.closed.' + GetCloseReasonKey(parser.closeReason)) + + NotificationUtilities.simpleAlert(message, NotificationAlertType.MODERATION, null, null, LocalizeText('mod.alert.title')); + }, []); + + CreateMessageHook(IssueCloseNotificationMessageEvent, onIssueCloseNotificationMessageEvent); + return null; } diff --git a/src/views/help/common/CallForHelpResult.ts b/src/views/help/common/CallForHelpResult.ts new file mode 100644 index 00000000..37e7ea1b --- /dev/null +++ b/src/views/help/common/CallForHelpResult.ts @@ -0,0 +1,5 @@ +export class CallForHelpResult +{ + public static readonly TOO_MANY_PENDING_CALLS_CODE = 1; + public static readonly HAS_ABUSIVE_CALL_CODE = 2; +} From b684715075d8f7094fc8674c7ad8126ab28051f4 Mon Sep 17 00:00:00 2001 From: dank074 Date: Sat, 27 Nov 2021 00:58:21 -0600 Subject: [PATCH 10/17] finished logic --- public/ui-config.json | 2 +- src/views/campaign/CampaignView.tsx | 71 ++++++++++++++++--- src/views/campaign/common/Utils.ts | 2 +- .../views/calendar-item/CalendarItemView.tsx | 8 ++- .../campaign/views/calendar/CalendarView.scss | 11 +++ .../campaign/views/calendar/CalendarView.tsx | 59 +++++++++------ .../views/calendar/CalendarView.types.ts | 2 + 7 files changed, 121 insertions(+), 34 deletions(-) diff --git a/public/ui-config.json b/public/ui-config.json index 050c4e4c..e8fc85d1 100644 --- a/public/ui-config.json +++ b/public/ui-config.json @@ -5,7 +5,7 @@ "thumbnails.url": "https://nitro.nitrots.co/camera/thumbnail/%thumbnail%.png", "url.prefix": "http://localhost:3000", "floorplan.tile.url": "${asset.url}/floorplan-editor/tiles.json", - "habbopages.url": "http://localhost:3000/", + "habbopages.url": "https://swf.nitrots.co/gamedata/habbopages/", "chat.viewer.height.percentage": 0.40, "widget.dimmer.colorwheel": false, "hotelview": { diff --git a/src/views/campaign/CampaignView.tsx b/src/views/campaign/CampaignView.tsx index 0f2307ee..2178333d 100644 --- a/src/views/campaign/CampaignView.tsx +++ b/src/views/campaign/CampaignView.tsx @@ -1,12 +1,14 @@ -import { CampaignCalendarData, CampaignCalendarDataMessageEvent } from '@nitrots/nitro-renderer'; +import { CampaignCalendarData, CampaignCalendarDataMessageEvent, CampaignCalendarDoorOpenedMessageEvent, OpenCampaignCalendarDoorAsStaffComposer, OpenCampaignCalendarDoorComposer } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useState } from 'react'; import { AddEventLinkTracker, RemoveLinkEventTracker } from '../../api'; -import { CreateMessageHook } from '../../hooks'; +import { BatchUpdates, CreateMessageHook, SendMessageHook } from '../../hooks'; import { CalendarView } from './views/calendar/CalendarView'; export const CampaignView: FC<{}> = props => { const [ calendarData, setCalendarData ] = useState(null); + const [ lastOpenAttempt, setLastOpenAttempt ] = useState(-1); + const [ receivedProducts, setReceivedProducts ] = useState>(new Map()); const [ isCalendarOpen, setCalendarOpen ] = useState(false); const onCampaignCalendarDataMessageEvent = useCallback((event: CampaignCalendarDataMessageEvent) => @@ -14,12 +16,68 @@ export const CampaignView: FC<{}> = props => const parser = event.getParser(); if(!parser) return; - console.log(parser); setCalendarData(parser.calendarData); }, []); CreateMessageHook(CampaignCalendarDataMessageEvent, onCampaignCalendarDataMessageEvent); + const onCampaignCalendarDoorOpenedMessageEvent = useCallback((event: CampaignCalendarDoorOpenedMessageEvent) => + { + const parser = event.getParser(); + + if(!parser) return; + + const lastAttempt = lastOpenAttempt; + + if(parser.doorOpened) + { + BatchUpdates(() => + { + setCalendarData(prev => + { + const copy = prev.clone(); + copy.openedDays.push(lastOpenAttempt); + + return copy; + }); + + setReceivedProducts(prev => + { + const copy = new Map(prev); + copy.set(lastAttempt, parser.furnitureClassName); + + return copy; + }); + }); + } + + setLastOpenAttempt(-1); + }, [lastOpenAttempt]); + + CreateMessageHook(CampaignCalendarDoorOpenedMessageEvent, onCampaignCalendarDoorOpenedMessageEvent); + + const openPackage = useCallback((id: number, asStaff = false) => + { + if(!calendarData) return; + + setLastOpenAttempt(id); + + if(asStaff) + { + SendMessageHook(new OpenCampaignCalendarDoorAsStaffComposer(calendarData.campaignName, id)); + } + + else + { + SendMessageHook(new OpenCampaignCalendarDoorComposer(calendarData.campaignName, id)); + } + }, [calendarData]); + + const onCalendarClose = useCallback(() => + { + setCalendarOpen(false); + }, []); + const onLinkReceived = useCallback((link: string) => { const value = link.split('/'); @@ -45,15 +103,10 @@ export const CampaignView: FC<{}> = props => } }, [onLinkReceived]); - const onCalendarClose = useCallback(() => - { - setCalendarOpen(false); - }, []); - return ( <> {(calendarData && isCalendarOpen) && - + } ) diff --git a/src/views/campaign/common/Utils.ts b/src/views/campaign/common/Utils.ts index 2695539e..75c3c5b7 100644 --- a/src/views/campaign/common/Utils.ts +++ b/src/views/campaign/common/Utils.ts @@ -1,4 +1,4 @@ export const getNumItemsDisplayed = (): number => { - return Math.max(Math.min(2, window.screen.width / 135), 7); + return Math.min(Math.max(2, Math.floor(window.screen.width / 135)), 7); } diff --git a/src/views/campaign/views/calendar-item/CalendarItemView.tsx b/src/views/campaign/views/calendar-item/CalendarItemView.tsx index 4841a67b..fe2eba0c 100644 --- a/src/views/campaign/views/calendar-item/CalendarItemView.tsx +++ b/src/views/campaign/views/calendar-item/CalendarItemView.tsx @@ -26,8 +26,12 @@ export const CalendarItemView: FC = props => return ( onClick(id)}> { (state === CalendarItemState.STATE_UNLOCKED) && -
- +
+
+ { productName && + + } +
} diff --git a/src/views/campaign/views/calendar/CalendarView.scss b/src/views/campaign/views/calendar/CalendarView.scss index f583ee0b..4c3f5dc0 100644 --- a/src/views/campaign/views/calendar/CalendarView.scss +++ b/src/views/campaign/views/calendar/CalendarView.scss @@ -20,6 +20,17 @@ //width: 190px; //height: 189px; + + .opened { + background: url("../../../../assets/images/campaign/campaign_opened.png"); + width: 96px; + height: 66px; + + .furni-icon + { + margin-bottom: 10px; + } + } } .locked-generic-bg { diff --git a/src/views/campaign/views/calendar/CalendarView.tsx b/src/views/campaign/views/calendar/CalendarView.tsx index b89864dc..4eeb3aab 100644 --- a/src/views/campaign/views/calendar/CalendarView.tsx +++ b/src/views/campaign/views/calendar/CalendarView.tsx @@ -1,5 +1,5 @@ import { FC, useCallback, useState } from 'react'; -import { LocalizeText } from '../../../../api'; +import { GetSessionDataManager, LocalizeText } from '../../../../api'; import { NitroCardContentView, NitroCardHeaderView, NitroCardView, NitroLayoutFlex } from '../../../../layout'; import { CalendarItemState } from '../../common/CalendarItemState'; import { getNumItemsDisplayed } from '../../common/Utils'; @@ -8,9 +8,9 @@ import { CalendarViewProps } from './CalendarView.types'; export const CalendarView: FC = props => { - const { close = null, campaignName = null, currentDay = null, numDays = null, missedDays = null, openedDays = null } = props; - const [ selectedDay, setSelectedDay ] = useState(currentDay); - const [ index, setIndex ] = useState(0); + const { close = null, campaignName = null, currentDay = null, numDays = null, missedDays = null, openedDays = null, openPackage = null, receivedProducts = null } = props; + const [selectedDay, setSelectedDay] = useState(currentDay); + const [index, setIndex] = useState(Math.max(0, selectedDay - 1)); const getDayState = useCallback((day: number) => { @@ -22,12 +22,12 @@ export const CalendarView: FC = props => { return CalendarItemState.STATE_LOCKED_FUTURE; } - + if(missedDays.includes(day)) { return CalendarItemState.STATE_LOCKED_EXPIRED; } - + return CalendarItemState.STATE_LOCKED_AVAILABLE; }, [currentDay, missedDays, openedDays]); @@ -51,11 +51,11 @@ export const CalendarView: FC = props => { const nextDay = selectedDay + 1; - if( (nextDay) === numDays) return; + if((nextDay) === numDays) return; setSelectedDay(nextDay); - if( (index + getNumItemsDisplayed()) < nextDay + 1 ) + if((index + getNumItemsDisplayed()) < nextDay + 1) { setIndex(index + 1); } @@ -66,11 +66,11 @@ export const CalendarView: FC = props => { const prevDay = selectedDay - 1; - if( (prevDay < 0)) return; + if((prevDay < 0)) return; setSelectedDay(prevDay); - if( index > prevDay) + if(index > prevDay) { setIndex(index - 1); } @@ -81,32 +81,49 @@ export const CalendarView: FC = props => if(selectedDay === item) { //handle opening + const state = getDayState(item); + if(state === CalendarItemState.STATE_LOCKED_AVAILABLE) openPackage(item, false); } else { setSelectedDay(item); } - }, [selectedDay]); + }, [getDayState, openPackage, selectedDay]); + + const forceOpen = useCallback(() => + { + const id = selectedDay; + const state = getDayState(id); + if(GetSessionDataManager().isModerator && state !== CalendarItemState.STATE_UNLOCKED) + { + openPackage(id, true); + } + }, [getDayState, openPackage, selectedDay]); return ( - + -
-

{ LocalizeText('campaign.calendar.heading.day', ['number'], [(selectedDay + 1).toString()]) }

-

{ dayMessage(selectedDay) }

+
+
+

{LocalizeText('campaign.calendar.heading.day', ['number'], [(selectedDay + 1).toString()])}

+

{dayMessage(selectedDay)}

+
+ {GetSessionDataManager().isModerator && + + }
-
-
+
+
- - { + + { [...Array(getNumItemsDisplayed())].map((e, i) => { const day = index + i; - return - }) + return + }) } diff --git a/src/views/campaign/views/calendar/CalendarView.types.ts b/src/views/campaign/views/calendar/CalendarView.types.ts index 77539e8e..754f592b 100644 --- a/src/views/campaign/views/calendar/CalendarView.types.ts +++ b/src/views/campaign/views/calendar/CalendarView.types.ts @@ -1,6 +1,8 @@ export interface CalendarViewProps { close(): void; + openPackage(id: number, asStaff: boolean); + receivedProducts: Map; campaignName: string; currentDay: number; numDays: number; From 44a89f0262aa004a567e1be92578d0b1892e32eb Mon Sep 17 00:00:00 2001 From: dank074 Date: Sat, 27 Nov 2021 01:27:07 -0600 Subject: [PATCH 11/17] some style changes --- .../campaign/views/calendar/CalendarView.scss | 36 +++++++------------ .../campaign/views/calendar/CalendarView.tsx | 10 +++--- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/views/campaign/views/calendar/CalendarView.scss b/src/views/campaign/views/calendar/CalendarView.scss index 4c3f5dc0..f621d2af 100644 --- a/src/views/campaign/views/calendar/CalendarView.scss +++ b/src/views/campaign/views/calendar/CalendarView.scss @@ -1,5 +1,5 @@ .nitro-campaign-calendar { - width: 1010px; + width: 1055px; height: 400px; .calendar-item { @@ -52,29 +52,17 @@ } } - .button-container { - position: relative; - width: 100%; - height: 0px; + .calendar-prev { + background: url("../../../../assets/images/campaign/prev.png"); + width: 33px; + min-width: 33px; + height: 34px; + } - .calendar-prev { - background: url("../../../../assets/images/campaign/prev.png"); - width: 33px; - height: 34px; - position: absolute; - margin-top: 15%; - left: 5px; - z-index: 10; - } - - .calendar-next { - background: url("../../../../assets/images/campaign/next.png"); - width: 33px; - height: 34px; - position: absolute; - margin-top: 15%; - right: 5px; - z-index: 10; - } + .calendar-next { + background: url("../../../../assets/images/campaign/next.png"); + width: 33px; + min-width: 33px; + height: 34px; } } diff --git a/src/views/campaign/views/calendar/CalendarView.tsx b/src/views/campaign/views/calendar/CalendarView.tsx index 4eeb3aab..b6566791 100644 --- a/src/views/campaign/views/calendar/CalendarView.tsx +++ b/src/views/campaign/views/calendar/CalendarView.tsx @@ -104,7 +104,7 @@ export const CalendarView: FC = props => -
+

{LocalizeText('campaign.calendar.heading.day', ['number'], [(selectedDay + 1).toString()])}

{dayMessage(selectedDay)}

@@ -114,10 +114,11 @@ export const CalendarView: FC = props => }
-
-
+ +
- + +
{ [...Array(getNumItemsDisplayed())].map((e, i) => { @@ -125,6 +126,7 @@ export const CalendarView: FC = props => return }) } +
From ce1b1c556892e2a450497d0c2685d4f7e856702d Mon Sep 17 00:00:00 2001 From: dank074 Date: Sat, 27 Nov 2021 01:33:30 -0600 Subject: [PATCH 12/17] changes --- src/views/campaign/common/Utils.ts | 2 +- src/views/campaign/views/calendar/CalendarView.types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/campaign/common/Utils.ts b/src/views/campaign/common/Utils.ts index 75c3c5b7..7b7be678 100644 --- a/src/views/campaign/common/Utils.ts +++ b/src/views/campaign/common/Utils.ts @@ -1,4 +1,4 @@ export const getNumItemsDisplayed = (): number => { - return Math.min(Math.max(2, Math.floor(window.screen.width / 135)), 7); + return Math.min(Math.max(2, Math.floor(window.screen.width / 135) - 3), 7); } diff --git a/src/views/campaign/views/calendar/CalendarView.types.ts b/src/views/campaign/views/calendar/CalendarView.types.ts index 754f592b..454021e3 100644 --- a/src/views/campaign/views/calendar/CalendarView.types.ts +++ b/src/views/campaign/views/calendar/CalendarView.types.ts @@ -1,7 +1,7 @@ export interface CalendarViewProps { close(): void; - openPackage(id: number, asStaff: boolean); + openPackage(id: number, asStaff: boolean): void; receivedProducts: Map; campaignName: string; currentDay: number; From aac2c494691fae6aa0967a072bf2b2c3b091b9ec Mon Sep 17 00:00:00 2001 From: dank074 Date: Sat, 4 Dec 2021 19:12:26 -0600 Subject: [PATCH 13/17] fixes --- src/layout/card/header/NitroCardHeaderView.scss | 5 ----- src/views/chat-history/ChatHistoryView.scss | 9 +++++++++ .../RelationshipsContainerView.tsx | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/layout/card/header/NitroCardHeaderView.scss b/src/layout/card/header/NitroCardHeaderView.scss index ded3c2bd..fe6c9d8e 100644 --- a/src/layout/card/header/NitroCardHeaderView.scss +++ b/src/layout/card/header/NitroCardHeaderView.scss @@ -16,11 +16,6 @@ } } - &.theme-dark { - background-color: #3d5f6e !important; - color: #fff; - } - .bg-tertiary-split { position: relative; border-bottom: 2px solid darken($quaternary, 5); diff --git a/src/views/chat-history/ChatHistoryView.scss b/src/views/chat-history/ChatHistoryView.scss index 9f8e6385..84bafc9f 100644 --- a/src/views/chat-history/ChatHistoryView.scss +++ b/src/views/chat-history/ChatHistoryView.scss @@ -2,6 +2,15 @@ width: $chat-history-width; height: $chat-history-height; + background-color: #1C323F; + border: 2px solid rgba(255, 255, 255, 0.5); + border-radius: 0.25rem; + + .nitro-card-header-container { + background-color: #3d5f6e; + color: #fff; + } + .chat-history-content { .chat-history-container { min-height: 200px; diff --git a/src/views/user-profile/views/relationships-container/RelationshipsContainerView.tsx b/src/views/user-profile/views/relationships-container/RelationshipsContainerView.tsx index e1bb648c..4f1745cb 100644 --- a/src/views/user-profile/views/relationships-container/RelationshipsContainerView.tsx +++ b/src/views/user-profile/views/relationships-container/RelationshipsContainerView.tsx @@ -25,7 +25,7 @@ export const RelationshipsContainerView: FC = p return (
- +
OnUserClick(relationshipInfo)}> From a33f06ad27dc43a6ae36694d7130cd6509881d19 Mon Sep 17 00:00:00 2001 From: dank074 Date: Sat, 4 Dec 2021 22:42:48 -0600 Subject: [PATCH 14/17] fix click detection --- .../floorplan-editor/FloorplanEditorView.scss | 2 +- .../common/FloorplanEditor.ts | 29 +++++++++---------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/views/floorplan-editor/FloorplanEditorView.scss b/src/views/floorplan-editor/FloorplanEditorView.scss index b11b5107..7bc41e59 100644 --- a/src/views/floorplan-editor/FloorplanEditorView.scss +++ b/src/views/floorplan-editor/FloorplanEditorView.scss @@ -6,7 +6,7 @@ width: 100%; height: 300px; min-height: 300px; - overflow-x: scroll; + overflow: scroll; } .color { diff --git a/src/views/floorplan-editor/common/FloorplanEditor.ts b/src/views/floorplan-editor/common/FloorplanEditor.ts index 99cdd12c..71fcbed9 100644 --- a/src/views/floorplan-editor/common/FloorplanEditor.ts +++ b/src/views/floorplan-editor/common/FloorplanEditor.ts @@ -43,7 +43,7 @@ export class FloorplanEditor extends PixiApplicationProxy this._width = 0; this._height = 0; this._isHolding = false; - this._lastUsedTile = new NitroPoint(-1,-1); + this._lastUsedTile = new NitroPoint(-1, -1); this._actionSettings = new ActionSettings(); } @@ -52,7 +52,7 @@ export class FloorplanEditor extends PixiApplicationProxy if(!this._isInitialized) { this.loader.add('tiles', GetConfiguration('floorplan.tile.url')); - + this.loader.load((_, resources) => { this._tilemapRenderer = new NitroTilemap(resources['tiles'].spritesheet.baseTexture); @@ -127,9 +127,8 @@ export class FloorplanEditor extends PixiApplicationProxy const bufIndex = j + bufSize; const data = buffer.slice(j, bufIndex); - const width = data[4]; - const height = data[5]; - + const width = TILE_SIZE; + const height = TILE_SIZE / 2; const mousePositionX = Math.floor(tempPoint.x); const mousePositionY = Math.floor(tempPoint.y); @@ -137,12 +136,11 @@ export class FloorplanEditor extends PixiApplicationProxy const tileStartX = data[2]; const tileStartY = data[3]; - const centreX = tileStartX + (width / 2); const centreY = tileStartY + (height / 2); - const dx = Math.abs(mousePositionX - centreX - 2); - const dy = Math.abs(mousePositionY - centreY - 2); + const dx = Math.abs(mousePositionX - centreX); + const dy = Math.abs(mousePositionY - centreY); const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1);//todo: improve this if(solution) @@ -171,7 +169,6 @@ export class FloorplanEditor extends PixiApplicationProxy return false; } - private onClick(x: number, y: number): void { const tile = this._tilemap[y][x]; @@ -212,7 +209,7 @@ export class FloorplanEditor extends PixiApplicationProxy { if((x + 1) > this._width) this._width = x + 1; - if( (y + 1) > this._height) this._height = y + 1; + if((y + 1) > this._height) this._height = y + 1; } const newHeight = HEIGHT_SCHEME[futureHeightIndex]; @@ -229,7 +226,7 @@ export class FloorplanEditor extends PixiApplicationProxy public renderTiles(): void { this.tilemapRenderer.clear(); - + for(let y = 0; y < this._tilemap.length; y++) { for(let x = 0; x < this.tilemap[y].length; x++) @@ -237,13 +234,13 @@ export class FloorplanEditor extends PixiApplicationProxy const tile = this.tilemap[y][x]; let assetName = tile.height; - if(this._doorLocation.x === x && this._doorLocation.y === y) + if(this._doorLocation.x === x && this._doorLocation.y === y) assetName = FloorplanEditor.TILE_DOOR; if(tile.isBlocked) assetName = FloorplanEditor.TILE_BLOCKED; - + //if((tile.height === 'x') || tile.height === 'X') continue; - const [positionX, positionY ] = getScreenPositionForTile(x, y); + const [positionX, positionY] = getScreenPositionForTile(x, y); this._tilemapRenderer.tile(`${assetName}.png`, positionX, positionY); } } @@ -337,10 +334,10 @@ export class FloorplanEditor extends PixiApplicationProxy if(tile.height !== 'x') { - if( (x + 1) > this._width) + if((x + 1) > this._width) this._width = x + 1; - if( (y + 1) > this._height) + if((y + 1) > this._height) this._height = y + 1; } } From ea5bea4a804a5f810ef5498f1dc0778cd766e3ee Mon Sep 17 00:00:00 2001 From: dank074 Date: Sun, 5 Dec 2021 00:27:15 -0600 Subject: [PATCH 15/17] fix floorplan touch interactions --- .../floorplan-editor/FloorplanEditorView.scss | 8 ++-- .../common/FloorplanEditor.ts | 4 +- .../views/FloorplanCanvasView.tsx | 38 ++++++++++++++++++- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/views/floorplan-editor/FloorplanEditorView.scss b/src/views/floorplan-editor/FloorplanEditorView.scss index 7bc41e59..dcacff14 100644 --- a/src/views/floorplan-editor/FloorplanEditorView.scss +++ b/src/views/floorplan-editor/FloorplanEditorView.scss @@ -9,9 +9,11 @@ overflow: scroll; } - .color { - height: 50px; - width: 10px; + .arrow-button { + + @include media-breakpoint-up(md) { + display:none; + } } } diff --git a/src/views/floorplan-editor/common/FloorplanEditor.ts b/src/views/floorplan-editor/common/FloorplanEditor.ts index 71fcbed9..7d1aad13 100644 --- a/src/views/floorplan-editor/common/FloorplanEditor.ts +++ b/src/views/floorplan-editor/common/FloorplanEditor.ts @@ -87,10 +87,10 @@ export class FloorplanEditor extends PixiApplicationProxy this._tilemapRenderer.on('pointerdown', (event: PixiInteractionEventProxy) => { - if(!(event.data.originalEvent instanceof PointerEvent)) return; + if(!(event.data.originalEvent instanceof PointerEvent) && !(event.data.originalEvent instanceof TouchEvent)) return; const pointerEvent = event.data.originalEvent; - if(pointerEvent.button === 2) return; + if((pointerEvent instanceof MouseEvent) && pointerEvent.button === 2) return; const location = event.data.global; diff --git a/src/views/floorplan-editor/views/FloorplanCanvasView.tsx b/src/views/floorplan-editor/views/FloorplanCanvasView.tsx index f68a9248..a52fae94 100644 --- a/src/views/floorplan-editor/views/FloorplanCanvasView.tsx +++ b/src/views/floorplan-editor/views/FloorplanCanvasView.tsx @@ -1,6 +1,7 @@ import { GetOccupiedTilesMessageComposer, GetRoomEntryTileMessageComposer, NitroPoint, RoomEntryTileMessageEvent, RoomOccupiedTilesMessageEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { CreateMessageHook, SendMessageHook, UseMountEffect } from '../../../hooks'; +import { NitroLayoutFlex } from '../../../layout'; import { FloorplanEditor } from '../common/FloorplanEditor'; import { useFloorplanEditorContext } from '../context/FloorplanEditorContext'; @@ -68,6 +69,29 @@ export const FloorplanCanvasView: FC<{}> = props => CreateMessageHook(RoomEntryTileMessageEvent, onRoomEntryTileMessageEvent); + const onClickArrowButton = useCallback((scrollDirection: string) => + { + const element = elementRef.current; + + if(!element) return; + + switch(scrollDirection) + { + case 'up': + element.scrollBy({ top: -10 }); + break; + case 'down': + element.scrollBy({ top: 10 }); + break; + case 'left': + element.scrollBy({ left: -10 }); + break; + case 'right': + element.scrollBy({ left: 10 }); + break; + } + }, []); + useEffect(() => { if(entryTileReceived && occupiedTilesReceived) @@ -75,6 +99,18 @@ export const FloorplanCanvasView: FC<{}> = props => }, [entryTileReceived, occupiedTilesReceived]) return ( -
+ <> + +
+
+ +
+
+
+ + +
+
+ ); } From 7cb42452078c1e49dd6e20a0ede4f05e4fa53842 Mon Sep 17 00:00:00 2001 From: dank074 Date: Sun, 5 Dec 2021 20:29:23 -0600 Subject: [PATCH 16/17] add habblet link handler --- src/views/main/MainView.tsx | 41 +++++++++++++++++++++++++-- src/views/navigator/NavigatorView.tsx | 13 ++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/views/main/MainView.tsx b/src/views/main/MainView.tsx index 5cd09f84..a01a09c7 100644 --- a/src/views/main/MainView.tsx +++ b/src/views/main/MainView.tsx @@ -1,6 +1,6 @@ -import { RoomSessionEvent } from '@nitrots/nitro-renderer'; +import { HabboWebTools, RoomSessionEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useState } from 'react'; -import { GetCommunication } from '../../api'; +import { AddEventLinkTracker, GetCommunication, RemoveLinkEventTracker } from '../../api'; import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event'; import { TransitionAnimation, TransitionAnimationTypes } from '../../layout'; import { AchievementsView } from '../achievements/AchievementsView'; @@ -46,6 +46,32 @@ export const MainView: FC = props => useRoomSessionManagerEvent(RoomSessionEvent.CREATED, onRoomSessionEvent); useRoomSessionManagerEvent(RoomSessionEvent.ENDED, onRoomSessionEvent); + const onLinkReceived = useCallback((link: string) => + { + const parts = link.split('/'); + + if(parts.length < 2) return; + + switch(parts[1]) + { + case 'open': + if(parts.length > 2) + { + switch(parts[2]) + { + case 'credits': + //HabboWebTools.openWebPageAndMinimizeClient(this._windowManager.getProperty(ExternalVariables.WEB_SHOP_RELATIVE_URL)); + break; + default: { + const name = parts[2]; + HabboWebTools.openHabblet(name); + } + } + } + return; + } + }, []); + useEffect(() => { setIsReady(true); @@ -53,6 +79,17 @@ export const MainView: FC = props => GetCommunication().connection.onReady(); }, []); + useEffect(() => + { + const linkTracker = { linkReceived: onLinkReceived, eventUrlPrefix: 'habblet/' }; + AddEventLinkTracker(linkTracker); + + return () => + { + RemoveLinkEventTracker(linkTracker); + } + }, [onLinkReceived]); + return (
diff --git a/src/views/navigator/NavigatorView.tsx b/src/views/navigator/NavigatorView.tsx index d26d9147..62f8acad 100644 --- a/src/views/navigator/NavigatorView.tsx +++ b/src/views/navigator/NavigatorView.tsx @@ -1,7 +1,8 @@ -import { ILinkEventTracker, NavigatorInitComposer, NavigatorSearchComposer, RoomDataParser, RoomSessionEvent } from '@nitrots/nitro-renderer'; +import { ConvertGlobalRoomIdMessageComposer, HabboWebTools, ILinkEventTracker, LegacyExternalInterface, NavigatorInitComposer, NavigatorSearchComposer, RoomDataParser, RoomSessionEvent } from '@nitrots/nitro-renderer'; import { FC, useCallback, useEffect, useMemo, useReducer, useState } from 'react'; import { AddEventLinkTracker, GoToDesktop, LocalizeText, RemoveLinkEventTracker, TryVisitRoom } from '../../api'; import { NavigatorEvent, UpdateDoorStateEvent } from '../../events'; +import { UseMountEffect } from '../../hooks'; import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event'; import { useUiEvent } from '../../hooks/events/ui/ui-event'; import { SendMessageHook } from '../../hooks/messages/message-event'; @@ -181,6 +182,16 @@ export const NavigatorView: FC = props => return () => RemoveLinkEventTracker(linkTracker); }, [ linkReceived]); + const enterRoomWebRequest = useCallback((k: string, _arg_2:boolean=false, _arg_3:string=null) => + { + SendMessageHook(new ConvertGlobalRoomIdMessageComposer(k)); + }, []); + + UseMountEffect(() => + { + LegacyExternalInterface.addCallback(HabboWebTools.OPENROOM, enterRoomWebRequest); + }); + useEffect(() => { if(!isVisible || !needsNavigatorUpdate) return; From 2fd73efa1dbb62fba6f0a5b7accc086d5094a092 Mon Sep 17 00:00:00 2001 From: dank074 Date: Wed, 8 Dec 2021 02:20:00 -0600 Subject: [PATCH 17/17] updated renderer packet --- .../views/groups-container/GroupsContainerView.tsx | 8 ++++---- .../views/groups-container/GroupsContainerView.types.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/views/user-profile/views/groups-container/GroupsContainerView.tsx b/src/views/user-profile/views/groups-container/GroupsContainerView.tsx index a5dcb17f..92fdf691 100644 --- a/src/views/user-profile/views/groups-container/GroupsContainerView.tsx +++ b/src/views/user-profile/views/groups-container/GroupsContainerView.tsx @@ -28,7 +28,7 @@ export const GroupsContainerView: FC = props => useEffect(() => { - if(groups.length > 0 && !selectedGroupId) setSelectedGroupId(groups[0].id); + if(groups.length > 0 && !selectedGroupId) setSelectedGroupId(groups[0].groupId); }, [ groups, selectedGroupId ]); useEffect(() => @@ -49,9 +49,9 @@ export const GroupsContainerView: FC = props =>
{ groups.map((group, index) => { - return
setSelectedGroupId(group.id) } className={ 'profile-groups-item position-relative flex-shrink-0 d-flex align-items-center justify-content-center cursor-pointer' + classNames({ ' active': selectedGroupId === group.id }) }> - { itsMe && favoriteGroup(group.id) } /> } - + return
setSelectedGroupId(group.groupId) } className={ 'profile-groups-item position-relative flex-shrink-0 d-flex align-items-center justify-content-center cursor-pointer' + classNames({ ' active': selectedGroupId === group.groupId }) }> + { itsMe && favoriteGroup(group.groupId) } /> } +
}) }
diff --git a/src/views/user-profile/views/groups-container/GroupsContainerView.types.ts b/src/views/user-profile/views/groups-container/GroupsContainerView.types.ts index 40b273af..0bfdf75e 100644 --- a/src/views/user-profile/views/groups-container/GroupsContainerView.types.ts +++ b/src/views/user-profile/views/groups-container/GroupsContainerView.types.ts @@ -1,8 +1,8 @@ -import { GroupDataParser } from '@nitrots/nitro-renderer'; +import { HabboGroupEntryData } from '@nitrots/nitro-renderer'; export interface GroupsContainerViewProps { itsMe: boolean; - groups: GroupDataParser[]; + groups: HabboGroupEntryData[]; onLeaveGroup: () => void; }