v0.5.0 UI and new message rules
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jama-backend",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"description": "TeamChat backend server",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -182,6 +182,19 @@ function initDb() {
|
||||
console.log('[DB] Migration: added direct_peer2_id column');
|
||||
} catch (e) { /* column already exists */ }
|
||||
|
||||
// Migration: user-customised group display names (per-user, per-group)
|
||||
try {
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS user_group_names (
|
||||
user_id INTEGER NOT NULL,
|
||||
group_id INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
PRIMARY KEY (user_id, group_id)
|
||||
)
|
||||
`);
|
||||
console.log('[DB] Migration: user_group_names table ready');
|
||||
} catch (e) { console.error('[DB] user_group_names migration error:', e.message); }
|
||||
|
||||
console.log('[DB] Schema initialized');
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -91,11 +91,17 @@ router.get('/', authMiddleware, (req, res) => {
|
||||
if (otherUserId) {
|
||||
const other = db.prepare('SELECT display_name, name FROM users WHERE id = ?').get(otherUserId);
|
||||
if (other) {
|
||||
g.peer_real_name = other.name; // always the real name for sidebar title
|
||||
g.name = other.display_name || other.name; // display name for chat header
|
||||
g.peer_real_name = other.name;
|
||||
g.name = other.display_name || other.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Apply user's custom group name if set
|
||||
const custom = db.prepare('SELECT name FROM user_group_names WHERE user_id = ? AND group_id = ?').get(userId, g.id);
|
||||
if (custom) {
|
||||
g.owner_name_original = g.name; // original name shown in brackets in GroupInfoModal
|
||||
g.name = custom.name;
|
||||
}
|
||||
return g;
|
||||
});
|
||||
|
||||
@@ -155,6 +161,31 @@ router.post('/', authMiddleware, (req, res) => {
|
||||
return res.json({ group });
|
||||
}
|
||||
|
||||
// For private groups: check if exact same set of members already exists in a group
|
||||
if ((type === 'private' || !type) && !isDirect && memberIds && memberIds.length > 0) {
|
||||
const allMemberIds = [...new Set([req.user.id, ...memberIds])].sort((a, b) => a - b);
|
||||
const count = allMemberIds.length;
|
||||
|
||||
// Find all private non-direct groups where the creator is a member
|
||||
const candidates = db.prepare(`
|
||||
SELECT g.id FROM groups g
|
||||
JOIN group_members gm ON gm.group_id = g.id AND gm.user_id = ?
|
||||
WHERE g.type = 'private' AND g.is_direct = 0
|
||||
`).all(req.user.id);
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const members = db.prepare(
|
||||
'SELECT user_id FROM group_members WHERE group_id = ? ORDER BY user_id'
|
||||
).all(candidate.id).map(r => r.user_id);
|
||||
if (members.length === count &&
|
||||
members.every((id, i) => id === allMemberIds[i])) {
|
||||
// Exact duplicate found — return the existing group
|
||||
const group = db.prepare('SELECT * FROM groups WHERE id = ?').get(candidate.id);
|
||||
return res.json({ group, duplicate: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = db.prepare(`
|
||||
INSERT INTO groups (name, type, owner_id, is_readonly, is_direct)
|
||||
VALUES (?, ?, ?, ?, 0)
|
||||
@@ -342,5 +373,28 @@ router.delete('/:id', authMiddleware, (req, res) => {
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
|
||||
// Set or update user's custom name for a group
|
||||
router.patch('/:id/custom-name', authMiddleware, (req, res) => {
|
||||
const db = getDb();
|
||||
const groupId = parseInt(req.params.id);
|
||||
const userId = req.user.id;
|
||||
const { name } = req.body;
|
||||
|
||||
if (!name || !name.trim()) {
|
||||
// Empty name = remove custom name (revert to owner name)
|
||||
db.prepare('DELETE FROM user_group_names WHERE user_id = ? AND group_id = ?').run(userId, groupId);
|
||||
return res.json({ success: true, name: null });
|
||||
}
|
||||
|
||||
db.prepare(`
|
||||
INSERT INTO user_group_names (user_id, group_id, name)
|
||||
VALUES (?, ?, ?)
|
||||
ON CONFLICT(user_id, group_id) DO UPDATE SET name = excluded.name
|
||||
`).run(userId, groupId, name.trim());
|
||||
|
||||
res.json({ success: true, name: name.trim() });
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user