mirror of
https://github.com/zulip/zulip-desktop.git
synced 2025-11-03 13:33:18 +00:00
functional-tab: Split ‘name’ into ‘page’ and ‘label’.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
@@ -20,9 +20,11 @@ export type ServerConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TabRole = "server" | "function";
|
export type TabRole = "server" | "function";
|
||||||
|
export type TabPage = "Settings" | "About";
|
||||||
|
|
||||||
export type TabData = {
|
export type TabData = {
|
||||||
role: TabRole;
|
role: TabRole;
|
||||||
name: string;
|
page?: TabPage;
|
||||||
|
label: string;
|
||||||
index: number;
|
index: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -428,7 +428,7 @@ ${error}`,
|
|||||||
AppMenu.setMenu(properties);
|
AppMenu.setMenu(properties);
|
||||||
if (properties.activeTabIndex !== undefined) {
|
if (properties.activeTabIndex !== undefined) {
|
||||||
const activeTab = properties.tabs[properties.activeTabIndex];
|
const activeTab = properties.tabs[properties.activeTabIndex];
|
||||||
mainWindow.setTitle(`Zulip - ${activeTab.name}`);
|
mainWindow.setTitle(`Zulip - ${activeTab.label}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -318,12 +318,12 @@ function getWindowSubmenu(
|
|||||||
if (tab === undefined) continue;
|
if (tab === undefined) continue;
|
||||||
|
|
||||||
// Do not add functional tab settings to list of windows in menu bar
|
// Do not add functional tab settings to list of windows in menu bar
|
||||||
if (tab.role === "function" && tab.name === "Settings") {
|
if (tab.role === "function" && tab.page === "Settings") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
initialSubmenu.push({
|
initialSubmenu.push({
|
||||||
label: tab.name,
|
label: tab.label,
|
||||||
accelerator:
|
accelerator:
|
||||||
tab.role === "function" ? "" : `${shortcutKey} + ${tab.index + 1}`,
|
tab.role === "function" ? "" : `${shortcutKey} + ${tab.index + 1}`,
|
||||||
checked: tab.index === activeTabIndex,
|
checked: tab.index === activeTabIndex,
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import {type Html, html} from "../../../common/html.js";
|
import {type Html, html} from "../../../common/html.js";
|
||||||
|
import type {TabPage} from "../../../common/types.js";
|
||||||
|
|
||||||
import {generateNodeFromHtml} from "./base.js";
|
import {generateNodeFromHtml} from "./base.js";
|
||||||
import Tab, {type TabProperties} from "./tab.js";
|
import Tab, {type TabProperties} from "./tab.js";
|
||||||
|
|
||||||
export type FunctionalTabProperties = {
|
export type FunctionalTabProperties = {
|
||||||
$view: Element;
|
$view: Element;
|
||||||
|
page: TabPage;
|
||||||
} & TabProperties;
|
} & TabProperties;
|
||||||
|
|
||||||
export default class FunctionalTab extends Tab {
|
export default class FunctionalTab extends Tab {
|
||||||
@@ -17,7 +19,7 @@ export default class FunctionalTab extends Tab {
|
|||||||
|
|
||||||
this.$view = $view;
|
this.$view = $view;
|
||||||
this.$el = generateNodeFromHtml(this.templateHtml());
|
this.$el = generateNodeFromHtml(this.templateHtml());
|
||||||
if (this.properties.name !== "Settings") {
|
if (properties.page !== "Settings") {
|
||||||
this.properties.$root.append(this.$el);
|
this.properties.$root.append(this.$el);
|
||||||
this.$closeButton = this.$el.querySelector(".server-tab-badge")!;
|
this.$closeButton = this.$el.querySelector(".server-tab-badge")!;
|
||||||
this.registerListeners();
|
this.registerListeners();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default class ServerTab extends Tab {
|
|||||||
return html`
|
return html`
|
||||||
<div class="tab" data-tab-id="${this.properties.tabIndex}">
|
<div class="tab" data-tab-id="${this.properties.tabIndex}">
|
||||||
<div class="server-tooltip" style="display:none">
|
<div class="server-tooltip" style="display:none">
|
||||||
${this.properties.name}
|
${this.properties.label}
|
||||||
</div>
|
</div>
|
||||||
<div class="server-tab-badge"></div>
|
<div class="server-tab-badge"></div>
|
||||||
<div class="server-tab">
|
<div class="server-tab">
|
||||||
@@ -60,9 +60,9 @@ export default class ServerTab extends Tab {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setName(name: string): void {
|
setLabel(label: string): void {
|
||||||
this.properties.name = name;
|
this.properties.label = label;
|
||||||
this.$name.textContent = name;
|
this.$name.textContent = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIcon(icon: string): void {
|
setIcon(icon: string): void {
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import type {TabRole} from "../../../common/types.js";
|
import type {TabPage, TabRole} from "../../../common/types.js";
|
||||||
|
|
||||||
export type TabProperties = {
|
export type TabProperties = {
|
||||||
role: TabRole;
|
role: TabRole;
|
||||||
|
page?: TabPage;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
name: string;
|
label: string;
|
||||||
$root: Element;
|
$root: Element;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
index: number;
|
index: number;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import type {
|
|||||||
NavigationItem,
|
NavigationItem,
|
||||||
ServerConfig,
|
ServerConfig,
|
||||||
TabData,
|
TabData,
|
||||||
|
TabPage,
|
||||||
} from "../../common/types.js";
|
} from "../../common/types.js";
|
||||||
import defaultIcon from "../img/icon.png";
|
import defaultIcon from "../img/icon.png";
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ export class ServerManagerView {
|
|||||||
loading: Set<string>;
|
loading: Set<string>;
|
||||||
activeTabIndex: number;
|
activeTabIndex: number;
|
||||||
tabs: ServerOrFunctionalTab[];
|
tabs: ServerOrFunctionalTab[];
|
||||||
functionalTabs: Map<string, number>;
|
functionalTabs: Map<TabPage, number>;
|
||||||
tabIndex: number;
|
tabIndex: number;
|
||||||
presetOrgs: string[];
|
presetOrgs: string[];
|
||||||
preferenceView?: PreferenceView;
|
preferenceView?: PreferenceView;
|
||||||
@@ -333,7 +334,7 @@ export class ServerManagerView {
|
|||||||
server.url,
|
server.url,
|
||||||
i,
|
i,
|
||||||
);
|
);
|
||||||
tab.setName(serverConfig.alias);
|
tab.setLabel(serverConfig.alias);
|
||||||
tab.setIcon(DomainUtil.iconAsUrl(serverConfig.icon));
|
tab.setIcon(DomainUtil.iconAsUrl(serverConfig.icon));
|
||||||
(await tab.webview).setUnsupportedMessage(
|
(await tab.webview).setUnsupportedMessage(
|
||||||
DomainUtil.getUnsupportedMessage(serverConfig),
|
DomainUtil.getUnsupportedMessage(serverConfig),
|
||||||
@@ -376,7 +377,7 @@ export class ServerManagerView {
|
|||||||
const tab = new ServerTab({
|
const tab = new ServerTab({
|
||||||
role: "server",
|
role: "server",
|
||||||
icon: DomainUtil.iconAsUrl(server.icon),
|
icon: DomainUtil.iconAsUrl(server.icon),
|
||||||
name: server.alias,
|
label: server.alias,
|
||||||
$root: this.$tabsContainer,
|
$root: this.$tabsContainer,
|
||||||
onClick: this.activateLastTab.bind(this, index),
|
onClick: this.activateLastTab.bind(this, index),
|
||||||
index,
|
index,
|
||||||
@@ -558,18 +559,19 @@ export class ServerManagerView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async openFunctionalTab(tabProperties: {
|
async openFunctionalTab(tabProperties: {
|
||||||
name: string;
|
label: string;
|
||||||
|
page: TabPage;
|
||||||
materialIcon: string;
|
materialIcon: string;
|
||||||
makeView: () => Promise<Element>;
|
makeView: () => Promise<Element>;
|
||||||
destroyView: () => void;
|
destroyView: () => void;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
if (this.functionalTabs.has(tabProperties.name)) {
|
if (this.functionalTabs.has(tabProperties.page)) {
|
||||||
await this.activateTab(this.functionalTabs.get(tabProperties.name)!);
|
await this.activateTab(this.functionalTabs.get(tabProperties.page)!);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = this.tabs.length;
|
const index = this.tabs.length;
|
||||||
this.functionalTabs.set(tabProperties.name, index);
|
this.functionalTabs.set(tabProperties.page, index);
|
||||||
|
|
||||||
const tabIndex = this.getTabIndex();
|
const tabIndex = this.getTabIndex();
|
||||||
const $view = await tabProperties.makeView();
|
const $view = await tabProperties.makeView();
|
||||||
@@ -579,13 +581,14 @@ export class ServerManagerView {
|
|||||||
new FunctionalTab({
|
new FunctionalTab({
|
||||||
role: "function",
|
role: "function",
|
||||||
materialIcon: tabProperties.materialIcon,
|
materialIcon: tabProperties.materialIcon,
|
||||||
name: tabProperties.name,
|
label: tabProperties.label,
|
||||||
|
page: tabProperties.page,
|
||||||
$root: this.$tabsContainer,
|
$root: this.$tabsContainer,
|
||||||
index,
|
index,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
onClick: this.activateTab.bind(this, index),
|
onClick: this.activateTab.bind(this, index),
|
||||||
onDestroy: async () => {
|
onDestroy: async () => {
|
||||||
await this.destroyTab(tabProperties.name, index);
|
await this.destroyFunctionalTab(tabProperties.page, index);
|
||||||
tabProperties.destroyView();
|
tabProperties.destroyView();
|
||||||
},
|
},
|
||||||
$view,
|
$view,
|
||||||
@@ -596,14 +599,15 @@ export class ServerManagerView {
|
|||||||
// closed when the functional tab DOM is ready, handled in webview.js
|
// closed when the functional tab DOM is ready, handled in webview.js
|
||||||
this.$webviewsContainer.classList.remove("loaded");
|
this.$webviewsContainer.classList.remove("loaded");
|
||||||
|
|
||||||
await this.activateTab(this.functionalTabs.get(tabProperties.name)!);
|
await this.activateTab(this.functionalTabs.get(tabProperties.page)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
async openSettings(
|
async openSettings(
|
||||||
navigationItem: NavigationItem = "General",
|
navigationItem: NavigationItem = "General",
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.openFunctionalTab({
|
await this.openFunctionalTab({
|
||||||
name: "Settings",
|
page: "Settings",
|
||||||
|
label: "Settings",
|
||||||
materialIcon: "settings",
|
materialIcon: "settings",
|
||||||
makeView: async () => {
|
makeView: async () => {
|
||||||
this.preferenceView = await PreferenceView.create();
|
this.preferenceView = await PreferenceView.create();
|
||||||
@@ -622,7 +626,8 @@ export class ServerManagerView {
|
|||||||
async openAbout(): Promise<void> {
|
async openAbout(): Promise<void> {
|
||||||
let aboutView: AboutView;
|
let aboutView: AboutView;
|
||||||
await this.openFunctionalTab({
|
await this.openFunctionalTab({
|
||||||
name: "About",
|
page: "About",
|
||||||
|
label: "About",
|
||||||
materialIcon: "sentiment_very_satisfied",
|
materialIcon: "sentiment_very_satisfied",
|
||||||
async makeView() {
|
async makeView() {
|
||||||
aboutView = await AboutView.create();
|
aboutView = await AboutView.create();
|
||||||
@@ -660,7 +665,8 @@ export class ServerManagerView {
|
|||||||
get tabsForIpc(): TabData[] {
|
get tabsForIpc(): TabData[] {
|
||||||
return this.tabs.map((tab) => ({
|
return this.tabs.map((tab) => ({
|
||||||
role: tab.properties.role,
|
role: tab.properties.role,
|
||||||
name: tab.properties.name,
|
page: tab.properties.page,
|
||||||
|
label: tab.properties.label,
|
||||||
index: tab.properties.index,
|
index: tab.properties.index,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -680,7 +686,7 @@ export class ServerManagerView {
|
|||||||
// If old tab is functional tab Settings, remove focus from the settings icon at sidebar bottom
|
// If old tab is functional tab Settings, remove focus from the settings icon at sidebar bottom
|
||||||
if (
|
if (
|
||||||
this.tabs[this.activeTabIndex].properties.role === "function" &&
|
this.tabs[this.activeTabIndex].properties.role === "function" &&
|
||||||
this.tabs[this.activeTabIndex].properties.name === "Settings"
|
this.tabs[this.activeTabIndex].properties.page === "Settings"
|
||||||
) {
|
) {
|
||||||
this.$settingsButton.classList.remove("active");
|
this.$settingsButton.classList.remove("active");
|
||||||
}
|
}
|
||||||
@@ -722,7 +728,7 @@ export class ServerManagerView {
|
|||||||
this.$loadingIndicator.classList.toggle("hidden", !loading);
|
this.$loadingIndicator.classList.toggle("hidden", !loading);
|
||||||
}
|
}
|
||||||
|
|
||||||
async destroyTab(name: string, index: number): Promise<void> {
|
async destroyFunctionalTab(page: TabPage, index: number): Promise<void> {
|
||||||
const tab = this.tabs[index];
|
const tab = this.tabs[index];
|
||||||
if (tab instanceof ServerTab && (await tab.webview).loading) {
|
if (tab instanceof ServerTab && (await tab.webview).loading) {
|
||||||
return;
|
return;
|
||||||
@@ -731,7 +737,7 @@ export class ServerManagerView {
|
|||||||
await tab.destroy();
|
await tab.destroy();
|
||||||
|
|
||||||
delete this.tabs[index]; // eslint-disable-line @typescript-eslint/no-array-delete
|
delete this.tabs[index]; // eslint-disable-line @typescript-eslint/no-array-delete
|
||||||
this.functionalTabs.delete(name);
|
this.functionalTabs.delete(page);
|
||||||
|
|
||||||
// Issue #188: If the functional tab was not focused, do not activate another tab.
|
// Issue #188: If the functional tab was not focused, do not activate another tab.
|
||||||
if (this.activeTabIndex === index) {
|
if (this.activeTabIndex === index) {
|
||||||
@@ -1053,7 +1059,7 @@ export class ServerManagerView {
|
|||||||
for (const [index, domain] of DomainUtil.getDomains().entries()) {
|
for (const [index, domain] of DomainUtil.getDomains().entries()) {
|
||||||
if (domain.url === serverURL) {
|
if (domain.url === serverURL) {
|
||||||
const tab = this.tabs[index];
|
const tab = this.tabs[index];
|
||||||
if (tab instanceof ServerTab) tab.setName(realmName);
|
if (tab instanceof ServerTab) tab.setLabel(realmName);
|
||||||
domain.alias = realmName;
|
domain.alias = realmName;
|
||||||
DomainUtil.updateDomain(index, domain);
|
DomainUtil.updateDomain(index, domain);
|
||||||
// Update the realm name also on the Window menu
|
// Update the realm name also on the Window menu
|
||||||
|
|||||||
Reference in New Issue
Block a user