aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/group-page.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/group-page.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/group-page.js35
1 files changed, 33 insertions, 2 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js
index fe858b2..a2d6c18 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/group-page.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/group-page.js
@@ -5,6 +5,7 @@ import { t } from './i18n.js';
import { Icon } from './icon.js';
import { transfers } from './transfers.js';
import { downloadEntry } from './file-utils.js';
+import { resolveLinkedPath } from './group-link.js';
import {
HUB, session, hubFetch, ensureFreshToken,
_loadBundleKey, _loadRecoveryKey, _storeBundleKey,
@@ -33,7 +34,8 @@ import { clearPending, nodePkFromLink, pendingFor } from './invite-link.js';
*/
function GroupPage({ groupId, group, token, username, userId, userPrefs,
onRefreshAuth, onJoined, onGroupUpdated, onPresence, onLeft,
- onPlayQueue: parentOnPlayQueue, onStopMusic }) {
+ onPlayQueue: parentOnPlayQueue, onStopMusic,
+ openPath = '', onLinkOpened }) {
const [status, setStatus] = useState('idle');
// The tab bar pins under the navigation bar and tells the application's own
// toolbar how far down to pin (style.css, "Sticky chrome").
@@ -313,12 +315,18 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs,
});
}, []);
+ // Which group `entries` is the index of. The page is not remounted between
+ // groups, so for one render after a switch `status` and `entries` are still
+ // the last group's — and a link into the new one must not be looked up there.
+ const indexGroupRef = useRef(null);
+
// One place that takes an index from the node and puts it everywhere it has to
// go. Deleting a file used to refresh the table and leave the cache alone, so
// the search page went on offering a file that no longer existed until the
// group was reconnected.
const applyIndex = useCallback((indexMsg) => {
const fresh = indexMsg.entries || [];
+ indexGroupRef.current = groupId;
setEntries(fresh);
if (indexMsg.dirs) setNodeDirs(indexMsg.dirs);
if (indexMsg.roots) setNodeRoots(indexMsg.roots);
@@ -731,6 +739,28 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs,
await downloadEntry(transfers, transport, gekRef.current, entry);
}, []);
+ // A link that named a path inside the group (`#/name@owner/root/dir/file`,
+ // group-link.js): a file is downloaded, and Files opens on its folder either
+ // way. Acted on once the index is in — before that, nothing can say whether
+ // the path is a file, a folder or nothing — and then handed back to the
+ // router, which takes the path out of the address so a reload does not
+ // download it again.
+ const [openDirectory, setOpenDirectory] = useState(null);
+ useEffect(() => { setOpenDirectory(null); }, [groupId]);
+ useEffect(() => {
+ if (!openPath || status !== 'connected' || indexGroupRef.current !== groupId) return;
+ const target = resolveLinkedPath(entries, nodeDirs, openPath);
+ if (!target) {
+ setError(t('group.link_path_unknown', { path: openPath }));
+ } else {
+ const dir = target.kind === 'file' ? (target.entry.path || '') : target.dir;
+ setOpenDirectory({ dir });
+ chooseTab('files');
+ if (target.kind === 'file') downloadFileForModal(target.entry);
+ }
+ if (onLinkOpened) onLinkOpened();
+ }, [openPath, status, groupId]);
+
const refreshIndex = useCallback(async () => {
const transport = transportRef.current;
if (!transport || !transport.connected) return;
@@ -987,7 +1017,8 @@ function GroupPage({ groupId, group, token, username, userId, userPrefs,
</div>
${apps.map(a => tab === a.key && html`
- <${a.Component} key=${a.key + '-' + groupId} ...${commonProps} />
+ <${a.Component} key=${a.key + '-' + groupId} ...${commonProps}
+ ...${a.key === 'files' ? { openDirectory } : {}} />
`)}
${tab === 'settings' && html`