diff --git a/package.json b/package.json
index 759094c..528d5e8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jank",
- "version": "26.15.2",
+ "version": "26.15.3",
"description": "A TweetDeck-style multi-column deck for Nostr — just another nostr klient",
"type": "module",
"author": "DocNR",
diff --git a/src/components/Column/ColumnHeader/index.tsx b/src/components/Column/ColumnHeader/index.tsx
index ab13659..87f8a3f 100644
--- a/src/components/Column/ColumnHeader/index.tsx
+++ b/src/components/Column/ColumnHeader/index.tsx
@@ -10,7 +10,7 @@ import { useUserPreferences } from '@/providers/UserPreferencesProvider'
import { TColumn } from '@/types/column'
import { notificationUnreadCountAtom } from '@/atoms/notification-unread-count'
import { useAtomValue } from 'jotai'
-import { Pin, PinOff, X } from 'lucide-react'
+import { X } from 'lucide-react'
import { HTMLAttributes, MouseEvent as ReactMouseEvent, memo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import ColumnHeaderMenu from './ColumnHeaderMenu'
@@ -20,20 +20,16 @@ import { signingState } from './signing-state'
/**
* Column header. Adaptive layout:
* - matched / view-only columns: a single row —
- * avatar · label · [signing chip] · ——— · 📌 · ⋯ · ✕
+ * avatar · label · [signing chip] · ——— · ⋯ · ✕
* - mismatched ("loud") columns: two rows — row 1 carries identity + controls,
* row 2 is the full-width "Acting as" signing indicator so it can never be
* squeezed or clipped.
*
- * Pin/unpin stays an inline button (the icon is the pin-state indicator —
- * lit when pinned, muted when transient). Compose + the list-style toggle
- * live in the ⋯ ColumnHeaderMenu.
+ * Compose + the list-style toggle live in the ⋯ ColumnHeaderMenu.
*/
const ColumnHeader = memo(function ColumnHeader({
column,
onRemove,
- onPin,
- onUnpin,
onScrollToTop,
dragHandleProps,
isFocused,
@@ -44,8 +40,6 @@ const ColumnHeader = memo(function ColumnHeader({
}: {
column: TColumn
onRemove: (id: string) => void
- onPin: (id: string) => void
- onUnpin: (id: string) => void
/** Scrolls the column body to the top. Fired on a plain title-bar click
* (not on the inner controls or a drag). */
onScrollToTop: () => void
@@ -145,39 +139,6 @@ const ColumnHeader = memo(function ColumnHeader({
)}
- {column.transient ? (
-
-
-
-
- {t('Pin column')}
-
- ) : (
-
-
-
-
- {t('Unpin column')}
-
- )}
{showMenu && (
{
- const a = getActive()
- return !!a && a.transient === true
- },
- run: () => {
- const a = getActive()
- if (a) pinColumn(a.id)
- }
- })
- list.push({
- id: 'column.unpin',
- label: t('Unpin column'),
- group: 'columns',
- condition: () => {
- const a = getActive()
- return !!a && a.transient !== true
- },
- run: () => {
- const a = getActive()
- if (a) unpinColumn(a.id)
- }
- })
- list.push({
- id: 'column.closeAllUnpinned',
- label: t('Close all unpinned columns'),
+ id: 'column.closeAllTransient',
+ label: t('Close all temporary columns'),
group: 'columns',
condition: () => columns.some((c) => c.transient === true),
- run: () => closeAllUnpinned()
+ run: () => closeAllTransient()
})
list.push({
id: 'column.moveLeft',
@@ -489,10 +461,8 @@ export default function StarterCommands() {
accounts,
account?.pubkey,
profileByPubkey,
- pinColumn,
- unpinColumn,
removeColumn,
- closeAllUnpinned,
+ closeAllTransient,
reorderColumns,
focusOrCreateColumn,
switchAccount,
diff --git a/src/components/DeckArea/index.tsx b/src/components/DeckArea/index.tsx
index ec33a3b..b281aa9 100644
--- a/src/components/DeckArea/index.tsx
+++ b/src/components/DeckArea/index.tsx
@@ -145,7 +145,7 @@ export default function DeckArea() {
if (activeColumnId !== null) setActiveColumnId(null)
// Defensive: the modal-split rule wraps `column.close` to exit beam
// before removing, so single-column close lands here with beam already
- // OFF. Catches bulk-close paths (closeAllUnpinned) and any future
+ // OFF. Catches bulk-close paths (closeAllTransient) and any future
// out-of-band removal.
if (focusBeamActive) setFocusBeamActive(false)
return
diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts
index 9d00ab6..3c6beb5 100644
--- a/src/i18n/locales/en.ts
+++ b/src/i18n/locales/en.ts
@@ -1107,6 +1107,7 @@ export default {
'Your agent never gets your signing key — your signer still gates every event you publish. {{brand}} must stay open in a browser tab for your agent to work.':
'Your agent never gets your signing key — your signer still gates every event you publish. {{brand}} must stay open in a browser tab for your agent to work.',
'Columns in this deck that view your other paired {{brand}} accounts (their npubs become visible to the agent)':
- 'Columns in this deck that view your other paired {{brand}} accounts (their npubs become visible to the agent)'
+ 'Columns in this deck that view your other paired {{brand}} accounts (their npubs become visible to the agent)',
+ 'Close all temporary columns': 'Close all temporary columns'
}
}
diff --git a/src/providers/ColumnsProvider.tsx b/src/providers/ColumnsProvider.tsx
index 52b4cd1..d3eed22 100644
--- a/src/providers/ColumnsProvider.tsx
+++ b/src/providers/ColumnsProvider.tsx
@@ -68,10 +68,6 @@ type TColumnsContext = {
source: { viewContext: string; signingIdentity: string | null } | null,
parentColumnId?: string
) => void
- /** Promote a transient column to persisted (transient: false), then write through to localStorage. */
- pinColumn: (id: string) => void
- /** Demote a pinned column to transient (transient: true). Drops it from the persisted set without removing it from the live deck. */
- unpinColumn: (id: string) => void
/**
* Remove any column (transient or persisted). Animates: marks the id
* as removing for 280ms (column-fade-out keyframe) before the actual
@@ -79,8 +75,8 @@ type TColumnsContext = {
* already in `removingIds`.
*/
removeColumn: (id: string) => void
- /** Remove every column where transient === true. Pinned columns are untouched. */
- closeAllUnpinned: () => void
+ /** Remove every column where transient === true. Permanent columns are untouched. */
+ closeAllTransient: () => void
/**
* Patch a column's `config` object in-place (shallow merge). Persists
* immediately. Used today by the per-column notification list-style
@@ -810,31 +806,6 @@ export function ColumnsProvider({ children }: { children: ReactNode }) {
[transientColumnMode, account?.pubkey, requestFocusedColumn]
)
- const pinColumn = useCallback(
- (id: string) => {
- setColumns((prev) => {
- const next = prev.map((c) => (c.id === id ? { ...c, transient: false } : c))
- persist(next)
- return next
- })
- },
- [persist]
- )
-
- const unpinColumn = useCallback(
- (id: string) => {
- setColumns((prev) => {
- const next = prev.map((c) => (c.id === id ? { ...c, transient: true } : c))
- // Persist drops `transient: true` entries, so demoting a column writes
- // through to the persisted set as "removed". The column stays in the
- // live deck until the user explicitly closes it (or reloads).
- persist(next)
- return next
- })
- },
- [persist]
- )
-
// 280ms matches the `column-fade-out` keyframe in src/index.css. Holding
// the id in `removingIds` for the duration of the animation is what makes
// the keyboard shortcut animate identically to the mouse X click — both
@@ -871,7 +842,7 @@ export function ColumnsProvider({ children }: { children: ReactNode }) {
[persist]
)
- const closeAllUnpinned = useCallback(() => {
+ const closeAllTransient = useCallback(() => {
setColumns((prev) => {
const next = prev.filter((c) => !c.transient)
persist(next)
@@ -1185,10 +1156,8 @@ export function ColumnsProvider({ children }: { children: ReactNode }) {
addColumn,
focusOrCreateColumn,
addTransientColumn,
- pinColumn,
- unpinColumn,
removeColumn,
- closeAllUnpinned,
+ closeAllTransient,
updateColumnConfig,
closeColumnsForAccount,
reorderColumns,
@@ -1220,10 +1189,8 @@ export function ColumnsProvider({ children }: { children: ReactNode }) {
addColumn,
focusOrCreateColumn,
addTransientColumn,
- pinColumn,
- unpinColumn,
removeColumn,
- closeAllUnpinned,
+ closeAllTransient,
updateColumnConfig,
v2Decks,
activeDeck,
diff --git a/src/release-notes.ts b/src/release-notes.ts
index f44ab17..2057623 100644
--- a/src/release-notes.ts
+++ b/src/release-notes.ts
@@ -14,6 +14,13 @@ export type ReleaseNote = {
}
export const RELEASE_NOTES: ReleaseNote[] = [
+ {
+ version: '26.15.3',
+ date: '2026-06-17',
+ highlights: [
+ 'Columns you open by clicking are now always temporary and clear when you reload; the per-column pin button is gone. Use the + button to add the columns you want to keep.'
+ ]
+ },
{
version: '26.15.2',
date: '2026-06-16',