Files
eranos/src/hooks/useDefaultPostCountry.ts
T
mkfain f4688137bc Persistent default country, drop weather + organize feed, simplify mode switcher
Five small UX improvements bundled together.

Default post-to-country with localStorage persistence
- New `useDefaultPostCountry` hook (localStorage-backed) hydrates the
  composer's destination from a saved preference on every fresh compose.
- ComposeBox's country-destination picker (formerly a shadcn Select)
  becomes a DropdownMenu so it can mix country options with an action
  item.
- New "Set as default" item appears at the bottom of the dropdown
  when the current selection is not already the saved default; clicking
  it persists the choice and shows a toast.
- A passive "Country X is your default" label replaces the action
  item when the current selection already is the default.
- resetComposeState now resets to the saved default instead of
  hardcoded 'world', so the next compose lands where the user expects.
- The existing snap-back-to-world guard now also clears the saved
  default if it points at a country the user has just unfollowed.

Remove weather from country feed pages
- Drop `WeatherVitalsRow`'s weather panel — the row keeps the
  population / languages / currency vitals but no longer renders
  temperature, sky description, or icon.
- Remove the live day/night sky-overlay flip on the country hero;
  default to the warm daytime gradient.
- Remove the `PrecipitationEffect` overlay (animated rain/snow) from
  country pages.
- Delete the now-orphan `useWeather` hook and
  `PrecipitationEffect` component.

Remove organization activity feed from /communities
- Drop the `OrganizationActivityFeed` section and its helpers.
- /communities is now a directory page: hero + My organizations shelf
  + Featured organizations shelf.
- Delete the now-orphan `useOrganizationHomeActivityFeed` and
  `useOrganizationMembersOnlyFilter` hooks.

Compact FeedModeSwitcher
- Strip the per-item descriptions ("Campaigns, pledges, donations,
  and Agora posts", etc.) from the home-feed mode dropdown.
- Each menu item is now a single line: icon + label + optional check.
- Shrink menu width from w-72 to w-56 to match the new content density.
- Keep the disabled-Following tooltip — that's a state explanation,
  not help text.
2026-05-21 20:26:01 -05:00

69 lines
2.2 KiB
TypeScript

import { useCallback, useState } from 'react';
import { useAppContext } from '@/hooks/useAppContext';
import { getCountryInfo } from '@/lib/countries';
import { getStorageKey } from '@/lib/storageKey';
/**
* Sentinel value for "post to the global / world feed" (a plain kind 1 note
* with no country root). Matches the value used by ComposeBox's `destination`
* state.
*/
export type PostCountryDestination = 'world' | string;
const WORLD = 'world' as const;
const STORAGE_SUFFIX = 'compose-default-country';
function readStored(key: string): PostCountryDestination {
try {
const raw = localStorage.getItem(key);
if (!raw || raw === WORLD) return WORLD;
// Validate against the country directory so a stale code (or an
// invalid string from a different version) doesn't pin the composer
// to a country that no longer parses.
return getCountryInfo(raw) ? raw : WORLD;
} catch {
return WORLD;
}
}
/**
* The user's preferred default post destination — either `'world'` (plain
* kind 1) or an ISO 3166 country code (NIP-22 country-rooted kind 1111).
*
* Persisted to localStorage so the choice survives reloads. Hydrates
* synchronously from storage on first render, so the composer never flashes
* the wrong default.
*
* The act of selecting a destination in ComposeBox does NOT auto-save the
* default — there is an explicit "Set as default" affordance for that. This
* means a user posting once to a country they don't normally post to does
* not unintentionally change their default.
*/
export function useDefaultPostCountry(): [
PostCountryDestination,
(value: PostCountryDestination) => void,
] {
const { config } = useAppContext();
const key = getStorageKey(config.appId, STORAGE_SUFFIX);
const [value, setValue] = useState<PostCountryDestination>(() => readStored(key));
const setDefault = useCallback(
(next: PostCountryDestination) => {
setValue(next);
try {
if (next === WORLD) {
localStorage.setItem(key, WORLD);
} else if (getCountryInfo(next)) {
localStorage.setItem(key, next);
}
} catch {
// localStorage unavailable — non-critical.
}
},
[key],
);
return [value, setDefault];
}