Fix account tab persistence and viewer fallback
This commit is contained in:
@@ -142,7 +142,7 @@ kubectl apply -f k8s/telegram-scraper.yaml
|
||||
Then open:
|
||||
|
||||
```text
|
||||
http://<server-ip>:8080
|
||||
http://<server-ip>:7887
|
||||
```
|
||||
|
||||
### Volumes (Docker)
|
||||
|
||||
+38
-7
@@ -10,6 +10,8 @@ const state = {
|
||||
authStates: {},
|
||||
};
|
||||
|
||||
const ACTIVE_ACCOUNT_STORAGE_KEY = "telegramScraper.activeAccount";
|
||||
|
||||
/* ── API helper ─────────────────────────────────────── */
|
||||
|
||||
async function api(path, options = {}) {
|
||||
@@ -78,6 +80,33 @@ function isAccountAuthorized(auth) {
|
||||
);
|
||||
}
|
||||
|
||||
function saveActiveAccount(accountId) {
|
||||
if (accountId) {
|
||||
localStorage.setItem(ACTIVE_ACCOUNT_STORAGE_KEY, accountId);
|
||||
}
|
||||
}
|
||||
|
||||
function loadSavedActiveAccount(accounts) {
|
||||
let savedId = localStorage.getItem(ACTIVE_ACCOUNT_STORAGE_KEY);
|
||||
if (!savedId) {
|
||||
savedId = localStorage.getItem("activeAccount");
|
||||
if (savedId) {
|
||||
localStorage.setItem(ACTIVE_ACCOUNT_STORAGE_KEY, savedId);
|
||||
localStorage.removeItem("activeAccount");
|
||||
}
|
||||
}
|
||||
if (savedId && accounts.some((account) => account.id === savedId)) {
|
||||
return savedId;
|
||||
}
|
||||
if (savedId) {
|
||||
localStorage.removeItem(ACTIVE_ACCOUNT_STORAGE_KEY);
|
||||
}
|
||||
if (state.activeAccount && accounts.some((account) => account.id === state.activeAccount)) {
|
||||
return state.activeAccount;
|
||||
}
|
||||
return accounts[0]?.id || null;
|
||||
}
|
||||
|
||||
/* ── Account tab management ─────────────────────────── */
|
||||
|
||||
function renderAccountTabs(accounts) {
|
||||
@@ -175,9 +204,8 @@ function renderAccountPanel(accountId) {
|
||||
}
|
||||
|
||||
function switchAccount(accountId) {
|
||||
if (state.activeAccount === accountId) return;
|
||||
state.activeAccount = accountId;
|
||||
localStorage.setItem("activeAccount", accountId);
|
||||
saveActiveAccount(accountId);
|
||||
|
||||
// Update tabs
|
||||
document.querySelectorAll(".account-tab").forEach((tab) => {
|
||||
@@ -490,9 +518,10 @@ async function loadAccounts() {
|
||||
accounts.forEach((acc) => renderAccountPanel(acc.id));
|
||||
|
||||
// Determine active account (persisted across reloads)
|
||||
const savedId = localStorage.getItem("activeAccount");
|
||||
const activeId = (savedId && accounts.some(a => a.id === savedId)) ? savedId : (state.activeAccount || accounts[0].id);
|
||||
switchAccount(activeId);
|
||||
const activeId = loadSavedActiveAccount(accounts);
|
||||
if (activeId) {
|
||||
switchAccount(activeId);
|
||||
}
|
||||
|
||||
// Update settings
|
||||
renderSettingsAccounts();
|
||||
@@ -524,11 +553,13 @@ function renderSettingsAccounts() {
|
||||
node.querySelector(".account-remove-btn").addEventListener("click", async () => {
|
||||
if (!confirmAction(`Remove account "${acc.label || acc.id}"? All its data will be deleted.`)) return;
|
||||
try {
|
||||
const removingActive = state.activeAccount === acc.id;
|
||||
await api(`/api/accounts/${acc.id}`, { method: "DELETE" });
|
||||
await loadAccounts();
|
||||
if (state.activeAccount === acc.id) {
|
||||
if (removingActive) {
|
||||
state.activeAccount = null;
|
||||
localStorage.removeItem(ACTIVE_ACCOUNT_STORAGE_KEY);
|
||||
}
|
||||
await loadAccounts();
|
||||
} catch (err) {
|
||||
alert(`Failed to remove account: ${err.message}`);
|
||||
}
|
||||
|
||||
+46
-9
@@ -87,6 +87,25 @@ function scrollToBottom() {
|
||||
setTimeout(go, 150);
|
||||
}
|
||||
|
||||
function makeScrollSentinel() {
|
||||
const sentinel = document.createElement("div");
|
||||
sentinel.id = "scroll-sentinel";
|
||||
sentinel.className = "scroll-sentinel";
|
||||
return sentinel;
|
||||
}
|
||||
|
||||
function resetMessageView(title = "Select a channel", subtitle = "Reading messages from the local SQLite database.") {
|
||||
const root = document.getElementById("messages-list");
|
||||
if (root) {
|
||||
root.innerHTML = "";
|
||||
root.appendChild(makeScrollSentinel());
|
||||
}
|
||||
document.getElementById("viewer-title").textContent = title;
|
||||
document.getElementById("viewer-subtitle").textContent = subtitle;
|
||||
viewerState.oldestMessageId = null;
|
||||
viewerState.newestMessageId = null;
|
||||
}
|
||||
|
||||
function renderChannelList() {
|
||||
const root = document.getElementById("viewer-channel-list");
|
||||
if (!root) return;
|
||||
@@ -179,6 +198,13 @@ async function switchViewerAccount(accountId) {
|
||||
renderChannelList();
|
||||
if (viewerState.channelId) {
|
||||
await loadChannel(viewerState.channelId);
|
||||
} else {
|
||||
resetMessageView(
|
||||
"No channels",
|
||||
viewerState.accountId
|
||||
? "This account has no tracked channels yet."
|
||||
: "No local legacy channels found."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,10 +216,10 @@ async function loadViewerAccount(params) {
|
||||
} catch {
|
||||
viewerState.accounts = [];
|
||||
}
|
||||
viewerState.accountId =
|
||||
requested ||
|
||||
viewerState.accounts[0]?.id ||
|
||||
null;
|
||||
const requestedExists = requested && viewerState.accounts.some((acc) => acc.id === requested);
|
||||
viewerState.accountId = requestedExists
|
||||
? requested
|
||||
: viewerState.accounts[0]?.id || null;
|
||||
|
||||
renderAccountSelector();
|
||||
|
||||
@@ -289,8 +315,9 @@ function makeDateSep(text) {
|
||||
|
||||
function renderMessages(payload, append = false) {
|
||||
const root = document.getElementById("messages-list");
|
||||
const sentinel = document.getElementById("scroll-sentinel");
|
||||
if (!root) return;
|
||||
let sentinel = document.getElementById("scroll-sentinel");
|
||||
if (!sentinel) sentinel = makeScrollSentinel();
|
||||
|
||||
const channel = payload.channel;
|
||||
document.getElementById("viewer-title").textContent =
|
||||
@@ -408,14 +435,24 @@ async function main() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
await loadViewerAccount(params);
|
||||
viewerState.channels = await api(channelsEndpoint());
|
||||
viewerState.channelId =
|
||||
params.get("channel") ||
|
||||
viewerState.channels[0]?.channel_id ||
|
||||
null;
|
||||
const requestedChannel = params.get("channel");
|
||||
const requestedChannelExists =
|
||||
requestedChannel &&
|
||||
viewerState.channels.some((channel) => channel.channel_id === requestedChannel);
|
||||
viewerState.channelId = requestedChannelExists
|
||||
? requestedChannel
|
||||
: viewerState.channels[0]?.channel_id || null;
|
||||
renderChannelList();
|
||||
|
||||
if (viewerState.channelId) {
|
||||
await loadChannel(viewerState.channelId);
|
||||
} else {
|
||||
resetMessageView(
|
||||
"No channels",
|
||||
viewerState.accountId
|
||||
? "This account has no tracked channels yet."
|
||||
: "No local legacy channels found."
|
||||
);
|
||||
}
|
||||
|
||||
setupInfiniteScroll();
|
||||
|
||||
Reference in New Issue
Block a user