feat(web)!: sign in before joining a space and drop the stranger option

Opening a space link while signed out shows the sign-in page first and keeps
the link in memory. The channel settings no longer offer the stranger switch,
and the client supports API contract major 8.
This commit is contained in:
justme committed 2026-10-16 06:46:15 +08:00
1 parent c858bd2a09
commit 8233369cd4
16 files changed
+27 -30

No files matched your search

@@ -16,7 +16,7 @@ interface Props {
export function ChannelSettingsSheet(props: Props) {
const { info, error, load } = useServerSettings();
if (!info || props.channel.ttlSeconds === undefined || props.channel.membersCanUpload === undefined || props.channel.maxDownloads === undefined || props.channel.joinPolicy === undefined || props.channel.allowGuests === undefined)
if (!info || props.channel.ttlSeconds === undefined || props.channel.membersCanUpload === undefined || props.channel.maxDownloads === undefined || props.channel.joinPolicy === undefined)
return <Sheet title="空间设置" onClose={props.onClose}><p role={error ? 'alert' : 'status'}>{error ?? '正在读取空间设置…'}</p>
{error ? <Button onClick={() => { void load().catch(() => {}); }}>重试</Button> : null}</Sheet>;
return <SettingsForm {...props} info={info} />;
@@ -29,7 +29,6 @@ function SettingsForm({ channel, onClose, onSave, info }: Props & { info: Server
const [ttlSeconds, setTtlSeconds] = useState(channel.ttlSeconds!);
const [fileMaxDownloads, setFileMaxDownloads] = useState(channel.maxDownloads!);
const [joinPolicy, setJoinPolicy] = useState<'open' | 'invite'>(channel.joinPolicy!);
const [allowGuests, setAllowGuests] = useState(channel.allowGuests!);
const [joinPassword, setJoinPassword] = useState('');
const [clearPassword, setClearPassword] = useState(false);
const [saving, setSaving] = useState(false);
@@ -42,7 +41,7 @@ function SettingsForm({ channel, onClose, onSave, info }: Props & { info: Server
setSaving(true);
setFailed(false);
try {
await onSave({ name: name.trim(), maxMembers, membersCanUpload, ttlSeconds, fileMaxDownloads, joinPolicy, allowGuests,
await onSave({ name: name.trim(), maxMembers, membersCanUpload, ttlSeconds, fileMaxDownloads, joinPolicy,
...(clearPassword ? { joinPassword: '' } : joinPassword ? { joinPassword } : {}) });
onClose();
} catch {
@@ -87,10 +86,9 @@ function SettingsForm({ channel, onClose, onSave, info }: Props & { info: Server
<label className={styles.field}><span>加入方式</span>
<select value={joinPolicy} disabled={!owner} onChange={(event) => setJoinPolicy(event.target.value as 'open' | 'invite')}>
<option value="open">持链接加入</option><option value="invite">仅受邀账号加入</option>
<option value="open">登录后持链接加入</option><option value="invite">仅受邀账号加入</option>
</select>
</label>
<label className={styles.check}><input type="checkbox" checked={allowGuests} disabled={!owner || joinPolicy === 'invite'} onChange={(event) => setAllowGuests(event.target.checked)} /><span>允许未登录的陌生人加入</span></label>
<label className={styles.field}><span>{channel.passwordRequired ? '更换空间加入密码' : '空间加入密码(可选)'}</span>
<input type="password" autoComplete="new-password" minLength={8} maxLength={256} value={joinPassword} disabled={!owner || clearPassword} placeholder="至少 8 个字符,留空不修改" onChange={(event) => setJoinPassword(event.target.value)} />
<span className={styles.note}>空间主及受邀用户无需加入密码。修改规则不移除已加入成员。</span>