Browse Source

支持自定义头衔

pull/16/head
hole-thu 4 years ago
parent
commit
e78bf90799
  1. 5
      src/Flows.css
  2. 11
      src/Flows.js
  3. 14
      src/UserAction.css
  4. 148
      src/UserAction.js
  5. 18
      src/flows_api.js

5
src/Flows.css

@ -296,6 +296,11 @@
padding: .1em .5em;
}
.box-header-name.author-title {
color: white;
background-color: #333;
}
.root-dark-mode .box-header-cw {
background-color: #00a;
}

11
src/Flows.js

@ -129,6 +129,9 @@ class Reply extends PureComponent {
{(
<span className="box-header-name">{info.name}</span>
)}
{info.author_title && (
<span className="box-header-name author-title">{`"${info.author_title}"`}</span>
)}
{!!do_delete && !!info.can_del && (
<span
className="clickable"
@ -282,6 +285,10 @@ class FlowItem extends PureComponent {
#{info.pid}
</a>
</code>
&nbsp;
{info.author_title && (
<span className="box-header-name author-title">{`"${info.author_title}"`}</span>
)}
{!!do_delete && !!info.can_del && (
<span
className="clickable"
@ -1098,6 +1105,9 @@ class FlowItemRow extends PureComponent {
)}
<code className="box-id">#{this.props.info.pid}</code>
&nbsp;
{this.props.info.author_title && (
<span className="box-header-name author-title">{`"${this.props.info.author_title}"`}</span>
)}
{this.props.info.cw !== null && (
<span className="box-header-cw">{this.props.info.cw}</span>
)}
@ -1360,6 +1370,7 @@ class SubFlow extends PureComponent {
});
localStorage['_LATEST_POST_ID'] = '' + max_id;
}
window.TITLE = json.custom_title;
json.data.forEach((x) => {
if (x.comments) {
let comment_json = {

14
src/UserAction.css

@ -129,3 +129,17 @@
.post-form-poll-options h6 {
margin-bottom: 0;
}
.reply-form-opt-box {
display: flex;
flex-direction: column;
flex: 0 0 6rem;
}
.reply-form-opt-box > label {
margin-left: 5px;
}
.reply-form-buttons {
display: flex;
}

148
src/UserAction.js

@ -136,6 +136,27 @@ export function InfoSidebar(props) {
}
export class LoginForm extends Component {
constructor(props) {
super(props);
this.state = {
'custom_title': window.TITLE || ''
}
}
update_title(title, token) {
if (title === window.TITLE) {
alert('无变化');
return;
}
API.set_title(title, token)
.then((json) => {
if (json.code === 0) {
window.TITLE = title
alert('自定义头衔设置成功');
}
});
}
copy_token(token) {
if (copy(token)) alert('复制成功!\n请一定不要泄露哦');
}
@ -175,7 +196,7 @@ export class LoginForm extends Component {
查看系统日志
</a>
<br />
举报记录管理日志等都是公开的
举报记录管理日志等都是公开的
</p>
<p>
<a onClick={this.copy_token.bind(this, token.value)}>
@ -184,6 +205,22 @@ export class LoginForm extends Component {
<br />
User Token仅用于开发bot切勿告知他人若怀疑被盗号请刷新Token(刷新功能即将上线)
</p>
<p>
自定义头衔
<input
value={this.state.custom_title}
onChange={(e) => {
this.setState({ custom_title: e.target.value})
}}
maxLength={10}
/>
<button
type="button"
onClick={(e) => {this.update_title(this.state.custom_title, token.value)}}
>提交</button>
<br />
设置自定义头衔后可在发言时选择使用重置后需重新设置临时用户如需保持头衔请使用相同后缀
</p>
</div>
) : (
<LoginPopup token_callback={token.set_value}>
@ -220,8 +257,10 @@ export class ReplyForm extends Component {
text: '',
loading_status: 'done',
preview: false,
use_title: false,
};
this.on_change_bound = this.on_change.bind(this);
this.on_use_title_change_bound = this.on_use_title_change.bind(this);
this.area_ref = this.props.area_ref || React.createRef();
this.global_keypress_handler_bound = this.global_keypress_handler.bind(
this,
@ -258,6 +297,12 @@ export class ReplyForm extends Component {
});
}
on_use_title_change(event) {
this.setState({
use_title: event.target.checked,
});
}
on_submit(event) {
if (event) event.preventDefault();
if (this.state.loading_status === 'loading') return;
@ -266,10 +311,13 @@ export class ReplyForm extends Component {
loading_status: 'loading',
});
let data = new URLSearchParams();
let pid = this.props.pid;
data.append('pid', pid);
data.append('text', this.state.text);
const { pid } = this.props;
const { text, use_title } = this.state;
let data = new URLSearchParams({
pid: pid,
text: text,
use_title: use_title ? '1' : '',
});
fetch(
API_BASE + '/docomment',
{
@ -339,27 +387,41 @@ export class ReplyForm extends Component {
on_submit={this.on_submit.bind(this)}
/>
)}
<button
type="button"
onClick={() => {
this.toggle_preview();
}}
>
{this.state.preview ? (
<span className="icon icon-eye-blocked" />
) : (
<span className="icon icon-eye" />
<div className="reply-form-opt-box">
<div className="reply-form-buttons">
<button
type="button"
onClick={() => {
this.toggle_preview();
}}
>
{this.state.preview ? (
<span className="icon icon-eye-blocked" />
) : (
<span className="icon icon-eye" />
)}
</button>
{this.state.loading_status === 'loading' ? (
<button disabled="disabled">
<span className="icon icon-loading" />
</button>
) : (
<button type="submit">
<span className="icon icon-send" />
</button>
)}
</div>
{window.TITLE && (
<label>
<input
type="checkbox"
onChange={this.on_use_title_change_bound}
checked={this.state.use_title}
/>
{' '}使用头衔
</label>
)}
</button>
{this.state.loading_status === 'loading' ? (
<button disabled="disabled">
<span className="icon icon-loading" />
</button>
) : (
<button type="submit">
<span className="icon icon-send" />
</button>
)}
</div>
</form>
);
}
@ -377,11 +439,13 @@ export class PostForm extends Component {
preview: false,
has_poll: !!window.POLL_BACKUP,
poll_options: JSON.parse(window.POLL_BACKUP || '[""]'),
use_title: false,
};
this.img_ref = React.createRef();
this.area_ref = React.createRef();
this.on_change_bound = this.on_change.bind(this);
this.on_allow_search_change_bound = this.on_allow_search_change.bind(this);
this.on_use_title_change_bound = this.on_use_title_change.bind(this);
this.on_cw_change_bound = this.on_cw_change.bind(this);
this.on_poll_option_change_bound = this.on_poll_option_change.bind(this);
this.on_img_change_bound = this.on_img_change.bind(this);
@ -406,6 +470,12 @@ export class PostForm extends Component {
});
}
on_use_title_change(event) {
this.setState({
use_title: event.target.checked,
});
}
on_cw_change(event) {
this.setState({
cw: event.target.value,
@ -419,14 +489,14 @@ export class PostForm extends Component {
}
do_post() {
let data = new URLSearchParams();
const { cw, text, allow_search, has_poll, poll_options } = this.state;
data.append('cw', this.state.cw);
data.append('text', this.state.text);
data.append('allow_search', this.state.allow_search ? '1' : '');
//data.append('type', img ? 'image' : 'text');
//if (img) data.append('data', img);
data.append('type', 'text')
const { cw, text, allow_search, use_title, has_poll, poll_options } = this.state;
let data = new URLSearchParams({
cw: cw,
text: text,
allow_search: allow_search ? '1' : '',
use_title: use_title ? '1' : '',
type: 'text'
});
if (has_poll) {
poll_options.forEach((opt) => {
if (opt)
@ -676,8 +746,18 @@ export class PostForm extends Component {
onChange={this.on_allow_search_change_bound}
checked={this.state.allow_search}
/>
允许搜索
{' '}允许搜索
</label>
{window.TITLE && (
<label>
<input
type="checkbox"
onChange={this.on_use_title_change_bound}
checked={this.state.use_title}
/>
{' '}使用头衔
</label>
)}
</div>
{!!this.state.img_tip && (

18
src/flows_api.js

@ -251,4 +251,22 @@ export const API = {
);
return handle_response(response, true);
},
set_title: async (title, token) => {
console.log('title: ', title);
let data = new URLSearchParams([['title', title]]);
let response = await fetch(
API_BASE + '/title',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Token': token,
},
body: data,
},
);
return handle_response(response, true);
},
};

Loading…
Cancel
Save