mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-18 04:08:55 -06:00
reorganize clipboard code
This commit is contained in:
@@ -9,7 +9,7 @@ import { Language } from 'highlight.js';
|
||||
|
||||
import { LayoutContext } from '../layouting';
|
||||
import { getElementHeight, getElementWidth } from '../layoutHelpers';
|
||||
import { copyToClipboard, firstDefined } from '../utils';
|
||||
import { setClipboard, firstDefined } from '../utils';
|
||||
import { applyIcon } from '../designApplication';
|
||||
|
||||
export type CodeBlockState = ComponentState & {
|
||||
@@ -109,7 +109,7 @@ export function convertDivToCodeBlock(
|
||||
copyButton.addEventListener('click', (event) => {
|
||||
const codeToCopy = (preElement as HTMLPreElement).textContent ?? '';
|
||||
|
||||
copyToClipboard(codeToCopy);
|
||||
setClipboard(codeToCopy);
|
||||
|
||||
copyButton.title = 'Copied!';
|
||||
applyIcon(
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
import { ComponentId } from '../dataModels';
|
||||
import { getTextDimensions } from '../layoutHelpers';
|
||||
import { LayoutContext } from '../layouting';
|
||||
import { copyToClipboard } from '../utils';
|
||||
import { setClipboard } from '../utils';
|
||||
import { ComponentBase, ComponentState } from './componentBase';
|
||||
|
||||
export type ScrollTargetState = ComponentState & {
|
||||
@@ -106,7 +106,7 @@ export class ScrollTargetComponent extends ComponentBase {
|
||||
let url = new URL(window.location.href);
|
||||
url.hash = this.state.id;
|
||||
|
||||
copyToClipboard(url.toString());
|
||||
setClipboard(url.toString());
|
||||
}
|
||||
|
||||
updateNaturalWidth(ctx: LayoutContext): void {
|
||||
|
||||
@@ -6,10 +6,8 @@ import {
|
||||
registerFont,
|
||||
closeSession,
|
||||
setTitle,
|
||||
setClipboard,
|
||||
getClipboard,
|
||||
ClipboardError,
|
||||
} from './rpcFunctions';
|
||||
import { setClipboard, getClipboard, ClipboardError } from './utils';
|
||||
import { AsyncQueue, commitCss } from './utils';
|
||||
|
||||
let websocket: WebSocket | null = null;
|
||||
|
||||
@@ -132,34 +132,3 @@ export function setTitle(title: string): void {
|
||||
export function closeSession(): void {
|
||||
window.close(); // TODO: What if the browser doesn't allow this?
|
||||
}
|
||||
|
||||
export class ClipboardError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
}
|
||||
|
||||
export async function setClipboard(text: string): Promise<void> {
|
||||
if (!navigator.clipboard) {
|
||||
throw new ClipboardError('Clipboard API is not available');
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (error) {
|
||||
console.warn(`Failed to set clipboard content: ${error}`);
|
||||
throw new ClipboardError(`Failed to set clipboard content: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getClipboard(): Promise<string> {
|
||||
if (!navigator.clipboard) {
|
||||
throw new ClipboardError('Clipboard API is not available');
|
||||
}
|
||||
try {
|
||||
return await navigator.clipboard.readText();
|
||||
} catch (error) {
|
||||
console.warn(`Failed to get clipboard content: ${error}`);
|
||||
throw new ClipboardError(`Failed to get clipboard content: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,28 +120,56 @@ export class TimeoutError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies the given text to the clipboard
|
||||
export function copyToClipboard(text: string): void {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(text).catch((error) => {
|
||||
console.warn(
|
||||
`Failed to set clipboard content using navigator.clipboard: ${error}`
|
||||
);
|
||||
fallbackCopyToClipboard(text);
|
||||
});
|
||||
} else {
|
||||
fallbackCopyToClipboard(text);
|
||||
export class ClipboardError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackCopyToClipboard(text: string): void {
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
export async function setClipboard(text: string): Promise<void> {
|
||||
if (navigator.clipboard) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return;
|
||||
} catch (error) {
|
||||
console.warn(`Failed to set clipboard content: ${error}`);
|
||||
throw new ClipboardError(
|
||||
`Failed to set clipboard content: ${error}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
// Fallback in case `navigator.clipboard` isn't available or didn't work
|
||||
if (document.execCommand) {
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
console.warn('Failed to set clipboard content: No clipboard API available');
|
||||
throw new ClipboardError(
|
||||
'Failed to set clipboard content: No clipboard API available'
|
||||
);
|
||||
}
|
||||
|
||||
export async function getClipboard(): Promise<string> {
|
||||
if (navigator.clipboard) {
|
||||
try {
|
||||
return await navigator.clipboard.readText();
|
||||
} catch (error) {
|
||||
console.warn(`Failed to get clipboard content: ${error}`);
|
||||
throw new ClipboardError(
|
||||
`Failed to get clipboard content: ${error}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ClipboardError('Clipboard API is not available');
|
||||
}
|
||||
|
||||
/// Checks if there's an #url-fragment, and if so, scrolls the corresponding
|
||||
|
||||
@@ -33,3 +33,16 @@ class NavigationFailed(Exception):
|
||||
will simply display their fallback in that case. Thus this exception will
|
||||
not be raised in that case.
|
||||
"""
|
||||
|
||||
|
||||
class ClipboardError(Exception):
|
||||
"""
|
||||
Exception raised for errors related to clipboard operations.
|
||||
"""
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message)
|
||||
|
||||
@property
|
||||
def message(self) -> str:
|
||||
return self.args[0]
|
||||
|
||||
@@ -67,19 +67,6 @@ class WontSerialize(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ClipboardError(Exception):
|
||||
"""
|
||||
Exception raised for errors related to clipboard operations.
|
||||
"""
|
||||
|
||||
def __init__(self, message: str):
|
||||
super().__init__(message)
|
||||
|
||||
@property
|
||||
def message(self) -> str:
|
||||
return self.args[0]
|
||||
|
||||
|
||||
async def dummy_send_message(message: Jsonable) -> None:
|
||||
raise NotImplementedError() # pragma: no cover
|
||||
|
||||
@@ -2483,26 +2470,32 @@ a.remove();
|
||||
|
||||
async def set_clipboard(self, text: str) -> None:
|
||||
"""
|
||||
Set the client's clipboard to the given text.
|
||||
Copies the given text to the client's clipboard.
|
||||
|
||||
## Parameters
|
||||
|
||||
`text`: The text to set on the clipboard.
|
||||
`text`: The text to copy to the clipboard.
|
||||
|
||||
## Raises
|
||||
|
||||
`ClipboardError`: If the user's browser doesn't allow or support
|
||||
clipboard operations.
|
||||
"""
|
||||
try:
|
||||
await self._remote_set_clipboard(text)
|
||||
except Exception as e:
|
||||
raise ClipboardError(f"Failed to set clipboard content: {str(e)}")
|
||||
except unicall.RpcError as e:
|
||||
raise errors.ClipboardError(e.message) from None
|
||||
|
||||
async def get_clipboard(self) -> str:
|
||||
"""
|
||||
Get the current text from the client's clipboard.
|
||||
Gets the current text from the client's clipboard.
|
||||
|
||||
## Returns
|
||||
## Raises
|
||||
|
||||
The text currently on the clipboard.
|
||||
`ClipboardError`: If the user's browser doesn't allow or support
|
||||
clipboard operations.
|
||||
"""
|
||||
try:
|
||||
return await self._remote_get_clipboard()
|
||||
except Exception as e:
|
||||
raise ClipboardError(f"Failed to get clipboard content: {str(e)}")
|
||||
except unicall.RpcError as e:
|
||||
raise errors.ClipboardError(e.message) from None
|
||||
|
||||
Reference in New Issue
Block a user