f4688137bc
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.
69 lines
2.2 KiB
TypeScript
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];
|
|
}
|