From 854c3a0306d42f0aa2d4a458f4aefd65863a8edc Mon Sep 17 00:00:00 2001 From: xmcp Date: Wed, 17 Apr 2019 01:26:10 +0800 Subject: [PATCH] feature update - search query highlight - id quote - add some icons --- README.md | 3 +- public/index.html | 2 +- public/static/fonts_2/icomoon.ttf | Bin 2972 -> 0 bytes public/static/fonts_2/icomoon.woff | Bin 3048 -> 0 bytes .../static/{fonts_2 => fonts_5}/icomoon.css | 22 +- .../static/{fonts_2 => fonts_5}/icomoon.svg | 5 + public/static/fonts_5/icomoon.ttf | Bin 0 -> 3992 bytes public/static/fonts_5/icomoon.woff | Bin 0 -> 4068 bytes src/Common.css | 5 + src/Common.js | 18 +- src/Flows.css | 22 ++ src/Flows.js | 195 ++++++++++++++---- 12 files changed, 218 insertions(+), 54 deletions(-) delete mode 100644 public/static/fonts_2/icomoon.ttf delete mode 100644 public/static/fonts_2/icomoon.woff rename public/static/{fonts_2 => fonts_5}/icomoon.css (71%) rename public/static/{fonts_2 => fonts_5}/icomoon.svg (67%) create mode 100644 public/static/fonts_5/icomoon.ttf create mode 100644 public/static/fonts_5/icomoon.woff diff --git a/README.md b/README.md index 57424a0..2f82131 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,5 @@ React 版 P大树洞,[pkuhelper.pku.edu.cn/hole](http://pkuhelper.pku.edu.cn/h - 检测瀑布流中被删除的树洞和树洞被删除的评论(`//setflag DELETION_DETECT=on`) - 自定义背景图片(`//setflag REPLACE_ERIRI_WITH_URL=http://...`) -- 禁用 3D Touch 功能(`//setflag DISABLE_PRESSURE=on`) \ No newline at end of file +- 禁用 3D Touch 功能(`//setflag DISABLE_PRESSURE=on`) +- 禁用自动显示引用树洞功能(`//setflag DISABLE_QUOTE=on`) \ No newline at end of file diff --git a/public/index.html b/public/index.html index a77cd9f..98e7161 100644 --- a/public/index.html +++ b/public/index.html @@ -6,7 +6,7 @@ - + diff --git a/public/static/fonts_2/icomoon.ttf b/public/static/fonts_2/icomoon.ttf deleted file mode 100644 index 132accf5e0ec4a120d75d00ded663a2e9bb33fb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2972 zcmai0U2Gf25uUw0@^t(WNs&C7ltl4JiIgaZ6#tI0E!!svaUz>ST3fK6sEUzk$*LtP zlHA%(fbz*GY6K1PP&7dy_#v>-Jfv>Z)O{$>LtmPQqCk-rfq|lF>!N^E^yeWh5LY^O zZts{-j*#y0Zf9m^cE6dOSuPL&a6%I(jJkxKS0UP@LgD3t*zhxp#EC`(ue$8 zOSR2)?7hfq*mo^myLshL|M>2&kbfUQm|L#bF88d~{sJHx`pPm2gkR9#AU}uv;PUF$ zjXVLg6>lIvajmgf6W@0J9{C?5A6u>6Scd?tAdhQ8Y^}Chf8(t9U*tc=HEyprHn$Kb zHs>qGI8gdK@*3CxxHmXN0pB)z@;4|D(a`H?1YsX+D!}dos6|j4)O+ z-aZ^Nd&;!>fQN6QJc`kv(2cU#4(xn&=jP6^^Aiw_0qbFB&JU z$01&NQ+idpC6%PSl#_@A!H*PLGBuVMd`SmOQT)#mpvo7)<*DTTGY<6>c`gw26i@)cmr#G`%`7oKTo>5OP zr;>rofn;j=w0h<#mc$31JE9(WZopd@h~>Q&GjQWv-44F{7-Qvbg!U zAoxrW(BY%>dr#KapS+jm3I#H$|Ge--zkBZ}ZH15jk)qJ zEFyDYe?pQ{njk5AGM6E_q>_u0oW#zk_HnC}Go(Bwh0MQ#Q#foFqFB=A*=$gDtnYIB zpkx6^w2$XVq&lfq{9dv$)ssr3lEd+;#P>Ky)9I-|urJKJg41WCld?P+Jv$wA@!`H; zU^+cA+8rcbe`QjwMk1!e^j++$^DA?+v(0Qa%=b7%B^H`HI&egw`4fWUNZes_xyQ5F zne?;0;!KI=xu&iYkou6)ahiMr( zAmD(Bk3)LFqAAjfMe|5sw`d#Q7K0XTNBKF6c0dHa1$bZKMU-^oh)HuuFIlv4Q#xtU zJkqaNv<)PPS+pJH=PlX+MR@D#Vq>+@Sc9vWqzzcbw*hMx>l>R_8*8y#W(+Pu9X4PS z6>tFO$w3Cj4z)T|c)q@L{aS4U7p)`E>u?QfuyLs7na0{yY^lCh->7ZXFUMZI8Jk&b r%p$f7oMCHk;p$5`%^E{ggDvbYqwGbviQgIKz^v&2Vl?g*U)cT!i+m$S diff --git a/public/static/fonts_2/icomoon.woff b/public/static/fonts_2/icomoon.woff deleted file mode 100644 index 25b7f5b25d30629f3e497166c988bdfd515b89a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3048 zcmai0U2Gf25uUw0^29%p6v?AWNfeKiNQrVtQ6!JDE!!svQ6gJ}8{4p-sEUzk$*Ltf zlHAx%f%3^HY6K1PP&7dx=pnGtJfu#7)O{;a6lflT06`iA28yPwi=tA|pNFJF`2p+UL(qPXhsLjz5Eg_pcc|!~5HrbD2>9(t*->M(!@@Ckrc; zYbaYn{&hz8KC1qDv9gXb!HGQ6W#n1Bdh;^M`~cE6=RBADVR^N( zQbn1DKHg^Z$|>7_uGQ8zFy8mL4zs6-DE*kc1Qzu172$p4e_-_FFOVZPGtHc=10cAPXH1x5K)`9=AbT#!fQtW0DGd>WWDSK|}>j}HNYE4aB= zhKc}CJi*7!W9Bo6KTqHbkIxIE>6_FhYWIz>l6tR_2qHBdKtL6!M8= zf;p8a~6(bNSARBQ}wzasa=)Qu1Mo2I5^O=-15gz7K!^b^df$ZKU zg4c6=IF)Zn=&hDy?^ka3k)f2TriPBV-9n?C`==_)YH!x3U-o5t8CFY9@^5E}G?Ywc zeQN4yPt=2dPfty)XEMq`GF_Y2PA(-A{!9Kua_OWt{Uw&f`kp$Z9eS$Ilk1C)dQ7J8 z#_8GT+1_F1@w03|5^}h6F@AV#lW^bUW2BH{zhVS4%G^`FZ@w5Fsft+^@LPq(1Fsayc@g|2+3t-@1F3 z%s{<9Nz5AXDlsc2mYh?( zY}ZHCf>#+;G4T@gclwsk)o}UrEtk*dBJ-Rf^T-Gq?_38dFh9l5&(;kgD8MtgVqV4B zWtPLZZld5*@Oa~eoHs{XC(qM<|7p`$dlBdMRXl0*_@n+F{%JHp(;8a6y~x|KQL^o| z&9U&3Y2V}5zk&8m5E{k}(Qa(u-TAMWo7Y5pE-NsJu^J^EHv`KVm2P?;loYSzYh7B# zT~Nf_GOE56KD`wmPR$nzW5(j<+Udi?XJYZ*ACmdo3B#L~MBlo-&wz##eSO0YrxA@2 zzTMUz4n>)ZH#?z~!(k&}`VRKxx#jbvQazIi ziCuP^8V#O5+;>Q#qsJusp_tv`bd6;)GpQ%LZ8HU$?XcN8va~Q`>wYqIDw7^_x-5>7 zcz)Jp?-E0qk?)pD=a=Wo_#ecqL$*h0`M1??y2t+o4orA#pWN&G*%y8D0k1apX2N@c zH?-mJ3J?+TGU2^3$iHr5CPTu^m?o1UX=YzH` + + + + + \ No newline at end of file diff --git a/public/static/fonts_5/icomoon.ttf b/public/static/fonts_5/icomoon.ttf new file mode 100644 index 0000000000000000000000000000000000000000..03e2423da8143bc3345a15cddf4b9279ebf32965 GIT binary patch literal 3992 zcma(UZA@F&_1t%#{rrKkjqPV_z}OgUFo}(AY?Bbk16C3eXqpctQzTO;ArKZm3ZzZa zNP9n~{8&~s%Ct#Ur-&b2s%h24R&|-CNqbssLh8cfqFwVl?CJny`B zpBpIzd6oZ?I2H%}*{Jd-a$IKpGMM zU}kb<2}c*=|G?2QbMeagb?Y|rl21{IWp;Yf9~Sq)MWi9Vm;z-BA%F^yu1Vfm_z&{#KQ}d^V6>%vHlNn)K9K2Ev~Gh zo!Fe0wRxcQ6LJ$w0Nm@`2S|C1jpUz@C032Eq7hdGqJt8^_BvHc3P=VRBlinc5xXUk`47Y^xzwE4|Cxc(a|SKNmdqom&L2%%WU`sfZj2Y_yzSnOy?cvYU0vBRLiR+X=~{L#nI8zr$ zMKIh#q=|TSO_3zw?sX?R`&@30>|7_D+tt^Z=q^*})iUM5@14$l9f^EC(Xr3z#QNplkVP3$GPto9T_ znAv)y8h-P%VCd#C+kIX$rwsP)KNAR0PJN}VL6T+pWH8^vXo0|){k@^~o}PB>RMF8v zXOmNXMQLb5){|BnqcL_>(HW7s+BOqBi`6TlC9$#cev&OD@e~ak1V0k+=c%AY6C_GQ zxD7K_EaWW2k$^ve(J;YxKwi^q<9Ke?V$qhiSY{F7DEXJ)B=fMNoBOss z=+v}0gZ8&c!rrJO?LF!r4N#*qp09FJs}TvkhUvvXD_5*&X>a2M^ziG&!j;Qr@)*h{ zUo;mj_~|u{8y~cLZJu+|;I!M_>dB>&!(ME|$y81zurWA3s(w#i+t}dxEpF@JIOX;q zefEIK#5fqYqKpsre)BU$+1SwPgpBzkWB%}9!x(T|i8~%~7u*rNMI<804`hjxsI-HH zPDMs}N0zjLjP<2-59{4qD22B^X|odtp=~DGMubBAAZaFop9l5!?c3^Y0tW~_2MDO} zx5T^mmzM6oo8YopGNAr8dtY65^;COI!TM!=Z>_PF@eQw#H~d)I@TS@om|X#tcZCjfHx2nlulgLymw;2)jZ-Pi;GK!b#Eol*ojdbw z1O{=htaO$GH(O=BUx>H`k8wq_?ZpciTdca4w@4#+E zdW>09rl@Pzs|08;*4*4_uVK4k+qYR;gMqLntlp`jpl~I({>5k1zy>HlAAqT<)|EHL zu94kuQMPA)+)4`Z>dU;+wNE&g&(5kJlhE1UNl!Wqy7r{Q`0H79Q{6oKo}McoV!Xct zQ+Og(G3FQZxdS9_j-`_%9m}UfBrWRqS@{zrkCn90CHmRtTR%>l^%|)cB33Q&E+~{Q zRsG_OmUkHp76+tJkBiI=*2SaoSbIxRF6iNv7S*BIbyd_zY<1Chu;=*W<-h7UCQ zyhDkO&RQRFc}54MVlc>dP2a(>I6il3Y)nq20(_m#nh*O=?P;zTXr@=N)wkG8HIANC zY9#SYgLNcF(-y1MlBT&4Yr`{%BdKIhjl*Q`igu4WY;}Af)%ESMu~T#7Mf|EVYKi8f zFMjY*=kv}3Uw|Ex7Tcfy^49djv2+)|E)~QrT5Z!C%INDtEeG355EMJEORbyoO_?v(Ig$G*XS?!1b>VF-1Hsf z)U5HstS+o)rY>Fis)e5!HWLsG35`>L34=}%&Kod~@FfE_;Xg&60h^J2)PQXegzp0W z8{w@;sl^!va|q8EFh#h}fO&+k8L$aN2pg~&=_d@>2Ho)Hg{j5)#l;1(K%7w*+a5~uqr(qhFVFej*0`;UJ30=EN?Mgf`J#*>egK@aSjF)i(q4co_#V+WFvd23 NHtIE|@=zXy{|{GJ?ymp< literal 0 HcmV?d00001 diff --git a/public/static/fonts_5/icomoon.woff b/public/static/fonts_5/icomoon.woff new file mode 100644 index 0000000000000000000000000000000000000000..991336810165338e1338ad93ef2be9ca34910961 GIT binary patch literal 4068 zcma)9Yit|G5#GH$^7s%%QY4QeB~hd(krHK-;#;;JK1qpe*-{)oU>63cNReg9swFv+ z96w^9_oMKSCP54rEgGaS^rLl9G$_;tsf(gO4^4sQM-db#(AFr5s!SC^wFQW=D>1<(mvopq8n zH9vU~uvy@LPwUawkIFNX%YX?v;HfOFu9*v0&jHqpkR5otWzD+vtJ&$vvj{n!f%gSk zee$>aX8{E4I`FNuT8QYKonN^E*edYP(>gqW)-NnhQMpfmPtaQbv0Ohtc?IUJZ3I5d zY5>hGOwLaO2J_+@w7z-R`oD{d%PX+n-#(NhKoRmWzKKj=&Fr5mB8QjJJNYtXlYoCw~+D7=X_$2Pyd zd3p2d=IfhpZN9(x$IU-)-rKTm)odlVp4nO}KPZ<$14jNzlDNF#7v*2bZ^<|1H{|Q` zqI^i+Cl}$$LiP;nnyGHV$4RIGfLl*wJx0nQ3x ziPU1L7DroR@iwDR;y!G}@g$Dt3Ps$Hvl-b>KCxPaTi7OvRuhp#U4PZ&v=B3~JMh0B z-2TW`gRNF_SG0*{yGVX2dFl9*@5~dIbB*NF^#4<0=z7f>b5;Laq#+J$7(- zCe);>DpoXVANaMbi3sf5^O$wuGiH)m%5x*BnekXY$IKJZTxtB(b||lom*%|f-j2O{ zOI=-E*)fdwM5F0i2YW-*Ncg4E(Nm{JM_&p@h|m!XG?`37L-2G?a!QS@t;dteG=E9$ zf!#%lh{1O;G=`9;+Fvc)fH=1x>*Fr#$C0ll_K##oN1wZ{&fVA1k>oVy4pT1ewYnrr zoiOrr5mc$q=`eS=+Lg3;Yyy6&0OSRvlr;hm7W=#`PW;^eKCkSL z&@Eugk7K_4V&2$~bcBbK?(2)7V!!d^B~B#DK4xkP85%PrvT8(46= z`Z^Q29fVxlK_2|h>Dc_$a0}6?a|M9(oK{ujMd=(){J2-l1eQP z4IOfYUGO_JG_;&bMRvn|%^Rz(d7T~n|yk_wiZf_`2Pf=}jA`%I|74I9=Q0n^B+U^C zmcv*wpy`SyE!rA8z{0Nw5?4N(DL^Qje9?Tg=qJ|&VSLc;wRz4egVSzzt0$jI4tt>t zCsTP9qxHe@QT;V_b$wmvx45l?<3!khStbUFyC+p0nnGUS)?J;--&gO(Tc+U(eYNt=nZ zVW}8DfSa-87mHvxDfXH>wm!FxK4MX|Lg{;mfyKTZ4fx zRo3rRA)s6-P45qWZ)>Ol6;U5Trm9@GvoL;*?0$>#HT&aMT#Q#==9R8}!oGZZM*j$h z&iqDs(q@p=CvC>x&gdKZ#+mooS@{s+{arK#J5m*6ez}nE#c^{ioy6%_AsxbLncZhQ zpCARuq{S}T&p+S#;kB9NNS26rwuHN&xO1tpi!-{j%3!cGpp1H4cy6#R9*xJ^TS~H6 zXYWiT2ED$ulCS*ne_QbG<||J(8`y#b&B;bf;1yiDw(EBYBdxSgn>c$&XkYo=qH1CA(`J zCVN*jH|ns}iGfttH^#GI?mGI2;!t~PQ%JkXri&w)VQ;TC@TM`Yk nxmRHJ85m}PSu}}Opg#-Pi|8t}BWwX!!x).map(escape_regex).join('|')})`,'g') : /^$/g; +} + export function format_time(time) { return `${time.getMonth()+1}-${pad2(time.getDate())} ${time.getHours()}:${pad2(time.getMinutes())}:${pad2(time.getSeconds())}`; } @@ -41,23 +49,19 @@ export function TitleLine(props) { export class HighlightedText extends PureComponent { render() { - let parts=split_text(this.props.text,[ - ['url',URL_RE], - ['pid',PID_RE], - ['nickname',NICKNAME_RE], - ]); function normalize_url(url) { return /^https?:\/\//.test(url) ? url : 'http://'+url; } return (
-                {parts.map((part,idx)=>{
+                {this.props.parts.map((part,idx)=>{
                     let [rule,p]=part;
                     return (
                         {
                             rule==='url' ? {p} :
                             rule==='pid' ? {e.preventDefault(); this.props.show_pid(p);}}>{p} :
                             rule==='nickname' ? {p} :
+                            rule==='search' ? {p} :
                             p
                         }
                     );
diff --git a/src/Flows.css b/src/Flows.css
index b758871..9986afe 100644
--- a/src/Flows.css
+++ b/src/Flows.css
@@ -169,4 +169,26 @@
     color: white;
     background-color: rgba(0,0,0,.6);
     pointer-events: none;
+}
+
+.flow-item-row-quote {
+    opacity: .8;
+    filter: brightness(90%);
+}
+
+.flow-item-quote>.box {
+    margin-left: 2.5em;
+    max-height: 15em;
+    overflow-y: hidden;
+}
+
+.quote-tip {
+    margin-top: .5em;
+    margin-bottom: -10em; /* so that it will not block reply bar */
+    float: left;
+    display: flex;
+    flex-direction: column;
+    width: 2.5em;
+    text-align: center;
+    color: white;
 }
\ No newline at end of file
diff --git a/src/Flows.js b/src/Flows.js
index b83df7a..d29fa6a 100644
--- a/src/Flows.js
+++ b/src/Flows.js
@@ -1,7 +1,8 @@
 import React, {Component, PureComponent} from 'react';
 import copy from 'copy-to-clipboard';
 import {ColorPicker} from './color_picker';
-import {format_time, Time, TitleLine, HighlightedText, ClickHandler} from './Common';
+import {split_text,NICKNAME_RE,PID_RE,URL_RE} from './text_splitter';
+import {format_time, build_highlight_re, Time, TitleLine, HighlightedText, ClickHandler} from './Common';
 import './Flows.css';
 import LazyLoad from 'react-lazyload';
 import {AudioWidget} from './AudioWidget';
@@ -62,6 +63,11 @@ class Reply extends PureComponent {
     }
 
     render() {
+        let parts=split_text(this.props.info.text,[
+            ['url',URL_RE],
+            ['pid',PID_RE],
+            ['nickname',NICKNAME_RE],
+        ]);
         return (
             
- +
); @@ -95,41 +101,54 @@ class FlowItem extends PureComponent { render() { let props=this.props; + let parts=props.parts||split_text(props.info.text,[ + ['url',URL_RE], + ['pid',PID_RE], + ['nickname',NICKNAME_RE], + ]); return ( -
- {parseInt(props.info.pid,10)>window.LATEST_POST_ID &&
} -
- {!!parseInt(props.info.likenum,10) && - - {props.info.likenum}  - - - } - {!!parseInt(props.info.reply,10) && - - {props.info.reply}  - - - } - #{props.info.pid} -   -
-
- - {props.info.type==='image' && -

- {props.img_clickable ? - : - - } -

+
+ {!!props.is_quote && +
+
+
提到
+
+ } +
+ {parseInt(props.info.pid,10)>window.LATEST_POST_ID &&
} +
+ {!!parseInt(props.info.likenum,10) && + + {props.info.likenum}  + + + } + {!!parseInt(props.info.reply,10) && + + {props.info.reply}  + + + } + #{props.info.pid} +   +
+
+ + {props.info.type==='image' && +

+ {props.img_clickable ? + : + + } +

+ } + {props.info.type==='audio' && } +
+ {!!(props.attention && props.info.variant.latest_reply) && +

最新回复

} - {props.info.type==='audio' && }
- {!!(props.attention && props.info.variant.latest_reply) && -

最新回复

- }
); } @@ -331,10 +350,9 @@ class FlowItemRow extends PureComponent { this.state={ replies: [], reply_status: 'done', - info: props.info, + info: Object.assign({},props.info,{variant: {}}), attention: false, }; - this.state.info.variant={}; this.color_picker=new ColorPicker(); this.show_pid=load_single_meta(this.props.show_sidebar,this.props.token); } @@ -385,12 +403,32 @@ class FlowItemRow extends PureComponent { } render() { - return ( -
{ + let hl_rules=[ + ['url',URL_RE], + ['pid',PID_RE], + ['nickname',NICKNAME_RE], + ]; + if(this.props.search_param) + hl_rules.push(['search',build_highlight_re(this.props.search_param,' ')]); + let parts=split_text(this.state.info.text,hl_rules); + + let quote_id=null; + if(!this.props.is_quote && localStorage['DISABLE_QUOTE']!=='on') + for(let [mode,content] of parts) + if(mode==='pid') + if(quote_id===null) + quote_id=parseInt(content); + else { + quote_id=null; + break; + } + + let res=( +
{ if(!CLICKABLE_TAGS[event.target.tagName.toLowerCase()]) this.show_sidebar(); }}> -
{this.state.reply_status==='loading' &&
加载中
} @@ -406,6 +444,78 @@ class FlowItemRow extends PureComponent {
); + + return quote_id ? ( +
+ {res} + +
+ ) : res; + } +} + +class FlowItemQuote extends PureComponent { + constructor(props) { + super(props); + this.state={ + loading_status: 'empty', + error_msg: null, + info: null, + }; + } + + componentDidMount() { + this.load(); + } + + load() { + this.setState({ + loading_status: 'loading', + },()=>{ + API.get_single(this.props.pid,this.props.token) + .then((json)=>{ + this.setState({ + loading_status: 'done', + info: json.data, + }); + }) + .catch((err)=>{ + if((''+err).indexOf('没有这条树洞')!==-1) + this.setState({ + loading_status: 'empty', + }); + else + this.setState({ + loading_status: 'error', + error_msg: ''+err, + }); + }); + }); + } + + render() { + if(this.state.loading_status==='empty') + return null; + else if(this.state.loading_status==='loading') + return ( +
+ + 提到了 #{this.props.pid} +
+ ); + else if(this.state.loading_status==='error') + return ( +
+

重新加载

+

{this.state.error_msg}

+
+ ); + else // 'done' + return ( + + ); } } @@ -425,7 +535,7 @@ function FlowChunk(props) {
} + deletion_detect={props.deletion_detect} search_param={props.search_param} />
))} @@ -562,8 +672,9 @@ export class Flow extends PureComponent { return (
{this.state.loading_status==='failed' &&