addons/isl/src/platform/browserPlatformImpl.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {Json} from 'shared/typeUtils';
b69ab319import type {Platform} from '../platform';
b69ab3110import type {OneIndexedLineNumber, PlatformName, RepoRelativePath} from '../types';
b69ab3111
b69ab3112import {LocalWebSocketEventBus} from '../LocalWebSocketEventBus';
b69ab3113import {computeInitialParams} from '../urlParams';
b69ab3114
b69ab3115// important: this file should not try to import other code from 'isl',
b69ab3116// since it will end up getting duplicated when bundling.
b69ab3117
b69ab3118export function browserClipboardCopy(text: string, html?: string) {
b69ab3119 if (html) {
b69ab3120 const htmlBlob = new Blob([html], {type: 'text/html'});
b69ab3121 const textBlob = new Blob([text], {type: 'text/plain'});
b69ab3122 const clipboardItem = new window.ClipboardItem({
b69ab3123 'text/html': htmlBlob,
b69ab3124 'text/plain': textBlob,
b69ab3125 });
b69ab3126 navigator.clipboard.write([clipboardItem]);
b69ab3127 } else {
b69ab3128 navigator.clipboard.writeText(text);
b69ab3129 }
b69ab3130}
b69ab3131
b69ab3132export const makeBrowserLikePlatformImpl = (platformName: PlatformName): Platform => {
b69ab3133 const initialUrlParams = computeInitialParams(platformName === 'browser');
b69ab3134 return {
b69ab3135 platformName,
b69ab3136 confirm: (message: string, details?: string) => {
b69ab3137 const ok = window.confirm(message + '\n' + (details ?? ''));
b69ab3138 return Promise.resolve(ok);
b69ab3139 },
b69ab3140
b69ab3141 openFile: (path: RepoRelativePath, options?: {line?: OneIndexedLineNumber}) => {
b69ab3142 window.clientToServerAPI?.postMessage({type: 'platform/openFile', path, options});
b69ab3143 },
b69ab3144 openFiles: (paths: Array<RepoRelativePath>, options?: {line?: OneIndexedLineNumber}) => {
b69ab3145 window.clientToServerAPI?.postMessage({type: 'platform/openFiles', paths, options});
b69ab3146 },
b69ab3147 canCustomizeFileOpener: true,
b69ab3148 upsellExternalMergeTool: true,
b69ab3149
b69ab3150 openContainingFolder: (path: RepoRelativePath) => {
b69ab3151 window.clientToServerAPI?.postMessage({type: 'platform/openContainingFolder', path});
b69ab3152 },
b69ab3153
b69ab3154 openExternalLink(url: string): void {
b69ab3155 window.open(url, '_blank');
b69ab3156 },
b69ab3157
b69ab3158 getPersistedState<T>(key: string): T | null {
b69ab3159 try {
b69ab3160 const found = localStorage.getItem(key) as string | null;
b69ab3161 if (found == null) {
b69ab3162 return null;
b69ab3163 }
b69ab3164 return JSON.parse(found) as T;
b69ab3165 } catch {
b69ab3166 return null;
b69ab3167 }
b69ab3168 },
b69ab3169 setPersistedState<T>(key: string, value: T | undefined): void {
b69ab3170 try {
b69ab3171 if (value === undefined) {
b69ab3172 localStorage.removeItem(key);
b69ab3173 } else {
b69ab3174 localStorage.setItem(key, JSON.stringify(value));
b69ab3175 }
b69ab3176 } catch {}
b69ab3177 },
b69ab3178 clearPersistedState(): void {
b69ab3179 try {
b69ab3180 localStorage.clear();
b69ab3181 } catch {}
b69ab3182 },
b69ab3183 getAllPersistedState(): Json | undefined {
b69ab3184 try {
b69ab3185 return Object.fromEntries(
b69ab3186 Object.entries({...localStorage})
b69ab3187 .map(([key, value]: [string, unknown]) => {
b69ab3188 try {
b69ab3189 return [key, JSON.parse(value as string)];
b69ab3190 } catch {
b69ab3191 return null;
b69ab3192 }
b69ab3193 })
b69ab3194 .filter((e): e is [string, Json] => e != null),
b69ab3195 );
b69ab3196 } catch {
b69ab3197 return undefined;
b69ab3198 }
b69ab3199 },
b69ab31100
b69ab31101 clipboardCopy: browserClipboardCopy,
b69ab31102
b69ab31103 messageBus: new LocalWebSocketEventBus(
b69ab31104 process.env.NODE_ENV === 'development'
b69ab31105 ? // in dev mode, Vite hosts our files for hot-reloading.
b69ab31106 // This means we can't host the ws server on the same port as the page.
b69ab31107 'localhost:3001'
b69ab31108 : // in production, we serve both the static files and ws from the same port
b69ab31109 location.host,
b69ab31110 WebSocket,
b69ab31111 {
b69ab31112 cwd: initialUrlParams.get('cwd'),
b69ab31113 sessionId: initialUrlParams.get('sessionId'),
b69ab31114 token: initialUrlParams.get('token'),
b69ab31115 platformName,
b69ab31116 },
b69ab31117 ),
b69ab31118
b69ab31119 initialUrlParams,
b69ab31120 };
b69ab31121};