aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/app.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/app.js80
1 files changed, 37 insertions, 43 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js
index eb11469..62bbfa5 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js
@@ -1005,7 +1005,6 @@ function ExplorePage({ token, myGroupIds }) {
function CreateGroupPage({ token, onCreated }) {
const [name, setName] = useState('');
const [description, setDescription] = useState('');
- const [visibility, setVisibility] = useState('private');
const [joinPolicy, setJoinPolicy] = useState('invite');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
@@ -1016,7 +1015,10 @@ function CreateGroupPage({ token, onCreated }) {
setLoading(true);
setError('');
try {
- const body = { name: name.trim(), visibility, join_policy: joinPolicy };
+ // Derived, not asked: "open" is what makes a group listed, and there is
+ // no third combination the server would accept.
+ const body = { name: name.trim(), join_policy: joinPolicy,
+ visibility: joinPolicy === 'open' ? 'public' : 'private' };
if (description.trim()) body.description = description.trim().slice(0, 512);
const data = await hubFetch('/v1/groups', {
method: 'POST', token, body,
@@ -1055,59 +1057,39 @@ function CreateGroupPage({ token, onCreated }) {
</div>
</div>
+ ${/* One question, not two. Visibility and admission were separate
+ selectors that could only ever be set together: a public group
+ admits everyone by definition, and a private one that anyone may
+ join is a directory listing nobody can find. The server already
+ refused public+invite with a 422 — the form could build a request
+ that could not succeed. Now the answer to "who can join" settles
+ both, and the descriptions say what each one means for who can
+ *find* the group, which is the part the visibility box was there
+ to state and no longer needs to. */ html`
<div class="settings-section">
- <h3 class="settings-heading">${t('create_group.visibility')}</h3>
+ <h3 class="settings-heading">${t('create_group.join_policy')}</h3>
<div class="choice-list">
- <label class="choice ${visibility === 'private' ? 'selected' : ''}">
- <input type="radio" name="visibility" checked=${visibility === 'private'}
- onChange=${() => { setVisibility('private'); setJoinPolicy('invite'); }} />
+ <label class="choice ${joinPolicy === 'invite' ? 'selected' : ''}">
+ <input type="radio" name="join_policy" checked=${joinPolicy === 'invite'}
+ onChange=${() => setJoinPolicy('invite')} />
<${Icon} name="lock" cls="choice-icon" />
<span class="choice-text">
- <span class="choice-title">${t('create_group.private')}</span>
- <span class="choice-desc">${t('create_group.private_desc')}</span>
+ <span class="choice-title">${t('create_group.invite')}</span>
+ <span class="choice-desc">${t('create_group.invite_desc')}</span>
</span>
</label>
- <label class="choice ${visibility === 'public' ? 'selected' : ''}">
- <input type="radio" name="visibility" checked=${visibility === 'public'}
- onChange=${() => { setVisibility('public'); setJoinPolicy('open'); }} />
+ <label class="choice ${joinPolicy === 'open' ? 'selected' : ''}">
+ <input type="radio" name="join_policy" checked=${joinPolicy === 'open'}
+ onChange=${() => setJoinPolicy('open')} />
<${Icon} name="globe" cls="choice-icon" />
<span class="choice-text">
- <span class="choice-title">${t('create_group.public')}</span>
- <span class="choice-desc">${t('create_group.public_desc')}</span>
+ <span class="choice-title">${t('create_group.open')}</span>
+ <span class="choice-desc">${t('create_group.open_desc')}</span>
</span>
</label>
</div>
-
- ${visibility === 'public'
- ? html`<p class="settings-hint" style="margin-top:12px">
- ${t('create_group.public_is_open')}
- </p>`
- : html`
- <h3 class="settings-heading" style="margin-top:20px">
- ${t('create_group.join_policy')}
- </h3>
- <div class="choice-list">
- <label class="choice ${joinPolicy === 'invite' ? 'selected' : ''}">
- <input type="radio" name="join_policy" checked=${joinPolicy === 'invite'}
- onChange=${() => setJoinPolicy('invite')} />
- <${Icon} name="envelope" cls="choice-icon" />
- <span class="choice-text">
- <span class="choice-title">${t('create_group.invite')}</span>
- <span class="choice-desc">${t('create_group.invite_desc')}</span>
- </span>
- </label>
- <label class="choice ${joinPolicy === 'open' ? 'selected' : ''}">
- <input type="radio" name="join_policy" checked=${joinPolicy === 'open'}
- onChange=${() => setJoinPolicy('open')} />
- <${Icon} name="door" cls="choice-icon" />
- <span class="choice-text">
- <span class="choice-title">${t('create_group.open')}</span>
- <span class="choice-desc">${t('create_group.open_desc')}</span>
- </span>
- </label>
- </div>
- `}
</div>
+ `}
<button class="btn-primary" type="submit" disabled=${loading}>
${loading ? t('create_group.creating') : t('create_group.submit')}
@@ -2875,6 +2857,18 @@ function ChatPanel({ transportRef, username, entries, gekRef, onRefreshIndex, on
// the result — the answer must be the same either way.
const top = el.getBoundingClientRect().top + window.scrollY;
el.style.height = `${Math.max(CHAT_MIN_HEIGHT, vh - top - CHAT_BOTTOM_GAP)}px`;
+ // What sits *below* the panel is not knowable from up here — today it is
+ // `.main`'s 24px bottom padding against this 16px gap, which left the
+ // document 8px taller than the window and a scrollbar on the chat tab at
+ // every window size. Rather than encode 24 somewhere and have the next
+ // change to the page break it again, the leftover is measured and taken
+ // off. Self-correcting: anything added under the panel is absorbed the
+ // same way.
+ const over = document.documentElement.scrollHeight - vh;
+ if (over > 0) {
+ el.style.height =
+ `${Math.max(CHAT_MIN_HEIGHT, el.getBoundingClientRect().height - over)}px`;
+ }
};
fit();
window.addEventListener('resize', fit);