refactor: remove stale code

This commit is contained in:
log101 2024-07-25 19:53:59 +03:00
parent 5097f70d90
commit 9e798f1b15
12 changed files with 6 additions and 1800 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -20,20 +20,15 @@
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@types/leaflet": "^1.9.12",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"astro": "^4.11.6",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.11",
"htmx.org": "^1.9.12",
"hyperscript.org": "^0.9.12",
"kysely": "^0.26.3",
"leaflet": "^1.9.4",
"lit": "^3.1.4",
"lucide-react": "^0.309.0",
"nanoid": "^5.0.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwind-merge": "^2.4.0",
@ -43,6 +38,9 @@
"typescript": "^5.5.3"
},
"devDependencies": {
"@types/leaflet": "^1.9.12",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/bun": "^1.1.6",
"@types/google.maps": "^3.55.11",
"@types/toastify-js": "^1.12.3"

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 KiB

View File

@ -1,59 +0,0 @@
import L, { type LatLngTuple } from "leaflet";
const GoToTargetControl = L.Control.extend({
_targetLocation: null as LatLngTuple | null,
setTargetLocation: function (latlng: LatLngTuple) {
this._targetLocation = latlng;
},
onAdd: function (map: L.Map) {
const locationButton = document.createElement("button");
locationButton.id = "go-to-target-control-button";
locationButton.textContent = "Hedefe Git";
locationButton.classList.add("custom-map-control-button");
L.DomEvent.on(locationButton, "click", () => {
if (!this._targetLocation) return;
map.setView(this._targetLocation, 18);
});
return locationButton;
},
});
const GeolocationControl = L.Control.extend({
_containerEl: null as HTMLButtonElement | null,
_currentLocationMarker: null as L.Marker | null,
setCurrentLocationMarker: function (marker?: L.Marker) {
if (marker) this._currentLocationMarker = marker;
},
onAdd: function (map: L.Map) {
const locationButton = document.createElement("button");
this._containerEl = locationButton;
locationButton.id = "ask-permission-control-button";
locationButton.textContent = "Konumuma Git";
locationButton.classList.add("custom-map-control-button");
locationButton.type = "button";
L.DomEvent.on(locationButton, "click", () => {
console.log(this._currentLocationMarker);
if (this._currentLocationMarker) {
map.setView(this._currentLocationMarker.getLatLng(), 12);
}
});
return locationButton;
},
onRemove: function () {
L.DomEvent.off(this._containerEl!);
},
});
export { GoToTargetControl, GeolocationControl };

View File

@ -1,63 +0,0 @@
import Toastify from "toastify-js";
import L from "leaflet";
import { currentLocationIcon } from "./icons";
function onLocationError(err: L.ErrorEvent) {
let errorMessage;
switch (err.code) {
case 1:
errorMessage =
"Konum izni alınamadı, lütfen tarayıcınızın ve cihazınızın gizlilik ayarlarını kontrol edin.";
break;
case 2:
errorMessage =
"Konumunuz tespit edilemedi, lütfen biraz sonra tekrar deneyiniz.";
break;
case 3:
errorMessage =
"Konum isteği zaman aşımına uğradı, lütfen sayfayı yenileyip tekrar deneyiniz.";
break;
default:
errorMessage =
"Konum izni alınamadı, lütfen tarayıcınızın ve cihazınızın gizlilik ayarlarını kontrol edin.";
break;
}
Toastify({
text: errorMessage,
duration: 3000,
gravity: "top", // `top` or `bottom`
position: "center", // `left`, `center` or `right`
stopOnFocus: true, // Prevents dismissing of toast on hover
style: {
background: "black",
borderRadius: "6px",
margin: "16px",
},
onClick: function () {}, // Callback after click
}).showToast();
}
function onLocationSuccess(
locationEvent: L.LocationEvent,
map: L.Map,
currentLocationMarker: L.Marker | undefined
) {
const position = locationEvent.latlng;
const currentPos = {
lat: position.lat,
lng: position.lng,
};
if (currentLocationMarker) {
currentLocationMarker.setLatLng(currentPos);
} else {
currentLocationMarker = L.marker(currentPos, {
icon: currentLocationIcon,
});
currentLocationMarker.addTo(map);
}
}
export { onLocationError, onLocationSuccess };

View File

@ -1,13 +0,0 @@
import L from "leaflet";
var targetLocationIcon = L.icon({
iconUrl: "goal.svg",
iconSize: [32, 32],
});
var currentLocationIcon = L.icon({
iconUrl: "blue-dot.png",
iconSize: [32, 32],
});
export { targetLocationIcon, currentLocationIcon };

View File

@ -1,31 +0,0 @@
import { html } from "lit";
// Locked lock icon
const lockSVG = html`<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="#ffffff"
viewBox="0 0 256 256"
>
<path
d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z"
></path>
</svg>`;
// Unlocked lock icon
const unlockSVG = html`
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="#ffffff"
viewBox="0 0 256 256"
>
<path
d="M208,80H96V56a32,32,0,0,1,32-32c15.37,0,29.2,11,32.16,25.59a8,8,0,0,0,15.68-3.18C171.32,24.15,151.2,8,128,8A48.05,48.05,0,0,0,80,56V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80Zm0,128H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z"
></path>
</svg>
`;
export { lockSVG, unlockSVG };

View File

@ -1,95 +0,0 @@
import { html } from "lit";
import { lockSVG, unlockSVG } from "./icons";
// This template is shown when user hasn't give geolocation permission yet
// When user click the button user is asked for geolocation permission
function permissionButtonTemplate(onClickHandler: () => void) {
return html`
<div class="flex flex-col justify-center gap-4 overlay">
<button
id="unlock-content-button"
class="inline-flex items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-11 rounded-md text-lg p-6 text-md">
İçerik Kilitli
</button>
<div class="rounded-lg border bg-card text-card-foreground shadow-sm p-2">
<div class="pb-0 text-center flex flex-col gap-4">
<p id="locked-content-description">
Ne kadar yaklaştığını görmek için aşağıdaki butona bas.
</p>
<button
@click="${onClickHandler}"
class="inline-flex items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 text-primary-foreground h-9 rounded-md px-3 bg-green-700 hover:bg-green-600 text-md">
Konum İzni Ver
</button>
</div>
</div>
</div>
`;
}
// This template is shown when user has not given permission
function permissionDeniedButtonTemplate() {
return html`<div class="flex flex-col justify-center gap-4 overlay">
<button
id="unlock-content-button"
class="inline-flex gap-2 items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-11 rounded-md text-lg p-6 text-md">
${lockSVG}
<p>İçerik Kilitli</p>
</button>
<div class="rounded-lg border bg-card text-card-foreground shadow-sm p-2">
<div class="pb-0 px-4 text-center">
<p id="locked-content-description">
Konumuna erişim izni vermediğin için hedefe ne kadar <br />
yakın olduğun tespit edilemiyor.
</p>
</div>
</div>
</div>`;
}
// This template is shown when user has given permission but has not arrived yet
function lockedButtonTemplate(proximityText: string | undefined) {
return html`<div class="flex flex-col justify-center gap-4 overlay">
<button
id="unlock-content-button"
class="inline-flex gap-2 items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-11 rounded-md text-lg p-6 text-md">
${lockSVG}
<p>İçerik Kilitli</p>
</button>
<div class="rounded-lg border bg-card text-card-foreground shadow-sm p-2">
<div class="pb-0 px-4 text-center">
<p id="locked-content-description">
İçeriği görmek için konuma gitmelisin! Kalan mesafe: ${proximityText}
</p>
</div>
</div>
</div>`;
}
// This template is shown when user has arrived to the target location
// When user click the button counter at the bottom of the page is incremented
// and image is revealed
function unlockedButtonTemplate(onClickHandler: () => void) {
return html` <div class="flex flex-col justify-center gap-4 overlay">
<button
@click="${onClickHandler}"
id="unlock-content-button"
class="inline-flex gap-2 items-center justify-center whitespace-nowrap font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 text-primary-foreground h-11 rounded-md text-lg p-6 animate-pulse bg-indigo-600 hover:bg-indigo-700 hover:animate-none border-2 border-indigo-800 transition-1000">
${unlockSVG}
<p>İçeriğin Kilidi ıldı</p>
</button>
<div class="rounded-lg border bg-card text-card-foreground shadow-sm p-2">
<div class="pb-0 px-4 text-center">
<p id="locked-content-description">İçeriği görmek için butona bas!</p>
</div>
</div>
</div>`;
}
export {
lockedButtonTemplate,
unlockedButtonTemplate,
permissionButtonTemplate,
permissionDeniedButtonTemplate,
};

View File

@ -1,100 +0,0 @@
// Lit
import {
html,
LitElement,
unsafeCSS,
type CSSResultGroup,
type PropertyValues,
} from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
// Leaflet
import L, { Map } from "leaflet";
import type { LatLngTuple } from "leaflet";
import { currentLocationIcon, targetLocationIcon } from "./LeafletMap/icons";
import { GeolocationControl, GoToTargetControl } from "./LeafletMap/controls";
// Styles
import leafletStyles from "leaflet/dist/leaflet.css?inline";
import globalStyles from "@/styles/globals.css?inline";
import mapStyles from "@/styles/locked-page.css?inline";
@customElement("leaflet-map")
export class LeafletMap extends LitElement {
// Styles
static styles?: CSSResultGroup | undefined = [
unsafeCSS(leafletStyles),
unsafeCSS(globalStyles),
unsafeCSS(mapStyles),
];
// Div element to initialize Leaflet in
@query("#mapid")
_mapElement!: HTMLDivElement;
// Properties and states
@property({ type: Object, noAccessor: true }) targetPosition?: LatLngTuple;
@property({ type: Object })
currentPosition?: LatLngTuple;
protected _map?: L.Map;
protected _currentLocationMarker?: L.Marker;
firstUpdated(): void {
if (!this._mapElement || !this.targetPosition) return;
this._map = new Map(this._mapElement).setView(this.targetPosition, 13);
L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 19,
attribution:
'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>',
}).addTo(this._map);
// Add target location icon marker
L.marker(this.targetPosition, { icon: targetLocationIcon }).addTo(
this._map
);
L.circle(this.targetPosition, {
color: "blue",
fillColor: "#30f",
fillOpacity: 0.2,
radius: 50,
}).addTo(this._map);
// Add target location control
const targetLocationControl = new GoToTargetControl({
position: "bottomleft",
});
targetLocationControl.setTargetLocation(this.targetPosition);
targetLocationControl.addTo(this._map);
}
protected update(changedProperties: PropertyValues): void {
super.update(changedProperties);
if (changedProperties.get("currentPosition")) {
if (!this._currentLocationMarker && this._map) {
this._currentLocationMarker = L.marker(this.currentPosition!, {
icon: currentLocationIcon,
});
this._currentLocationMarker.addTo(this._map);
const geolocationControl = new GeolocationControl({
position: "bottomleft",
});
geolocationControl.setCurrentLocationMarker(
this._currentLocationMarker
);
geolocationControl.addTo(this._map);
} else if (this._currentLocationMarker) {
this._currentLocationMarker.setLatLng(this.currentPosition!);
}
}
}
render() {
return html`<div id="mapid" class="w-full h-[450px] rounded"></div>`;
}
}

View File

@ -1,151 +0,0 @@
// Lit imports
import { LitElement, html, nothing, unsafeCSS, type CSSResultGroup } from "lit";
import { customElement, property, state } from "lit/decorators.js";
// Leaflet
import { type LatLngTuple } from "leaflet";
// Styles
import globalStyles from "@/styles/globals.css?inline";
import lockedContentStyles from "../styles/locked-content.css?inline";
// Templates
import {
lockedButtonTemplate,
permissionButtonTemplate,
permissionDeniedButtonTemplate,
unlockedButtonTemplate,
} from "./LockedContent/templates";
// Geolocation utils
import { calculateDistance } from "./LockedContent/geolocation";
import { incrementUnlockCounter } from "./LockedContent/serverUtils";
// LockedContent is a custom element watching user location and blurring
// given image until user has arrived a certain position
@customElement("locked-content")
export class LockedContent extends LitElement {
// Constants
geolocationOptions = {
enableHighAccuracy: true,
timeout: 15000,
maximumAge: 0,
};
// Tailwind and custom styles
static styles: CSSResultGroup | undefined = [
unsafeCSS(globalStyles),
unsafeCSS(lockedContentStyles),
];
// Components properties/attributes, no accessor attribute disables detecting
// changes as these are readonly attributes there is no need to attach setters
@property({ noAccessor: true }) readonly imageId?: string;
@property({ noAccessor: true }) readonly imageURL?: string;
@property({ type: Object, noAccessor: true })
readonly targetPosition?: LatLngTuple;
@property({ type: Object })
currentPosition?: LatLngTuple;
// Reactive states, template is rendered according to this states
@state()
protected _unlocked = false;
@state()
protected _arrived = false;
@state()
protected _distanceText?: string;
private _updateDistanceText(distance: number) {
// Update the proximity text according to the distance remaining
if (distance > 1000) {
this._distanceText = `${(distance / 1000).toFixed()} KM`;
} else if (distance > 100) {
this._distanceText = `${distance.toFixed(0)} M`;
}
}
private _checkArrived(distance: number) {
// If target is close less then 100 meters user has arrived to target location
if (distance < 100) {
// Update state to reveal the image
this._arrived = true;
}
}
private _dispatchAskPermissionEvent() {
const event = new Event("askpermission", { bubbles: true, composed: true });
this.dispatchEvent(event);
}
// This template is shown when user hasn't give geolocation permission yet
// When user click the button user is asked for geolocation permission
private _permissionButtonTemplate = () =>
permissionButtonTemplate(this._dispatchAskPermissionEvent);
// This template is shown when user has given permission but has not arrived yet
private _lockedButtonTemplate = () => {
// Target position must be set
if (!this.targetPosition || !this.currentPosition) return;
// Calculate the distance between target and current position in meters
const distance = calculateDistance(
this.currentPosition,
this.targetPosition
);
// Update the text based on the distance
this._updateDistanceText(distance);
this._checkArrived(distance);
return lockedButtonTemplate(this._distanceText);
};
// This template is shown when user has arrived to the target location
// When user click the button counter at the bottom of the page is incremented
// and image is revealed
private _unlockedButtonTemplate = () =>
unlockedButtonTemplate(() => {
incrementUnlockCounter(this.imageId);
this._unlocked = true;
});
connectedCallback(): void {
super.connectedCallback();
}
render() {
let buttonTemplate;
// Determine which template to show, there are 3 states:
// 1 - No current location provided
// 2 - Current location given but has no arrived to target position yet
// 3 - Arrived to target position
// 4 - User did not give geolocation permission
if (this._arrived) {
buttonTemplate = this._unlockedButtonTemplate;
} else if (this.currentPosition) {
buttonTemplate = this._lockedButtonTemplate;
} else if (!this.currentPosition) {
buttonTemplate = this._permissionButtonTemplate;
} else {
buttonTemplate = permissionDeniedButtonTemplate;
}
return html`
<div
class="w-full h-[475px] overflow-hidden border border-zinc-200 shadow-sm p-4 rounded"
>
<div class="flex flex-col justify-center items-center image-wrapper">
<img
id="content"
src="${this.imageURL}"
class="h-[450px] ${this._unlocked ? "" : "blur-2xl"}"
/>
${this._unlocked ? nothing : buttonTemplate()}
</div>
</div>
`;
}
}

View File

@ -1,10 +1,6 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function remoteLog(data: any) {
fetch("/api/debug", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) })
return twMerge(clsx(inputs));
}