images-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev b674d6e71b51
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 604467e480f8468389092a3b
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
src/ui.tsx
// Small shared pieces: toast, saving and sharing a file, sizes.
import { useEffect, useState } from "react";

let pushToast: ((text: string) => void) | null = null;
export function toast(text: string) { pushToast?.(text); }

export function Toaster() {
  const [shown, setShown] = useState<{ text: string; n: number; leaving: boolean } | null>(null);
  useEffect(() => {
    let timer: number | undefined;
    let n = 0;
    pushToast = (text) => {
      setShown({ text, n: ++n, leaving: false });
      window.clearTimeout(timer);
      timer = window.setTimeout(() => setShown((t) => t && { ...t, leaving: true }), 2600);
    };
    return () => { pushToast = null; window.clearTimeout(timer); };
  }, []);
  if (!shown) return null;
  return (
    <div key={shown.n} className={`toast${shown.leaving ? " leaving" : ""}`} role="status"
      onAnimationEnd={() => shown.leaving && setShown(null)}>
      {shown.text}
    </div>
  );
}

/** Hands a file made on this device to the browser's download. */
export function save(blob: Blob, name: string) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = name;
  document.body.append(a);
  a.click();
  a.remove();
  window.setTimeout(() => URL.revokeObjectURL(url), 60_000);
  toast(`Saved ${name} (${size(blob.size)})`);
}

/** Phones can hand images to the share sheet, which has Save Image (to Photos on iPhone). */
export const canShareFiles = (() => {
  try {
    return window.matchMedia("(pointer: coarse)").matches && !!navigator.canShare?.({ files: [new File([""], "a.png", { type: "image/png" })] });
  } catch {
    return false;
  }
})();

export async function share(files: File[]) {
  try {
    await navigator.share({ files });
  } catch (err) {
    if ((err as Error).name !== "AbortError") toast("This browser could not share the images. Use Download instead.");
  }
}

// A no-break space keeps the number and its unit on one line.
export function size(bytes: number): string {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
}

Change history

Quality pass: background removal, blur background, paste images
b674d6e71b · 5 hours ago
Bounded source sync
c6622bcbd1 · 1 day ago
Bounded source sync
92ecc89502 · 1 day ago
Bounded source sync
ae2f8b8be0 · 1 day ago