Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 218 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -235,6 +320,7 @@
color: var(--theme);
}
.bottomNav {
z-index: 100;
display: flex;
justify-content: space-around;
position: fixed;
Expand Down Expand Up @@ -605,6 +691,13 @@
<label><input type="radio" name="theme" id="theme-dark">Dark</label>
</radio-picker>
</pseudo-label>
<pseudo-label>Display mode
<radio-picker aria-label="View mode" role="radiogroup">
<label><input type="radio" name="viewMode" id="mode-classic" checked>Scroll</label>
<label><input type="radio" name="viewMode" id="mode-tinder">Swipe</label>
<label><input type="radio" name="viewMode" id="mode-tiktok">Scroll(full page post)</label>
</radio-picker>
</pseudo-label>
<div style="flex:1"></div>
<button class="btn-outline" onclick=showAboutModal() style="margin-bottom:8px">About Xikipedia</button>
<button class="btn-danger-outline" onclick=resetAlgorithm() style="margin-bottom:8px">Reset the algorithm</button>
Expand Down Expand Up @@ -687,7 +780,7 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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 = {
Expand All @@ -697,6 +790,7 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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);
Expand All @@ -710,7 +804,14 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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() {
Expand Down Expand Up @@ -1029,6 +1130,7 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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));
Expand Down Expand Up @@ -1069,6 +1171,59 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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);
}

Expand Down Expand Up @@ -1112,8 +1267,23 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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);
}

Expand Down Expand Up @@ -1201,6 +1371,50 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">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))
Expand Down Expand Up @@ -1283,4 +1497,4 @@ <h3 style="font-size: 100%;opacity:0.85;font-style:italic;margin-bottom:16px">A
window.onload = main;
</script>
</body>
</html>
</html>
2 changes: 1 addition & 1 deletion sw.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const SW_VERSION = '1.1.3';
const SW_VERSION = '1.1.4';

self.addEventListener('install', () => {
self.skipWaiting();
Expand Down
4 changes: 2 additions & 2 deletions version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"html": "1.1.4",
"sw": "1.1.3",
"html": "1.1.5",
"sw": "1.1.4",
"simple": 228005406
}