experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

add OS url handler, and visit-source tracking

+105 -2
+36
app/datastore/schema.js
··· 1 1 // Datastore schema definitions for TinyBase 2 + // 3 + // STORAGE NOTES (Dec 2024): 4 + // 5 + // Current state: 6 + // - TinyBase datastore: SQLite-backed via sqlite3 + createSqlite3Persister 7 + // - Stores: addresses, visits, content, tags, blobs, scripts_data, feeds 8 + // - Location: {userData}/{PROFILE}/datastore.sqlite 9 + // 10 + // - Feature settings: localStorage via openStore() in app/utils.js 11 + // - Stores: peeks, slides, scripts, cmd, groups configs 12 + // 13 + // - Adaptive matching (cmd): localStorage 14 + // - Stores: typed -> command selection feedback 15 + // 16 + // - App prefs: localStorage 17 + // - Stores: shortcuts, window size, startup feature, etc. 18 + // 19 + // Future consideration: 20 + // - May move away from TinyBase toward loosely-coupled SQLite everywhere 21 + // - Some storage should converge, but not all 22 + // - localStorage items that need to scale (like history) should move to SQLite 23 + // - Simple key-value prefs can stay in localStorage 24 + // 25 + // URL SOURCE TAXONOMY: 26 + // The visits table tracks where each URL navigation came from via source/sourceId fields: 27 + // 28 + // | Source | SourceId | Description | 29 + // |------------|---------------|------------------------------------------------| 30 + // | external | os | URL opened from another app via OS handler | 31 + // | external | cli | URL passed as CLI argument | 32 + // | cmd | open | User typed URL in cmd bar | 33 + // | cmd | history | User selected from history command | 34 + // | peek | <peek-id> | Opened from a peek | 35 + // | slide | <slide-id> | Opened from a slide | 36 + // | link | <source-url> | Link clicked in peek:// content | 37 + // | window | '' | Default fallback | 2 38 3 39 export const schema = { 4 40 addresses: {
+17
app/index.js
··· 124 124 } 125 125 }); 126 126 127 + // Handle URLs opened from external apps (e.g., when Peek is default browser) 128 + api.subscribe('external:open-url', async (msg) => { 129 + console.log('external:open-url', msg); 130 + const { url, trackingSource, trackingSourceId } = msg; 131 + 132 + try { 133 + // Use URL as key to reuse existing windows 134 + await windowManager.createWindow(url, { 135 + key: url, 136 + trackingSource, 137 + trackingSourceId 138 + }); 139 + } catch (error) { 140 + console.error('Error opening external URL:', error); 141 + } 142 + }); 143 + 127 144 // Open settings window on startup if configured 128 145 if (p.startupFeature == settingsAddress) { 129 146 try {
+5
forge.config.js
··· 9 9 icon: './assets/appicon', 10 10 appBundleId: 'com.peek.app', 11 11 appCategoryType: 'public.app-category.productivity', 12 + // Register as handler for http/https URLs 13 + protocols: [ 14 + { name: 'HTTP', schemes: ['http'] }, 15 + { name: 'HTTPS', schemes: ['https'] } 16 + ], 12 17 // Uncomment this section when ready to sign the app for distribution 13 18 /* 14 19 osxSign: {
+47 -2
index.js
··· 474 474 return; 475 475 } 476 476 477 + // Windows/Linux: handle URLs when another instance tries to open 478 + app.on('second-instance', (event, argv) => { 479 + const url = argv.find(arg => 480 + arg.startsWith('http://') || arg.startsWith('https://') 481 + ); 482 + if (url) { 483 + console.log('second-instance URL:', url); 484 + handleExternalUrl(url, 'os'); 485 + } 486 + }); 487 + 477 488 // handle peek:// 478 489 initAppProtocol(); 490 + 491 + // Register as default handler for http/https URLs 492 + app.setAsDefaultProtocolClient('http'); 493 + app.setAsDefaultProtocolClient('https'); 494 + 495 + // Handle CLI arguments (e.g., yarn start -- "https://example.com") 496 + const urlArg = process.argv.find(arg => 497 + arg.startsWith('http://') || arg.startsWith('https://') 498 + ); 499 + if (urlArg) { 500 + console.log('CLI URL argument:', urlArg); 501 + // Defer until background app is ready 502 + setTimeout(() => handleExternalUrl(urlArg, 'cli'), 1000); 503 + } 479 504 480 505 // listen for app prefs to configure ourself 481 506 // TODO: kinda janky, needs rethink ··· 514 539 // Create a BrowserWindow directly for the core background process 515 540 const winPrefs = { 516 541 show: false, 542 + // TODO: maybe not necessary now? 517 543 key: 'background-core', 518 544 webPreferences: { 519 545 preload: preloadPath, ··· 648 674 _quitShortcut = strings.defaults.quitShortcut; 649 675 registerShortcut(_quitShortcut, onQuit); 650 676 }; 677 + 678 + // ***** External URL Handler ***** 679 + 680 + // Handle URLs opened from external apps (e.g., when Peek is default browser) 681 + const handleExternalUrl = (url, sourceId = 'os') => { 682 + console.log('External URL received:', url, 'from:', sourceId); 683 + 684 + // Note: Using trackingSource/trackingSourceId because preload.js overwrites msg.source 685 + pubsub.publish(systemAddress, scopes.GLOBAL, 'external:open-url', { 686 + url, 687 + trackingSource: 'external', 688 + trackingSourceId: sourceId, 689 + timestamp: Date.now() 690 + }); 691 + }; 692 + 693 + // macOS: handle open-url event (must be registered before app.whenReady) 694 + app.on('open-url', (event, url) => { 695 + event.preventDefault(); 696 + handleExternalUrl(url, 'os'); 697 + }); 651 698 652 699 app.whenReady().then(onReady); 653 700 ··· 1429 1476 } 1430 1477 }); 1431 1478 }; 1432 - 1433 - // Nothing here - removed old window handler code 1434 1479 1435 1480 // show/configure devtools when/after a window is opened 1436 1481 const winDevtoolsConfig = bw => {