minor changes
This commit is contained in:
117
web/app.js
117
web/app.js
@@ -242,6 +242,7 @@ const REFRESH_SETTINGS_KEY = 'trackerRefreshSettings';
|
||||
const SORT_SETTINGS_KEY = 'trackerSortSettings';
|
||||
const SORT_SETTINGS_LEGACY_KEY = 'trackerSortMode';
|
||||
const FACEBOOK_TRACKING_PARAMS = ['__cft__', '__tn__', '__eep__', 'mibextid', 'set', 'comment_id', 'hoisted_section_header_type'];
|
||||
const FACEBOOK_PROFILE_SEGMENT_BLOCKLIST = new Set(['reel', 'reels', 'watch', 'video.php', 'videos', 'photo.php', 'photos', 'story.php', 'permalink.php', 'share', 'posts']);
|
||||
const VALID_SORT_MODES = new Set(['created', 'deadline', 'smart', 'lastCheck', 'lastChange']);
|
||||
const DEFAULT_SORT_SETTINGS = { mode: 'created', direction: 'desc' };
|
||||
const BOOKMARKS_BASE_URL = 'https://www.facebook.com/search/top';
|
||||
@@ -444,6 +445,99 @@ function formatUrlForDisplay(url) {
|
||||
}
|
||||
}
|
||||
|
||||
function deriveFacebookProfileUrl(rawValue) {
|
||||
if (typeof rawValue !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const trimmed = rawValue.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = new URL(trimmed);
|
||||
} catch (error) {
|
||||
try {
|
||||
parsed = new URL(trimmed, window.location.origin);
|
||||
} catch (innerError) {
|
||||
try {
|
||||
parsed = new URL(trimmed, 'https://www.facebook.com');
|
||||
} catch (fallbackError) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hostname = parsed.hostname.toLowerCase();
|
||||
if (!hostname.endsWith('facebook.com')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const origin = `${parsed.protocol}//${parsed.hostname}`;
|
||||
const normalizedPath = parsed.pathname.replace(/\/+$/, '') || '/';
|
||||
const segments = normalizedPath.split('/').filter(Boolean);
|
||||
const firstSegment = segments[0] || '';
|
||||
const lowerFirst = firstSegment.toLowerCase();
|
||||
const idParam = parsed.searchParams.get('id');
|
||||
|
||||
if (lowerFirst === 'groups' && segments[1]) {
|
||||
return `${origin}/groups/${segments[1]}`;
|
||||
}
|
||||
|
||||
if (lowerFirst === 'profile.php' && idParam) {
|
||||
return `${origin}/profile.php?id=${encodeURIComponent(idParam)}`;
|
||||
}
|
||||
|
||||
if (idParam && (lowerFirst === 'story.php' || lowerFirst === 'permalink.php')) {
|
||||
return `${origin}/profile.php?id=${encodeURIComponent(idParam)}`;
|
||||
}
|
||||
|
||||
if (lowerFirst === 'people' && segments[1] && segments[2]) {
|
||||
return `${origin}/people/${segments[1]}/${segments[2]}`;
|
||||
}
|
||||
|
||||
if (firstSegment && !FACEBOOK_PROFILE_SEGMENT_BLOCKLIST.has(lowerFirst)) {
|
||||
return `${origin}/${firstSegment}`;
|
||||
}
|
||||
|
||||
if (idParam) {
|
||||
return `${origin}/profile.php?id=${encodeURIComponent(idParam)}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getProfileLinkForPost(post) {
|
||||
if (!post || typeof post !== 'object') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const candidates = [];
|
||||
|
||||
if (typeof post.url === 'string') {
|
||||
candidates.push(post.url);
|
||||
}
|
||||
|
||||
if (Array.isArray(post.alternate_urls)) {
|
||||
for (const alt of post.alternate_urls) {
|
||||
if (typeof alt === 'string') {
|
||||
candidates.push(alt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const profileUrl = deriveFacebookProfileUrl(candidate);
|
||||
if (profileUrl) {
|
||||
return profileUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function toTimestamp(value, fallback = null) {
|
||||
if (!value) {
|
||||
return fallback;
|
||||
@@ -3454,14 +3548,6 @@ function createPostCard(post, status, meta = {}) {
|
||||
const tabTotalCount = typeof meta.tabTotalCount === 'number' ? meta.tabTotalCount : posts.length;
|
||||
const searchActive = !!meta.searchActive;
|
||||
|
||||
const counterBadge = displayIndex !== null
|
||||
? `
|
||||
<div class="post-counter" aria-hidden="true">
|
||||
<span class="post-counter__value">${String(displayIndex).padStart(2, '0')}</span>
|
||||
</div>
|
||||
`
|
||||
: '';
|
||||
|
||||
const profileRowsHtml = status.profileStatuses.map((profileStatus) => {
|
||||
const classes = ['profile-line', `profile-line--${profileStatus.status}`];
|
||||
const isCurrentProfile = parseInt(profileStatus.profile_number, 10) === status.profileNumber;
|
||||
@@ -3555,6 +3641,10 @@ function createPostCard(post, status, meta = {}) {
|
||||
const creatorDisplay = creatorName || 'Unbekannt';
|
||||
|
||||
const titleText = (post.title && post.title.trim()) ? post.title.trim() : creatorDisplay;
|
||||
const profileLink = getProfileLinkForPost(post);
|
||||
const creatorContent = profileLink
|
||||
? `<a href="${escapeHtml(profileLink)}" target="_blank" rel="noopener noreferrer" class="post-creator__link">${escapeHtml(creatorDisplay)}</a>`
|
||||
: escapeHtml(creatorDisplay);
|
||||
|
||||
const deadlineText = formatDeadline(post.deadline_at);
|
||||
const hasDeadline = Boolean(post.deadline_at);
|
||||
@@ -3598,7 +3688,6 @@ function createPostCard(post, status, meta = {}) {
|
||||
return `
|
||||
<div class="post-card ${status.isComplete ? 'complete' : ''}" id="post-${post.id}">
|
||||
<div class="post-header">
|
||||
${counterBadge}
|
||||
<div class="post-title-with-checkbox">
|
||||
<div class="post-title">${escapeHtml(titleText)}</div>
|
||||
<label class="success-checkbox success-checkbox--header">
|
||||
@@ -3607,6 +3696,9 @@ function createPostCard(post, status, meta = {}) {
|
||||
</label>
|
||||
</div>
|
||||
<div class="post-header-right">
|
||||
<div class="post-status ${status.isComplete ? 'complete' : ''}">
|
||||
${status.checkedCount}/${status.targetCount} ${status.isComplete ? '✓' : ''}
|
||||
</div>
|
||||
<div class="post-target">
|
||||
<span>Benötigte Profile:</span>
|
||||
<select class="control-select post-target__select" data-post-id="${post.id}">
|
||||
@@ -3616,9 +3708,6 @@ function createPostCard(post, status, meta = {}) {
|
||||
`).join('')}
|
||||
</select>
|
||||
</div>
|
||||
<div class="post-status ${status.isComplete ? 'complete' : ''}">
|
||||
${status.checkedCount}/${status.targetCount} ${status.isComplete ? '✓' : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3640,9 +3729,8 @@ function createPostCard(post, status, meta = {}) {
|
||||
<div>Erstellt: ${escapeHtml(createdDate)}</div>
|
||||
<div>Letzte Änderung: ${escapeHtml(lastChangeDate)}</div>
|
||||
</div>
|
||||
<div class="post-creator">Erstellt von: ${escapeHtml(creatorDisplay)}</div>
|
||||
<div class="post-creator">Erstellt von: ${creatorContent}</div>
|
||||
</div>
|
||||
${directLinkHtml}
|
||||
|
||||
<div class="post-deadline-row" data-post-id="${post.id}">
|
||||
<span class="${deadlineClasses.join(' ')}" ${deadlineStyle}>Deadline: ${escapeHtml(deadlineText)}</span>
|
||||
@@ -3655,6 +3743,7 @@ function createPostCard(post, status, meta = {}) {
|
||||
</button>
|
||||
` : ''}
|
||||
</div>
|
||||
${directLinkHtml}
|
||||
|
||||
<div class="post-profiles">
|
||||
${profileRowsHtml}
|
||||
|
||||
Reference in New Issue
Block a user