diff --git a/src/Flows.js b/src/Flows.js
index ce3deaef..2c5efeaa 100644
--- a/src/Flows.js
+++ b/src/Flows.js
@@ -48,7 +48,8 @@ function load_single_meta(show_sidebar,token) {
show_sidebar(
'帖子详情',
);
})
@@ -139,6 +140,7 @@ class FlowSidebar extends PureComponent {
info: props.info,
replies: props.replies,
loading_status: 'done',
+ error_msg: null,
};
this.color_picker=props.color_picker;
this.show_pid=load_single_meta(this.props.show_sidebar,this.props.token);
@@ -172,6 +174,7 @@ class FlowSidebar extends PureComponent {
load_replies(update_count=true) {
this.setState({
loading_status: 'loading',
+ error_msg: null,
});
API.load_replies(this.state.info.pid,this.props.token,this.color_picker)
.then((json)=>{
@@ -182,6 +185,7 @@ class FlowSidebar extends PureComponent {
}) : prev.info,
attention: !!json.attention,
loading_status: 'done',
+ error_msg: null,
}), ()=>{
this.syncState({
replies: this.state.replies,
@@ -195,6 +199,7 @@ class FlowSidebar extends PureComponent {
this.setState({
replies: [],
loading_status: 'done',
+ error_msg: ''+e,
});
});
}
@@ -240,8 +245,13 @@ class FlowSidebar extends PureComponent {
show_reply_bar(name,event) {
if(this.reply_ref.current && event.target.tagName.toLowerCase()!=='a') {
let text=this.reply_ref.current.get();
- if(/^\s*(Re (洞主|\b[A-Z][a-z]+){0,2}:)?\s*$/.test(text)) // text is nearly empty so we can replace it
- this.reply_ref.current.set('Re '+name+': ');
+ if(/^\s*(Re (洞主|\b[A-Z][a-z]+){0,2}:)?\s*$/.test(text)) {// text is nearly empty so we can replace it
+ let should_text='Re '+name+': ';
+ if(should_text===this.reply_ref.current.get())
+ this.reply_ref.current.set('');
+ else
+ this.reply_ref.current.set(should_text);
+ }
}
}
@@ -278,7 +288,13 @@ class FlowSidebar extends PureComponent {
set_variant={(variant)=>{this.set_variant(null,variant);}}
/>
- {(this.props.deletion_detect && parseInt(this.state.info.reply)>this.state.replies.length) &&
+ {!!this.state.error_msg &&
+
+
回复加载失败
+
{this.state.error_msg}
+
+ }
+ {(this.props.deletion_detect && parseInt(this.state.info.reply)>this.state.replies.length) && !!this.state.replies.length &&
{parseInt(this.state.info.reply)-this.state.replies.length} 条回复被删除
@@ -422,6 +438,7 @@ export class Flow extends PureComponent {
data: [],
},
loading_status: 'done',
+ error_msg: null,
};
this.on_scroll_bound=this.on_scroll.bind(this);
window.LATEST_POST_ID=parseInt(localStorage['_LATEST_POST_ID'],10)||0;
@@ -433,6 +450,7 @@ export class Flow extends PureComponent {
this.setState((prev,props)=>({
loaded_pages: prev.loaded_pages-1,
loading_status: 'failed',
+ error_msg: ''+err,
}));
};
@@ -508,6 +526,7 @@ export class Flow extends PureComponent {
this.setState((prev,props)=>({
loaded_pages: prev.loaded_pages+1,
loading_status: 'loading',
+ error_msg: null,
}));
}
}
@@ -540,7 +559,8 @@ export class Flow extends PureComponent {
/>
{this.state.loading_status==='failed' &&
}
{
let width=image.width;
let height=image.height;
+ let compressed=false;
if(width>MAX_IMG_PX) {
height=height*MAX_IMG_PX/width;
width=MAX_IMG_PX;
+ compressed=true;
}
if(height>MAX_IMG_PX) {
width=width*MAX_IMG_PX/height;
height=MAX_IMG_PX;
+ compressed=true;
}
let canvas=document.createElement('canvas');
@@ -354,23 +359,58 @@ export class PostForm extends Component {
canvas.height=height;
ctx.drawImage(image,0,0,width,height);
- for(let quality=.9;quality>0;quality-=0.1) {
- const url=canvas.toDataURL('image/jpeg',quality);
- console.log('quality',quality,'size',url.length);
- if(url.length<=MAX_IMG_FILESIZE) {
- console.log('chosen img quality',quality);
- return return_url(url);
- }
+ let quality_l=.1,quality_r=.9,quality,new_url;
+ while(quality_r-quality_l>=.06) {
+ quality=(quality_r+quality_l)/2;
+ new_url=canvas.toDataURL('image/jpeg',quality);
+ console.log(quality_l,quality_r,'trying quality',quality,'size',new_url.length);
+ if(new_url.length<=MAX_IMG_FILESIZE)
+ quality_l=quality;
+ else
+ quality_r=quality;
+ }
+ if(quality_l>=.101) {
+ console.log('chosen img quality',quality);
+ resolve({
+ img: return_url(new_url),
+ quality: quality,
+ width: Math.round(width),
+ height: Math.round(height),
+ compressed: compressed,
+ });
+ } else {
+ reject('图片过大,无法上传');
}
- // else
- alert('图片过大,无法上传');
- reject('img too large');
});
});
reader.readAsDataURL(file);
});
}
+ on_img_change() {
+ if(this.img_ref.current && this.img_ref.current.files.length)
+ this.setState({
+ img_tip: '(正在处理图片……)'
+ },()=>{
+ this.proc_img(this.img_ref.current.files[0])
+ .then((d)=>{
+ this.setState({
+ img_tip: `(${d.compressed?'压缩到':'尺寸'} ${d.width}*${d.height} / `+
+ `质量 ${Math.floor(d.quality*100)}% / ${Math.floor(d.img.length/1000)}KB)`,
+ });
+ })
+ .catch((e)=>{
+ this.setState({
+ img_tip: `图片无效:${e}`,
+ });
+ });
+ });
+ else
+ this.setState({
+ img_tip: null,
+ });
+ }
+
on_submit(event) {
if(event) event.preventDefault();
if(this.state.loading_status==='loading')
@@ -380,12 +420,15 @@ export class PostForm extends Component {
loading_status: 'processing',
});
this.proc_img(this.img_ref.current.files[0])
- .then((img)=>{
+ .then((d)=>{
this.setState({
loading_status: 'loading',
});
- this.do_post(this.state.text,img);
+ this.do_post(this.state.text,d.img);
})
+ .catch((e)=>{
+ alert(e);
+ });
} else {
this.setState({
loading_status: 'loading',
@@ -400,8 +443,9 @@ export class PostForm extends Component {
{this.state.loading_status!=='done' ?
}
+ {!!this.state.img_tip &&
+
+ {this.img_ref.current.value=""; this.on_img_change();}}>删除图片
+ {this.state.img_tip}
+
+ }
)
diff --git a/src/flows_api.js b/src/flows_api.js
index 36465272..b1f801c7 100644
--- a/src/flows_api.js
+++ b/src/flows_api.js
@@ -17,8 +17,10 @@ export const API={
)
.then((res)=>res.json())
.then((json)=>{
- if(json.code!==0)
- throw new Error(json);
+ if(json.code!==0) {
+ if(json.msg) throw new Error(json.msg);
+ else throw new Error(json);
+ }
json.data=json.data
.sort((a,b)=>{
@@ -121,8 +123,8 @@ export const API={
.then((res)=>res.json())
.then((json)=>{
if(json.code!==0) {
- if(json.msg) alert(json.msg);
- throw new Error(json);
+ if(json.msg) throw new Error(json.msg);
+ else throw new Error(json);
}
return json;
});
diff --git a/src/text_splitter.js b/src/text_splitter.js
index 4eb694d6..93e817a7 100644
--- a/src/text_splitter.js
+++ b/src/text_splitter.js
@@ -1,6 +1,6 @@
export const PID_RE=/(^|[^\d])([1-9]\d{4,5})(?!\d|\u20e3)/g;
export const NICKNAME_RE=/(^|[^A-Za-z])((?:(?:Angry|Baby|Crazy|Diligent|Excited|Fat|Greedy|Hungry|Interesting|Japanese|Kind|Little|Magic|Naïve|Old|Powerful|Quiet|Rich|Superman|THU|Undefined|Valuable|Wifeless|Xiangbuchulai|Young|Zombie)\s)?(?:Alice|Bob|Carol|Dave|Eve|Francis|Grace|Hans|Isabella|Jason|Kate|Louis|Margaret|Nathan|Olivia|Paul|Queen|Richard|Susan|Thomas|Uma|Vivian|Winnie|Xander|Yasmine|Zach)|You Win(?: \d+)?|洞主)(?![A-Za-z])/gi;
-export const URL_RE=/(?:^|\b)((?:https?:\/\/)?(?:[\w-]+\.)+[a-zA-Z]{2,3}(?::\d{1,5})?(?:\/[\w~!@#$%^&*()-_=+[\];,./?]*)?)(?:$|\b)/gi;
+export const URL_RE=/(?:^|\b)((?:https?:\/\/)?(?:[\w-]+\.)+[a-zA-Z]{2,3}(?::\d{1,5})?(?:\/[\w~!@#$%^&*()-_=+[\];,./?]*)?)/gi;
export function split_text(txt,rules) {
// rules: [['name',/regex/],...]