feat(social): supprime le code Social mort (jamais branché)
- suppression social-core/views/auth/privacy/css (0 référence dans src/, aucune page) - suppression branches isSocial() mortes dans components.js - nettoyage isFpTest() mort + footer-back CSS orphelin - simplification isTorBrowser() (suppression debug logs + conditions redondantes)
This commit is contained in:
parent
8e7ec41f18
commit
515393c040
8 changed files with 14 additions and 3401 deletions
|
|
@ -10,8 +10,6 @@
|
|||
function path() { return location.pathname; }
|
||||
function lang() { return /^\/en(\/|$)/.test(path()) ? 'en' : 'fr'; }
|
||||
function isHome() { var p = path(); return p === '/' || p === '/index.html' || p === '/en/' || p === '/en/index.html'; }
|
||||
function isFpTest() { return /\/fingerprint-test/.test(path()); }
|
||||
function isSocial() { return /\/social/.test(path()); }
|
||||
|
||||
function frLink() {
|
||||
var p = path();
|
||||
|
|
@ -39,16 +37,7 @@
|
|||
html += '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg>';
|
||||
html += '</label>';
|
||||
|
||||
if (isSocial()) {
|
||||
html += '<nav id="nav" class="site-nav" aria-label="Navigation">';
|
||||
html += '<div class="lang-switch" role="group" aria-label="Langue / Language">';
|
||||
html += '<button type="button" data-lang="fr" class="lang-btn' + (h === 'fr' ? ' active' : '') + '">' + (h === 'fr' ? '<strong>FR</strong>' : 'FR') + '</button>';
|
||||
html += '<button type="button" data-lang="en" class="lang-btn' + (h === 'en' ? ' active' : '') + '">' + (h === 'en' ? '<strong>EN</strong>' : 'EN') + '</button>';
|
||||
html += '</div>';
|
||||
html += THEME_BTN;
|
||||
html += '</nav>';
|
||||
} else {
|
||||
html += '<nav class="site-nav" aria-label="Navigation">';
|
||||
html += '<nav class="site-nav" aria-label="Navigation">';
|
||||
|
||||
html += '<a href="/blog" data-lang-path="/blog" data-i18n="nav.blog">Blog</a>';
|
||||
html += '<a href="/projets" data-lang-path="/projets" data-i18n="nav.projects">Projets</a>';
|
||||
|
|
@ -65,7 +54,6 @@
|
|||
html += '</div>';
|
||||
html += THEME_BTN;
|
||||
html += '</nav>';
|
||||
}
|
||||
|
||||
return '<header class="site-header">' + html + '</header>';
|
||||
}
|
||||
|
|
@ -79,10 +67,6 @@
|
|||
var privHref = h === 'fr' ? '/privacy-policy' : '/en/privacy-policy';
|
||||
|
||||
var html = '';
|
||||
if (isSocial()) {
|
||||
var backText = h === 'fr' ? 'Retour au site' : 'Back to site';
|
||||
html += '<p><a href="/" class="footer-back">' + backText + ' \u2190</a></p>';
|
||||
}
|
||||
html += '<p>Zektyc \u00b7 France</p>';
|
||||
html += '<p class="footer-note">' + note + '</p>';
|
||||
html += '<nav class="footer-nav" aria-label="Legal">';
|
||||
|
|
@ -116,69 +100,19 @@
|
|||
}
|
||||
|
||||
function isTorBrowser() {
|
||||
var dbg = {
|
||||
hostname: location.hostname,
|
||||
userAgent: navigator.userAgent,
|
||||
hasTorSensor: !!window.TorSensor,
|
||||
uaMatch: /TorBrowser|Tor\/|Tor Project/i.test(navigator.userAgent),
|
||||
timezoneOffset: new Date().getTimezoneOffset(),
|
||||
gmt: (new Date().getTimezoneOffset() === 0),
|
||||
screenW: window.screen && window.screen.width,
|
||||
screenH: window.screen && window.screen.height,
|
||||
innerW: window.innerWidth,
|
||||
innerH: window.innerHeight,
|
||||
letterboxed: !!(window.screen &&
|
||||
window.screen.width === window.innerWidth &&
|
||||
window.screen.height === window.innerHeight),
|
||||
pluginCount: (navigator.plugins && navigator.plugins.length) || 0,
|
||||
noPlugins: !navigator.plugins || navigator.plugins.length === 0,
|
||||
vendor: navigator.vendor
|
||||
};
|
||||
if (isOnion()) return true;
|
||||
if (window.TorSensor) return true;
|
||||
if (/TorBrowser|Tor\/|Tor Project/i.test(navigator.userAgent)) return true;
|
||||
|
||||
if (isOnion()) {
|
||||
dbg.result = 'onion:' + location.hostname;
|
||||
console.log('[TorToast] on .onion, skip', dbg);
|
||||
return true;
|
||||
}
|
||||
var gmt = new Date().getTimezoneOffset() === 0;
|
||||
var letterboxed = !!(window.screen &&
|
||||
window.screen.width === window.innerWidth &&
|
||||
window.screen.height === window.innerHeight);
|
||||
var noPlugins = !navigator.plugins || navigator.plugins.length === 0;
|
||||
var vendor = navigator.vendor;
|
||||
|
||||
if (dbg.hasTorSensor) {
|
||||
dbg.result = 'TorSensor';
|
||||
console.log('[TorToast] detected via TorSensor', dbg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dbg.uaMatch) {
|
||||
dbg.result = 'userAgent';
|
||||
console.log('[TorToast] detected via userAgent', dbg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dbg.gmt && dbg.letterboxed) {
|
||||
dbg.result = 'gmt+letterbox';
|
||||
console.log('[TorToast] detected via gmt+letterbox', dbg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dbg.gmt && dbg.letterboxed && dbg.noPlugins) {
|
||||
dbg.result = 'gmt+letterbox+noPlugins';
|
||||
console.log('[TorToast] detected via gmt+letterbox+noPlugins', dbg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dbg.vendor === '' && dbg.gmt && dbg.noPlugins) {
|
||||
dbg.result = 'vendorEmpty+gmt+noPlugins';
|
||||
console.log('[TorToast] detected via vendorEmpty+gmt+noPlugins', dbg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dbg.gmt && dbg.letterboxed && dbg.vendor === '') {
|
||||
dbg.result = 'gmt+letterbox+vendorEmpty';
|
||||
console.log('[TorToast] detected via gmt+letterbox+vendorEmpty', dbg);
|
||||
return true;
|
||||
}
|
||||
|
||||
dbg.result = 'NOT tor';
|
||||
console.log('[TorToast] not detected as Tor', dbg);
|
||||
if (gmt && letterboxed) return true;
|
||||
if (vendor === '' && gmt && noPlugins) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
// Zektyc Social — Auth views (moved to social-views.js)
|
||||
// This file is kept for backward compatibility but functions are now in social-views.js
|
||||
|
|
@ -1,554 +0,0 @@
|
|||
// Zektyc Social — Core v4 (CSP-safe)
|
||||
window.ZS = {
|
||||
user: null,
|
||||
view: "feed",
|
||||
viewData: null,
|
||||
lang: document.documentElement.lang === "en" ? "en" : "fr",
|
||||
_navOpen: false,
|
||||
_unreadNotifs: 0,
|
||||
_unreadMessages: 0,
|
||||
|
||||
icons: {
|
||||
home: '<svg viewBox="0 0 24 24"><path d="M3 9.5L12 3l9 6.5V20a1 1 0 01-1 1H4a1 1 0 01-1-1V9.5z"/><polyline points="9 21 9 12 15 12 15 21"/></svg>',
|
||||
users: '<svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>',
|
||||
mail: '<svg viewBox="0 0 24 24"><rect x="2" y="4" width="20" height="16" rx="2"/><polyline points="22 6 12 13 2 6"/></svg>',
|
||||
bell: '<svg viewBox="0 0 24 24"><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></svg>',
|
||||
user: '<svg viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
|
||||
shield: '<svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>',
|
||||
search: '<svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>',
|
||||
pen: '<svg viewBox="0 0 24 24"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>',
|
||||
heart: '<svg viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg>',
|
||||
heartFilled: '<svg viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z" fill="currentColor"/></svg>',
|
||||
comment: '<svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>',
|
||||
note: '<svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>',
|
||||
flag: '<svg viewBox="0 0 24 24"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg>',
|
||||
check: '<svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>',
|
||||
verifiedBlue: '<svg viewBox="0 0 24 24"><path d="M9 12l2 2 4-4" fill="none" stroke="#1d9bf0" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="12" r="10" fill="none" stroke="#1d9bf0" stroke-width="2"/></svg>',
|
||||
verifiedGold: '<svg viewBox="0 0 24 24"><path d="M9 12l2 2 4-4" fill="none" stroke="#f5a623" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="12" r="10" fill="none" stroke="#f5a623" stroke-width="2"/></svg>',
|
||||
close: '<svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>',
|
||||
arrowLeft: '<svg viewBox="0 0 24 24"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>',
|
||||
arrowRight: '<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>',
|
||||
star: '<svg viewBox="0 0 24 24"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>',
|
||||
lock: '<svg viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg>',
|
||||
globe: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></svg>',
|
||||
settings: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>',
|
||||
logout: '<svg viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>',
|
||||
menu: '<svg viewBox="0 0 24 24"><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="21" y2="18"/></svg>',
|
||||
plus: '<svg viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>',
|
||||
send: '<svg viewBox="0 0 24 24"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>',
|
||||
trash: '<svg viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>',
|
||||
reply: '<svg viewBox="0 0 24 24"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 00-4-4H4"/></svg>',
|
||||
user: '<svg viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
|
||||
},
|
||||
|
||||
_updateSEO: function(title, desc, url) {
|
||||
if (title) document.title = title;
|
||||
var md = document.querySelector('meta[name="description"]');
|
||||
if (md && desc) md.content = desc;
|
||||
var og = document.querySelector('meta[property="og:title"]');
|
||||
if (og && title) og.content = title;
|
||||
var ogd = document.querySelector('meta[property="og:description"]');
|
||||
if (ogd && desc) ogd.content = desc;
|
||||
var ogu = document.querySelector('meta[property="og:url"]');
|
||||
if (ogu && url) ogu.content = url;
|
||||
},
|
||||
|
||||
icon(name, cls) {
|
||||
var svg = this.icons[name] || '';
|
||||
if (cls) return '<span class="social-icon ' + cls + '">' + svg + '</span>';
|
||||
return '<span class="social-icon">' + svg + '</span>';
|
||||
},
|
||||
|
||||
// ── API ──
|
||||
async api(method, path, body) {
|
||||
var opts = { method: method, credentials: "same-origin" };
|
||||
if (body instanceof FormData) {
|
||||
opts.body = body;
|
||||
} else if (body) {
|
||||
opts.headers = { "Content-Type": "application/json" };
|
||||
opts.body = JSON.stringify(body);
|
||||
}
|
||||
try { var res = await fetch(path, opts); return res.json(); }
|
||||
catch (e) { return { error: "Erreur réseau" }; }
|
||||
},
|
||||
|
||||
esc(s) {
|
||||
if (!s) return "";
|
||||
var d = document.createElement("div");
|
||||
d.textContent = s;
|
||||
return d.innerHTML;
|
||||
},
|
||||
|
||||
navigate(view, data) {
|
||||
this.view = view;
|
||||
this.viewData = data || null;
|
||||
var basePath = location.pathname.replace(/\/(profile|post|chat|settings|notifications|community|mod|messages)\/?.*$/, "").replace(/\/$/, "");
|
||||
var newPath = basePath;
|
||||
if (view === "profile-view" && data) newPath += "/profile/" + encodeURIComponent(data);
|
||||
else if (view === "chat" && data) newPath += "/chat/" + encodeURIComponent(data);
|
||||
else if (view === "post" && data) newPath += "/post/" + encodeURIComponent(data);
|
||||
else if (view !== "feed") newPath += "/" + view;
|
||||
if (location.pathname !== newPath || location.hash) {
|
||||
history.pushState({ view: view, data: data }, "", newPath);
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
if (window._socialRender) window._socialRender();
|
||||
},
|
||||
|
||||
_parsePath() {
|
||||
var path = location.pathname;
|
||||
var profileMatch = path.match(/\/social\/profile\/([a-zA-Z0-9_]+)/);
|
||||
if (profileMatch) return { view: "profile-view", data: profileMatch[1] };
|
||||
var chatMatch = path.match(/\/social\/chat\/([a-zA-Z0-9_]+)/);
|
||||
if (chatMatch) return { view: "chat", data: chatMatch[1] };
|
||||
var postMatch = path.match(/\/social\/post\/(\d+)/);
|
||||
if (postMatch) return { view: "post", data: postMatch[1] };
|
||||
var viewMatch = path.match(/\/social\/(settings|notifications|community|mod|messages|login|signup)/);
|
||||
if (viewMatch) return { view: viewMatch[1], data: null };
|
||||
var hashView = location.hash.replace(/^#\/?/, "");
|
||||
if (hashView) {
|
||||
var parts = hashView.split("/");
|
||||
return { view: parts[0], data: parts[1] ? decodeURIComponent(parts[1]) : null };
|
||||
}
|
||||
return { view: "feed", data: null };
|
||||
},
|
||||
|
||||
t(fr, en) { return this.lang === "fr" ? fr : en; },
|
||||
|
||||
// ── Layout shell ──
|
||||
renderShell(sidebarLeft, mainContent, sidebarRight) {
|
||||
var header = document.getElementById("social-header");
|
||||
if (header) header.innerHTML = this._buildHeader();
|
||||
|
||||
var layout = document.getElementById("social-layout");
|
||||
if (!layout) return;
|
||||
|
||||
var left = sidebarLeft != null ? sidebarLeft : this._buildSidebarLeft();
|
||||
var right = sidebarRight != null ? sidebarRight : this._buildSidebarRight();
|
||||
|
||||
layout.innerHTML =
|
||||
'<aside class="social-sidebar-left">' + left + '</aside>' +
|
||||
'<section class="social-main" id="social-main">' + (typeof mainContent === "string" ? mainContent : "") + '</section>' +
|
||||
'<aside class="social-sidebar-right">' + right + '</aside>';
|
||||
|
||||
var navEl = document.getElementById("socialHeaderNav");
|
||||
if (navEl) navEl.innerHTML = this._buildNavLinks();
|
||||
|
||||
if (typeof _applyAvatarStyles === "function") _applyAvatarStyles();
|
||||
},
|
||||
|
||||
_buildHeader() {
|
||||
return '' +
|
||||
'<a href="#" class="social-logo" data-action="navFeed"><img src="/favicon.svg" alt="Zektyc" class="social-logo-img"> Zektyc Social</a>' +
|
||||
'<div class="social-header-search">' +
|
||||
'<span class="social-header-search-icon">' + this.icon("search") + '</span>' +
|
||||
'<input type="text" placeholder="' + (this.lang === "fr" ? "Rechercher" : "Search") + '" id="socialSearchInput" data-key="Enter" data-key-action="doSearch">' +
|
||||
'</div>' +
|
||||
'<nav class="social-header-nav" id="socialHeaderNav">' + this._buildNavLinks() + '</nav>' +
|
||||
(this.user
|
||||
? '<div class="social-header-user"><div class="social-header-avatar" data-action="navProfile">' + this.esc(this.user.username).charAt(0).toUpperCase() + '</div></div>'
|
||||
: '') +
|
||||
'<button class="social-mobile-toggle" data-action="toggleMobileNav">' + this.icon("menu") + '</button>';
|
||||
},
|
||||
|
||||
_buildNavLinks() {
|
||||
var L = this.lang;
|
||||
var v = this.view;
|
||||
var self = this;
|
||||
function link(view, iconName, label, badge) {
|
||||
var cls = v === view ? " nav-active" : "";
|
||||
return '<a href="#" data-action="nav" data-arg1="' + view + '" class="' + cls + '">' +
|
||||
self.icon(iconName) + '<span>' + label + '</span>' +
|
||||
(badge > 0 ? '<span class="nav-badge">' + badge + '</span>' : '') + '</a>';
|
||||
}
|
||||
|
||||
var html = "";
|
||||
if (this.user) {
|
||||
html = link("feed", "home", L ? "Accueil" : "Home", 0) +
|
||||
link("community", "users", L ? "Communauté" : "Community", 0) +
|
||||
link("messages", "mail", L ? "Messages" : "Messages", this._unreadMessages) +
|
||||
link("notifications", "bell", L ? "Alertes" : "Alerts", this._unreadNotifs) +
|
||||
link("profile", "user", L ? "Profil" : "Profile", 0);
|
||||
if (this.user.role === "admin" || this.user.role === "moderator") {
|
||||
html += link("mod", "shield", L ? "Modération" : "Mod", 0);
|
||||
}
|
||||
html += '<a href="#" data-action="logout" title="' + (L ? "Déconnexion" : "Logout") + '">' + this.icon("logout") + '</a>';
|
||||
} else {
|
||||
html = link("feed", "home", L ? "Accueil" : "Home", 0) +
|
||||
'<a href="#" data-action="nav" data-arg1="login" class="' + (v === "login" ? " nav-active" : "") + '">' +
|
||||
this.icon("arrowRight") + '<span>' + (L ? "Connexion" : "Login") + '</span></a>' +
|
||||
'<a href="#" data-action="nav" data-arg1="signup" class="' + (v === "signup" ? " nav-active" : "") + '">' +
|
||||
this.icon("star") + '<span>' + (L ? "Inscription" : "Sign up") + '</span></a>';
|
||||
}
|
||||
return html;
|
||||
},
|
||||
|
||||
_buildSidebarLeft() {
|
||||
var L = this.lang;
|
||||
var v = this.view;
|
||||
var self = this;
|
||||
var html = "";
|
||||
|
||||
if (this.user) {
|
||||
html += '<div class="sidebar-profile" data-action="navProfile">' +
|
||||
'<div class="sidebar-profile-avatar">' +
|
||||
(this.user.avatarUrl ? '<img src="' + this.esc(this.user.avatarUrl) + '" alt="' + this.esc(this.user.username) + '" loading="lazy">' : this.esc(this.user.username).charAt(0).toUpperCase()) +
|
||||
'</div>' +
|
||||
'<div><div class="sidebar-profile-name">' + this.esc(this.user.username) + '</div>' +
|
||||
'<div class="sidebar-profile-handle">@' + this.esc(this.user.username) + '</div></div></div>';
|
||||
}
|
||||
|
||||
function navLink(view, iconName, label, badge) {
|
||||
var cls = v === view ? " active" : "";
|
||||
return '<a href="#" class="sidebar-nav-link' + cls + '" data-action="nav" data-arg1="' + view + '">' +
|
||||
self.icon(iconName) +
|
||||
'<span class="sidebar-nav-label">' + label + '</span>' +
|
||||
(badge > 0 ? '<span class="sidebar-nav-badge">' + badge + '</span>' : '') + '</a>';
|
||||
}
|
||||
|
||||
if (this.user) {
|
||||
html += '<div class="mt-16">' +
|
||||
navLink("feed", "home", L ? "Fil d'actualité" : "Feed", 0) +
|
||||
navLink("community", "users", L ? "Communauté" : "Community", 0) +
|
||||
navLink("messages", "mail", L ? "Messages" : "Messages", this._unreadMessages) +
|
||||
navLink("notifications", "bell", L ? "Alertes" : "Alerts", this._unreadNotifs) +
|
||||
navLink("profile", "user", L ? "Mon profil" : "My profile", 0) +
|
||||
(this.user.role === "admin" || this.user.role === "moderator" ? navLink("mod", "shield", L ? "Modération" : "Moderation", 0) : '') +
|
||||
'</div>';
|
||||
} else {
|
||||
html += '<div class="mt-16">' +
|
||||
navLink("login", "arrowRight", L ? "Se connecter" : "Log in", 0) +
|
||||
navLink("signup", "star", L ? "S'inscrire" : "Sign up", 0) + '</div>';
|
||||
}
|
||||
|
||||
html += '<div class="sidebar-footer mt-24"><a href="/tos">CGU</a> · <a href="/privacy-policy">' + (L ? "Confidentialité" : "Privacy") + '</a><br>© 2025 Zektyc</div>';
|
||||
return html;
|
||||
},
|
||||
|
||||
_buildSidebarRight() {
|
||||
var L = this.lang;
|
||||
return '<div class="sidebar-widget"><h3>' + (L ? "À propos" : "About") + '</h3>' +
|
||||
'<p class="text-sm text-muted lh-15">' +
|
||||
(L ? "Réseau social respectueux de la vie privée. Pas d'algorithme, pas de pub, pas de tracking."
|
||||
: "Privacy-respecting social network. No algorithm, no ads, no tracking.") + '</p></div>';
|
||||
},
|
||||
|
||||
_renderMain(html) {
|
||||
var el = document.getElementById("social-main");
|
||||
if (el) el.innerHTML = html;
|
||||
},
|
||||
|
||||
toggleMobileNav() {
|
||||
var nav = document.getElementById("socialHeaderNav");
|
||||
if (!nav) return;
|
||||
this._navOpen = !this._navOpen;
|
||||
nav.classList.toggle("open", this._navOpen);
|
||||
},
|
||||
|
||||
doSearch() {
|
||||
var q = document.getElementById("socialSearchInput");
|
||||
if (!q || !q.value.trim()) return;
|
||||
this.navigate("community");
|
||||
setTimeout(function() {
|
||||
var si = document.getElementById("searchInput");
|
||||
if (si) { si.value = q.value; si.dispatchEvent(new KeyboardEvent("keydown", { key: "Enter" })); }
|
||||
}, 100);
|
||||
},
|
||||
|
||||
async logout() {
|
||||
await this.api("POST", "/api/social/auth/logout");
|
||||
this.user = null;
|
||||
this._unreadNotifs = 0;
|
||||
this._unreadMessages = 0;
|
||||
this.navigate("feed");
|
||||
},
|
||||
|
||||
async checkSession() {
|
||||
var data = await this.api("GET", "/api/social/auth/me");
|
||||
if (data.error) return false;
|
||||
this.user = data.user;
|
||||
this._unreadNotifs = data.unreadNotifs || 0;
|
||||
this._unreadMessages = data.unreadMessages || 0;
|
||||
return true;
|
||||
},
|
||||
|
||||
async refreshCounts() {
|
||||
if (!this.user) return;
|
||||
var data = await this.api("GET", "/api/social/auth/me");
|
||||
if (!data.error) {
|
||||
this._unreadNotifs = data.unreadNotifs || 0;
|
||||
this._unreadMessages = data.unreadMessages || 0;
|
||||
this._updateNavBadges();
|
||||
}
|
||||
},
|
||||
|
||||
_updateNavBadges() {
|
||||
var nav = document.getElementById("socialHeaderNav");
|
||||
if (nav) nav.innerHTML = this._buildNavLinks();
|
||||
var layout = document.getElementById("social-layout");
|
||||
if (layout) {
|
||||
var left = layout.querySelector(".social-sidebar-left");
|
||||
if (left) left.innerHTML = this._buildSidebarLeft();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════
|
||||
// EVENT DELEGATION (CSP-safe)
|
||||
// ═══════════════════════════════════════
|
||||
(function() {
|
||||
// Click delegation
|
||||
document.addEventListener("click", function(e) {
|
||||
var el = e.target.closest("[data-action]");
|
||||
if (!el) return;
|
||||
e.preventDefault();
|
||||
var action = el.getAttribute("data-action");
|
||||
var arg1 = el.getAttribute("data-arg1");
|
||||
var arg2 = el.getAttribute("data-arg2");
|
||||
|
||||
switch (action) {
|
||||
case "nav": ZS.navigate(arg1, arg2); break;
|
||||
case "navFeed": ZS.navigate("feed"); break;
|
||||
case "navProfile": ZS.navigate("profile"); break;
|
||||
case "toggleMobileNav": ZS.toggleMobileNav(); break;
|
||||
case "doSearch": ZS.doSearch(); break;
|
||||
case "logout": ZS.logout(); break;
|
||||
// Posts
|
||||
case "toggleLike": toggleLike(parseInt(arg1), el); break;
|
||||
case "toggleComments": toggleComments(parseInt(arg1)); break;
|
||||
case "toggleNotes": toggleNotes(parseInt(arg1)); break;
|
||||
case "reportItem": reportItem(arg1, parseInt(arg2)); break;
|
||||
case "postComment": postComment(parseInt(arg1)); break;
|
||||
case "deleteComment": deleteComment(parseInt(arg1), parseInt(arg2)); break;
|
||||
case "submitPost": submitPost(); break;
|
||||
case "submitFullPost": submitFullPost(); break;
|
||||
// Emoji
|
||||
case "toggleEmoji": _togglePicker("emojiPicker"); break;
|
||||
case "toggleEmojiFull": _togglePicker("fullEmojiPicker"); break;
|
||||
case "insertEmoji": _insertEmoji("composeText", arg1); break;
|
||||
case "insertEmojiFull": _insertEmoji("fullComposeText", arg1); break;
|
||||
// Auth
|
||||
case "selectPrivacy": selectPrivacy(arg1); break;
|
||||
case "confirmPrivacy": confirmPrivacy(); break;
|
||||
// Profile
|
||||
case "navigatePost": ZS.navigate("post"); break;
|
||||
case "navigateSettings": ZS.navigate("settings"); break;
|
||||
case "sendConnection": sendConnection(arg1); break;
|
||||
case "removeConnection": removeConnection(arg1); break;
|
||||
case "chatWith": ZS.navigate("chat", arg1); break;
|
||||
// Follow
|
||||
case "follow": followUser(parseInt(arg1)); break;
|
||||
case "unfollow": unfollowUser(parseInt(arg1)); break;
|
||||
// Dislike
|
||||
case "toggleDislike": toggleDislike(parseInt(arg1)); break;
|
||||
// Community
|
||||
case "searchUsers": searchUsers(); break;
|
||||
case "acceptConnection": acceptConnection(arg1); break;
|
||||
case "rejectConnection": rejectConnection(arg1); break;
|
||||
// Messages
|
||||
case "chatWithUser": ZS.navigate("chat", arg1); break;
|
||||
case "sendMsg": sendMsg(arg1); break;
|
||||
// Notifications
|
||||
case "markAllRead": markAllRead(); break;
|
||||
// Settings
|
||||
case "saveBio": saveBio(); break;
|
||||
case "saveDisplayName": saveDisplayName(); break;
|
||||
case "saveUsername": saveUsername(); break;
|
||||
case "savePassword": savePassword(); break;
|
||||
case "savePrivacy": savePrivacy(); break;
|
||||
case "deleteAccount": deleteAccount(); break;
|
||||
case "showSettingsTab": showSettingsTab(arg1, el); break;
|
||||
case "deleteAvatar": deleteAvatar(); break;
|
||||
// Verification
|
||||
case "proposeVerify": proposeVerify(arg1); break;
|
||||
case "acceptVerify": acceptVerify(parseInt(arg1)); break;
|
||||
case "rejectVerify": rejectVerify(parseInt(arg1)); break;
|
||||
// Mod
|
||||
case "modAction": modAction(arg1, parseInt(arg2), el.getAttribute("data-action-type")); break;
|
||||
case "modNoteAction": modNoteAction(parseInt(arg2), el.getAttribute("data-action-type")); break;
|
||||
case "resolveReport": resolveReport(parseInt(arg1)); break;
|
||||
case "switchModTab": switchModTab(arg1, el); break;
|
||||
// Mobile nav: close on link click
|
||||
default:
|
||||
if (el.closest("#socialHeaderNav a")) {
|
||||
var nav = document.getElementById("socialHeaderNav");
|
||||
if (nav) nav.classList.remove("open");
|
||||
ZS._navOpen = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function _togglePicker(id) {
|
||||
var picker = document.getElementById(id);
|
||||
if (picker) picker.classList.toggle("hidden");
|
||||
}
|
||||
|
||||
function _insertEmoji(textareaId, emoji) {
|
||||
var ta = document.getElementById(textareaId);
|
||||
if (!ta) return;
|
||||
var start = ta.selectionStart;
|
||||
var end = ta.selectionEnd;
|
||||
ta.value = ta.value.substring(0, start) + emoji + ta.value.substring(end);
|
||||
ta.selectionStart = ta.selectionEnd = start + emoji.length;
|
||||
ta.focus();
|
||||
var pickerId = textareaId === "fullComposeText" ? "fullEmojiPicker" : "emojiPicker";
|
||||
var picker = document.getElementById(pickerId);
|
||||
if (picker) picker.classList.add("hidden");
|
||||
}
|
||||
|
||||
// Keyboard delegation (Enter key for inputs)
|
||||
document.addEventListener("keydown", function(e) {
|
||||
if (e.key !== "Enter") return;
|
||||
var el = e.target.closest("[data-key-action]");
|
||||
if (!el) return;
|
||||
var action = el.getAttribute("data-key-action");
|
||||
var arg1 = el.getAttribute("data-arg1");
|
||||
|
||||
switch (action) {
|
||||
case "doSearch": ZS.doSearch(); break;
|
||||
case "searchUsers": searchUsers(); break;
|
||||
case "postComment": postComment(parseInt(arg1)); break;
|
||||
case "sendMsg": sendMsg(arg1); break;
|
||||
}
|
||||
});
|
||||
|
||||
// Form submit delegation
|
||||
document.addEventListener("submit", function(e) {
|
||||
e.preventDefault();
|
||||
var el = e.target.closest("[data-form]");
|
||||
if (!el) return;
|
||||
var form = el.getAttribute("data-form");
|
||||
|
||||
switch (form) {
|
||||
case "loginForm": _handleLogin(el); break;
|
||||
case "signupForm": _handleSignup(el); break;
|
||||
}
|
||||
});
|
||||
|
||||
// Input delegation (for character counters, strength bars)
|
||||
document.addEventListener("input", function(e) {
|
||||
var el = e.target;
|
||||
// Character counter
|
||||
if (el.id === "composeText") {
|
||||
var c = document.getElementById("composeCounter");
|
||||
if (c) c.textContent = el.value.length + "/5000";
|
||||
}
|
||||
if (el.id === "fullComposeText") {
|
||||
var c2 = document.getElementById("fullComposeCounter");
|
||||
if (c2) c2.textContent = el.value.length + "/5000";
|
||||
}
|
||||
// Password strength
|
||||
if (el.id === "suPass") {
|
||||
var v = el.value, s = 0;
|
||||
if (v.length >= 12) s++; if (v.length >= 16) s++;
|
||||
if (/[A-Z]/.test(v)) s++; if (/[a-z]/.test(v)) s++;
|
||||
if (/[0-9]/.test(v)) s++; if (/[^A-Za-z0-9]/.test(v)) s++;
|
||||
var fill = document.getElementById("strFill");
|
||||
var txt = document.getElementById("strText");
|
||||
if (fill && txt) {
|
||||
fill.style.width = Math.min((s / 6) * 100, 100) + "%";
|
||||
if (s <= 2) { fill.style.background = "#d32f2f"; txt.textContent = ZS.t("Faible", "Weak"); }
|
||||
else if (s <= 4) { fill.style.background = "#f57c00"; txt.textContent = ZS.t("Moyen", "Medium"); }
|
||||
else { fill.style.background = "#2e7d32"; txt.textContent = ZS.t("Fort", "Strong"); }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Avatar file input
|
||||
document.addEventListener("change", function(e) {
|
||||
var el = e.target;
|
||||
if (el.id === "avatarInput") uploadAvatar(el);
|
||||
});
|
||||
})();
|
||||
|
||||
// Avatar upload
|
||||
async function uploadAvatar(input) {
|
||||
var file = input.files && input.files[0];
|
||||
if (!file) return;
|
||||
var status = document.getElementById("avatarStatus");
|
||||
if (status) { status.classList.remove("hidden"); status.textContent = ZS.t("Envoi en cours...", "Uploading..."); status.className = "form-hint"; }
|
||||
|
||||
var fd = new FormData();
|
||||
fd.append("avatar", file);
|
||||
var data = await ZS.api("POST", "/api/social/user/avatar", fd);
|
||||
if (data.error) {
|
||||
if (status) { status.textContent = data.error; status.className = "form-hint text-error"; }
|
||||
return;
|
||||
}
|
||||
ZS.user.avatarUrl = data.avatar_url;
|
||||
var preview = document.getElementById("avatarPreview");
|
||||
if (preview) preview.innerHTML = _avatar(ZS.user.username, 80, ZS.user.avatarUrl);
|
||||
if (status) { status.textContent = ZS.t("Avatar mis à jour", "Avatar updated"); status.className = "form-hint text-success"; }
|
||||
}
|
||||
|
||||
async function deleteAvatar() {
|
||||
var data = await ZS.api("DELETE", "/api/social/user/avatar");
|
||||
if (data.error) return;
|
||||
ZS.user.avatarUrl = null;
|
||||
var preview = document.getElementById("avatarPreview");
|
||||
if (preview) preview.innerHTML = _avatar(ZS.user.username, 80, null);
|
||||
showSettingsTab("bio", document.querySelector(".tab-btn"));
|
||||
}
|
||||
|
||||
// Verification
|
||||
async function proposeVerify(userId) {
|
||||
if (!confirm(ZS.t("Envoyer une proposition de vérification ?", "Send a verification proposal?"))) return;
|
||||
var data = await ZS.api("POST", "/api/social/verification/propose/" + userId);
|
||||
if (data.error) { alert(data.error); return; }
|
||||
alert(data.message);
|
||||
}
|
||||
|
||||
async function acceptVerify(requestId) {
|
||||
var data = await ZS.api("POST", "/api/social/verification/accept/" + requestId);
|
||||
if (data.error) { alert(data.error); return; }
|
||||
ZS.user.verifiedLevel = 1;
|
||||
renderNotifications();
|
||||
}
|
||||
|
||||
async function rejectVerify(requestId) {
|
||||
var data = await ZS.api("POST", "/api/social/verification/reject/" + requestId);
|
||||
if (data.error) { alert(data.error); return; }
|
||||
renderNotifications();
|
||||
}
|
||||
|
||||
// Login handler
|
||||
async function _handleLogin(form) {
|
||||
var errEl = document.getElementById("loginError");
|
||||
if (errEl) errEl.style.display = "none";
|
||||
var btn = form.querySelector('button[type="submit"]');
|
||||
if (btn) btn.disabled = true;
|
||||
var data = await ZS.api("POST", "/api/social/auth/login", {
|
||||
login: form.querySelector('[name="login"]').value,
|
||||
password: form.querySelector('[name="password"]').value,
|
||||
});
|
||||
if (data.error) {
|
||||
if (errEl) { errEl.textContent = data.error; errEl.style.display = "block"; }
|
||||
if (btn) btn.disabled = false;
|
||||
return;
|
||||
}
|
||||
ZS.user = data.user;
|
||||
if (data.needsPrivacyChoice) ZS.navigate("privacy-choice");
|
||||
else ZS.navigate("feed");
|
||||
}
|
||||
|
||||
// Signup handler
|
||||
async function _handleSignup(form) {
|
||||
var errEl = document.getElementById("suError");
|
||||
if (errEl) errEl.style.display = "none";
|
||||
var btn = form.querySelector('button[type="submit"]');
|
||||
if (btn) btn.disabled = true;
|
||||
var data = await ZS.api("POST", "/api/social/auth/signup", {
|
||||
username: form.querySelector('[name="username"]').value,
|
||||
email: form.querySelector('[name="email"]').value || undefined,
|
||||
password: form.querySelector('[name="password"]').value,
|
||||
birthdate: form.querySelector('[name="birthdate"]').value,
|
||||
});
|
||||
if (data.error) {
|
||||
if (errEl) { errEl.textContent = data.error; errEl.style.display = "block"; }
|
||||
if (btn) btn.disabled = false;
|
||||
return;
|
||||
}
|
||||
ZS.user = data.user;
|
||||
if (data.needsPrivacyChoice) ZS.navigate("privacy-choice");
|
||||
else ZS.navigate("feed");
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
// Zektyc Social — Privacy views (moved to social-views.js)
|
||||
// This file is kept for backward compatibility but functions are now in social-views.js
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,98 +0,0 @@
|
|||
// Zektyc Social — Router v3 (CSP-safe)
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
window._socialRender = function() {
|
||||
switch (ZS.view) {
|
||||
case "login": renderLogin(); break;
|
||||
case "signup": renderSignup(); break;
|
||||
case "privacy-choice": renderPrivacyChoice(); break;
|
||||
case "profile": renderProfile(); break;
|
||||
case "profile-view": renderProfileView(ZS.viewData); break;
|
||||
case "settings": renderSettings(); break;
|
||||
case "post": _renderNewPost(); break;
|
||||
case "community": renderCommunity(); break;
|
||||
case "messages": renderMessages(); break;
|
||||
case "chat": renderChat(ZS.viewData); break;
|
||||
case "notifications": renderNotifications(); break;
|
||||
case "mod": renderMod(); break;
|
||||
default: renderFeed(); break;
|
||||
}
|
||||
var nav = document.getElementById("socialHeaderNav");
|
||||
if (nav) nav.classList.remove("open");
|
||||
ZS._navOpen = false;
|
||||
if (typeof _applyAvatarStyles === "function") _applyAvatarStyles();
|
||||
};
|
||||
|
||||
function _renderNewPost() {
|
||||
if (!ZS.user) { ZS.navigate("login"); return; }
|
||||
var avatarHtml = ZS.user.avatarUrl
|
||||
? '<div class="compose-avatar"><img src="' + ZS.esc(ZS.user.avatarUrl) + '" alt=""></div>'
|
||||
: '<div class="compose-avatar">' + ZS.esc(ZS.user.username).charAt(0).toUpperCase() + '</div>';
|
||||
var html = '<h2 class="mb-16">' + ZS.icon("pen") + ' ' + ZS.t("Nouvelle publication", "New post") + '</h2>' +
|
||||
'<div class="compose-box">' +
|
||||
'<div class="compose-row">' +
|
||||
avatarHtml +
|
||||
'<div class="compose-input-wrap">' +
|
||||
'<textarea id="fullComposeText" placeholder="' + ZS.t("Quoi de neuf ?", "What's new?") + '" rows="4" maxlength="5000" class="auto-resize"></textarea>' +
|
||||
'<div id="fullEmojiPicker" class="emoji-picker hidden">' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="😀">😀</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="😂">😂</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="❤️">❤️</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="🔥">🔥</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="👍">👍</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="👀">👀</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="💯">💯</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="🎉">🎉</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="🤔">🤔</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="😎">😎</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="🚀">🚀</span>' +
|
||||
'<span class="emoji-pick" data-action="insertEmojiFull" data-arg1="💡">💡</span>' +
|
||||
'</div>' +
|
||||
'</div></div>' +
|
||||
'<div class="compose-footer">' +
|
||||
'<div class="compose-meta">' +
|
||||
'<button type="button" class="compose-emoji-btn" data-action="toggleEmojiFull">' + ZS.icon("star") + '</button>' +
|
||||
'<span class="compose-counter" id="fullComposeCounter">0/5000</span>' +
|
||||
'<select class="compose-vis-select" id="fullComposeVis">' +
|
||||
'<option value="public">' + ZS.icon("globe") + ' ' + ZS.t("Public", "Public") + '</option>' +
|
||||
'<option value="connections_only">' + ZS.icon("users") + ' ' + ZS.t("Connexions", "Connections") + '</option>' +
|
||||
'<option value="private">' + ZS.icon("lock") + ' ' + ZS.t("Privé", "Private") + '</option>' +
|
||||
'</select></div>' +
|
||||
'<button class="btn-primary btn-primary-sm" data-action="submitFullPost">' + ZS.icon("send") + ' ' + ZS.t("Publier", "Post") + '</button>' +
|
||||
'</div></div>' +
|
||||
'<div class="info-box mt-12">' + ZS.icon("note") + ' ' + ZS.t("Vérifié par un modérateur avant publication.", "Reviewed by a moderator before publishing.") + '</div>' +
|
||||
'<p class="mt-12"><a href="#" class="text-sm" data-action="nav" data-arg1="feed">' + ZS.icon("arrowLeft") + ' ' + ZS.t("Retour au fil", "Back to feed") + '</a></p>';
|
||||
|
||||
ZS.renderShell(null, html, null);
|
||||
document.getElementById("fullComposeVis").value = ZS.user.privacyLevel || "connections_only";
|
||||
var ta = document.getElementById("fullComposeText");
|
||||
if (ta) ta.focus();
|
||||
}
|
||||
|
||||
window.submitFullPost = async function() {
|
||||
var textarea = document.getElementById("fullComposeText");
|
||||
if (!textarea || !textarea.value.trim()) return;
|
||||
var vis = document.getElementById("fullComposeVis").value;
|
||||
var data = await ZS.api("POST", "/api/social/posts", { content: textarea.value.trim(), visibility: vis });
|
||||
if (data.error) { alert(data.error); return; }
|
||||
ZS.navigate("feed");
|
||||
};
|
||||
|
||||
// Init
|
||||
window.addEventListener("popstate", function(e) {
|
||||
var parsed = e.state && e.state.view ? e.state : ZS._parsePath();
|
||||
ZS.view = parsed.view;
|
||||
ZS.viewData = parsed.data;
|
||||
if (window._socialRender) window._socialRender();
|
||||
});
|
||||
|
||||
ZS.checkSession().then(function() {
|
||||
var parsed = ZS._parsePath();
|
||||
if (parsed.view !== "feed" || parsed.data) {
|
||||
ZS.view = parsed.view;
|
||||
ZS.viewData = parsed.data;
|
||||
}
|
||||
ZS.navigate(ZS.view, ZS.viewData);
|
||||
});
|
||||
})();
|
||||
Loading…
Reference in a new issue