Prep for T3k Flow of user and tone URLS.
This commit is contained in:
@@ -1129,6 +1129,28 @@ export default withStyles(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleT3kLinkClick(href: string): boolean {
|
||||||
|
if (!href.startsWith("https://tone3000.com/")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
// STUB: Waiting for a way to do a popup flow starting with a tone or user home page.
|
||||||
|
// let uri = new URL(href);
|
||||||
|
// if (uri.pathname.split("/").filter(segment => segment.length > 0).length === 1) {
|
||||||
|
// // It's a username. Launch a select flow with username as a filter.
|
||||||
|
// let username = uri.pathname.split("/").filter(segment => segment.length > 0)[0];
|
||||||
|
// this.model.showTone3000DownloadPopup(
|
||||||
|
// Tone3000DownloadType.Nam,
|
||||||
|
// this.state.currentDirectory,
|
||||||
|
// {
|
||||||
|
// username: username
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const isTracksDirectory = this.isTracksDirectory();
|
const isTracksDirectory = this.isTracksDirectory();
|
||||||
const isToobNamModelFile = this.props.fileProperty.patchProperty === ToobNamModelFileUrl;
|
const isToobNamModelFile = this.props.fileProperty.patchProperty === ToobNamModelFileUrl;
|
||||||
@@ -1803,6 +1825,9 @@ export default withStyles(
|
|||||||
<TextInfoDialog open={true}
|
<TextInfoDialog open={true}
|
||||||
title={pathFileNameOnly(this.state.textFileName)}
|
title={pathFileNameOnly(this.state.textFileName)}
|
||||||
fileName={this.state.textFileName} onClose={() => this.setState({ textFileName: undefined })}
|
fileName={this.state.textFileName} onClose={() => this.setState({ textFileName: undefined })}
|
||||||
|
onT3kLinkClick={(href) => {
|
||||||
|
return this.handleT3kLinkClick(href); }
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</DialogEx>
|
</DialogEx>
|
||||||
|
|||||||
@@ -773,7 +773,10 @@ export class PiPedalModel //implements PiPedalModel
|
|||||||
|
|
||||||
showTone3000DownloadPopup(
|
showTone3000DownloadPopup(
|
||||||
downloadType: Tone3000DownloadType,
|
downloadType: Tone3000DownloadType,
|
||||||
downloadPath: string
|
downloadPath: string,
|
||||||
|
options?: {
|
||||||
|
userName?: string;
|
||||||
|
}
|
||||||
): void {
|
): void {
|
||||||
if (this.tone3000DownloadHandler === null) {
|
if (this.tone3000DownloadHandler === null) {
|
||||||
this.tone3000DownloadHandler = new Tone3000DownloadHandler(this);
|
this.tone3000DownloadHandler = new Tone3000DownloadHandler(this);
|
||||||
@@ -781,7 +784,7 @@ export class PiPedalModel //implements PiPedalModel
|
|||||||
this.tone3000DownloadHandler.launchTone3000Popup(
|
this.tone3000DownloadHandler.launchTone3000Popup(
|
||||||
downloadType,
|
downloadType,
|
||||||
downloadPath,
|
downloadPath,
|
||||||
);
|
options);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1375,6 +1378,7 @@ export class PiPedalModel //implements PiPedalModel
|
|||||||
}
|
}
|
||||||
this.debug = !!data.debug;
|
this.debug = !!data.debug;
|
||||||
let { socket_server_port, socket_server_address, max_upload_size } = data;
|
let { socket_server_port, socket_server_address, max_upload_size } = data;
|
||||||
|
|
||||||
if ((!socket_server_address) || socket_server_address === "*") {
|
if ((!socket_server_address) || socket_server_address === "*") {
|
||||||
socket_server_address = window.location.hostname;
|
socket_server_address = window.location.hostname;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2026 Robin E. R. Davies
|
||||||
|
* All rights reserved.
|
||||||
|
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Root } from 'hast';
|
||||||
|
|
||||||
|
// Rewrite <a> tags with "t3klink?id=xxx" hrefs to call the T3kLinkHandler handler instead of navigating to a new page.
|
||||||
|
|
||||||
|
// // Hook in the rewriter as follows:
|
||||||
|
// <ReactMarkdown urlTransform={urlTransform} rehypePlugins={
|
||||||
|
// [
|
||||||
|
// [remarkGfm],
|
||||||
|
// [rehypeRaw],
|
||||||
|
// [rehypeSanitize, extendedSchema],
|
||||||
|
// [rehypeExternalLinks, {target: '_blank'}]
|
||||||
|
// [rewriteT3kUrls, {...options}]
|
||||||
|
// ]}>
|
||||||
|
// {this.state.textFileContent}
|
||||||
|
// </ReactMarkdown>
|
||||||
|
|
||||||
|
type HastNode = {
|
||||||
|
type: string;
|
||||||
|
tagName?: string;
|
||||||
|
properties?: Record<string, unknown>;
|
||||||
|
children?: HastNode[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type T3kLinkClickHandler = (href: string) => boolean;
|
||||||
|
|
||||||
|
export interface RewriteT3kUrlsOptions {
|
||||||
|
prefixUrl?: string;
|
||||||
|
onT3kLinkClick?: T3kLinkClickHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default callback. Supply `onT3kLinkClick` in options to handle links.
|
||||||
|
export function T3kLinkHandler(href: string): boolean {
|
||||||
|
void href;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getHref(properties: Record<string, unknown>): string | null {
|
||||||
|
const href = properties.href;
|
||||||
|
return typeof href === 'string' ? href : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rewriteNode(node: HastNode, prefixUrl: string, onT3kLinkClick: T3kLinkClickHandler): void {
|
||||||
|
if (node.type === 'element' && node.tagName === 'a') {
|
||||||
|
const properties = node.properties ?? {};
|
||||||
|
const href = getHref(properties);
|
||||||
|
if (href && href.startsWith(prefixUrl)) {
|
||||||
|
properties.target = '_blank';
|
||||||
|
properties.rel = 'noopener noreferrer';
|
||||||
|
properties.onClick = (event: { preventDefault?: () => void; stopPropagation?: () => void; }) => {
|
||||||
|
const handled = onT3kLinkClick(href);
|
||||||
|
if (handled) {
|
||||||
|
event.preventDefault?.();
|
||||||
|
event.stopPropagation?.();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
node.properties = properties;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.children) {
|
||||||
|
for (const child of node.children) {
|
||||||
|
rewriteNode(child, prefixUrl, onT3kLinkClick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function rewriteT3kUrls(options?: RewriteT3kUrlsOptions) {
|
||||||
|
const prefixUrl = options?.prefixUrl;
|
||||||
|
const onT3kLinkClick = options?.onT3kLinkClick ?? ((href: string) => T3kLinkHandler(href));
|
||||||
|
return (tree: Root) => {
|
||||||
|
if (!prefixUrl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rewriteNode(tree as unknown as HastNode, prefixUrl, onT3kLinkClick);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user