···11-/*
22-33-The new app tab feature in Firefox is great. I use it a lot... which has shown starkly how apps and tabs have completely different use-cases and usage patterns. Often I will check my Gmail app tab because I see the glowing notification that a new email has arrived, do something (or nothing), and then pop back to where I was browsing - in one of those 78 tabs I have open. Well, not "pop" really.
44-55-The windowing model in operating systems allows me to do this with ease. But app tabs do not:
66-77-* If I opened no new tabs while using Gmail, I can still see the last tab I was at, and click on it. But I'm force to use the mouse.
88-* Out of sheer muscle memory and mouse-averseness, sometimes I can traverse tabs via the next/previous-tab keyboard shortcuts to get back to where I was. Sometimes it's a *lot* of tabs, so either I'll hold the arrow key down, speeding past the tab I wanted, or I'll just hit that arrow key a bunch of times in quick succession. Both options are sub-optimal.
99-* Or I have to expend mental energy to search in the awesomebar and switch to that tab, which often looks like this: "hm, type 'bug' and then try to remember some words in the bug summary, but those words match a bunch of other bugs, and i don't know the bug number, and also I'm on an attachment page because I'm reviewing a patch on the bug, so the summary won't be in the page title..." and on and on.
1010-* Then there's link opening. Links opened in app tabs are put at the beginning of the tab set, and the tab strip is animatedly scrolled there. Boom, already lost where I was before checking my email. We tried an experiment where they open at the end of the set of open tabs, but I found that to have serious "out of sight, out of mind" problems. That experiment was rolled back. Both approaches cause excess amounts of whizzing animations, either when you want to "go around the horn" to get to the tabs you just opened from app tabs, or when you want to go to them and then get back to where you were.
1111-* And the biggest problem in my opinion: The user is not in control of where these links are opened. Part of me thinks that I actually might work best in a one-tab-group-per-app-tab world... but that's a vision for another day (and blog post and add-on!).
1212-1313-1414-So I've tried to build a hybrid solution: Instead of making you go to your app tabs, your app tabs can come to you. Peek allows you to open your app tabs in a floating panel that opens on top of wherever you are in your tabs. Links open to the right of whatever your current active tab is, and in the background, so that when you're done peeking, you are exactly where you left off.
1515-1616-To use Peek, first create some app tabs. Then you can peek at them using the keyboard shortcut "ALT+SHIFT+1-9" where the number corresponds with the order your app tabs are in. To stop peeking, hit escape (or switch apps or anything else that takes focus away from the panel).
1717-1818-Features:
1919-- be able to interact with your apps and go exactly back to where you left off browsing.
2020-- links opened from app tabs are in context of... well, at least something! not at beginning or end of tabstrip, which gives you at least more control over where they end up.
2121-2222-*/
2323-2424-/*
2525-TODO
2626-- add a UI launcher somehow (drop button?)
2727-- remove pinned tabs altogether!
2828-*/
2929-3030-const {Cc, Ci, Cu, Cm} = require('chrome');
3131-const { Hotkey } = require('hotkeys');
3232-const { Panel } = require('panel-custom-frame');
3333-const Data = require('self').data;
3434-const Observers = require('observer-service');
3535-const Prefs = require('preferences-service');
3636-const Tabs = require('tabs');
3737-const Timers = require('timer');
3838-const Windows = require('windows').browserWindows;
3939-const WinUtils = require("window-utils");
11+//const {Cc, Ci, Cu, Cm} = require('chrome')
22+const { Hotkey } = require('hotkeys')
33+const { Panel } = require('panel')
44+const Data = require('self').data
55+const Prefs = require('preferences-service')
66+const Tabs = require('tabs')
4074141-const TAB_PREF = 'browser.tabs.loadDivertedInBackground';
4242-const COMBO = 'alt-shift-';
4343-4444-// 5 minutes
4545-const INTERVAL = 1000 * 60 * 5;
88+const TAB_PREF = 'browser.tabs.loadDivertedInBackground'
99+const COMBO = 'alt-shift-'
46104711let inited,
4812 lastPrefVal,
4949- cache = [],
5013 windowHeight,
5151- windowWidth;
1414+ windowWidth
52155353-function getPanel() {
1616+let hotkey = Hotkey({
1717+ combo: 'accel-shift-o',
1818+ onPress: function() {
1919+ getPanel(Data.url('panel.html')).show()
2020+ }
2121+})
2222+2323+function getPanel(url) {
5424 let panel = Panel({
5555- contentURL: 'about:blank',
2525+ contentURL: url || 'about:blank',
2626+ height: 600,
2727+ width: 800,
2828+ /*
5629 height: getPanelDimension(windowHeight),
5730 width: getPanelDimension(windowWidth),
3131+ */
5832 contentScriptFile: Data.url('panel.js'),
5933 contentScriptWhen: 'ready',
6034 onShow: function() {
6161- lastPrefVal = Prefs.get(TAB_PREF);
6262- if (!lastPrefVal)
6363- Prefs.set(TAB_PREF, true);
3535+ lastPrefVal = Prefs.get(TAB_PREF)
3636+ if (lastPrefVal === false)
3737+ Prefs.set(TAB_PREF, true)
6438 },
6539 onHide: function() {
6666- if (lastPrefVal != Prefs.get(TAB_PREF))
6767- Prefs.set(TAB_PREF, lastPrefVal);
4040+ if (lastPrefVal !== undefined && lastPrefVal != Prefs.get(TAB_PREF))
4141+ Prefs.set(TAB_PREF, lastPrefVal)
4242+ panel.destroy()
6843 }
6969- });
4444+ })
7045 return panel;
7146}
72477348function getPanelDimension(amount) Math.round(amount * 0.9)
74497575-// Build and cache hotkey+panels for each app tab
7676-function setup() {
7777- // destroy existing hotkey+panel combos
7878- cache.forEach(function(hotkey) {
7979- hotkey.destroy();
8080- });
8181- cache = [];
8282-8383- for (var i = 0; i < 10; i++) {
8484- var jetpackTab = Windows.activeWindow.tabs[i];
8585- if (jetpackTab && jetpackTab.isPinned) {
8686- let index = jetpackTab.index;
8787- let hotkeyNum = index == 9 ? 0 : (index + 1);
8888- let hotkey = Hotkey({
8989- // WTF - setting this to typo'd 'hotkeynum' doesn't throw!
9090- combo: (COMBO + hotkeyNum),
9191- onPress: function() {
9292- console.log('onPress(): index ', index);
9393- let panel = getPanel();
9494- //let oldFrame = panel.frame;
9595- //console.log('onPress(): oldFrame ', frame);
9696- let tabbrowser = WinUtils.activeBrowserWindow.gBrowser;
9797- let frame = tabbrowser.getBrowserAtIndex(index);
9898- console.log('onPress(): frame ', frame.currentURI.spec);
9999- panel.frame = frame;
100100- console.log('onPress(): new frame uri ', panel.frame.currentURI.spec);
101101- // need to support switching while panel is open
102102- panel.on('hide', function() {
103103- panel.frame = null;
104104- panel.destroy();
105105- });
106106- panel.show();
107107- console.log('onPress(): done');
108108- }
109109- });
110110-111111- cache[i] = hotkey;
112112- }
113113- }
114114-}
115115-5050+/*
11651// Window resize event handler
11752function onResize(msg) {
11853 windowHeight = msg.height;
···1205512156 // Initializing on the first received resize event ensures
12257 // that it occurs for both running and startup installs.
123123- if (!inited) {
124124- setup();
5858+ if (!inited)
12559 inited = true;
126126- }
12760}
1286112962// When a tab activates, attach our content script
···14073 });
14174}
142757676+// INITIALIZE
14377// Handle current tab activation manually in case we're installed
14478// in a running instance. This gets us initial window size which
14579// triggers initial filling of cache.
14680onTabActivate(Tabs.activeTab);
14781148148-// Listen for tab switching
8282+// Listen for tab switching so we always have a resize handler
8383+// TODO: might be a window-level way of doing this nowadays
14984Tabs.on('activate', onTabActivate);
150150-151151-let delegate = {
152152- onTrack: function (window) {
153153- if (window.document.documentElement.getAttribute('windowtype') == 'navigator:browser') {
154154- let container = window.gBrowser.tabContainer;
155155- container.addEventListener("TabPinned", setup, false);
156156- container.addEventListener("TabUnpinned", setup, false);
157157- }
158158- },
159159- onUntrack: function (window) {
160160- if (window.document.documentElement.getAttribute('windowtype') == 'navigator:browser') {
161161- let container = window.gBrowser.tabContainer;
162162- container.removeEventListener("TabPinned", setup, false);
163163- container.removeEventListener("TabUnpinned", setup, false);
164164- }
165165- }
166166-};
167167-new WinUtils.WindowTracker(delegate);
8585+*/
+1-1
package.json
···22 "name": "peek",
33 "license": "MPL 1.1/GPL 2.0/LGPL 2.1",
44 "author": "Dietrich Ayala",
55- "version": "2.0",
55+ "version": "2.1",
66 "fullName": "Peek",
77 "id": "jid1-xEAuRv8GzibUdw",
88 "description": "Peek at your app tabs without breaking your flow."