weiter
This commit is contained in:
206
web/app.js
206
web/app.js
@@ -1,17 +1,35 @@
|
||||
const API_URL = 'https://fb.srv.medeba-media.de/api';
|
||||
|
||||
// Check if we should redirect to dashboard
|
||||
(function checkViewRouting() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const view = params.get('view');
|
||||
if (view === 'dashboard') {
|
||||
// Remove view parameter and keep other params
|
||||
params.delete('view');
|
||||
const remainingParams = params.toString();
|
||||
window.location.href = 'dashboard.html' + (remainingParams ? '?' + remainingParams : '');
|
||||
let initialViewParam = null;
|
||||
|
||||
// Normalize incoming routing parameters without leaving the index view
|
||||
(function normalizeViewRouting() {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const view = params.get('view');
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (view === 'dashboard') {
|
||||
initialViewParam = view;
|
||||
params.delete('view');
|
||||
const remaining = params.toString();
|
||||
const newUrl = `${window.location.pathname}${remaining ? `?${remaining}` : ''}${window.location.hash}`;
|
||||
window.history.replaceState({}, document.title, newUrl);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Konnte view-Parameter nicht verarbeiten:', error);
|
||||
}
|
||||
})();
|
||||
|
||||
let focusPostIdParam = null;
|
||||
let focusPostUrlParam = null;
|
||||
let focusNormalizedUrl = '';
|
||||
let focusHandled = false;
|
||||
let initialTabOverride = null;
|
||||
let focusTabAdjusted = null;
|
||||
|
||||
let currentProfile = 1;
|
||||
let currentTab = 'pending';
|
||||
let posts = [];
|
||||
@@ -89,6 +107,30 @@ const BOOKMARK_WINDOW_DAYS = 28;
|
||||
const DEFAULT_BOOKMARKS = [];
|
||||
const BOOKMARK_SUFFIXES = ['Gewinnspiel', 'gewinnen', 'verlosen'];
|
||||
|
||||
function initializeFocusParams() {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const postIdParam = params.get('postId');
|
||||
const postUrlParam = params.get('postUrl');
|
||||
|
||||
if (postIdParam && postIdParam.trim()) {
|
||||
focusPostIdParam = postIdParam.trim();
|
||||
initialTabOverride = initialTabOverride || 'all';
|
||||
}
|
||||
|
||||
if (postUrlParam && postUrlParam.trim()) {
|
||||
focusPostUrlParam = postUrlParam.trim();
|
||||
const normalized = normalizeFacebookPostUrl(focusPostUrlParam);
|
||||
focusNormalizedUrl = normalized || focusPostUrlParam;
|
||||
initialTabOverride = initialTabOverride || 'all';
|
||||
}
|
||||
focusHandled = false;
|
||||
focusTabAdjusted = null;
|
||||
} catch (error) {
|
||||
console.warn('Konnte Fokus-Parameter nicht verarbeiten:', error);
|
||||
}
|
||||
}
|
||||
|
||||
let autoRefreshTimer = null;
|
||||
let autoRefreshSettings = {
|
||||
enabled: true,
|
||||
@@ -882,18 +924,28 @@ function setTab(tab, { updateUrl = true } = {}) {
|
||||
}
|
||||
|
||||
function initializeTabFromUrl() {
|
||||
let tabResolved = false;
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const tabParam = params.get('tab');
|
||||
if (tabParam === 'all' || tabParam === 'pending' || tabParam === 'expired') {
|
||||
currentTab = tabParam;
|
||||
tabResolved = true;
|
||||
} else if (initialTabOverride) {
|
||||
currentTab = initialTabOverride;
|
||||
tabResolved = true;
|
||||
} else if (initialViewParam === 'dashboard') {
|
||||
currentTab = 'pending';
|
||||
tabResolved = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Konnte Tab-Parameter nicht auslesen:', error);
|
||||
}
|
||||
|
||||
updateTabButtons();
|
||||
updateTabInUrl();
|
||||
if (tabResolved) {
|
||||
updateTabInUrl();
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeDeadlineInput(value) {
|
||||
@@ -2225,6 +2277,100 @@ async function normalizeLoadedPostUrls() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
function doesPostMatchFocus(post) {
|
||||
if (!post) {
|
||||
return false;
|
||||
}
|
||||
if (focusPostIdParam && String(post.id) === focusPostIdParam) {
|
||||
return true;
|
||||
}
|
||||
if (focusNormalizedUrl && post.url) {
|
||||
const candidateNormalized = normalizeFacebookPostUrl(post.url) || post.url;
|
||||
return candidateNormalized === focusNormalizedUrl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function resolveFocusTargetInfo(items) {
|
||||
if (!Array.isArray(items) || (!focusPostIdParam && !focusNormalizedUrl)) {
|
||||
return { index: -1, post: null };
|
||||
}
|
||||
const index = items.findIndex(({ post }) => doesPostMatchFocus(post));
|
||||
return {
|
||||
index,
|
||||
post: index !== -1 && items[index] ? items[index].post : null
|
||||
};
|
||||
}
|
||||
|
||||
function clearFocusParamsFromUrl() {
|
||||
try {
|
||||
const url = new URL(window.location.href);
|
||||
let changed = false;
|
||||
if (url.searchParams.has('postId')) {
|
||||
url.searchParams.delete('postId');
|
||||
changed = true;
|
||||
}
|
||||
if (url.searchParams.has('postUrl')) {
|
||||
url.searchParams.delete('postUrl');
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
const newQuery = url.searchParams.toString();
|
||||
const newUrl = `${url.pathname}${newQuery ? `?${newQuery}` : ''}${url.hash}`;
|
||||
window.history.replaceState({}, document.title, newUrl);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Konnte Fokus-Parameter nicht aus URL entfernen:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function highlightPostCard(post) {
|
||||
if (!post || focusHandled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const card = document.getElementById(`post-${post.id}`);
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
card.classList.add('post-card--highlight');
|
||||
|
||||
const hadTabIndex = card.hasAttribute('tabindex');
|
||||
if (!hadTabIndex) {
|
||||
card.setAttribute('tabindex', '-1');
|
||||
card.dataset.fbTrackerTempTabindex = '1';
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
try {
|
||||
card.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
} catch (error) {
|
||||
console.warn('Konnte Karte nicht scrollen:', error);
|
||||
}
|
||||
try {
|
||||
card.focus({ preventScroll: true });
|
||||
} catch (error) {
|
||||
// ignore focus errors
|
||||
}
|
||||
});
|
||||
|
||||
window.setTimeout(() => {
|
||||
card.classList.remove('post-card--highlight');
|
||||
if (card.dataset.fbTrackerTempTabindex === '1') {
|
||||
card.removeAttribute('tabindex');
|
||||
delete card.dataset.fbTrackerTempTabindex;
|
||||
}
|
||||
}, 4000);
|
||||
|
||||
focusPostIdParam = null;
|
||||
focusPostUrlParam = null;
|
||||
focusNormalizedUrl = '';
|
||||
focusHandled = true;
|
||||
focusTabAdjusted = null;
|
||||
clearFocusParamsFromUrl();
|
||||
}
|
||||
|
||||
// Render posts
|
||||
function renderPosts() {
|
||||
hideLoading();
|
||||
@@ -2245,6 +2391,9 @@ function renderPosts() {
|
||||
}));
|
||||
|
||||
const sortedItems = [...postItems].sort(comparePostItems);
|
||||
const focusCandidateEntry = (!focusHandled && (focusPostIdParam || focusNormalizedUrl))
|
||||
? sortedItems.find((item) => doesPostMatchFocus(item.post))
|
||||
: null;
|
||||
|
||||
let filteredItems = sortedItems;
|
||||
|
||||
@@ -2275,6 +2424,38 @@ function renderPosts() {
|
||||
});
|
||||
}
|
||||
|
||||
if (!focusHandled && focusCandidateEntry && !searchActive) {
|
||||
const candidateVisibleInCurrentTab = filteredItems.some(({ post }) => doesPostMatchFocus(post));
|
||||
if (!candidateVisibleInCurrentTab) {
|
||||
let desiredTab = 'all';
|
||||
if (focusCandidateEntry.status.isExpired || focusCandidateEntry.status.isComplete) {
|
||||
desiredTab = 'expired';
|
||||
} else if (focusCandidateEntry.status.canCurrentProfileCheck && !focusCandidateEntry.status.isExpired && !focusCandidateEntry.status.isComplete) {
|
||||
desiredTab = 'pending';
|
||||
}
|
||||
|
||||
if (currentTab !== desiredTab && focusTabAdjusted !== desiredTab) {
|
||||
focusTabAdjusted = desiredTab;
|
||||
setTab(desiredTab);
|
||||
return;
|
||||
}
|
||||
|
||||
if (desiredTab !== 'all' && currentTab !== 'all' && focusTabAdjusted !== 'all') {
|
||||
focusTabAdjusted = 'all';
|
||||
setTab('all');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const focusTargetInfo = resolveFocusTargetInfo(filteredItems);
|
||||
if (focusTargetInfo.index !== -1) {
|
||||
const requiredVisible = focusTargetInfo.index + 1;
|
||||
if (requiredVisible > getVisibleCount(currentTab)) {
|
||||
setVisibleCount(currentTab, requiredVisible);
|
||||
}
|
||||
}
|
||||
|
||||
updateFilteredCount(currentTab, filteredItems.length);
|
||||
|
||||
const visibleCount = Math.min(filteredItems.length, getVisibleCount(currentTab));
|
||||
@@ -2346,6 +2527,10 @@ function renderPosts() {
|
||||
|
||||
observeLoadMoreElement(loadMoreContainer, currentTab);
|
||||
}
|
||||
|
||||
if (!focusHandled && focusTargetInfo.index !== -1 && focusTargetInfo.post) {
|
||||
requestAnimationFrame(() => highlightPostCard(focusTargetInfo.post));
|
||||
}
|
||||
}
|
||||
|
||||
function attachPostEventHandlers(post, status) {
|
||||
@@ -3306,6 +3491,7 @@ window.addEventListener('resize', () => {
|
||||
// Initialize
|
||||
initializeBookmarks();
|
||||
loadAutoRefreshSettings();
|
||||
initializeFocusParams();
|
||||
initializeTabFromUrl();
|
||||
loadSortMode();
|
||||
resetManualPostForm();
|
||||
|
||||
@@ -466,6 +466,31 @@ h1 {
|
||||
border-left: 4px solid #059669;
|
||||
}
|
||||
|
||||
.post-card--highlight {
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0, 0, 0, 0.1),
|
||||
0 0 0 4px rgba(102, 126, 234, 0.35);
|
||||
animation: post-card-highlight-pulse 1.4s ease-in-out 2;
|
||||
}
|
||||
|
||||
@keyframes post-card-highlight-pulse {
|
||||
0% {
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0, 0, 0, 0.1),
|
||||
0 0 0 0 rgba(102, 126, 234, 0.45);
|
||||
}
|
||||
50% {
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0, 0, 0, 0.1),
|
||||
0 0 0 8px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
100% {
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0, 0, 0, 0.1),
|
||||
0 0 0 0 rgba(102, 126, 234, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
.post-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user