formatting

This commit is contained in:
2022-03-30 22:27:10 +08:00
parent bc076bd336
commit 528daa84fb
25 changed files with 1480 additions and 1382 deletions

View File

@@ -1,75 +1,72 @@
export function get_json(res) {
if(!res.ok) {
return (
res.text().then((t) => {
console.log('error:', res);
t = t.length < 100 ? t : '';
throw Error(`${res.status} ${res.statusText} ${t}`);
})
);
if (!res.ok) {
return res.text().then((t) => {
console.log('error:', res);
t = t.length < 100 ? t : '';
throw Error(`${res.status} ${res.statusText} ${t}`);
});
}
return res.text().then((t) => {
try {
return JSON.parse(t);
} catch (e) {
console.error('json parse error');
console.trace(e);
console.log(t);
throw new SyntaxError('JSON Parse Error ' + t.substr(0, 50));
}
return (
res
.text()
.then((t)=>{
try {
return JSON.parse(t);
} catch(e) {
console.error('json parse error');
console.trace(e);
console.log(t);
throw new SyntaxError('JSON Parse Error '+t.substr(0,50));
}
})
);
});
}
export function listen_darkmode(override) { // override: true/false/undefined
function update_color_scheme() {
if(override===undefined ? window.matchMedia('(prefers-color-scheme: dark)').matches : override)
document.body.classList.add('root-dark-mode');
else
document.body.classList.remove('root-dark-mode');
}
export function listen_darkmode(override) {
// override: true/false/undefined
function update_color_scheme() {
if (
override === undefined
? window.matchMedia('(prefers-color-scheme: dark)').matches
: override
)
document.body.classList.add('root-dark-mode');
else document.body.classList.remove('root-dark-mode');
}
update_color_scheme();
window.matchMedia('(prefers-color-scheme: dark)').addListener(() => {
update_color_scheme();
window.matchMedia('(prefers-color-scheme: dark)').addListener(()=>{
update_color_scheme();
});
});
}
const NAMES = [
'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'
]
'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',
];
export function gen_name(name_id) {
if (name_id == 0)
return '洞主';
if (name_id == 0) return '洞主';
let r = name_id;
let name = '';
@@ -81,4 +78,3 @@ export function gen_name(name_id) {
return name.substr(1);
}

View File

@@ -1,37 +1,40 @@
:root {
--foreground-dark: hsl(0,0%,93%);
--foreground-dark: hsl(0, 0%, 93%);
}
body {
margin: 0;
padding: 0;
overflow-x: hidden;
text-size-adjust: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
text-size-adjust: 100%;
}
body, textarea, pre {
font-family: 'Segoe UI', '微软雅黑', 'Microsoft YaHei', sans-serif;
body,
textarea,
pre {
font-family: 'Segoe UI', '微软雅黑', 'Microsoft YaHei', sans-serif;
}
* {
box-sizing: border-box;
word-wrap: break-word;
-webkit-overflow-scrolling: touch;
box-sizing: border-box;
word-wrap: break-word;
-webkit-overflow-scrolling: touch;
}
p, pre {
margin: 0;
p,
pre {
margin: 0;
}
a {
text-decoration: none;
cursor: pointer;
text-decoration: none;
cursor: pointer;
}
pre {
white-space: pre-line;
white-space: pre-line;
}
code {
font-family: Consolas, Courier, monospace;
}
font-family: Consolas, Courier, monospace;
}

View File

@@ -1,312 +1,322 @@
.centered-line {
overflow: hidden;
text-align: center;
overflow: hidden;
text-align: center;
}
.centered-line::before,
.centered-line::after {
background-color: #000;
content: "";
display: inline-block;
height: 1px;
position: relative;
vertical-align: middle;
width: 50%;
background-color: #000;
content: '';
display: inline-block;
height: 1px;
position: relative;
vertical-align: middle;
width: 50%;
}
.root-dark-mode .centered-line {
color: var(--foreground-dark);
color: var(--foreground-dark);
}
.root-dark-mode .centered-line::before, .root-dark-mode .centered-line::after {
background-color: var(--foreground-dark);
.root-dark-mode .centered-line::before,
.root-dark-mode .centered-line::after {
background-color: var(--foreground-dark);
}
.centered-line::before {
right: 1em;
margin-left: -50%;
right: 1em;
margin-left: -50%;
}
.centered-line::after {
left: 1em;
margin-right: -50%;
left: 1em;
margin-right: -50%;
}
.title-line {
color: #fff;
margin-top: 1em;
color: #fff;
margin-top: 1em;
}
.title-line::before,
.title-line::after {
background-color: #fff;
box-shadow: 0 1px 1px #000;
background-color: #fff;
box-shadow: 0 1px 1px #000;
}
.root-dark-mode .title-line {
color: var(--foreground-dark);
color: var(--foreground-dark);
}
.root-dark-mode .title-line::before, .root-dark-mode .title-line::after {
background-color: var(--foreground-dark);
.root-dark-mode .title-line::before,
.root-dark-mode .title-line::after {
background-color: var(--foreground-dark);
}
.app-switcher {
display: flex;
height: 2em;
text-align: center;
margin: 0 .1em;
user-select: none;
display: flex;
height: 2em;
text-align: center;
margin: 0 0.1em;
user-select: none;
}
.app-switcher-desc {
margin: 0 .5em;
flex: 1 1 0;
opacity: .5;
height: 2em;
line-height: 2rem;
font-size: .8em;
margin: 0 0.5em;
flex: 1 1 0;
opacity: 0.5;
height: 2em;
line-height: 2rem;
font-size: 0.8em;
}
.root-dark-mode .app-switcher-desc {
color: var(--foreground-dark);
color: var(--foreground-dark);
}
@media screen and (max-width: 570px) {
.app-switcher-desc {
flex: 1 1 0;
display: none;
}
.app-switcher-item {
flex: 1 1 0 !important;
padding: 0 !important;
}
.app-switcher-dropdown-title {
padding-left: 0 !important;
padding-right: 0 !important;
text-align: center !important;
}
.app-switcher-dropdown-item {
margin-left: -2em !important;
margin-right: 0 !important;
}
.app-switcher-desc {
flex: 1 1 0;
display: none;
}
.app-switcher-item {
flex: 1 1 0 !important;
padding: 0 !important;
}
.app-switcher-dropdown-title {
padding-left: 0 !important;
padding-right: 0 !important;
text-align: center !important;
}
.app-switcher-dropdown-item {
margin-left: -2em !important;
margin-right: 0 !important;
}
}
.app-switcher a:hover { /* reset underline from /hole style */
border-bottom: unset;
margin-bottom: unset;
.app-switcher a:hover {
/* reset underline from /hole style */
border-bottom: unset;
margin-bottom: unset;
}
.app-switcher-desc a {
color: unset;
color: unset;
}
.app-switcher-left {
text-align: right;
text-align: right;
}
.app-switcher-right {
text-align: left;
text-align: left;
}
.app-switcher-item {
flex: 0 0 auto;
border-radius: 3px;
height: 1.6em;
line-height: 1.6em;
margin: .2em .1em;
padding: 0 .45em;
flex: 0 0 auto;
border-radius: 3px;
height: 1.6em;
line-height: 1.6em;
margin: 0.2em 0.1em;
padding: 0 0.45em;
}
a.app-switcher-item, .app-switcher-item a {
transition: unset; /* override ant design */
color: black;
a.app-switcher-item,
.app-switcher-item a {
transition: unset; /* override ant design */
color: black;
}
.app-switcher-item img {
width: 1.2rem;
height: 1.2rem;
position: relative;
top: .2rem;
vertical-align: unset; /* override ant design */
width: 1.2rem;
height: 1.2rem;
position: relative;
top: 0.2rem;
vertical-align: unset; /* override ant design */
}
.app-switcher-item span:not(:empty) {
margin-left: .2rem;
margin-left: 0.2rem;
}
.app-switcher-logo-hover {
margin-left: -1.2rem;
margin-left: -1.2rem;
}
.app-switcher-item:hover {
background-color: black;
color: white !important;
background-color: black;
color: white !important;
}
.app-switcher-item:hover a {
color: white !important;
color: white !important;
}
.app-switcher-item-current {
background-color: rgba(0,0,0,.4);
text-shadow: 0 0 5px rgba(0,0,0,.5);
color: white !important;
background-color: rgba(0, 0, 0, 0.4);
text-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
color: white !important;
}
.app-switcher-item-current a {
color: white !important;
color: white !important;
}
.root-dark-mode .app-switcher-item, .root-dark-mode .app-switcher-dropdown-title a {
color: var(--foreground-dark);
.root-dark-mode .app-switcher-item,
.root-dark-mode .app-switcher-dropdown-title a {
color: var(--foreground-dark);
}
.root-dark-mode .app-switcher-item:hover, .root-dark-mode .app-switcher-item-current, .root-dark-mode .app-switcher-dropdown-title:hover a {
background-color: #555;
color: var(--foreground-dark);
.root-dark-mode .app-switcher-item:hover,
.root-dark-mode .app-switcher-item-current,
.root-dark-mode .app-switcher-dropdown-title:hover a {
background-color: #555;
color: var(--foreground-dark);
}
.app-switcher-item:hover .app-switcher-logo-normal, .app-switcher-item-current .app-switcher-logo-normal {
opacity: 0;
.app-switcher-item:hover .app-switcher-logo-normal,
.app-switcher-item-current .app-switcher-logo-normal {
opacity: 0;
}
.app-switcher-item:not(.app-switcher-item-current):not(:hover) .app-switcher-logo-hover {
opacity: 0;
.app-switcher-item:not(.app-switcher-item-current):not(:hover)
.app-switcher-logo-hover {
opacity: 0;
}
.root-dark-mode .app-switcher-logo-normal {
opacity: 0 !important;
opacity: 0 !important;
}
.root-dark-mode .app-switcher-logo-hover {
opacity: 1 !important;
opacity: 1 !important;
}
.app-switcher-dropdown {
padding: 0;
text-align: left;
padding: 0;
text-align: left;
}
.app-switcher-dropdown:not(:hover) {
max-height: 1.6rem;
overflow: hidden;
max-height: 1.6rem;
overflow: hidden;
}
.app-switcher-dropdown-item {
background-color: hsla(0,0%,35%,.9);
padding: .125em .25em;
margin-left: -.75em;
margin-right: -.75em;
position: relative;
z-index: 10;
cursor: pointer;
background-color: hsla(0, 0%, 35%, 0.9);
padding: 0.125em 0.25em;
margin-left: -0.75em;
margin-right: -0.75em;
position: relative;
z-index: 10;
cursor: pointer;
}
.app-switcher-dropdown-item:hover {
background-color: rgba(0,0,0,.9);
background-color: rgba(0, 0, 0, 0.9);
}
.app-switcher-dropdown-item:nth-child(2) {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.app-switcher-dropdown-item:last-child {
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
.app-switcher-dropdown-title {
padding-bottom: .2em;
padding-left: .5em;
padding-right: .25em;
padding-bottom: 0.2em;
padding-left: 0.5em;
padding-right: 0.25em;
}
.app-switcher-dropdown-title a {
cursor: unset;
cursor: unset;
}
.thuhole-login-popup {
font-size: 1rem;
background-color: #f7f7f7;
color: black;
position: fixed;
left: 50%;
top: 50%;
width: 320px;
z-index: 114515;
transform: translateX(-50%) translateY(-50%);
border-radius: 5px;
font-size: 1rem;
background-color: #f7f7f7;
color: black;
position: fixed;
left: 50%;
top: 50%;
width: 320px;
z-index: 114515;
transform: translateX(-50%) translateY(-50%);
border-radius: 5px;
}
.thuhole-login-popup a {
color: #00c;
color: #00c;
}
.thuhole-login-popup p {
margin: 1.25em 0;
text-align: center;
margin: 1.25em 0;
text-align: center;
}
.thuhole-login-popup-info p {
margin: .25em 1em;
text-align: left;
margin: 0.25em 1em;
text-align: left;
}
.thuhole-login-popup-info ul {
margin: .75em 1em;
text-align: left;
font-size: 75%;
margin: 0.75em 1em;
text-align: left;
font-size: 75%;
}
/* override ant design */
.thuhole-login-popup input, .thuhole-login-popup button {
font-size: .85em;
vertical-align: middle;
.thuhole-login-popup input,
.thuhole-login-popup button {
font-size: 0.85em;
vertical-align: middle;
}
.thuhole-login-popup input:not([type="checkbox"]) {
width: 8rem;
border-radius: 5px;
border: 1px solid black;
outline: none;
margin: 0;
padding: 0 .5em;
line-height: 2em;
.thuhole-login-popup input:not([type='checkbox']) {
width: 8rem;
border-radius: 5px;
border: 1px solid black;
outline: none;
margin: 0;
padding: 0 0.5em;
line-height: 2em;
}
.thuhole-login-popup button {
min-width: 6rem;
color: black;
background-color: rgba(235,235,235,.5);
border-radius: 5px;
text-align: center;
border: 1px solid black;
line-height: 2em;
margin: 0 .5rem;
min-width: 6rem;
color: black;
background-color: rgba(235, 235, 235, 0.5);
border-radius: 5px;
text-align: center;
border: 1px solid black;
line-height: 2em;
margin: 0 0.5rem;
}
.thuhole-login-popup button:hover {
background-color: rgba(255,255,255,.7);
background-color: rgba(255, 255, 255, 0.7);
}
.thuhole-login-popup button:disabled {
background-color: rgba(128,128,128,.5);
background-color: rgba(128, 128, 128, 0.5);
}
.thuhole-login-type {
display: inline-block;
width: 6rem;
margin: 0 .5rem;
display: inline-block;
width: 6rem;
margin: 0 0.5rem;
}
.thuhole-login-popup-shadow {
opacity: .5;
background-color: black;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
z-index: 114514;
opacity: 0.5;
background-color: black;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
z-index: 114514;
}
.thuhole-login-popup label.perm-item {
font-size: .8em;
vertical-align: .1rem;
margin-left: .5rem;
font-size: 0.8em;
vertical-align: 0.1rem;
margin-left: 0.5rem;
}
.aux-margin {
width: calc(100% - 2 * 50px);
margin: 0 50px;
width: calc(100% - 2 * 50px);
margin: 0 50px;
}
@media screen and (max-width: 1300px) {
.aux-margin {
width: calc(100% - 2 * 10px);
margin: 0 10px;
}
.aux-margin {
width: calc(100% - 2 * 10px);
margin: 0 10px;
}
}
.title {
font-size: 1.5em;
height: 4rem;
padding-top: 1rem;
text-align: center;
font-size: 1.5em;
height: 4rem;
padding-top: 1rem;
text-align: center;
}
.time-str {
color: #999999;
color: #999999;
}
a.button {

View File

@@ -1,4 +1,4 @@
import React, {Component, PureComponent} from 'react';
import React, { Component, PureComponent } from 'react';
import ReactDOM from 'react-dom';
import TimeAgo from 'react-timeago';
@@ -8,57 +8,63 @@ import buildFormatter from 'react-timeago/lib/formatters/buildFormatter';
import './global.css';
import './widgets.css';
import {get_json, API_VERSION_PARAM} from './functions';
import { get_json, API_VERSION_PARAM } from './functions';
function pad2(x) {
return x<10 ? '0'+x : ''+x;
return x < 10 ? '0' + x : '' + x;
}
export function format_time(time) {
return `${time.getMonth()+1}-${pad2(time.getDate())} ${time.getHours()}:${pad2(time.getMinutes())}:${pad2(time.getSeconds())}`;
return `${time.getMonth() + 1}-${pad2(
time.getDate(),
)} ${time.getHours()}:${pad2(time.getMinutes())}:${pad2(time.getSeconds())}`;
}
const chinese_format=buildFormatter(chineseStrings);
const chinese_format = buildFormatter(chineseStrings);
export function Time(props) {
const time=new Date(props.stamp*1000);
return (
<span className={"time-str"}>
<TimeAgo date={time} formatter={chinese_format} title={time.toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
hour12: false,
})} />
&nbsp;
{!props.short ? format_time(time) : null}
</span>
);
const time = new Date(props.stamp * 1000);
return (
<span className={'time-str'}>
<TimeAgo
date={time}
formatter={chinese_format}
title={time.toLocaleString('zh-CN', {
timeZone: 'Asia/Shanghai',
hour12: false,
})}
/>
&nbsp;
{!props.short ? format_time(time) : null}
</span>
);
}
export function TitleLine(props) {
return (
<p className="centered-line title-line aux-margin">
<span className="black-outline">{props.text}</span>
</p>
)
return (
<p className="centered-line title-line aux-margin">
<span className="black-outline">{props.text}</span>
</p>
);
}
export function GlobalTitle(props) {
return (
<div className="aux-margin">
<div className="title">
<p className="centered-line">{props.text}</p>
</div>
</div>
);
return (
<div className="aux-margin">
<div className="title">
<p className="centered-line">{props.text}</p>
</div>
</div>
);
}
class LoginPopupSelf extends Component {
constructor(props) {
super(props);
this.state={
loading_status: 'idle',
}
constructor(props) {
super(props);
this.state = {
loading_status: 'idle',
};
this.input_token_ref = React.createRef();
}
this.input_token_ref=React.createRef();
};
setThuhole(e, tar, ref) {
console.log(tar);
e.preventDefault();
@@ -67,105 +73,111 @@ class LoginPopupSelf extends Component {
alert('T大树洞已经没有啦😭');
}
render() {
return (
<div>
<div className="thuhole-login-popup-shadow" />
<div className="thuhole-login-popup">
<p>
<b>通过第三方验证登陆新T树洞</b>
</p>
<p>
<a href="/_login?p=cs" target="_blank">
<span className="icon icon-login" />
&nbsp;闭社
</a>
</p>
<p>
<input ref={this.input_token_ref} placeholder="T大树洞Token" />
<br/>
<a href="/_login?p=thuhole" target="_blank"
onClick={(e) =>{this.setThuhole(e, e.target, this.input_token_ref)}}
>
<span className="icon icon-login" />
&nbsp;T大树洞
</a>
</p>
<p>
<small>前往Telegram群查询15分钟临时token</small>
<br/>
<a href="//t.me/THUChatBot" target="_blank"
>
<span className="icon icon-login" />
&nbsp;清华大水群
</a>
</p>
<p>
<button type="button" disabled
>
<span className="icon icon-login" />
&nbsp;未名bbs
</button>
</p>
<p>
<button type="button" disabled
>
<span className="icon icon-login" />
&nbsp;清华统一身份认证
</button>
</p>
<hr />
<p>
<button onClick={this.props.on_close}>
取消
</button>
</p>
<hr/ >
<div className="thuhole-login-popup-info">
<p>提醒:
</p>
<ul>
<li> 无论采用哪种方式注册你后台记录的用户名都是本质实名的除临时token因为闭社/T大树洞的管理员可以根据你的闭社id/树洞评论区代号查到邮箱但是这不影响新T树洞的安全性新T树洞的匿名性来自隔离用户名与发布的内容而非试图隔离用户名与真实身份</li>
<li> 由于T大树洞仍未提供授权接口使用T大树洞方式登陆需要用你的token在特定洞发布一段随机内容以确定身份这是否违反用户条例由T大树洞管理员决定需自行承担相关风险完成登陆后建议立即重置T大树洞token </li>
<li> 目前一个人可能有两个帐号</li>
</ul>
</div>
</div>
</div>
);
}
render() {
return (
<div>
<div className="thuhole-login-popup-shadow" />
<div className="thuhole-login-popup">
<p>
<b>通过第三方验证登陆新T树洞</b>
</p>
<p>
<a href="/_login?p=cs" target="_blank">
<span className="icon icon-login" />
&nbsp;闭社
</a>
</p>
<p>
<input ref={this.input_token_ref} placeholder="T大树洞Token" />
<br />
<a
href="/_login?p=thuhole"
target="_blank"
onClick={(e) => {
this.setThuhole(e, e.target, this.input_token_ref);
}}
>
<span className="icon icon-login" />
&nbsp;T大树洞
</a>
</p>
<p>
<small>前往Telegram群查询15分钟临时token</small>
<br />
<a href="//t.me/THUChatBot" target="_blank">
<span className="icon icon-login" />
&nbsp;清华大水群
</a>
</p>
<p>
<button type="button" disabled>
<span className="icon icon-login" />
&nbsp;未名bbs
</button>
</p>
<p>
<button type="button" disabled>
<span className="icon icon-login" />
&nbsp;清华统一身份认证
</button>
</p>
<hr />
<p>
<button onClick={this.props.on_close}>取消</button>
</p>
<hr />
<div className="thuhole-login-popup-info">
<p>提醒:</p>
<ul>
<li>
{' '}
无论采用哪种方式注册你后台记录的用户名都是本质实名的除临时token因为闭社/T大树洞的管理员可以根据你的闭社id/树洞评论区代号查到邮箱但是这不影响新T树洞的安全性新T树洞的匿名性来自隔离用户名与发布的内容而非试图隔离用户名与真实身份
</li>
<li>
{' '}
由于T大树洞仍未提供授权接口使用T大树洞方式登陆需要用你的token在特定洞发布一段随机内容以确定身份这是否违反用户条例由T大树洞管理员决定需自行承担相关风险完成登陆后建议立即重置T大树洞token{' '}
</li>
<li> 目前一个人可能有两个帐号</li>
</ul>
</div>
</div>
</div>
);
}
}
export class LoginPopup extends Component {
constructor(props) {
super(props);
this.state={
popup_show: false,
};
this.on_popup_bound=this.on_popup.bind(this);
this.on_close_bound=this.on_close.bind(this);
}
constructor(props) {
super(props);
this.state = {
popup_show: false,
};
this.on_popup_bound = this.on_popup.bind(this);
this.on_close_bound = this.on_close.bind(this);
}
on_popup() {
this.setState({
popup_show: true,
});
}
on_close() {
this.setState({
popup_show: false,
});
}
on_popup() {
this.setState({
popup_show: true,
});
}
on_close() {
this.setState({
popup_show: false,
});
}
render() {
return (
<>
{this.props.children(this.on_popup_bound)}
{this.state.popup_show &&
<LoginPopupSelf token_callback={this.props.token_callback} on_close={this.on_close_bound} />
}
</>
);
}
render() {
return (
<>
{this.props.children(this.on_popup_bound)}
{this.state.popup_show && (
<LoginPopupSelf
token_callback={this.props.token_callback}
on_close={this.on_close_bound}
/>
)}
</>
);
}
}