~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
66 lines · 1.9 KB Raw History
import { useState } from 'react';
import { Panel } from '#/components/atoms/panel.jsx';
import { ErrorNotice } from '#/components/molecules/error-notice.jsx';
import { Section } from '#/components/molecules/section.jsx';
import { SelectField } from '#/components/molecules/select-field.jsx';
import { post } from '#/lib/api.js';
import { queryKeys, useApiMutation } from '#/lib/query.js';
import { applyTheme } from '#/lib/theme.js';

const THEMES = [
  ['system', 'Match this device'],
  ['light', 'Light'],
  ['dark', 'Dark'],
];

/**
 * The console's color palette. A change applies right away and is stored with
 * the account, so it follows the account to other browsers. On a server that
 * cannot store UI state the choice is shown but disabled.
 * @param {{data: {theme: string, features: {settings: boolean}}}} props
 */
export function AppearanceCard({ data }) {
  const available = data.features.settings;
  const [theme, setTheme] = useState(data.theme);
  const { run, busy, error } = useApiMutation([queryKeys.overview]);

  const change = (next) => {
    const previous = theme;
    setTheme(next);
    applyTheme(next);
    run(async () => {
      try {
        await post('/settings/appearance', { theme: next });
      } catch (err) {
        setTheme(previous);
        applyTheme(previous);
        throw err;
      }
    });
  };

  return (
    <Panel>
      <Section
        title="Appearance"
        description="Light, dark, or whatever this device prefers."
      >
        <div className="flex flex-col gap-4">
          <SelectField
            label="Theme"
            options={THEMES}
            value={theme}
            onChange={change}
            disabled={busy || !available}
          />
          {!available && (
            <p className="text-[13px] text-muted-foreground">
              This server does not store settings.
            </p>
          )}
          <ErrorNotice error={error} />
        </div>
      </Section>
    </Panel>
  );
}