irc: persist per-target history to files; preload last lines on switch
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
80
main.lua
80
main.lua
@@ -17,6 +17,7 @@ local socket = require("socket")
|
||||
local socketutil = require("socketutil")
|
||||
local _ = require("gettext")
|
||||
local T = require("ffi/util").template
|
||||
local lfs = require("libs/libkoreader-lfs")
|
||||
|
||||
-- Chat view based on TextViewer for scrollable text & menu buttons
|
||||
local IrcChatView = TextViewer:extend{
|
||||
@@ -38,6 +39,10 @@ local IrcChatView = TextViewer:extend{
|
||||
_current_target = nil, -- active target ("*" for server console)
|
||||
_server_label = nil,
|
||||
_unread = nil, -- map target => count of unseen messages
|
||||
-- History persistence
|
||||
_history_dir = nil,
|
||||
_history_server_dir = nil,
|
||||
_history_preload_lines = 500,
|
||||
}
|
||||
|
||||
function IrcChatView:init()
|
||||
@@ -64,6 +69,8 @@ function IrcChatView:init()
|
||||
self._current_target = nil
|
||||
self._server_label = self._server and (self._server.name or (self._server.host .. ":" .. tostring(self._server.port or 6667))) or "IRC"
|
||||
self._unread = {}
|
||||
-- Init history before selecting initial buffer
|
||||
self:initHistory()
|
||||
-- default to server console target
|
||||
self:switchTarget("*")
|
||||
self:updateTitle()
|
||||
@@ -72,6 +79,75 @@ function IrcChatView:init()
|
||||
UIManager:nextTick(function() self:startConnection() end)
|
||||
end
|
||||
|
||||
-- History helpers
|
||||
function IrcChatView:sanitizePathPart(part)
|
||||
part = part or ""
|
||||
part = part:gsub("[^%w%._%-#@]+", "_")
|
||||
if part == "" then part = "_" end
|
||||
return part
|
||||
end
|
||||
|
||||
function IrcChatView:getServerId()
|
||||
local name = self._server and (self._server.name or "") or ""
|
||||
local host = self._server and (self._server.host or "") or ""
|
||||
local port = self._server and tostring(self._server.port or 6667) or "6667"
|
||||
local id = string.format("%s_%s_%s", name, host, port)
|
||||
return self:sanitizePathPart(id)
|
||||
end
|
||||
|
||||
function IrcChatView:initHistory()
|
||||
self._history_dir = DataStorage:getDataDir() .. "/irc_logs"
|
||||
lfs.mkdir(self._history_dir)
|
||||
self._history_server_dir = self._history_dir .. "/" .. self:getServerId()
|
||||
lfs.mkdir(self._history_server_dir)
|
||||
end
|
||||
|
||||
function IrcChatView:getLogPath(target)
|
||||
target = target or "*"
|
||||
local fname = target == "*" and "console" or self:sanitizePathPart(target)
|
||||
return string.format("%s/%s.log", self._history_server_dir, fname)
|
||||
end
|
||||
|
||||
function IrcChatView:writeHistory(target, line)
|
||||
local path = self:getLogPath(target)
|
||||
local f = io.open(path, "a")
|
||||
if f then
|
||||
f:write(line, "\n")
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
function IrcChatView:readLastLines(path, max_lines)
|
||||
local f = io.open(path, "r")
|
||||
if not f then return nil end
|
||||
local buf = {}
|
||||
local count = 0
|
||||
for l in f:lines() do
|
||||
table.insert(buf, l)
|
||||
count = count + 1
|
||||
if count > max_lines then
|
||||
table.remove(buf, 1)
|
||||
count = count - 1
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
if #buf == 0 then return nil end
|
||||
return table.concat(buf, "\n")
|
||||
end
|
||||
|
||||
function IrcChatView:preloadHistory(target)
|
||||
target = target or self._current_target or "*"
|
||||
if self._buffers[target] and #self._buffers[target] > 0 then return end
|
||||
local path = self:getLogPath(target)
|
||||
local content = self:readLastLines(path, self._history_preload_lines)
|
||||
if content and #content > 0 then
|
||||
self._buffers[target] = content
|
||||
if target == (self._current_target or "*") and self.scroll_text_w and self.scroll_text_w.text_widget then
|
||||
self.scroll_text_w.text_widget:setText(content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function IrcChatView:updateTitle()
|
||||
local tgt = self._current_target
|
||||
local new_title
|
||||
@@ -106,6 +182,8 @@ end
|
||||
function IrcChatView:switchTarget(target)
|
||||
if not target then return end
|
||||
self:ensureBuffer(target)
|
||||
-- Preload history (if any) when switching to a buffer
|
||||
self:preloadHistory(target)
|
||||
self._current_target = target
|
||||
self:updateTitle()
|
||||
if self.scroll_text_w and self.scroll_text_w.text_widget then
|
||||
@@ -124,6 +202,8 @@ function IrcChatView:appendLine(line, target)
|
||||
local buf = self._buffers[target]
|
||||
buf = (buf and #buf > 0) and (buf .. "\n" .. prefix .. line) or (prefix .. line)
|
||||
self._buffers[target] = buf
|
||||
-- Persist to history
|
||||
self:writeHistory(target, prefix .. line)
|
||||
if target == (self._current_target or "*") then
|
||||
if self.scroll_text_w and self.scroll_text_w.text_widget then
|
||||
self.scroll_text_w.text_widget:setText(buf)
|
||||
|
||||
Reference in New Issue
Block a user