chatgui: rlottie animated emoji with hover-to-animate, drag-to-select
- Add LottieIcon class (TGS gzip decompress + rlottie C API render) - Add AnimTimer singleton (33ms tick, activate/deactivate refcount) - Add EmojiButton (hover-triggered animation in emoji picker) - Add AnimatedEmoji support to EmojiData (5 TGS mappings) - MessageDelegate: QTextLayout-based animated emoji overlay (text + reactions) - ChatView: drag-to-select (click deselects, 5px drag starts selection) - ChatView: hoveredIndexChanged signal for hover-triggered animations - MessageList: wire AnimTimer tick to viewport update, hover → activate - CMake: AUTORCC, rlottie, zlib dependencies - Add 5 TGS animations as Qt resources
This commit is contained in:
1 parent
0e2b0e28d8
commit
62b3695a77
42 files changed
+286658
-73
No files matched your search
@@ -0,0 +1,116 @@
|
||||
#include "db_manager.h"
|
||||
#include "../src/debug_ui.h"
|
||||
|
||||
DbManager::DbManager(const QString& path, QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
int rc = sqlite3_open(path.toUtf8().constData(), &m_db);
|
||||
if (rc != SQLITE_OK) {
|
||||
GUI_ERROR("Cannot open database: %s", sqlite3_errmsg(m_db));
|
||||
sqlite3_close(m_db);
|
||||
m_db = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
sqlite3_exec(m_db, "PRAGMA journal_mode=WAL", nullptr, nullptr, nullptr);
|
||||
|
||||
initTables();
|
||||
|
||||
GUI_INFO("Database opened: %s", path.toUtf8().constData());
|
||||
}
|
||||
|
||||
DbManager::~DbManager() {
|
||||
if (m_db) {
|
||||
sqlite3_close(m_db);
|
||||
m_db = nullptr;
|
||||
GUI_INFO("Database closed");
|
||||
}
|
||||
}
|
||||
|
||||
void DbManager::initTables() {
|
||||
sqlite3_exec(m_db, "PRAGMA foreign_keys = ON", nullptr, nullptr, nullptr);
|
||||
|
||||
const char* sql =
|
||||
"CREATE TABLE IF NOT EXISTS local_identity ("
|
||||
" id INTEGER PRIMARY KEY CHECK (id = 1),"
|
||||
" node_id INTEGER NOT NULL UNIQUE,"
|
||||
" name TEXT NOT NULL,"
|
||||
" x25519_pubkey BLOB NOT NULL,"
|
||||
" ed25519_pubkey BLOB,"
|
||||
" created_at TEXT DEFAULT (datetime('now')),"
|
||||
" updated_at TEXT DEFAULT (datetime('now'))"
|
||||
");"
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS nodes ("
|
||||
" node_id INTEGER PRIMARY KEY,"
|
||||
" name TEXT,"
|
||||
" x25519_pubkey BLOB,"
|
||||
" ed25519_pubkey BLOB,"
|
||||
" hop_count INTEGER DEFAULT 0,"
|
||||
" is_online INTEGER DEFAULT 0,"
|
||||
" last_seen_ver INTEGER DEFAULT 0,"
|
||||
" connectivity_json TEXT,"
|
||||
" created_at TEXT DEFAULT (datetime('now')),"
|
||||
" updated_at TEXT DEFAULT (datetime('now'))"
|
||||
");"
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS node_addresses ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
" node_id INTEGER NOT NULL REFERENCES nodes(node_id) ON DELETE CASCADE,"
|
||||
" family INTEGER NOT NULL DEFAULT 4,"
|
||||
" ip BLOB NOT NULL,"
|
||||
" port INTEGER NOT NULL,"
|
||||
" addr_type INTEGER NOT NULL DEFAULT 0,"
|
||||
" socket_type INTEGER DEFAULT 0,"
|
||||
" priority INTEGER DEFAULT 0"
|
||||
");"
|
||||
"CREATE INDEX IF NOT EXISTS idx_node_addr_node ON node_addresses(node_id);"
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS node_subnets ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
" node_id INTEGER NOT NULL REFERENCES nodes(node_id) ON DELETE CASCADE,"
|
||||
" family INTEGER NOT NULL DEFAULT 4,"
|
||||
" network BLOB NOT NULL,"
|
||||
" prefix_length INTEGER NOT NULL"
|
||||
");"
|
||||
"CREATE INDEX IF NOT EXISTS idx_subnet_node ON node_subnets(node_id);"
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS channels ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
" channel_id TEXT NOT NULL UNIQUE,"
|
||||
" name TEXT NOT NULL,"
|
||||
" member_ids_json TEXT NOT NULL,"
|
||||
" is_dm INTEGER DEFAULT 0,"
|
||||
" last_message TEXT,"
|
||||
" last_msg_at TEXT,"
|
||||
" created_at TEXT DEFAULT (datetime('now'))"
|
||||
");"
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_cid ON channels(channel_id);"
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS messages ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||
" channel_id TEXT NOT NULL REFERENCES channels(channel_id) ON DELETE CASCADE,"
|
||||
" author_node_id INTEGER NOT NULL,"
|
||||
" content TEXT NOT NULL,"
|
||||
" content_type TEXT DEFAULT 'text/plain',"
|
||||
" timestamp INTEGER NOT NULL,"
|
||||
" local_seq INTEGER DEFAULT 0,"
|
||||
" signature BLOB,"
|
||||
" is_outgoing INTEGER DEFAULT 0,"
|
||||
" is_read INTEGER DEFAULT 0,"
|
||||
" created_at TEXT DEFAULT (datetime('now'))"
|
||||
");"
|
||||
"CREATE INDEX IF NOT EXISTS idx_msg_channel_time ON messages(channel_id, timestamp);"
|
||||
"CREATE INDEX IF NOT EXISTS idx_msg_author ON messages(author_node_id);"
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS idx_msg_dedup ON messages(channel_id, author_node_id, timestamp);";
|
||||
|
||||
char* errMsg = nullptr;
|
||||
int rc = sqlite3_exec(m_db, sql, nullptr, nullptr, &errMsg);
|
||||
if (rc != SQLITE_OK) {
|
||||
GUI_ERROR("Failed to create tables: %s", errMsg);
|
||||
sqlite3_free(errMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
GUI_INFO("Database tables initialized (6 tables, 6 indexes)");
|
||||
}
|
||||
Reference in new issue
Block a user