import {
buildConversationPath,
buildSearchPath,
parseConversationRouteParts,
splitRouteQuery,
} from './router.js';
function getBaseUrl() {
const url = new URL(window.location.href);
url.hash = '';
url.search = '';
return url.toString();
}
export function getConversationLink(conversationId, messageId = null) {
const base = getBaseUrl();
const path = buildConversationPath(conversationId, messageId);
return `${base}#${path}`;
}
export function getSearchLink(query, filters = {}) {
const base = getBaseUrl();
const path = buildSearchPath(query, filters);
return `${base}#${path}`;
}
export function getSettingsLink() {
const base = getBaseUrl();
return `${base}#/settings`;
}
export function getStatsLink() {
const base = getBaseUrl();
return `${base}#/stats`;
}
export function getHomeLink() {
const base = getBaseUrl();
return `${base}#/`;
}
export async function copyTextToClipboard(text) {
const clipboard = globalThis.navigator?.clipboard;
if (clipboard?.writeText) {
try {
await clipboard.writeText(text);
return true;
} catch (error) {
console.error('[Share] Failed to copy text via Clipboard API:', error);
}
}
let textArea = null;
try {
if (!document.body || typeof document.execCommand !== 'function') {
return false;
}
textArea = document.createElement('textarea');
textArea.value = text;
textArea.setAttribute('readonly', '');
textArea.style.position = 'fixed';
textArea.style.left = '-9999px';
textArea.style.top = '-9999px';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
return document.execCommand('copy');
} catch (fallbackError) {
console.error('[Share] Fallback copy failed:', fallbackError);
return false;
} finally {
if (textArea?.parentNode) {
textArea.parentNode.removeChild(textArea);
}
}
}
export async function copyLinkToClipboard(link) {
return copyTextToClipboard(link);
}
export async function copyConversationLink(conversationId, messageId = null) {
const link = getConversationLink(conversationId, messageId);
const success = await copyLinkToClipboard(link);
return { success, link };
}
export async function copySearchLink(query, filters = {}) {
const link = getSearchLink(query, filters);
const success = await copyLinkToClipboard(link);
return { success, link };
}
export async function shareLink(options) {
if (!navigator.share) {
console.debug('[Share] Web Share API not available');
return false;
}
try {
await navigator.share(options);
return true;
} catch (error) {
if (error.name !== 'AbortError') {
console.error('[Share] Share failed:', error);
}
return false;
}
}
export async function shareConversation(conversationId, title, messageId = null) {
const link = getConversationLink(conversationId, messageId);
const shareOptions = {
title: title || 'Conversation',
text: `Check out this conversation${messageId ? ' (message #' + messageId + ')' : ''}`,
url: link,
};
return shareLink(shareOptions);
}
export function isWebShareAvailable() {
return !!navigator.share;
}
export function parseShareLink(link) {
try {
const url = new URL(link);
const hash = url.hash.slice(1);
if (!hash) {
return { view: 'search', params: {}, query: {} };
}
const [pathPart, queryPart] = splitRouteQuery(hash);
const parts = pathPart.split('/').filter(Boolean);
const query = {};
if (queryPart) {
const searchParams = new URLSearchParams(queryPart);
for (const [key, value] of searchParams) {
query[key] = value;
}
}
if (parts.length === 0) {
return { view: 'search', params: {}, query };
}
if (parts[0] === 'search' && parts.length === 1) {
return { view: 'search', params: {}, query };
}
if (parts[0] === 'c') {
const conversationParams = parseConversationRouteParts(parts);
if (!conversationParams) {
return null;
}
return {
view: 'conversation',
params: conversationParams,
query,
};
}
if (parts[0] === 'settings' && parts.length === 1) {
return { view: 'settings', params: {}, query };
}
if (parts[0] === 'stats' && parts.length === 1) {
return { view: 'stats', params: {}, query };
}
return null;
} catch (error) {
console.error('[Share] Failed to parse link:', error);
return null;
}
}
export default {
getConversationLink,
getSearchLink,
getSettingsLink,
getStatsLink,
getHomeLink,
copyTextToClipboard,
copyLinkToClipboard,
copyConversationLink,
copySearchLink,
shareLink,
shareConversation,
isWebShareAvailable,
parseShareLink,
};