Frontend lol
This commit is contained in:
		@@ -26,7 +26,11 @@
 | 
			
		||||
body {
 | 
			
		||||
  background-color: var(--bg-color);
 | 
			
		||||
  color: var(--font-color);
 | 
			
		||||
  /*overflow: hidden;*/
 | 
			
		||||
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
}
 | 
			
		||||
/* End of Body */
 | 
			
		||||
 | 
			
		||||
@@ -53,70 +57,9 @@ button {
 | 
			
		||||
  border-radius: 0px;
 | 
			
		||||
  vertical-align: bottom !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
img.logo {
 | 
			
		||||
  height: 48px;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
/* END OF NAV */
 | 
			
		||||
 | 
			
		||||
/* f0ck Grid! */
 | 
			
		||||
.f0ckgrid {
 | 
			
		||||
  display: grid;
 | 
			
		||||
  grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
 | 
			
		||||
  grid-gap: 20px;
 | 
			
		||||
  align-items: stretch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.f0ckgrid img {
 | 
			
		||||
  box-shadow: 2px 2px 6px 0px rgb(0, 0, 0);
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
}
 | 
			
		||||
/* End of f0ck Grid! */
 | 
			
		||||
 | 
			
		||||
/* Image Thumbs */
 | 
			
		||||
a img.thumb {
 | 
			
		||||
  border: 2px solid black;
 | 
			
		||||
  transition: .1s ease-out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
img.thumb:hover {
 | 
			
		||||
     box-shadow: 0px 0px 0px 2px #dac8d2;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  transition: .1s ease-in;
 | 
			
		||||
}
 | 
			
		||||
/* End of Image Thumbs */
 | 
			
		||||
 | 
			
		||||
/* List Styling
 | 
			
		||||
ul.f0ck-links {
 | 
			
		||||
  list-style: none;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
li.post {
 | 
			
		||||
  width: 128px;
 | 
			
		||||
  height: 128px;
 | 
			
		||||
  margin-top: 5px;
 | 
			
		||||
  line-height: 128px;
 | 
			
		||||
  float: left;
 | 
			
		||||
  margin: 5px;
 | 
			
		||||
  transition: .1s ease-out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
li.post:hover {
 | 
			
		||||
  box-shadow: 0px 0px 0px 2px #dac8d2;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  transition: .1s ease-in;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
li.post:hover img {
 | 
			
		||||
border-radius: 5px;
 | 
			
		||||
opacity: 0.8;
 | 
			
		||||
}
 | 
			
		||||
End of List Styling */
 | 
			
		||||
 | 
			
		||||
/* MISC */
 | 
			
		||||
::-webkit-scrollbar {
 | 
			
		||||
  width: 12px;
 | 
			
		||||
@@ -131,3 +74,121 @@ End of List Styling */
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Flummikram lol */
 | 
			
		||||
div.pscroll {
 | 
			
		||||
  opacity: 0.7;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  height: 64px;
 | 
			
		||||
  width: 64px;
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  margin-left: -36px;
 | 
			
		||||
  z-index: 999;
 | 
			
		||||
}
 | 
			
		||||
div.pscroll:hover {
 | 
			
		||||
  opacity: 0.9;
 | 
			
		||||
}
 | 
			
		||||
div#up {
 | 
			
		||||
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAANlBMVEUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyP///8iIiLm5uY3NzdKSkpAQEAqKipZf6aEAAAACnRSTlOxIfAAKvPn6quuQpaxIgAAAMZJREFUeF7t17uOwjAYROHjOMCuL0l4/5ddbQU0M4p/RIE8/flkyY1NTr/XNrjrT8qsSwtsWaGFBpcYcKEF9xFgAhMo9xIBytFrP8owUPb6v10JmN4K6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4L6N4LiN4LD2Cv53c8AaUPAL08AXVk9zeeoG3nhb69XuP5fdkLZQITmED840kMIP75zonbaH4j5T8NALtW477R3QAAAABJRU5ErkJggg==');
 | 
			
		||||
  top: 5.8em;
 | 
			
		||||
}
 | 
			
		||||
div#down {
 | 
			
		||||
  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAANlBMVEUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIjIyMiIiLm5uY3NzcqKipAQED///9KSkpHtWFIAAAACnRSTlMqACGx8/Cu6uerGsmyTAAAAM9JREFUeF7t1zkOwzAMBVEt3kLK2/0vm3KQivhWigTQ7+dBpZhyeW3+cNtSckqzd2xOafGu1TT1AVPyzv0YMIABDMD0fQB7u9S1HcCNXhAM4CAQZl98gZ8PgNsB3G69NwAEqQdAUHoABKUHQNB6AAStB0DQegAErQdA0HoABK0HQNB6AAShBwgE+gBACHuAWKCPAIS4B4gEegFAoHcFQKBXAAR6BUCgVwAEehlAoNcBt7Nd7TTXAYjD/uKDMYAB9B+etQ+o/cd3Lsv6NF9ryW9/v8EFMSsbFgAAAABJRU5ErkJggg==');
 | 
			
		||||
  bottom: 5em;
 | 
			
		||||
}
 | 
			
		||||
footer {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.content {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 54px;
 | 
			
		||||
  left: 8px;
 | 
			
		||||
  bottom: 25px;
 | 
			
		||||
  right: 8px;
 | 
			
		||||
  margin-top: 25px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
div.posts {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.posts > a {
 | 
			
		||||
  width: 128px;
 | 
			
		||||
  height: 128px;
 | 
			
		||||
  box-shadow: 2px 2px 6px 0px rgb(0, 0, 0);
 | 
			
		||||
  margin: 4px;
 | 
			
		||||
  float: left;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  box-shadow: inset 0 0 10px #4c4a4a;
 | 
			
		||||
}
 | 
			
		||||
div.posts > a > img.thumb {
 | 
			
		||||
  border: 2px solid black;
 | 
			
		||||
  transition: .1s ease-out;
 | 
			
		||||
}
 | 
			
		||||
div.posts > a > img.thumb:hover {
 | 
			
		||||
  box-shadow: 0px 0px 0px 2px #dac8d2;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  transition: .1s ease-in;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* fml */
 | 
			
		||||
div#header {
 | 
			
		||||
  height: 65px;
 | 
			
		||||
  left: 8px;
 | 
			
		||||
  right: 8px;
 | 
			
		||||
  top: 0;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  background-color: #292922;
 | 
			
		||||
}
 | 
			
		||||
#logoHead {
 | 
			
		||||
  margin: 6px 0 0 4px;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
}
 | 
			
		||||
#logo {
 | 
			
		||||
  padding: 1px 4px 1px 4px;
 | 
			
		||||
  height: 48px;
 | 
			
		||||
}
 | 
			
		||||
#itemInfo {
 | 
			
		||||
  display: none;
 | 
			
		||||
  height: 61px;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  left: 200px;
 | 
			
		||||
  right: 270px;
 | 
			
		||||
  top: 4px;
 | 
			
		||||
}
 | 
			
		||||
#itemInfo div.infoText {
 | 
			
		||||
  margin-top: 3px;
 | 
			
		||||
}
 | 
			
		||||
#pagePosition, #itemPosition {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 8px;
 | 
			
		||||
  bottom: 6px;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  color: #7d7b6a;
 | 
			
		||||
  background-color: #333;
 | 
			
		||||
}
 | 
			
		||||
#pagePosition span, #itemPosition span {
 | 
			
		||||
  color: #9d9b8a;
 | 
			
		||||
}
 | 
			
		||||
#pagePosition {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
#itemPosition {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div#wrapper {
 | 
			
		||||
  display: block;
 | 
			
		||||
}
 | 
			
		||||
div#itemview {
 | 
			
		||||
  z-index: 999;
 | 
			
		||||
  background-color: rgba(0,0,0,0.8);
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,151 @@
 | 
			
		||||
/* Todo:
 | 
			
		||||
 * - Event tracker (rt.events)
 | 
			
		||||
 * - Functions und Events in Module auslagern
 | 
			
		||||
 */
 | 
			
		||||
import rt from "./rt.js";
 | 
			
		||||
import "./test.js";
 | 
			
		||||
 | 
			
		||||
const calcItems = () => {
 | 
			
		||||
  const cs = window.getComputedStyle(rt.container.posts[0]);
 | 
			
		||||
  const height = parseInt(cs.height.replace("px", ""));
 | 
			
		||||
  const width = parseInt(cs.width.replace("px", ""));
 | 
			
		||||
  const cols = ~~(width  / ( rt.layout.itemsize + rt.layout.margin ));
 | 
			
		||||
  const rows = ~~(height / ( rt.layout.itemsize + rt.layout.margin ));
 | 
			
		||||
  rt.container.posts.forEach(e => {
 | 
			
		||||
    e.style.marginLeft = Math.max((width - (cols * (rt.layout.itemsize + rt.layout.margin)) + rt.layout.margin) / rt.layout.min_rows, 0) * 1.5;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    rows: rows,
 | 
			
		||||
    cols: cols,
 | 
			
		||||
    eps: rows * cols,
 | 
			
		||||
    width: width,
 | 
			
		||||
    height: height
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
const getItems = async ({ el, opt = "" }) => {
 | 
			
		||||
  const tmp = calcItems();
 | 
			
		||||
  if(tmp.eps === rt.items.eps)
 | 
			
		||||
    return;
 | 
			
		||||
  rt.items.eps = tmp.eps;
 | 
			
		||||
  el.innerHTML = "";
 | 
			
		||||
  const i = await (await fetch(`/api/p?eps=${tmp.eps}&${opt}`)).json();
 | 
			
		||||
  
 | 
			
		||||
  const items = i.items.sort((a, b) => b.id - a.id);
 | 
			
		||||
  items.forEach(item => {
 | 
			
		||||
    const _a = document.createElement("a");
 | 
			
		||||
    _a.title = item.mime;
 | 
			
		||||
    _a.href = `#${item.id}`;//`${rt.url}/${item.id}`;
 | 
			
		||||
    const _img = document.createElement("img");
 | 
			
		||||
    _img.classList.add("thumb");
 | 
			
		||||
    _img.src = `${rt.url}/t/${item.id}.png`;
 | 
			
		||||
    _a.insertAdjacentElement("afterbegin", _img);
 | 
			
		||||
    el.insertAdjacentElement("beforeend", _a);
 | 
			
		||||
  });
 | 
			
		||||
  rt.items.first = items[0].id;
 | 
			
		||||
  rt.items.last = items[items.length - 1].id;
 | 
			
		||||
  rt.items.oldest = i.oldest;
 | 
			
		||||
  rt.items.newest = i.newest;
 | 
			
		||||
  window.history.pushState(rt.items.first, `f0ck.me! page ${rt.items.first}`, `/page/${rt.items.first}`);
 | 
			
		||||
 | 
			
		||||
  document.querySelector("#pagePosition").innerHTML = `items ${rt.items.first} - ${rt.items.last}`;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const scroll = async e => { // uff
 | 
			
		||||
  if(rt.tmp.scroll)
 | 
			
		||||
    return;
 | 
			
		||||
  rt.tmp.scroll = true;
 | 
			
		||||
  const direction = e.target.id === "up" ? "up" : e.deltaY < 0 ? "up": "down";
 | 
			
		||||
  if((direction === "up" && rt.items.first === rt.items.newest) || (direction === "down" && rt.items.last === rt.items.oldest))
 | 
			
		||||
    return rt.tmp.scroll = false;
 | 
			
		||||
  rt.items.eps = 0;
 | 
			
		||||
  await getItems({
 | 
			
		||||
    el: rt.container.posts[direction === "up" ? 0 : 2],
 | 
			
		||||
    opt: direction === "up" ? `id=${rt.items.first}&order=asc` : `id=${rt.items.last}&order=desc`
 | 
			
		||||
  });
 | 
			
		||||
  rt.container.posts[direction === "up" ? 0 : 2].scrollIntoView({ block: rt.st.block, behavior: "smooth" });
 | 
			
		||||
  await new Promise(resolve => setTimeout(resolve, 500));
 | 
			
		||||
 | 
			
		||||
  rt.container.posts[1].innerHTML = rt.container.posts[direction === "up" ? 0 : 2].innerHTML;
 | 
			
		||||
  rt.container.posts[1].scrollIntoView({ block: rt.st.block, behavior: "auto" });
 | 
			
		||||
 | 
			
		||||
  rt.tmp.scroll = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const swiper = {
 | 
			
		||||
  touchStartY: 0,
 | 
			
		||||
  touchEndY: 0,
 | 
			
		||||
  minSwipePixels: 30,
 | 
			
		||||
  detectionZone: undefined,
 | 
			
		||||
  swiperCallback: () => {},
 | 
			
		||||
  init: (detectionZone, callback) => {
 | 
			
		||||
    swiper.swiperCallback = callback
 | 
			
		||||
    detectionZone.addEventListener("touchstart", event => {
 | 
			
		||||
      swiper.touchStartY = event.changedTouches[0].screenY;
 | 
			
		||||
    }, false);
 | 
			
		||||
    detectionZone.addEventListener("touchend", event => {
 | 
			
		||||
      swiper.touchEndY = event.changedTouches[0].screenY;
 | 
			
		||||
      swiper.handleSwipeGesture();
 | 
			
		||||
    }, false);
 | 
			
		||||
  },
 | 
			
		||||
  handleSwipeGesture: () => {
 | 
			
		||||
    let direction, moved;
 | 
			
		||||
    if (swiper.touchEndY <= swiper.touchStartY) {
 | 
			
		||||
      moved = swiper.touchStartY - swiper.touchEndY;
 | 
			
		||||
      direction = "down";
 | 
			
		||||
    }
 | 
			
		||||
    if (swiper.touchEndY >= swiper.touchStartY) {
 | 
			
		||||
      moved = swiper.touchEndY - swiper.touchStartY;
 | 
			
		||||
      direction = "up";
 | 
			
		||||
    }
 | 
			
		||||
    if (moved > swiper.minSwipePixels && direction !== "undefined")
 | 
			
		||||
      swiper.swipe(direction, moved);
 | 
			
		||||
  },
 | 
			
		||||
  swipe: (direction, movedPixels) => {
 | 
			
		||||
    const ret = {};
 | 
			
		||||
    ret.direction = direction;
 | 
			
		||||
    ret.movedPixels = movedPixels;
 | 
			
		||||
    swiper.swiperCallback(ret);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const resize = e => {
 | 
			
		||||
  e.preventDefault();
 | 
			
		||||
  clearTimeout(rt.tmp.resize);
 | 
			
		||||
  rt.tmp.resize = setTimeout(() => getItems({
 | 
			
		||||
    el: rt.container.posts[1],
 | 
			
		||||
    opt: `id=${rt.items.first + 1}&order=desc`
 | 
			
		||||
  }), 500);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// events
 | 
			
		||||
swiper.init(rt.container.wrapper, e => scroll({ target: { id: e.direction }}));
 | 
			
		||||
document.querySelectorAll("div.pscroll").forEach(p => p.addEventListener("click", scroll));
 | 
			
		||||
document.addEventListener("wheel", scroll);
 | 
			
		||||
 | 
			
		||||
(() => { // init
 | 
			
		||||
  window.addEventListener("resize", resize);
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    const pn = parseInt(document.location.pathname.split("/").splice(-1));
 | 
			
		||||
    rt.container.posts[1].scrollIntoView({ block: rt.st.block }); // mitte
 | 
			
		||||
    getItems({
 | 
			
		||||
      el: rt.container.posts[1],
 | 
			
		||||
      opt: pn > 0 ? `id=${pn + 1}&order=desc` : ""
 | 
			
		||||
    });
 | 
			
		||||
  }, 300);
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
window.addEventListener("hashchange", e => {
 | 
			
		||||
  const itemid = parseInt(e.newURL.split("#").slice(-1));
 | 
			
		||||
  if(itemid === "NaN")
 | 
			
		||||
    return rt.container.itemview.style.display = "none";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  rt.container.itemview.style.display = "block"; // show itemview
 | 
			
		||||
  // remove page events
 | 
			
		||||
  document.removeEventListener("wheel", scroll);
 | 
			
		||||
 | 
			
		||||
  console.log(itemid);
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								public/js/rt.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								public/js/rt.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
export default {
 | 
			
		||||
  layout: {
 | 
			
		||||
    margin: 6,
 | 
			
		||||
    min_cols: 3,
 | 
			
		||||
    min_rows: 4,
 | 
			
		||||
    itemsize: 130
 | 
			
		||||
  },
 | 
			
		||||
  st: {
 | 
			
		||||
    behavior: "smooth",
 | 
			
		||||
    block: "center"
 | 
			
		||||
  },
 | 
			
		||||
  url: "//f0ck.me",
 | 
			
		||||
  tmp: {
 | 
			
		||||
    scroll: false,
 | 
			
		||||
    resize: null
 | 
			
		||||
  },
 | 
			
		||||
  container: {
 | 
			
		||||
    wrapper: document.querySelector("div#wrapper"),
 | 
			
		||||
    itemview: document.querySelector("div#itemview"),
 | 
			
		||||
    posts: document.querySelectorAll("div.posts")
 | 
			
		||||
  },
 | 
			
		||||
  items: {
 | 
			
		||||
    first: null,
 | 
			
		||||
    last: null,
 | 
			
		||||
    newest: null,
 | 
			
		||||
    oldest: null,
 | 
			
		||||
    eps: 0
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										0
									
								
								public/js/test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								public/js/test.js
									
									
									
									
									
										Normal file
									
								
							
		Reference in New Issue
	
	Block a user