1const readHostEnv = (env) => String(env?.__HOST_ENV || '').trim().toLowerCase(); 2 3export const hasSwiftBridge = (env = globalThis) => !!( 4 env?.webkit?.messageHandlers?.swiftBridge 5 || env?.webkit?.messageHandlers?.squirrel 6 || env?.webkit?.messageHandlers?.callback 7); 8 9export const getTauriInvoke = (env = globalThis) => { 10 try { 11 if (typeof env?.__TAURI_INTERNALS__?.invoke === 'function') { 12 return env.__TAURI_INTERNALS__.invoke.bind(env.__TAURI_INTERNALS__); 13 } 14 } catch (_) { } 15 try { 16 if (typeof env?.__TAURI__?.invoke === 'function') { 17 return env.__TAURI__.invoke.bind(env.__TAURI__); 18 } 19 } catch (_) { } 20 try { 21 if (typeof env?.__TAURI__?.core?.invoke === 'function') { 22 return env.__TAURI__.core.invoke.bind(env.__TAURI__.core); 23 } 24 } catch (_) { } 25 try { 26 if (typeof env?.__ATOME_IOS_NATIVE_INVOKE === 'function') { 27 return env.__ATOME_IOS_NATIVE_INVOKE.bind(env); 28 } 29 } catch (_) { } 30 return null; 31}; 32 33const isNativeKiraPlaybackValue = (value) => { 34 const playback = String(value || '').trim().toLowerCase(); 35 return playback === 'tauri_native_kira' 36 || playback === 'ios_native_kira' 37 || playback === 'ios_auv3_native'; 38}; 39 40export const isAuv3AudioRuntime = (env = globalThis) => { 41 const hostEnv = readHostEnv(env); 42 // Only match when the native host explicitly declares AUv3 mode. 43 // hasSwiftBridge alone is NOT sufficient â the standalone iOS app 44 // also exposes webkit.messageHandlers.swiftBridge but is NOT an AUv3. 45 if (hostEnv === 'app') return false; 46 return hostEnv === 'auv3' 47 || env?.__AUV3_MODE__ === true; 48}; 49 50export const isIosHostAppRuntime = (env = globalThis) => { 51 const hostEnv = readHostEnv(env); 52 return hostEnv === 'app' && !isAuv3AudioRuntime(env); 53}; 54 55export const isTauriAudioRuntime = (env = globalThis) => { 56 if (env?.__SQUIRREL_FORCE_FASTIFY__ === true) return false; 57 if (isAuv3AudioRuntime(env)) return false; 58 if (env?.__SQUIRREL_FORCE_TAURI_RUNTIME__ === true) return true; 59 const tauriInvoke = getTauriInvoke(env); 60 const protocol = String(env?.location?.protocol || '').toLowerCase(); 61 const host = String(env?.location?.hostname || '').toLowerCase(); 62 const hostEnv = readHostEnv(env); 63 if (isIosHostAppRuntime(env)) return false; 64 if (hostEnv === 'app') return false; 65 if (protocol === 'tauri:' || protocol === 'asset:' || protocol === 'ipc:' || protocol === 'atome:') return true; 66 if (host === 'tauri.localhost') return true; 67 return !!tauriInvoke; 68}; 69 70export const describeAudioRuntimeEnvironment = (env = globalThis) => { 71 const hostEnv = readHostEnv(env); 72 const hasTauriInternalsInvoke = (() => { 73 try { return typeof env?.__TAURI_INTERNALS__?.invoke === 'function'; } 74 catch (_) { return false; } 75 })(); 76 const hasTauriInvoke = (() => { 77 try { return typeof env?.__TAURI__?.invoke === 'function'; } 78 catch (_) { return false; } 79 })(); 80 const hasTauriCoreInvoke = (() => { 81 try { return typeof env?.__TAURI__?.core?.invoke === 'function'; } 82 catch (_) { return false; } 83 })(); 84 const tauriInvokeAvailable = typeof getTauriInvoke(env) === 'function'; 85 const nativeKiraRequired = isAuv3AudioRuntime(env) 86 || isIosHostAppRuntime(env) 87 || isTauriAudioRuntime(env); 88 const nativeKiraAvailable = isAuv3AudioRuntime(env) 89 || ((isTauriAudioRuntime(env) || isIosHostAppRuntime(env)) && tauriInvokeAvailable); 90 const nativeKiraMissingReason = (() => { 91 if (!nativeKiraRequired || nativeKiraAvailable) return null; 92 if (isIosHostAppRuntime(env) && !tauriInvokeAvailable) { 93 return hasSwiftBridge(env) 94 ? 'ios_app_missing_native_invoke_swiftbridge_only' 95 : 'ios_app_missing_native_invoke'; 96 } 97 if (isAuv3AudioRuntime(env) && !hasSwiftBridge(env)) { 98 return 'auv3_missing_swift_bridge'; 99 } 100 return 'native_kira_backend_unavailable'; 101 })(); 102 return { 103 host_env: hostEnv || null, 104 auv3_mode: env?.__AUV3_MODE__ === true, 105 force_fastify: env?.__SQUIRREL_FORCE_FASTIFY__ === true, 106 force_tauri: env?.__SQUIRREL_FORCE_TAURI_RUNTIME__ === true, 107 tauri_invoke_available: tauriInvokeAvailable, 108 has_tauri_internals_invoke: hasTauriInternalsInvoke, 109 has_tauri_invoke: hasTauriInvoke, 110 has_tauri_core_invoke: hasTauriCoreInvoke, 111 has_tauri_object: !!env?.__TAURI__, 112 has_tauri_internals_object: !!env?.__TAURI_INTERNALS__, 113 has_swift_bridge: hasSwiftBridge(env), 114 is_auv3_audio_runtime: isAuv3AudioRuntime(env), 115 is_ios_host_app_runtime: isIosHostAppRuntime(env), 116 is_tauri_audio_runtime: isTauriAudioRuntime(env), 117 native_kira_required: nativeKiraRequired, 118 native_kira_available: nativeKiraAvailable, 119 native_kira_missing_reason: nativeKiraMissingReason 120 }; 121}; 122 123export const resolveAudioRuntime = (env = globalThis) => { 124 const tauriInvoke = getTauriInvoke(env); 125 const wasmAvailable = typeof env?.WebAssembly !== 'undefined'; 126 const hasWebCapture = !!env?.navigator?.mediaDevices?.getUserMedia; 127 128 if (isAuv3AudioRuntime(env)) { 129 return { 130 runtime: 'ios_auv3', 131 playback: 'ios_auv3_native', 132 record: 'ios_auv3_native', 133 preferredFacadeBackendOrder: ['kira'], 134 hasSwiftBridge: hasSwiftBridge(env), 135 tauriInvoke: null, 136 native_kira_required: true 137 }; 138 } 139 140 if (isTauriAudioRuntime(env) && tauriInvoke) { 141 return {
142 runtime: 'tauri_native', 143 playback: 'tauri_native_kira', 144 record: 'tauri_native_kira', 145 preferredFacadeBackendOrder: ['kira'], 146 hasSwiftBridge: false, 147 tauriInvoke, 148 native_kira_required: true 149 }; 150 } 151 152 if (isTauriAudioRuntime(env)) { 153 return { 154 runtime: 'tauri_native', 155 playback: 'unsupported', 156 record: 'unsupported', 157 preferredFacadeBackendOrder: ['kira'], 158 hasSwiftBridge: false, 159 tauriInvoke: null, 160 native_kira_required: true 161 }; 162 } 163 164 if (isIosHostAppRuntime(env)) { 165 if (tauriInvoke) { 166 return { 167 runtime: 'ios_app', 168 playback: 'ios_native_kira', 169 record: 'ios_native_kira', 170 preferredFacadeBackendOrder: ['kira'], 171 hasSwiftBridge: hasSwiftBridge(env), 172 tauriInvoke, 173 native_kira_required: true 174 }; 175 } 176 return { 177 runtime: 'ios_app', 178 playback: 'unsupported', 179 record: 'unsupported', 180 preferredFacadeBackendOrder: ['kira'], 181 hasSwiftBridge: hasSwiftBridge(env), 182 tauriInvoke: null, 183 native_kira_required: true 184 }; 185 } 186 187 if (wasmAvailable || hasWebCapture) { 188 return { 189 runtime: 'web', 190 playback: wasmAvailable ? 'web_wasm_kira' : 'unsupported', 191 record: hasWebCapture ? 'web_capture' : 'unsupported', 192 preferredFacadeBackendOrder: wasmAvailable ? ['kira'] : [], 193 hasSwiftBridge: false, 194 tauriInvoke: null 195 }; 196 } 197 198 return { 199 runtime: 'unknown', 200 playback: 'unsupported', 201 record: 'unsupported', 202 preferredFacadeBackendOrder: [], 203 hasSwiftBridge: hasSwiftBridge(env), 204 tauriInvoke: null 205 }; 206}; 207 208export const resolveVoiceCaptureProvider = (env = globalThis) => { 209 const explicit = String(env?.__SQUIRREL_RECORD_PROVIDER__ || '').trim().toLowerCase(); 210 if (explicit) return explicit; 211 const runtime = resolveAudioRuntime(env); 212 if (runtime.record === 'tauri_native_kira' 213 || runtime.record === 'ios_auv3_native' 214 || runtime.record === 'ios_native_kira') { 215 return 'native_audio_recorder'; 216 } 217 if (runtime.record === 'web_capture') { 218 return 'web_capture_recorder'; 219 } 220 return 'unsupported'; 221}; 222 223export const isNativeKiraPlayback = (env = globalThis) => ( 224 isNativeKiraPlaybackValue(resolveAudioRuntime(env)?.playback) 225); 226 227export const isStrictNativeKiraPlaybackRuntime = (env = globalThis) => ( 228 isNativeKiraPlayback(env) 229 || isIosHostAppRuntime(env) 230 || isAuv3AudioRuntime(env) 231 || isTauriAudioRuntime(env) 232); 233 234export const resolveNativeMediaLocalPath = (...values) => { 235 for (const value of values) { 236 const raw = String(value ?? '').trim(); 237 if (!raw || raw.startsWith('blob:') || raw.startsWith('data:')) continue; 238 const decoded = (() => { 239 try { return decodeURIComponent(raw); } 240 catch (_) { return raw; } 241 })(); 242 if (/^(?:\/var\/|\/private\/var\/|data\/users\/|recordings\/)/i.test(decoded)) { 243 return decoded; 244 } 245 if (/^\//.test(decoded) && !/^\/api\//i.test(decoded)) { 246 return decoded; 247 } 248 if (!/^[a-z][a-z0-9+.-]*:/i.test(decoded) && /^[^?#]+\.[a-z0-9]{2,8}$/i.test(decoded)) { 249 return decoded.replace(/^\/+/, ''); 250 } 251 let parsed = null; 252 try { 253 parsed = new URL(raw, 'atome:///'); 254 } catch (_) { 255 parsed = null; 256 } 257 const pathname = parsed ? String(parsed.pathname || '').trim() : raw; 258 const normalizedPath = (() => { 259 try { return decodeURIComponent(pathname); } 260 catch (_) { return pathname; } 261 })() 262 .replace(/^file:\/\/\/file\//i, '') 263 .replace(/^file:\/\//i, '') 264 .replace(/^\/file\//i, '') 265 .replace(/^file\//i, ''); 266 if (/^(?:\/var\/|\/private\/var\/|data\/users\/|recordings\/)/i.test(normalizedPath)) { 267 return normalizedPath; 268 } 269 if (/^\//.test(normalizedPath) && !/^\/api\//i.test(normalizedPath)) { 270 return normalizedPath; 271 } 272 if (!/^[a-z][a-z0-9+.-]*:/i.test(raw) 273 && !/^\/?api\//i.test(normalizedPath) 274 && /^[^?#]+\.[a-z0-9]{2,8}$/i.test(normalizedPath)) { 275 return normalizedPath.replace(/^\/+/, ''); 276 } 277 if (parsed && parsed.protocol === 'atome:') { 278 const atomePath = normalizedPath.replace(/^\/+/, ''); 279 if (/^api\//i.test(atomePath)) continue; 280 if (atomePath) return atomePath; 281 } 282 } 283 return ''; 284}; 285 286export const resolveNativeMediaLocalPathFromObject = (source = {}, extra = {}) => { 287 const object = source && typeof source === 'object' ? source : {}; 288 const meta = object.meta && typeof object.meta === 'object' ? object.meta : {}; 289 const extras = object.extras && typeof object.extras === 'object' ? object.extras : {}; 290 const extrasMeta = extras.meta && typeof extras.meta === 'object' ? extras.meta : {}; 291 const extraObject = extra && typeof extra === 'object' ? extra : {}; 292 return resolveNativeMediaLocalPath( 293 object.native_audio_path, 294 object.nativeAudioPath, 295 object.local_path, 296 object.localPath, 297 object.file_path, 298 object.filePath, 299 object.path_or_bookmark, 300 object.pathOrBookmark, 301 object.path, 302 meta.native_audio_path, 303 meta.nativeAudioPath, 304 meta.local_path, 305 meta.localPath, 306 meta.file_path, 307 meta.filePath, 308 meta.path_or_bookmark, 309 meta.pathOrBookmark, 310 meta.path, 311 extras.native_audio_path, 312 extras.nativeAudioPath, 313 extras.local_path, 314 extras.localPath, 315 extras.file_path, 316 extras.filePath, 317 extras.path_or_bookmark, 318 extras.pathOrBookmark, 319 extras.path, 320 extrasMeta.native_audio_path, 321 extrasMeta.nativeAudioPath, 322 extrasMeta.local_path, 323 extrasMeta.localPath, 324 extrasMeta.file_path, 325 extrasMeta.filePath, 326 extrasMeta.path_or_bookmark, 327 extrasMeta.pathOrBookmark, 328 extrasMeta.path, 329 extraObject.native_audio_path, 330 extraObject.nativeAudioPath, 331 extraObject.local_path, 332 extraObject.localPath, 333 extraObject.file_path, 334 extraObject.filePath, 335 extraObject.path_or_bookmark, 336 extraObject.pathOrBookmark, 337 extraObject.path 338 ); 339};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.