Make sure links open externally

This commit is contained in:
49lf
2024-07-31 15:08:18 -04:00
parent 4c2b807890
commit 871cc4df35
8 changed files with 33 additions and 12 deletions

View File

@ -1,4 +1,5 @@
import { ActionIcon, ActionIconProps } from './ActionIcon' import { ActionIcon, ActionIconProps } from './ActionIcon'
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
import React, { ForwardedRef, forwardRef } from 'react' import React, { ForwardedRef, forwardRef } from 'react'
import { paths } from 'lib/paths' import { paths } from 'lib/paths'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
@ -107,6 +108,7 @@ export const ActionButton = forwardRef((props: ActionButtonProps, ref) => {
ref={ref as ForwardedRef<HTMLAnchorElement>} ref={ref as ForwardedRef<HTMLAnchorElement>}
to={to || paths.INDEX} to={to || paths.INDEX}
className={classNames} className={classNames}
onClick={openExternalBrowserIfDesktop(to)}
{...rest} {...rest}
target="_blank" target="_blank"
> >

View File

@ -7,6 +7,7 @@ import { createAndOpenNewProject } from 'lib/desktopFS'
import { paths } from 'lib/paths' import { paths } from 'lib/paths'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath' import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import { useLspContext } from './LspProvider' import { useLspContext } from './LspProvider'
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
const HelpMenuDivider = () => ( const HelpMenuDivider = () => (
<div className="h-[1px] bg-chalkboard-110 dark:bg-chalkboard-80" /> <div className="h-[1px] bg-chalkboard-110 dark:bg-chalkboard-80" />
@ -141,6 +142,7 @@ function HelpMenuItem({
{as === 'a' ? ( {as === 'a' ? (
<a <a
{...(props as React.ComponentProps<'a'>)} {...(props as React.ComponentProps<'a'>)}
onClick={openExternalBrowserIfDesktop(props.href)}
className={`no-underline text-inherit ${baseClassName} ${className}`} className={`no-underline text-inherit ${baseClassName} ${className}`}
> >
{children} {children}

View File

@ -28,6 +28,7 @@ export function LowerRightControls({
async function reportbug(event: { preventDefault: () => void }) { async function reportbug(event: { preventDefault: () => void }) {
event?.preventDefault() event?.preventDefault()
event?.stopPropagation()
if (!coreDumpManager) { if (!coreDumpManager) {
// open default reporting option // open default reporting option

View File

@ -7,6 +7,7 @@ import { useConvertToVariable } from 'hooks/useToolbarGuards'
import { editorShortcutMeta } from './KclEditorPane' import { editorShortcutMeta } from './KclEditorPane'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
export const KclEditorMenu = ({ children }: PropsWithChildren) => { export const KclEditorMenu = ({ children }: PropsWithChildren) => {
const { enable: convertToVarEnabled, handleClick: handleConvertToVarClick } = const { enable: convertToVarEnabled, handleClick: handleConvertToVarClick } =
@ -60,6 +61,7 @@ export const KclEditorMenu = ({ children }: PropsWithChildren) => {
href="https://zoo.dev/docs/kcl" href="https://zoo.dev/docs/kcl"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
onClick={openExternalBrowserIfDesktop()}
> >
<span>Read the KCL docs</span> <span>Read the KCL docs</span>
<small> <small>
@ -78,6 +80,7 @@ export const KclEditorMenu = ({ children }: PropsWithChildren) => {
href="https://zoo.dev/docs/kcl-samples" href="https://zoo.dev/docs/kcl-samples"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
onClick={openExternalBrowserIfDesktop()}
> >
<span>KCL samples</span> <span>KCL samples</span>
<small> <small>

View File

@ -2,11 +2,6 @@ import { CommandLog, EngineCommandManager } from 'lang/std/engineConnection'
import { WebrtcStats } from 'wasm-lib/kcl/bindings/WebrtcStats' import { WebrtcStats } from 'wasm-lib/kcl/bindings/WebrtcStats'
import { OsInfo } from 'wasm-lib/kcl/bindings/OsInfo' import { OsInfo } from 'wasm-lib/kcl/bindings/OsInfo'
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import {
platform as tauriPlatform,
arch as tauriArch,
version as tauriKernelVersion,
} from '@tauri-apps/plugin-os'
import { APP_VERSION } from 'routes/Settings' import { APP_VERSION } from 'routes/Settings'
import { UAParser } from 'ua-parser-js' import { UAParser } from 'ua-parser-js'
import screenshot from 'lib/screenshot' import screenshot from 'lib/screenshot'
@ -70,12 +65,13 @@ export class CoreDumpManager {
getOsInfo(): Promise<string> { getOsInfo(): Promise<string> {
if (this.isDesktop()) { if (this.isDesktop()) {
const osinfo: OsInfo = { const osinfo: OsInfo = {
platform: tauriPlatform(), platform: window.electron.platform,
arch: tauriArch(), arch: window.electron.arch,
browser: 'tauri', browser: 'desktop',
version: tauriKernelVersion(), version: window.electron.version,
} }
return new Promise((resolve) => resolve(JSON.stringify(osinfo))) return new Promise((resolve) => resolve(JSON.stringify(osinfo)))
// (lf94) I'm not sure if this comment is specific to tauri or just desktop...
// TODO: get rid of promises now that the tauri api doesn't require them anymore // TODO: get rid of promises now that the tauri api doesn't require them anymore
} }

View File

@ -4,6 +4,7 @@ import fs from 'node:fs/promises'
import packageJson from '../../package.json' import packageJson from '../../package.json'
const open = (args: any) => ipcRenderer.invoke('dialog', args) const open = (args: any) => ipcRenderer.invoke('dialog', args)
const openExternal = (url: any) => ipcRenderer.invoke('shell.openExternal', url)
const showInFolder = (path: string) => ipcRenderer.invoke('shell.showItemInFolder', path) const showInFolder = (path: string) => ipcRenderer.invoke('shell.showItemInFolder', path)
const login = (host: string) => ipcRenderer.invoke('login', host) const login = (host: string) => ipcRenderer.invoke('login', host)
@ -47,10 +48,14 @@ import('@kittycad/lib').then((kittycad) => {
mkdir: fs.mkdir, mkdir: fs.mkdir,
// opens a dialog // opens a dialog
open, open,
// opens the URL
openExternal,
showInFolder, showInFolder,
getPath, getPath,
packageJson, packageJson,
arch: process.arch,
platform: process.platform, platform: process.platform,
version: process.version,
process: { process: {
// Setter/getter has to be created because // Setter/getter has to be created because
// these are read-only over the boundary. // these are read-only over the boundary.

View File

@ -1,10 +1,18 @@
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import { open as tauriOpen } from '@tauri-apps/plugin-shell'
export const openExternalBrowserIfDesktop = (to) => function(e) {
if (isDesktop()) {
window.electron.openExternal(to || e.currentTarget.href)
e.preventDefault()
e.stopPropagation()
return false
}
}
// Open a new browser window tauri style or browser style. // Open a new browser window tauri style or browser style.
export default async function openWindow(url: string) { export default async function openWindow(url: string) {
if (isDesktop()) { if (isDesktop()) {
await tauriOpen(url) await window.electron.openExternal(url)
} else { } else {
window.open(url, '_blank') window.open(url, '_blank')
} }

View File

@ -63,6 +63,10 @@ ipcMain.handle('shell.showItemInFolder', (event, data) => {
return shell.showItemInFolder(data) return shell.showItemInFolder(data)
}) })
ipcMain.handle('shell.openExternal', (event, data) => {
return shell.openExternal(data)
})
ipcMain.handle('login', async (event, host) => { ipcMain.handle('login', async (event, host) => {
console.log('Logging in...') console.log('Logging in...')
// Do an OAuth 2.0 Device Authorization Grant dance to get a token. // Do an OAuth 2.0 Device Authorization Grant dance to get a token.
@ -104,5 +108,5 @@ ipcMain.handle('login', async (event, host) => {
// Wait for the user to login. // Wait for the user to login.
const tokenSet = await handle.poll() const tokenSet = await handle.poll()
return tokenSet return tokenSet.access_token
}) })