[0.9.1] Mobile: fixed topbar, global hive, per-message chat reply/switcher, forum subtopics, square module grid
- Topbar: single fixed line [logo][Personal][Community][avatar] in one dark tone (#121212) with gold accents only; the hive hexagons scroll below it. - Hive: Personal/Community filter the home hive from any page; opening a category shows its modules as a 2x2 grid of square buttons (a lone odd button is centered instead of left-aligned). - Chats: per-message reply (?replyTo=), chat switcher strip and quote banner; the message rate limit is lifted on mobile. - Forums: optional subtopics (?topic=) with threaded rendering. - Bottombar: fixed Inbox - PM - Write - Search - Graphos - Peers.
This commit is contained in:
parent
2b2c65fc7a
commit
ed9f01e8e6
8 changed files with 280 additions and 129 deletions
|
|
@ -3832,7 +3832,7 @@ router
|
|||
try { const oi = await forumModel.getOpenInvite(forumId).catch(() => null); if (oi && forumObj) forumObj.openInviteCode = oi.code; } catch (_) {}
|
||||
const forumMsgs = await forumModel.getMessagesByForumId(forumId);
|
||||
await warmAuthorNames(forumObj, forumMsgs);
|
||||
ctx.body = await singleForumView(forumObj, forumMsgs, ctx.query.filter, isReply ? ctx.params.forumId : null, { spreads: spreadInfo });
|
||||
ctx.body = await singleForumView(forumObj, forumMsgs, ctx.query.filter, ctx.query.topic || '');
|
||||
})
|
||||
.get('/welcome', async (ctx) => {
|
||||
const lang = ctx.cookies.get('language') || getConfig().language || 'en';
|
||||
|
|
@ -4601,7 +4601,7 @@ router
|
|||
.get("/chats/:chatId", async (ctx) => {
|
||||
if (!checkMod(ctx, 'chatsMod')) { ctx.redirect('/modules'); return; }
|
||||
await chatsModel.ingestKeys().catch(() => {});
|
||||
const { filter = 'all', q = '' } = ctx.query;
|
||||
const { filter = 'all', q = '', replyTo = '' } = ctx.query;
|
||||
const uid = getViewerId();
|
||||
let chat = await chatsModel.getChatById(ctx.params.chatId);
|
||||
if (!chat) { ctx.redirect('/chats'); return; }
|
||||
|
|
@ -4621,7 +4621,8 @@ router
|
|||
const fav = await mediaFavorites.getFavoriteSet('chats');
|
||||
const messages = await chatsModel.listMessages(chat.rootId || chat.key);
|
||||
const isTribeMember = !!parentTribe;
|
||||
ctx.body = await singleChatView({ ...chat, isFavorite: fav.has(String(chat.rootId || chat.key)), isTribeMember }, filter, messages, { q, returnTo: safeReturnTo(ctx, `/chats?filter=${encodeURIComponent(filter)}`, ['/chats']) });
|
||||
const chatListForSwitcher = process.env.OASIS_MOBILE === '1' ? await chatsModel.listAll({ viewerId: uid }).catch(() => []) : [];
|
||||
ctx.body = await singleChatView({ ...chat, isFavorite: fav.has(String(chat.rootId || chat.key)), isTribeMember }, filter, messages, { q, returnTo: safeReturnTo(ctx, `/chats?filter=${encodeURIComponent(filter)}`, ['/chats']), replyTo: typeof replyTo === 'string' ? replyTo : '', chatList: chatListForSwitcher });
|
||||
})
|
||||
.get("/pads", async (ctx) => {
|
||||
if (!checkMod(ctx, 'padsMod')) { ctx.redirect('/modules'); return; }
|
||||
|
|
@ -6116,8 +6117,9 @@ router
|
|||
.post('/forum/:id/message', koaBody(), async ctx => {
|
||||
const { message, parentId } = ctx.request.body;
|
||||
const cleanedMsg = stripDangerousTags(message);
|
||||
const subtopic = stripDangerousTags(String(ctx.request.body.subtopic || '').trim()).slice(0, 40);
|
||||
const mentions = await extractMentions(cleanedMsg);
|
||||
await forumModel.addMessageToForum(ctx.params.id, { text: cleanedMsg, author: getViewerId(), timestamp: new Date().toISOString(), mentions: mentions.length > 0 ? mentions : undefined }, parentId);
|
||||
await forumModel.addMessageToForum(ctx.params.id, { text: cleanedMsg, author: getViewerId(), timestamp: new Date().toISOString(), mentions: mentions.length > 0 ? mentions : undefined, subtopic: subtopic || undefined }, parentId);
|
||||
ctx.redirect(`/forum/${encodeURIComponent(ctx.params.id)}`);
|
||||
})
|
||||
.post('/forum/:forumId/vote', koaBody(), async ctx => {
|
||||
|
|
@ -7500,8 +7502,10 @@ router
|
|||
}
|
||||
const text = stripDangerousTags(String(ctx.request.body.text || '').trim());
|
||||
const imageBlob = ctx.request.files?.image ? extractBlobId(await handleBlobUpload(ctx, 'image')) : null;
|
||||
const replyToRaw = String(ctx.request.body.replyTo || '').trim();
|
||||
const replyTo = replyToRaw.startsWith('%') ? replyToRaw : null;
|
||||
if (!text && !imageBlob) { ctx.redirect(`/chats/${encodeURIComponent(ctx.params.chatId)}`); return; }
|
||||
await chatsModel.sendMessage(ctx.params.chatId, text, imageBlob);
|
||||
await chatsModel.sendMessage(ctx.params.chatId, text, imageBlob, replyTo);
|
||||
ctx.redirect(safeReturnTo(ctx, `/chats/${encodeURIComponent(ctx.params.chatId)}`, ['/chats']));
|
||||
})
|
||||
.post("/pads/create", koaBody(), async (ctx) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue