feat(android): a name is not a link on a phone, the menu carries it
Every track, album and artist name in the app navigates through `utils/explore-link.ts`, and every sentence of how it does that is a desktop compromise: the navigation is held for one double-click interval so double-clicking the row can still play it, and the target is a few characters of text inside a row. On touch that is a delay on an ambiguous target, and since #63 the row's own tap claims the click anyway -- so the link was unreachable as well as fiddly. So below the phone breakpoint a name renders as plain text and the row's context menu carries the destination instead: `go-to-menu.ts` draws "Go to Artist" / "Go to Album" under exactly the condition the link is not, using `explore-link`'s own exported routing so an untagged entity reaches the library page by the same lookup. Three things this leans on. Suppressing a link with no menu behind it is not a smaller affordance but a destination the phone cannot reach, so `keepOnPhone` is the exception for the three surfaces with no row menu. The items are drawn for a single selection only, which is the Play item's rule one step on. And there is no "Go to Genre", because no row renders a genre link to lose -- that would be new navigation rather than a replacement. Closes #67
This commit is contained in:
@@ -51,6 +51,8 @@ import {
|
||||
trackLink,
|
||||
exploreLinkStyles,
|
||||
} from '@utils/explore-link';
|
||||
import { goToMenuItems } from '@utils/go-to-menu';
|
||||
import type { GoToTarget } from '@utils/go-to-menu';
|
||||
import {
|
||||
setDragPayload,
|
||||
emitDragActive,
|
||||
@@ -1954,6 +1956,33 @@ export class TrackList
|
||||
emitDragActive(false);
|
||||
};
|
||||
|
||||
/**
|
||||
* The row the menu can navigate from, for "Go to Artist" / "Go to
|
||||
* Album" — which exist only below the phone breakpoint, where the
|
||||
* row's own names are no longer links (#67).
|
||||
*
|
||||
* One row only, on the rule the Play item already states: one row
|
||||
* is a position, several are an explicit choice of *those* tracks,
|
||||
* and "go to the album" of five different albums means nothing.
|
||||
*/
|
||||
private get goToTarget(): GoToTarget | undefined {
|
||||
if (this.selection.selectionCount !== 1) return undefined;
|
||||
|
||||
const [path] = this.selection.selectedItems;
|
||||
const track = path
|
||||
? tracksByFilePath(this.tracks).get(path)
|
||||
: undefined;
|
||||
|
||||
if (!track) return undefined;
|
||||
|
||||
return {
|
||||
artistName: track.ArtistName,
|
||||
artistMBID: track.ArtistMBID,
|
||||
albumName: track.Album,
|
||||
albumMBID: track.ReleaseGroupMBID,
|
||||
};
|
||||
}
|
||||
|
||||
private onContextMenuAction(action: string) {
|
||||
const filePaths =
|
||||
this.selection.getSelectedKeysOrdered();
|
||||
@@ -2563,6 +2592,13 @@ export class TrackList
|
||||
></wa-icon>
|
||||
Track Details
|
||||
</wa-dropdown-item>
|
||||
${goToMenuItems(this.goToTarget, {
|
||||
onSelect: () => {
|
||||
this.selection.clear();
|
||||
this.ctxMenu.close();
|
||||
},
|
||||
onHover: () => this.ctxMenu.closePlaylistSubmenu(),
|
||||
})}
|
||||
<wa-dropdown-item
|
||||
@click=${() =>
|
||||
this.onContextMenuAction(
|
||||
|
||||
Reference in New Issue
Block a user