diff --git a/pretty.GeWrIIb3A/pretty.iHne78Dzi b/pretty.GeWrIIb3A/pretty.iHne78Dzi deleted file mode 100644 index 0eafaa59..00000000 --- a/pretty.GeWrIIb3A/pretty.iHne78Dzi +++ /dev/null @@ -1,235 +0,0 @@ -import * as Perf from "@src/perf" -import { browserBg } from "@src/lib/webext" -import * as Containers from "@src/lib/containers" -import * as Completions from "@src/completions" -import * as Messaging from "@src/lib/messaging" -import * as config from "@src/lib/config" -import { - tgroups, - tabTgroup, -} from "@src/lib/tab_groups" - -class TabAllCompletionOption - extends Completions.CompletionOptionHTML - implements Completions.CompletionOptionFuse { - public fuseKeys = [] - public tab: browser.tabs.Tab - constructor( - public value: string, - tab: browser.tabs.Tab, - isAlternative: boolean, - isCurrent: boolean, - winindex: number, - container: browser.contextualIdentities.ContextualIdentity, - incognito: boolean, - tgroupname: string - ) { - super() - const valueStr = `${winindex}.${tab.index + 1}` - this.value = valueStr - this.fuseKeys.push(this.value, tab.title, tab.url) - this.tab = tab - - // pre contains max four uppercase characters for tab status. - // If statusstylepretty is set to true replace use unicode characters, - // but keep plain letters in hidden column for completion. - let preplain = "" - if (isCurrent) { - preplain += "%" - } else if (isAlternative) { - preplain += "#" - this.value = "#" - } - let pre = preplain - if (tab.pinned) preplain += "P" - if (tab.audible) preplain += "A" - if (tab.mutedInfo.muted) preplain += "M" - if (tab.discarded) preplain += "D" - - if (config.get("completions", "Tab", "statusstylepretty") === "true") { - if (tab.pinned) pre += "\uD83D\uDCCC" - if (tab.audible) pre += "\uD83D\uDD0A" - if (tab.mutedInfo.muted) pre += "\uD83D\uDD07" - if (tab.discarded) pre += "\u2296" - } else { - pre = preplain - } - - tgroupname = (tgroupname === undefined) ? "" : tgroupname - - // Push prefix before padding so we don't match on whitespace - this.fuseKeys.push(pre) - this.fuseKeys.push(preplain) - this.fuseKeys.push(tgroupname) - - // Push properties we want to fuzmatch on - this.fuseKeys.push(String(tab.index + 1), tab.title, tab.url) - - // Create HTMLElement - const favIconUrl = tab.favIconUrl - ? tab.favIconUrl - : Completions.DEFAULT_FAVICON - this.html = html` - ${pre} - ${preplain} - - - - ${valueStr}: ${tab.title} - ${tgroupname} - - ${tab.url} - - ` - } -} - -export class TabAllCompletionSource extends Completions.CompletionSourceFuse { - public options: TabAllCompletionOption[] - private shouldSetStateFromScore = true - - constructor(private _parent) { - super(["taball", "tabgrab"], "TabAllCompletionSource", "All Tabs") - - this.updateOptions() - this._parent.appendChild(this.node) - this.shouldSetStateFromScore = - config.get("completions", "TabAll", "autoselect") === "true" - - Messaging.addListener("tab_changes", () => this.reactToTabChanges()) - } - - async onInput(exstr) { - return this.updateOptions(exstr) - } - - setStateFromScore(scoredOpts: Completions.ScoredOption[]) { - super.setStateFromScore(scoredOpts, this.shouldSetStateFromScore) - } - - /** - * Map all windows into a {[windowId]: window} object - */ - private async getWindows() { - const windows = await browserBg.windows.getAll() - const response: { [windowId: number]: browser.windows.Window } = {} - windows.forEach(win => (response[win.id] = win)) - return response - } - - /** - * Update the list of possible tab options and select (focus on) - * the appropriate option. - */ - private async reactToTabChanges(): Promise { - // const prevOptions = this.options - await this.updateOptions(this.lastExstr) - - // TODO: update this from Tab.ts for TabAll.ts - // if (!prevOptions || !this.options || !this.lastFocused) return - - // // Determine which option to focus on - // const diff = R.differenceWith( - // (x, y) => x.tab.id === y.tab.id, - // prevOptions, - // this.options, - // ) - // const lastFocusedTabCompletion = this - // .lastFocused as TabAllCompletionOption - - // // If the focused option was removed then focus on the next option - // if ( - // diff.length === 1 && - // diff[0].tab.id === lastFocusedTabCompletion.tab.id - // ) { - // //this.select(this.getTheNextTabOption(lastFocusedTabCompletion)) - // } - } - - /** - * Gets the next option in this BufferCompletionSource assuming - * that this BufferCompletionSource length has been reduced by 1 - * - * TODO: this ain't going to work, need to work out position based on win.tab - */ - // private getTheNextTabOption(option: TabAllCompletionOption) { - // if (option.tab.index === this.options.length) { - // return this.options[this.options.length - 1] - // } - // return this.options[option.tab.index] - // } - - // Eslint doesn't like this decorator but there's nothing we can do about it - // eslint-disable-next-line @typescript-eslint/member-ordering - @Perf.measuredAsync - private async updateOptions(exstr = "") { - this.lastExstr = exstr - const [prefix] = this.splitOnPrefix(exstr) - - // Hide self and stop if prefixes don't match - if (prefix) { - // Show self if prefix and currently hidden - if (this.state === "hidden") { - this.state = "normal" - } - } else { - this.state = "hidden" - return - } - - const tabsPromise = browserBg.tabs.query({}) - const windowsPromise = this.getWindows() - const [tabs, windows] = await Promise.all([tabsPromise, windowsPromise]) - - const options = [] - - tabs.sort((a, b) => { - if (a.windowId === b.windowId) return a.index - b.index - return a.windowId - b.windowId - }) - - const currentWindowTabs = await browserBg.tabs.query({ - currentWindow: true - }) - currentWindowTabs.sort((a, b) => b.lastAccessed - a.lastAccessed) - const altTab = currentWindowTabs[1] - - // Check to see if this is a command that needs to exclude the current - // window - const excludeCurrentWindow = ["tabgrab"].includes(prefix.trim()) - const currentWindow = await browserBg.windows.getCurrent() - // Window Ids don't make sense so we're using LASTID and WININDEX to compute a window index - // This relies on the fact that tabs are sorted by window ids - let lastId = 0 - let winindex = 0 - for (const tab of tabs) { - if (lastId !== tab.windowId) { - lastId = tab.windowId - winindex += 1 - } - // if we are excluding the current window and this tab is in the current window - // then skip it - if (excludeCurrentWindow && tab.windowId === currentWindow.id) continue - options.push( - new TabAllCompletionOption( - tab.id.toString(), - tab, - tab.index === altTab.index && tab.windowId === altTab.windowId, - tab.active && tab.windowId === currentWindowTabs[0].windowId, - winindex, - await Containers.getFromId(tab.cookieStoreId), - windows[tab.windowId].incognito, - await tabTgroup(tab.id) - ), - ) - } - - this.completion = undefined - this.options = options - return this.updateChain() - } -} diff --git a/src/lib/tab_groups.ts b/src/lib/tab_groups.ts index 16ce9e6d..8007c0ea 100644 --- a/src/lib/tab_groups.ts +++ b/src/lib/tab_groups.ts @@ -81,6 +81,9 @@ export async function setWindowTgroup(name: string, id?: number) { */ export async function windowLastTgroup(id?: number) { const otherGroupsTabs = await tgroupTabs(await windowTgroup(id), true) + if (otherGroupsTabs.length === 0) { + return undefined + } otherGroupsTabs.sort((a, b) => b.lastAccessed - a.lastAccessed) const lastTabId = otherGroupsTabs[0].id return tabTgroup(lastTabId)