feat(cordn): 'Open in Staircase' link on the crew coordinator card
CrewCoordinatorCard now offers a StaircaseLink in both branches: our coordinator (SKATESPOTS_COORDINATOR add-link) when a crew has none, and the crew's own coordinator add-link when it has a pubkey (falls back to the Cordn home otherwise). Lets crews jump to real MLS chat in the native Cordn client.
This commit is contained in:
parent
a8e411faa0
commit
e262aed938
4 changed files with 34 additions and 2 deletions
|
|
@ -2134,7 +2134,10 @@ The community relay moved off the hosted relay.tools instance
|
||||||
default; **Settings → Coordinator** shows a "Use SkateSpots coordinator" block
|
default; **Settings → Coordinator** shows a "Use SkateSpots coordinator" block
|
||||||
and **CrewForm** prefills it for new crews. Disclosure copy lives in
|
and **CrewForm** prefills it for new crews. Disclosure copy lives in
|
||||||
`socialUi.coordinator.ourDefault*` + the existing `privacyNote` (coordinators see
|
`socialUi.coordinator.ourDefault*` + the existing `privacyNote` (coordinators see
|
||||||
ciphertext + metadata, never contents).
|
ciphertext + metadata, never contents). `CrewCoordinatorCard` shows an **"Open in
|
||||||
|
Staircase"** link (`coordinatorAddUrl`) in both branches (the native Cordn client
|
||||||
|
for real MLS) — our coordinator by default, a BYO coordinator's add-link when it
|
||||||
|
has a pubkey.
|
||||||
- **Cutover (2026-10-12):** `SKATE_RELAY` (`src/lib/types.ts`) → the new relay; the
|
- **Cutover (2026-10-12):** `SKATE_RELAY` (`src/lib/types.ts`) → the new relay; the
|
||||||
default pools, the DM/CVM/zap relay arrays, the `cvm-server` + `push-service`
|
default pools, the DM/CVM/zap relay arrays, the `cvm-server` + `push-service`
|
||||||
defaults, and the archive default all point at the new relay.
|
defaults, and the archive default all point at the new relay.
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { useTranslation } from '@/contexts/language';
|
||||||
import { genUserName } from '@/lib/genUserName';
|
import { genUserName } from '@/lib/genUserName';
|
||||||
import { sanitizeUrl, urlDomain } from '@/lib/sanitizeUrl';
|
import { sanitizeUrl, urlDomain } from '@/lib/sanitizeUrl';
|
||||||
import { resolveCordnEndpoint } from '@/lib/cordn/endpoint';
|
import { resolveCordnEndpoint } from '@/lib/cordn/endpoint';
|
||||||
import { CORDN_RELAY_URL } from '@/lib/coordinator';
|
import { CORDN_RELAY_URL, coordinatorAddUrl, CORDN_HOME, SKATESPOTS_COORDINATOR } from '@/lib/coordinator';
|
||||||
import type { CrewCoordinator, SkateCrew } from '@/lib/types';
|
import type { CrewCoordinator, SkateCrew } from '@/lib/types';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { nip19 } from 'nostr-tools';
|
||||||
|
|
||||||
|
|
@ -61,6 +61,7 @@ export function CrewCoordinatorCard({
|
||||||
<span className="font-semibold text-gray-200">{t('socialUi.crewCoordinator.chatWord')}</span> {t('socialUi.crewCoordinator.defaultB')}{' '}
|
<span className="font-semibold text-gray-200">{t('socialUi.crewCoordinator.chatWord')}</span> {t('socialUi.crewCoordinator.defaultB')}{' '}
|
||||||
<span className="font-bold text-teal-300">{t('socialUi.crewCoordinator.e2ee')}</span> {t('socialUi.crewCoordinator.defaultC')}
|
<span className="font-bold text-teal-300">{t('socialUi.crewCoordinator.e2ee')}</span> {t('socialUi.crewCoordinator.defaultC')}
|
||||||
</p>
|
</p>
|
||||||
|
<StaircaseLink coordinator={SKATESPOTS_COORDINATOR} />
|
||||||
{isFounder && (
|
{isFounder && (
|
||||||
<p className="text-[11px] leading-relaxed text-gray-600">
|
<p className="text-[11px] leading-relaxed text-gray-600">
|
||||||
{t('socialUi.crewCoordinator.advancedA')}{' '}
|
{t('socialUi.crewCoordinator.advancedA')}{' '}
|
||||||
|
|
@ -101,6 +102,13 @@ export function CrewCoordinatorCard({
|
||||||
|
|
||||||
{coordinator.operator && <CoordinatorOperator pubkey={coordinator.operator} />}
|
{coordinator.operator && <CoordinatorOperator pubkey={coordinator.operator} />}
|
||||||
|
|
||||||
|
<StaircaseLink
|
||||||
|
coordinator={{
|
||||||
|
pubkey: coordinator.pubkey,
|
||||||
|
relays: /^wss?:\/\//i.test(coordinator.url) ? [coordinator.url] : [],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{endpoint && (
|
{endpoint && (
|
||||||
<p className="text-[11px] leading-relaxed text-gray-500">
|
<p className="text-[11px] leading-relaxed text-gray-500">
|
||||||
{t('socialUi.crewCoordinator.deliveredOver')}{' '}
|
{t('socialUi.crewCoordinator.deliveredOver')}{' '}
|
||||||
|
|
@ -135,6 +143,25 @@ export function CrewCoordinatorCard({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Link to open a coordinator in Staircase (the native Cordn client) for real
|
||||||
|
* MLS chat. Falls back to the Cordn home when the coordinator has no pubkey. */
|
||||||
|
function StaircaseLink({ coordinator }: { coordinator: { pubkey?: string; relays?: string[] } }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const href = coordinator.pubkey
|
||||||
|
? coordinatorAddUrl({ pubkey: coordinator.pubkey, relays: coordinator.relays ?? [] })
|
||||||
|
: CORDN_HOME;
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center gap-1.5 rounded-lg border border-teal-500/30 bg-teal-500/10 px-2.5 py-1.5 text-xs font-bold text-teal-300 transition-colors hover:bg-teal-500/20"
|
||||||
|
>
|
||||||
|
<ExternalLink className="h-3.5 w-3.5" /> {t('socialUi.crewCoordinator.openInStaircase')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function CoordinatorEndpoint({ coordinator }: { coordinator: CrewCoordinator }) {
|
function CoordinatorEndpoint({ coordinator }: { coordinator: CrewCoordinator }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const safe = sanitizeUrl(coordinator.url);
|
const safe = sanitizeUrl(coordinator.url);
|
||||||
|
|
|
||||||
|
|
@ -4045,6 +4045,7 @@ socialUi: {
|
||||||
ownRelaySafe: "Nothing crew-specific leaves your crew's own relay.",
|
ownRelaySafe: "Nothing crew-specific leaves your crew's own relay.",
|
||||||
manage: 'Manage coordinator',
|
manage: 'Manage coordinator',
|
||||||
open: 'Open {{domain}}',
|
open: 'Open {{domain}}',
|
||||||
|
openInStaircase: 'Open in Staircase',
|
||||||
runBy: 'Coordinator run by',
|
runBy: 'Coordinator run by',
|
||||||
},
|
},
|
||||||
dms: {
|
dms: {
|
||||||
|
|
|
||||||
|
|
@ -4045,6 +4045,7 @@ socialUi: {
|
||||||
ownRelaySafe: 'Nada específico de la peña sale del relé propio de tu peña.',
|
ownRelaySafe: 'Nada específico de la peña sale del relé propio de tu peña.',
|
||||||
manage: 'Gestionar coordinador',
|
manage: 'Gestionar coordinador',
|
||||||
open: 'Abrir {{domain}}',
|
open: 'Abrir {{domain}}',
|
||||||
|
openInStaircase: 'Abrir en Staircase',
|
||||||
runBy: 'Coordinador gestionado por',
|
runBy: 'Coordinador gestionado por',
|
||||||
},
|
},
|
||||||
dms: {
|
dms: {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue