Skip to content

Commit

Permalink
Improved error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
invpt committed Mar 11, 2024
1 parent 8420c6c commit 828dc80
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 170 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"maplibre-gl": "^4.1.0",
"solid-icons": "^1.1.0",
"solid-js": "^1.8.15",
"solid-toast": "^0.5.0",
"uuid": "^9.0.1"
}
}
52 changes: 11 additions & 41 deletions src/components/Asset.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { FiArrowDown, FiArrowUp, FiImage, FiMusic, FiTrash, FiUpload } from "solid-icons/fi";
import { Component, createEffect, createResource, createSignal, createUniqueId, For, JSX, Show } from "solid-js";
import { Component, createSignal, createUniqueId, For, JSX, Show } from "solid-js";

import styles from "./Asset.module.css";
import { useDB } from "../db";
import { useProject } from "../hooks/Project";
import { useAssetUrl } from "../hooks/AssetUrl";

export const Asset: Component<{
id?: string,
Expand All @@ -16,46 +17,21 @@ export const Asset: Component<{
}> = (props) => {
const datalistId = createUniqueId();
const fileInputId = createUniqueId();
const db = useDB();
const [project, setProject] = useProject();

const [imageLoaded, setImageLoaded] = createSignal(false);
const [query, setQuery] = createSignal(props.asset);
const asset = () => props.asset && project() && props.asset in project()!.assets ? project()?.assets[props.asset] : undefined;
const [assetBlob] = createResource(() => props.asset, asset => {
if (asset === undefined) {
return undefined;
}
const currentProject = project();
if (currentProject === undefined) {
return undefined;
}
if (!currentProject.assets[asset]) {
return undefined;
}
return db.loadAsset(currentProject.assets[asset].hash);
});
const assetUrl = () => {
const blob = assetBlob();
if (blob === undefined) {
return undefined;
}
return URL.createObjectURL(blob);
};
const assets = () => {
const currentProject = project();
if (currentProject === undefined) {
return undefined;
}
return Object.keys(currentProject.assets);
}

const resolved = () => !!asset();
const db = useDB();
const [project, setProject] = useProject();
const assetUrl = useAssetUrl(project, () => props.asset);

const assets = () => Object.keys(project()?.assets ?? {});

const handleQueryInput: JSX.EventHandlerUnion<HTMLInputElement, InputEvent> = async (event) => {
const newQuery = event.currentTarget.value;
setQuery(newQuery);

const match = Object.keys(project()?.assets ?? {}).find(asset => asset === newQuery);
const match = assets().find(asset => asset === newQuery);
if (match) {
props.onIdChange(match);
}
Expand All @@ -77,13 +53,7 @@ export const Asset: Component<{

const file = files[0];
let assetHash: string;
try {
assetHash = await db.storeAsset(file);
} catch (e) {
alert(`Failed to add asset. The storage alloted to this site by your web browser may have become full.`)
console.error("Failed to add asset", e);
return;
}
assetHash = await db.storeAsset(file);

setProject(project => ({
...project,
Expand Down Expand Up @@ -141,7 +111,7 @@ export const Asset: Component<{
<Show when={props.onDownClick}>
<button class={styles.AssetButton} title="Move Down" onClick={props.onDownClick}><FiArrowDown /></button>
</Show>
<button class={styles.AssetButton} title={resolved() ? "Change Image" : "Create New Asset"} onClick={() => document.getElementById(fileInputId)?.click()}><FiUpload /></button>
<button class={styles.AssetButton} title={"Upload New Asset"} onClick={() => document.getElementById(fileInputId)?.click()}><FiUpload /></button>
<Show when={props.onDeleteClick}>
<button class={styles.AssetButton} title="Remove Item" onClick={props.onDeleteClick}><FiTrash /></button>
</Show>
Expand Down
15 changes: 10 additions & 5 deletions src/components/Gallery.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Component, createEffect, createResource, JSX, For, createUniqueId, createSignal, Index, Show } from "solid-js";
import { FiArrowDown, FiArrowUp, FiImage, FiTrash, FiUpload } from "solid-icons/fi";
import { Component, Index } from "solid-js";

import { GalleryModel } from "../data";
import { Asset } from "./Asset";

import styles from "./Gallery.module.css";
import { Asset } from "./Asset";

export const Gallery: Component<{
id?: string | undefined,
Expand All @@ -24,11 +23,17 @@ export const Gallery: Component<{
};

const handleUpClick = (i: number) => () => {

if (i <= 0 || i >= props.value.length) {
return;
}
props.onChange([...props.value.slice(0, i - 1), props.value[i], props.value[i - 1], ...props.value.slice(i + 1)])
};

const handleDownClick = (i: number) => () => {

if (i < 0 || i >= props.value.length - 1) {
return;
}
props.onChange([...props.value.slice(0, i), props.value[i + 1], props.value[i], ...props.value.slice(i + 2)]);
};

return (
Expand Down
18 changes: 11 additions & 7 deletions src/components/LatLngEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ export const LatLngEditor: Component<{
lng: number,
onChange: (newLat: number, newLng: number) => void,
}> = (props) => {
const maxDigitsAfterDot = 6;

const [latVal, setLatVal] = createSignal(props.lat ?? 0);
const [lngVal, setLngVal] = createSignal(props.lng ?? 0);
const [latTxt, setLatTxt] = createSignal(truncateDecimal(latVal().toString(), 6));
const [lngTxt, setLngTxt] = createSignal(truncateDecimal(lngVal().toString(), 6));
const [latTxt, setLatTxt] = createSignal(truncateDecimal(latVal().toString(), maxDigitsAfterDot));
const [lngTxt, setLngTxt] = createSignal(truncateDecimal(lngVal().toString(), maxDigitsAfterDot));

const handleLatChange: JSX.EventHandlerUnion<HTMLInputElement, InputEvent> = (ev) => {
const trimmed = ev.currentTarget.value.trim();
Expand All @@ -25,7 +27,7 @@ export const LatLngEditor: Component<{
const group = /-?0*(\d*(\.\d*)?)/.exec(trimmed)?.[1];
if (!group) return;

let newLatTxt = truncateDecimal(trimmed.startsWith("-") ? "-" + group : group, 6);
let newLatTxt = truncateDecimal(trimmed.startsWith("-") ? "-" + group : group, maxDigitsAfterDot);

setLatVal(newLat = Number.parseFloat(newLatTxt));
setLatTxt(newLatTxt);
Expand All @@ -43,7 +45,7 @@ export const LatLngEditor: Component<{
const group = /-?0*(\d*(\.\d*)?)/.exec(trimmed)?.[1];
if (!group) return;

let newLngTxt = truncateDecimal(trimmed.startsWith("-") ? "-" + group : group, 6);
let newLngTxt = truncateDecimal(trimmed.startsWith("-") ? "-" + group : group, maxDigitsAfterDot);

setLngVal(newLng = Number.parseFloat(newLngTxt));
setLngTxt(newLngTxt);
Expand All @@ -54,11 +56,11 @@ export const LatLngEditor: Component<{
createEffect(() => {
if (props.lat && latVal() !== props.lat) {
setLatVal(props.lat);
setLatTxt(truncateDecimal(latVal().toString(), 6));
setLatTxt(truncateDecimal(latVal().toString(), maxDigitsAfterDot));
}
if (props.lng && lngVal() !== props.lng) {
setLngVal(props.lng);
setLngTxt(truncateDecimal(lngVal().toString(), 6));
setLngTxt(truncateDecimal(lngVal().toString(), maxDigitsAfterDot));
}
});

Expand All @@ -81,7 +83,9 @@ export const LatLngEditor: Component<{
function truncateDecimal(s: string, maxDigitsAfterDot: number): string {
let parts = s.split(".");

if (parts.length === 1) {
if (parts.length === 0) {
return "";
} else if (parts.length === 1) {
return s;
} else {
return `${parts[0]}.${parts[1].substring(0, maxDigitsAfterDot)}`;
Expand Down
46 changes: 46 additions & 0 deletions src/hooks/AssetUrl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { createEffect, createSignal, onCleanup, untrack } from "solid-js";

import { DbProject, useDB } from "../db";

export const useAssetUrl = (project: () => DbProject | undefined, asset: () => string | undefined) => {
const db = useDB();
const [assetUrl, setAssetUrl] = createSignal<string | undefined>();

createEffect(async () => {
const oldAssetUrl = untrack(assetUrl);
if (oldAssetUrl !== undefined) {
URL.revokeObjectURL(oldAssetUrl);
}

const currentProject = project();
if (currentProject === undefined) {
return;
}

const currentAsset = asset();
if (currentAsset === undefined) {
return;
}

const assetInfo = currentProject.assets[currentAsset];
if (assetInfo === undefined) {
return;
}

const blob = await db.loadAsset(assetInfo.hash);
if (blob === undefined) {
return;
}

setAssetUrl(URL.createObjectURL(blob));
});

onCleanup(() => {
const finalAssetUrl = assetUrl();
if (finalAssetUrl !== undefined) {
URL.revokeObjectURL(finalAssetUrl);
}
});

return assetUrl;
};
19 changes: 10 additions & 9 deletions src/hooks/RouteCalculator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function useRouteCalculator() {

const [prevLatLongs, setPrevLatLongs] = createSignal<(LatLng & { control: "path" | "route" })[]>([]);

createEffect(() => {
createEffect(async () => {
if (!tour()) return;

const latLongs = tour()!.route
Expand All @@ -31,13 +31,14 @@ export function useRouteCalculator() {

setPrevLatLongs(latLongs);

route(latLongs)
.then(route => setTour(({
...tour()!,
path: polyline.encode(route),
})))
.catch(err => {
console.error(err);
});
const routePoints = await route(latLongs);
if (!routePoints) {
return;
}

setTour(tour => ({
...tour,
path: polyline.encode(routePoints),
}));
});
}
4 changes: 2 additions & 2 deletions src/hooks/Tour.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export const TourProvider: Component<{ id: string, children: JSX.Element }> = (p
if (deleted()) return;

const currentProject = project();
const currentTourIndex = project()?.tours.findIndex(tour => tour.id === props.id);
if (currentProject === undefined || currentTourIndex === undefined || currentTourIndex === -1) {
const currentTourIndex = currentProject?.tours.findIndex(tour => tour.id === props.id);
if (currentProject === undefined || currentTourIndex === undefined || currentTourIndex < 0) {
console.warn("Ignoring update with undefined currentTour");
return;
}
Expand Down
24 changes: 14 additions & 10 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { render } from "solid-js/web";
import { HashRouter, Route } from "@solidjs/router";
import { Component } from "solid-js";
import { Toaster } from "solid-toast";

import "./index.css";
import "maplibre-gl/dist/maplibre-gl.css";
Expand All @@ -24,17 +25,20 @@ const Blank: Component = () => <></>;

render(
() => (
<HashRouter>
<Route path="/" component={Navbar}>
<Route path="/" component={Home} />
<Route path="/projects/:pid" component={ProjectEditor}>
<Route path="/" component={Blank} />
<Route path="/assets" component={ProjectAssetsEditor} />
<Route path="/manage" component={ProjectManager} />
<Route path="/tours/:tid" component={TourEditor} />
<>
<HashRouter>
<Route path="/" component={Navbar}>
<Route path="/" component={Home} />
<Route path="/projects/:pid" component={ProjectEditor}>
<Route path="/" component={Blank} />
<Route path="/assets" component={ProjectAssetsEditor} />
<Route path="/manage" component={ProjectManager} />
<Route path="/tours/:tid" component={TourEditor} />
</Route>
</Route>
</Route>
</HashRouter>
</HashRouter>
<Toaster position="bottom-right" toastOptions={{ duration: 10000 }} />
</>
),
root!
);
Expand Down
7 changes: 0 additions & 7 deletions src/pages/login/Login.module.css

This file was deleted.

Loading

0 comments on commit 828dc80

Please sign in to comment.