diff --git a/index.html b/index.html
index cdde661..c465a8c 100644
--- a/index.html
+++ b/index.html
@@ -50,6 +50,91 @@
justify-content: center;
margin: 0;
}
+
+ .posts.mode-tinder,
+ .posts.mode-tiktok {
+ height: calc(100vh - 48px - var(--safe-bottom));
+ overflow: hidden;
+ position: relative;
+ max-width: 600px;
+ margin-bottom: 0 !important;
+ }
+
+ .posts.mode-tiktok {
+ overflow-y: scroll;
+ scroll-snap-type: y mandatory;
+ -ms-overflow-style: none;
+ /* IE and Edge */
+ scrollbar-width: none;
+ /* Firefox */
+ height: calc(100vh - 48px - var(--safe-bottom));
+ overflow-y: scroll;
+ scroll-snap-type: y mandatory;
+ }
+
+ .posts.mode-tiktok .post {
+ height: calc(100vh - 48px - var(--safe-bottom));
+ scroll-snap-align: start;
+ box-sizing: border-box;
+ justify-content: center;
+ }
+
+ .posts.mode-tiktok::-webkit-scrollbar {
+ display: none;
+ }
+
+ .posts.mode-tinder .post {
+ position: absolute;
+ box-sizing: border-box;
+ justify-content: center;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 100%;
+ width: 100%;
+ background: var(--bg);
+ z-index: 2;
+ transition: transform 0.3s ease, opacity 0.3s ease;
+ touch-action: none;
+ }
+
+ .swipe-right {
+ transform: translateX(200%) rotate(30deg);
+ opacity: 0;
+ }
+
+ .swipe-left {
+ transform: translateX(-200%) rotate(-30deg);
+ opacity: 0;
+ }
+
+ .swipe-indicator {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%) scale(0);
+ font-size: 80px;
+ z-index: 10;
+ pointer-events: none;
+ opacity: 0;
+ transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.2s;
+ }
+
+ .swipe-indicator.visible {
+ transform: translate(-50%, -50%) scale(1.2);
+ opacity: 1;
+ }
+
+ .indicator-heart {
+ color: #ff4b4b;
+ text-shadow: 0 0 20px rgba(255, 75, 75, 0.4);
+ }
+
+ .indicator-cross {
+ color: #8899a6;
+ text-shadow: 0 0 20px rgba(136, 153, 166, 0.4);
+ }
+
.posts {
max-width: 600px;
width: 100vw;
@@ -235,6 +320,7 @@
color: var(--theme);
}
.bottomNav {
+ z-index: 100;
display: flex;
justify-content: space-around;
position: fixed;
@@ -605,6 +691,13 @@
+ Display mode
+
+
+
+
+
+
@@ -687,7 +780,7 @@ A
const defaultCategories = ["nature", "science", "animals", "anthropology", "places", "sociology", "art", "mathematics", "games", "technology", "music", "human sexuality"];
let postsWithoutLike = 0;
- const HTML_VERSION = "1.1.4";
+ const HTML_VERSION = "1.1.5";
function loadSettings() {
const baseSettings = {
@@ -697,6 +790,7 @@ A
profile: "default",
profiles: ["default"],
theme: "theme-auto",
+ viewMode: "mode-classic"
};
const loadedSettings = JSON.parse(localStorage.getItem("xikipedia-settings") ?? '{}');
const computedSettings = Object.assign(baseSettings, loadedSettings);
@@ -710,7 +804,14 @@ A
settings.theme = document.querySelector('[name=theme]:checked')?.id ?? "theme-auto";
settings.storeData = document.getElementById("setting-storeData").checked;
settings.openMainWiki = document.getElementById("setting-openMainWiki").checked;
+ settings.viewMode = document.querySelector('[name=viewMode]:checked')?.id ?? "mode-classic";
localStorage.setItem("xikipedia-settings", JSON.stringify(settings));
+ applyViewMode();
+ }
+
+ function applyViewMode() {
+ const container = document.querySelector(".posts");
+ container.className = "posts " + settings.viewMode;
}
function resetAlgorithm() {
@@ -1029,6 +1130,7 @@ A
const postTitle = document.createElement("h1");
const postP = document.createElement("p");
const postYes = document.createElement("button");
+ postDiv.dataset.id = nextPost.id;
postDiv.classList.add("post");
postDiv.onclick = () => {
window.open(getArticleLink(nextPost.title));
@@ -1069,6 +1171,59 @@ A
//nextPost.allCategories.forEach(e => categoryScores[e] -= 1);
engagePost(nextPost, -5);
postsWithoutLike++;
+ let startX = 0;
+ let isDragging = false;
+
+ const start = (x) => {
+ if (settings.viewMode !== "mode-tinder") return;
+ startX = x;
+ isDragging = true;
+ postDiv.style.transition = 'none';
+ };
+
+ const move = (x) => {
+ if (!isDragging || settings.viewMode !== "mode-tinder") return;
+ let moveX = x - startX;
+ postDiv.style.transform = `translateX(${moveX}px) rotate(${moveX / 10}deg)`;
+ };
+
+ const end = (x) => {
+ if (!isDragging || settings.viewMode !== "mode-tinder") return;
+ isDragging = false;
+ postDiv.style.transition = 'transform 0.3s ease, opacity 0.3s ease';
+
+ let diffX = x - startX;
+ if (Math.abs(diffX) > 100) {
+ postDiv.style.pointerEvents = "none";
+ const parent = document.querySelector(".posts.mode-tinder");
+ if (diffX > 0) {
+ showSwipeIndicator('like', parent);
+ postDiv.classList.add('swipe-right');
+ likedPosts.push(nextPost.id);
+ engagePost(nextPost, 50);
+ } else {
+ showSwipeIndicator('dislike', parent);
+ postDiv.classList.add('swipe-left');
+ engagePost(nextPost, -25);
+ }
+ setTimeout(() => postDiv.remove(), 300);
+ } else {
+ postDiv.style.transform = "";
+ }
+ };
+
+ postDiv.addEventListener('touchstart', e => start(e.touches[0].clientX));
+ postDiv.addEventListener('touchmove', e => move(e.touches[0].clientX));
+ postDiv.addEventListener('touchend', e => end(e.changedTouches[0].clientX));
+
+ postDiv.addEventListener('mousedown', e => {
+ if(e.button !== 0) return;
+ start(e.clientX);
+ });
+ window.addEventListener('mousemove', e => move(e.clientX));
+ window.addEventListener('mouseup', e => end(e.clientX));
+
+ postDiv.querySelectorAll('img').forEach(img => img.draggable = false);
document.querySelector(".posts").appendChild(postDiv);
}
@@ -1112,8 +1267,23 @@ A
}
function render() {
- if (document.documentElement.scrollHeight < scrollY+innerHeight + 1500)
- createNextPost();
+ const container = document.querySelector(".posts");
+ if (!container) return;
+
+ if (settings.viewMode === "mode-classic") {
+ if (document.documentElement.scrollHeight < scrollY + innerHeight + 1500) {
+ createNextPost();
+ }
+ } else if (settings.viewMode === "mode-tinder") {
+ const activePosts = container.querySelectorAll('.post:not(.swipe-right):not(.swipe-left)');
+ if (activePosts.length < 2) {
+ createNextPost();
+ }
+ } else if (settings.viewMode === "mode-tiktok") {
+ if (container.scrollHeight - container.scrollTop <= container.clientHeight + 500) {
+ createNextPost();
+ }
+ }
requestAnimationFrame(render);
}
@@ -1201,6 +1371,50 @@ A
loading.innerText = `Loading...\n(${text})`;
}
+ function showSwipeIndicator(type, parent) {
+ const indicator = document.createElement("div");
+ indicator.className = `swipe-indicator ${type === 'like' ? 'indicator-heart' : 'indicator-cross'}`;
+ indicator.innerHTML = type === 'like' ? '❤️' : '✖️';
+ parent.appendChild(indicator);
+
+ requestAnimationFrame(() => {
+ indicator.classList.add("visible");
+ });
+
+ setTimeout(() => {
+ indicator.classList.remove("visible");
+ setTimeout(() => indicator.remove(), 200);
+ }, 500);
+ }
+
+ window.addEventListener('keydown', (e) => {
+ if (settings.viewMode === "mode-tinder") {
+ const topPost = document.querySelector(".posts.mode-tinder .post:last-child");
+ if (!topPost) return;
+ const parent = document.querySelector(".posts.mode-tinder");
+ if (e.key === "ArrowRight") {
+ showSwipeIndicator('like', parent);
+ topPost.classList.add('swipe-right');
+ likedPosts.push(topPost.dataset.id);
+ topPost.querySelector('button').click();
+ setTimeout(() => topPost.remove(), 300);
+ } else if (e.key === "ArrowLeft") {
+ showSwipeIndicator('dislike', parent);
+ topPost.classList.add('swipe-left');
+ setTimeout(() => topPost.remove(), 300);
+ }
+ } else if (settings.viewMode === "mode-tiktok") {
+ const container = document.querySelector(".posts.mode-tiktok");
+ if (e.key === "ArrowDown") {
+ e.preventDefault(); // Prevent page jitter
+ container.scrollBy({ top: container.clientHeight, behavior: 'smooth' });
+ } else if (e.key === "ArrowUp") {
+ e.preventDefault();
+ container.scrollBy({ top: -container.clientHeight, behavior: 'smooth' });
+ }
+ }
+ });
+
let downloadFinished = false;
async function main() {
if (/iPad|iPhone|iPod/.test(navigator.userAgent))
@@ -1283,4 +1497,4 @@ A
window.onload = main;