mirror of
				https://github.com/zulip/zulip-desktop.git
				synced 2025-11-04 05:53:21 +00:00 
			
		
		
		
	Compare commits
	
		
			23 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					56ab0833b8 | ||
| 
						 | 
					c62b393c52 | ||
| 
						 | 
					991de77cad | ||
| 
						 | 
					94780c44c8 | ||
| 
						 | 
					82542a6390 | ||
| 
						 | 
					53ff8443dc | ||
| 
						 | 
					3855ecab58 | ||
| 
						 | 
					a57cbb4aa8 | ||
| 
						 | 
					56a4461c2a | ||
| 
						 | 
					cd023ec5ab | ||
| 
						 | 
					1aa4ade3c0 | ||
| 
						 | 
					dcb46eef4f | ||
| 
						 | 
					e3e8ef6e3e | ||
| 
						 | 
					6808b1971a | ||
| 
						 | 
					1dd5269549 | ||
| 
						 | 
					d33adca1e8 | ||
| 
						 | 
					8ea7f7864f | ||
| 
						 | 
					493ae06e52 | ||
| 
						 | 
					2b8f3536d3 | ||
| 
						 | 
					544d23ec09 | ||
| 
						 | 
					588d32fd22 | ||
| 
						 | 
					1c471fe624 | ||
| 
						 | 
					52486d687d | 
@@ -6,10 +6,10 @@ import {JsonDB} from "node-json-db";
 | 
			
		||||
import {DataError} from "node-json-db/dist/lib/Errors";
 | 
			
		||||
import type * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import {configSchemata} from "./config-schemata";
 | 
			
		||||
import * as EnterpriseUtil from "./enterprise-util";
 | 
			
		||||
import Logger from "./logger-util";
 | 
			
		||||
import {app, dialog} from "./remote";
 | 
			
		||||
import {configSchemata} from "./config-schemata.js";
 | 
			
		||||
import * as EnterpriseUtil from "./enterprise-util.js";
 | 
			
		||||
import Logger from "./logger-util.js";
 | 
			
		||||
import {app, dialog} from "./remote.js";
 | 
			
		||||
 | 
			
		||||
export type Config = {
 | 
			
		||||
  [Key in keyof typeof configSchemata]: z.output<typeof configSchemata[Key]>;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import fs from "node:fs";
 | 
			
		||||
 | 
			
		||||
import {app} from "./remote";
 | 
			
		||||
import {app} from "./remote.js";
 | 
			
		||||
 | 
			
		||||
let setupCompleted = false;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,8 @@ import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import type * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import type {dndSettingsSchemata} from "./config-schemata";
 | 
			
		||||
import * as ConfigUtil from "./config-util";
 | 
			
		||||
import type {dndSettingsSchemata} from "./config-schemata.js";
 | 
			
		||||
import * as ConfigUtil from "./config-util.js";
 | 
			
		||||
 | 
			
		||||
export type DndSettings = {
 | 
			
		||||
  [Key in keyof typeof dndSettingsSchemata]: z.output<
 | 
			
		||||
@@ -13,10 +13,10 @@ export type DndSettings = {
 | 
			
		||||
 | 
			
		||||
type SettingName = keyof DndSettings;
 | 
			
		||||
 | 
			
		||||
interface Toggle {
 | 
			
		||||
type Toggle = {
 | 
			
		||||
  dnd: boolean;
 | 
			
		||||
  newSettings: Partial<DndSettings>;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function toggle(): Toggle {
 | 
			
		||||
  const dnd = !ConfigUtil.getConfigItem("dnd", false);
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@ import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import {enterpriseConfigSchemata} from "./config-schemata";
 | 
			
		||||
import Logger from "./logger-util";
 | 
			
		||||
import {enterpriseConfigSchemata} from "./config-schemata.js";
 | 
			
		||||
import Logger from "./logger-util.js";
 | 
			
		||||
 | 
			
		||||
type EnterpriseConfig = {
 | 
			
		||||
  [Key in keyof typeof enterpriseConfigSchemata]: z.output<
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import fs from "node:fs";
 | 
			
		||||
import os from "node:os";
 | 
			
		||||
import path from "node:path";
 | 
			
		||||
 | 
			
		||||
import {html} from "./html";
 | 
			
		||||
import {html} from "./html.js";
 | 
			
		||||
 | 
			
		||||
export async function openBrowser(url: URL): Promise<void> {
 | 
			
		||||
  if (["http:", "https:", "mailto:"].includes(url.protocol)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
import {Console} from "node:console";
 | 
			
		||||
import {Console} from "node:console"; // eslint-disable-line n/prefer-global/console
 | 
			
		||||
import fs from "node:fs";
 | 
			
		||||
import os from "node:os";
 | 
			
		||||
import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import {initSetUp} from "./default-util";
 | 
			
		||||
import {app} from "./remote";
 | 
			
		||||
import {initSetUp} from "./default-util.js";
 | 
			
		||||
import {app} from "./remote.js";
 | 
			
		||||
 | 
			
		||||
interface LoggerOptions {
 | 
			
		||||
type LoggerOptions = {
 | 
			
		||||
  file?: string;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
initSetUp();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
interface DialogBoxError {
 | 
			
		||||
type DialogBoxError = {
 | 
			
		||||
  title: string;
 | 
			
		||||
  content: string;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function invalidZulipServerError(domain: string): string {
 | 
			
		||||
  return `${domain} does not appear to be a valid Zulip server. Make sure that
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import path from "node:path";
 | 
			
		||||
 | 
			
		||||
import i18n from "i18n";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "./config-util";
 | 
			
		||||
import * as ConfigUtil from "./config-util.js";
 | 
			
		||||
 | 
			
		||||
i18n.configure({
 | 
			
		||||
  directory: path.join(__dirname, "../translations/"),
 | 
			
		||||
@@ -14,5 +14,5 @@ const appLocale = ConfigUtil.getConfigItem("appLanguage", "en");
 | 
			
		||||
 | 
			
		||||
/* If no locale present in the json, en is set default */
 | 
			
		||||
export function __(phrase: string): string {
 | 
			
		||||
  return i18n.__({phrase, locale: appLocale ? appLocale : "en"});
 | 
			
		||||
  return i18n.__({phrase, locale: appLocale ?? "en"});
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import type {DndSettings} from "./dnd-util";
 | 
			
		||||
import type {MenuProps, ServerConf} from "./types";
 | 
			
		||||
import type {DndSettings} from "./dnd-util.js";
 | 
			
		||||
import type {MenuProps, ServerConf} from "./types.js";
 | 
			
		||||
 | 
			
		||||
export interface MainMessage {
 | 
			
		||||
export type MainMessage = {
 | 
			
		||||
  "clear-app-settings": () => void;
 | 
			
		||||
  "configure-spell-checker": () => void;
 | 
			
		||||
  "fetch-user-agent": () => string;
 | 
			
		||||
@@ -22,15 +22,15 @@ export interface MainMessage {
 | 
			
		||||
  "update-badge": (messageCount: number) => void;
 | 
			
		||||
  "update-menu": (props: MenuProps) => void;
 | 
			
		||||
  "update-taskbar-icon": (data: string, text: string) => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface MainCall {
 | 
			
		||||
export type MainCall = {
 | 
			
		||||
  "get-server-settings": (domain: string) => ServerConf;
 | 
			
		||||
  "is-online": (url: string) => boolean;
 | 
			
		||||
  "save-server-icon": (iconURL: string) => string;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface RendererMessage {
 | 
			
		||||
export type RendererMessage = {
 | 
			
		||||
  back: () => void;
 | 
			
		||||
  "copy-zulip-url": () => void;
 | 
			
		||||
  destroytray: () => void;
 | 
			
		||||
@@ -79,4 +79,4 @@ export interface RendererMessage {
 | 
			
		||||
  zoomActualSize: () => void;
 | 
			
		||||
  zoomIn: () => void;
 | 
			
		||||
  zoomOut: () => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
export interface MenuProps {
 | 
			
		||||
export type MenuProps = {
 | 
			
		||||
  tabs: TabData[];
 | 
			
		||||
  activeTabIndex?: number;
 | 
			
		||||
  enableMenu?: boolean;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type NavItem =
 | 
			
		||||
  | "General"
 | 
			
		||||
@@ -11,16 +11,16 @@ export type NavItem =
 | 
			
		||||
  | "Organizations"
 | 
			
		||||
  | "Shortcuts";
 | 
			
		||||
 | 
			
		||||
export interface ServerConf {
 | 
			
		||||
export type ServerConf = {
 | 
			
		||||
  url: string;
 | 
			
		||||
  alias: string;
 | 
			
		||||
  icon: string;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type TabRole = "server" | "function";
 | 
			
		||||
 | 
			
		||||
export interface TabData {
 | 
			
		||||
export type TabData = {
 | 
			
		||||
  role: TabRole;
 | 
			
		||||
  name: string;
 | 
			
		||||
  index: number;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,20 @@
 | 
			
		||||
import {shell} from "electron/common";
 | 
			
		||||
import {app, dialog, session} from "electron/main";
 | 
			
		||||
import process from "node:process";
 | 
			
		||||
import util from "node:util";
 | 
			
		||||
 | 
			
		||||
import log from "electron-log";
 | 
			
		||||
import type {UpdateDownloadedEvent, UpdateInfo} from "electron-updater";
 | 
			
		||||
import {autoUpdater} from "electron-updater";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
 | 
			
		||||
import {linuxUpdateNotification} from "./linuxupdater"; // Required only in case of linux
 | 
			
		||||
import {linuxUpdateNotification} from "./linuxupdater.js"; // Required only in case of linux
 | 
			
		||||
 | 
			
		||||
const sleep = util.promisify(setTimeout);
 | 
			
		||||
let quitting = false;
 | 
			
		||||
 | 
			
		||||
export function shouldQuitForUpdate(): boolean {
 | 
			
		||||
  return quitting;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function appUpdater(updateFromMenu = false): Promise<void> {
 | 
			
		||||
  // Don't initiate auto-updates in development
 | 
			
		||||
@@ -37,7 +40,10 @@ export async function appUpdater(updateFromMenu = false): Promise<void> {
 | 
			
		||||
 | 
			
		||||
  autoUpdater.allowPrerelease = isBetaUpdate;
 | 
			
		||||
 | 
			
		||||
  const eventsListenerRemove = ["update-available", "update-not-available"];
 | 
			
		||||
  const eventsListenerRemove = [
 | 
			
		||||
    "update-available",
 | 
			
		||||
    "update-not-available",
 | 
			
		||||
  ] as const;
 | 
			
		||||
  autoUpdater.on("update-available", async (info: UpdateInfo) => {
 | 
			
		||||
    if (updateFromMenu) {
 | 
			
		||||
      updateAvailable = true;
 | 
			
		||||
@@ -104,10 +110,8 @@ Current Version: ${app.getVersion()}`,
 | 
			
		||||
      detail: "It will be installed the next time you restart the application",
 | 
			
		||||
    });
 | 
			
		||||
    if (response === 0) {
 | 
			
		||||
      await sleep(1000);
 | 
			
		||||
      quitting = true;
 | 
			
		||||
      autoUpdater.quitAndInstall();
 | 
			
		||||
      // Force app to quit. This is just a workaround, ideally autoUpdater.quitAndInstall() should relaunch the app.
 | 
			
		||||
      app.quit();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  // Init for updates
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,9 @@ import type {BrowserWindow} from "electron/main";
 | 
			
		||||
import {app} from "electron/main";
 | 
			
		||||
import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
 | 
			
		||||
import {send} from "./typed-ipc-main";
 | 
			
		||||
import {send} from "./typed-ipc-main.js";
 | 
			
		||||
 | 
			
		||||
function showBadgeCount(messageCount: number, mainWindow: BrowserWindow): void {
 | 
			
		||||
  if (process.platform === "win32") {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,10 @@ import {Notification, app} from "electron/main";
 | 
			
		||||
import fs from "node:fs";
 | 
			
		||||
import path from "node:path";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import * as LinkUtil from "../common/link-util";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
import * as LinkUtil from "../common/link-util.js";
 | 
			
		||||
 | 
			
		||||
import {send} from "./typed-ipc-main";
 | 
			
		||||
import {send} from "./typed-ipc-main.js";
 | 
			
		||||
 | 
			
		||||
function isUploadsUrl(server: string, url: URL): boolean {
 | 
			
		||||
  return url.origin === server && url.pathname.startsWith("/user_uploads/");
 | 
			
		||||
@@ -105,7 +105,13 @@ export default function handleExternalLink(
 | 
			
		||||
  details: HandlerDetails,
 | 
			
		||||
  mainContents: WebContents,
 | 
			
		||||
): void {
 | 
			
		||||
  const url = new URL(details.url);
 | 
			
		||||
  let url: URL;
 | 
			
		||||
  try {
 | 
			
		||||
    url = new URL(details.url);
 | 
			
		||||
  } catch {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const downloadPath = ConfigUtil.getConfigItem(
 | 
			
		||||
    "downloadsPath",
 | 
			
		||||
    `${app.getPath("downloads")}`,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,18 +6,20 @@ import process from "node:process";
 | 
			
		||||
import * as remoteMain from "@electron/remote/main";
 | 
			
		||||
import windowStateKeeper from "electron-window-state";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import type {RendererMessage} from "../common/typed-ipc";
 | 
			
		||||
import type {MenuProps} from "../common/types";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
import type {RendererMessage} from "../common/typed-ipc.js";
 | 
			
		||||
import type {MenuProps} from "../common/types.js";
 | 
			
		||||
 | 
			
		||||
import {appUpdater} from "./autoupdater";
 | 
			
		||||
import * as BadgeSettings from "./badge-settings";
 | 
			
		||||
import handleExternalLink from "./handle-external-link";
 | 
			
		||||
import * as AppMenu from "./menu";
 | 
			
		||||
import {_getServerSettings, _isOnline, _saveServerIcon} from "./request";
 | 
			
		||||
import {sentryInit} from "./sentry";
 | 
			
		||||
import {setAutoLaunch} from "./startup";
 | 
			
		||||
import {ipcMain, send} from "./typed-ipc-main";
 | 
			
		||||
import {appUpdater, shouldQuitForUpdate} from "./autoupdater.js";
 | 
			
		||||
import * as BadgeSettings from "./badge-settings.js";
 | 
			
		||||
import handleExternalLink from "./handle-external-link.js";
 | 
			
		||||
import * as AppMenu from "./menu.js";
 | 
			
		||||
import {_getServerSettings, _isOnline, _saveServerIcon} from "./request.js";
 | 
			
		||||
import {sentryInit} from "./sentry.js";
 | 
			
		||||
import {setAutoLaunch} from "./startup.js";
 | 
			
		||||
import {ipcMain, send} from "./typed-ipc-main.js";
 | 
			
		||||
 | 
			
		||||
import "gatemaker/electron-setup"; // eslint-disable-line import/no-unassigned-import
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/naming-convention
 | 
			
		||||
const {GDK_BACKEND} = process.env;
 | 
			
		||||
@@ -73,6 +75,7 @@ function createMainWindow(): BrowserWindow {
 | 
			
		||||
    minHeight: 400,
 | 
			
		||||
    webPreferences: {
 | 
			
		||||
      preload: require.resolve("../renderer/js/main"),
 | 
			
		||||
      sandbox: false,
 | 
			
		||||
      webviewTag: true,
 | 
			
		||||
    },
 | 
			
		||||
    show: false,
 | 
			
		||||
@@ -91,7 +94,7 @@ function createMainWindow(): BrowserWindow {
 | 
			
		||||
      app.quit();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!isQuitting) {
 | 
			
		||||
    if (!isQuitting && !shouldQuitForUpdate()) {
 | 
			
		||||
      event.preventDefault();
 | 
			
		||||
 | 
			
		||||
      if (process.platform === "darwin") {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ import path from "node:path";
 | 
			
		||||
import {JsonDB} from "node-json-db";
 | 
			
		||||
import {DataError} from "node-json-db/dist/lib/Errors";
 | 
			
		||||
 | 
			
		||||
import Logger from "../common/logger-util";
 | 
			
		||||
import Logger from "../common/logger-util.js";
 | 
			
		||||
 | 
			
		||||
const logger = new Logger({
 | 
			
		||||
  file: "linux-update-util.log",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,11 @@ import getStream from "get-stream";
 | 
			
		||||
import * as semver from "semver";
 | 
			
		||||
import * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import Logger from "../common/logger-util";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
import Logger from "../common/logger-util.js";
 | 
			
		||||
 | 
			
		||||
import * as LinuxUpdateUtil from "./linux-update-util";
 | 
			
		||||
import {fetchResponse} from "./request";
 | 
			
		||||
import * as LinuxUpdateUtil from "./linux-update-util.js";
 | 
			
		||||
import {fetchResponse} from "./request.js";
 | 
			
		||||
 | 
			
		||||
const logger = new Logger({
 | 
			
		||||
  file: "linux-update-util.log",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,14 +5,14 @@ import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import AdmZip from "adm-zip";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import * as DNDUtil from "../common/dnd-util";
 | 
			
		||||
import * as t from "../common/translation-util";
 | 
			
		||||
import type {RendererMessage} from "../common/typed-ipc";
 | 
			
		||||
import type {MenuProps, TabData} from "../common/types";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
import * as DNDUtil from "../common/dnd-util.js";
 | 
			
		||||
import * as t from "../common/translation-util.js";
 | 
			
		||||
import type {RendererMessage} from "../common/typed-ipc.js";
 | 
			
		||||
import type {MenuProps, TabData} from "../common/types.js";
 | 
			
		||||
 | 
			
		||||
import {appUpdater} from "./autoupdater";
 | 
			
		||||
import {send} from "./typed-ipc-main";
 | 
			
		||||
import {appUpdater} from "./autoupdater.js";
 | 
			
		||||
import {send} from "./typed-ipc-main.js";
 | 
			
		||||
 | 
			
		||||
const appName = app.name;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,9 @@ import * as Sentry from "@sentry/electron";
 | 
			
		||||
import getStream from "get-stream";
 | 
			
		||||
import * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import Logger from "../common/logger-util";
 | 
			
		||||
import * as Messages from "../common/messages";
 | 
			
		||||
import type {ServerConf} from "../common/types";
 | 
			
		||||
import Logger from "../common/logger-util.js";
 | 
			
		||||
import * as Messages from "../common/messages.js";
 | 
			
		||||
import type {ServerConf} from "../common/types.js";
 | 
			
		||||
 | 
			
		||||
export async function fetchResponse(
 | 
			
		||||
  request: ClientRequest,
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import {app} from "electron/main";
 | 
			
		||||
 | 
			
		||||
import * as Sentry from "@sentry/electron";
 | 
			
		||||
 | 
			
		||||
import {getConfigItem} from "../common/config-util";
 | 
			
		||||
import {getConfigItem} from "../common/config-util.js";
 | 
			
		||||
 | 
			
		||||
export const sentryInit = (): void => {
 | 
			
		||||
  Sentry.init({
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import AutoLaunch from "auto-launch";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../common/config-util";
 | 
			
		||||
import * as ConfigUtil from "../common/config-util.js";
 | 
			
		||||
 | 
			
		||||
export const setAutoLaunch = async (
 | 
			
		||||
  AutoLaunchValue: boolean,
 | 
			
		||||
 
 | 
			
		||||
@@ -16,11 +16,11 @@ import crypto from "node:crypto";
 | 
			
		||||
// don’t leak anything from the user’s clipboard other than the token
 | 
			
		||||
// intended for us.
 | 
			
		||||
 | 
			
		||||
export interface ClipboardDecrypter {
 | 
			
		||||
export type ClipboardDecrypter = {
 | 
			
		||||
  version: number;
 | 
			
		||||
  key: Uint8Array;
 | 
			
		||||
  pasted: Promise<string>;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export class ClipboardDecrypterImpl implements ClipboardDecrypter {
 | 
			
		||||
  version: number;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import type {Html} from "../../../common/html";
 | 
			
		||||
import type {Html} from "../../../common/html.js";
 | 
			
		||||
 | 
			
		||||
export function generateNodeFromHtml(html: Html): Element {
 | 
			
		||||
  const wrapper = document.createElement("div");
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import {Menu} from "@electron/remote";
 | 
			
		||||
 | 
			
		||||
import * as t from "../../../common/translation-util";
 | 
			
		||||
import * as t from "../../../common/translation-util.js";
 | 
			
		||||
 | 
			
		||||
export const contextMenu = (
 | 
			
		||||
  webContents: WebContents,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
import type {Html} from "../../../common/html";
 | 
			
		||||
import {html} from "../../../common/html";
 | 
			
		||||
import type {Html} from "../../../common/html.js";
 | 
			
		||||
import {html} from "../../../common/html.js";
 | 
			
		||||
 | 
			
		||||
import {generateNodeFromHtml} from "./base";
 | 
			
		||||
import type {TabProps} from "./tab";
 | 
			
		||||
import Tab from "./tab";
 | 
			
		||||
import {generateNodeFromHtml} from "./base.js";
 | 
			
		||||
import type {TabProps} from "./tab.js";
 | 
			
		||||
import Tab from "./tab.js";
 | 
			
		||||
 | 
			
		||||
export interface FunctionalTabProps extends TabProps {
 | 
			
		||||
export type FunctionalTabProps = {
 | 
			
		||||
  $view: Element;
 | 
			
		||||
}
 | 
			
		||||
} & TabProps;
 | 
			
		||||
 | 
			
		||||
export default class FunctionalTab extends Tab {
 | 
			
		||||
  $view: Element;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,17 @@
 | 
			
		||||
import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import type {Html} from "../../../common/html";
 | 
			
		||||
import {html} from "../../../common/html";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import type {Html} from "../../../common/html.js";
 | 
			
		||||
import {html} from "../../../common/html.js";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
import {generateNodeFromHtml} from "./base";
 | 
			
		||||
import type {TabProps} from "./tab";
 | 
			
		||||
import Tab from "./tab";
 | 
			
		||||
import type WebView from "./webview";
 | 
			
		||||
import {generateNodeFromHtml} from "./base.js";
 | 
			
		||||
import type {TabProps} from "./tab.js";
 | 
			
		||||
import Tab from "./tab.js";
 | 
			
		||||
import type WebView from "./webview.js";
 | 
			
		||||
 | 
			
		||||
export interface ServerTabProps extends TabProps {
 | 
			
		||||
export type ServerTabProps = {
 | 
			
		||||
  webview: Promise<WebView>;
 | 
			
		||||
}
 | 
			
		||||
} & TabProps;
 | 
			
		||||
 | 
			
		||||
export default class ServerTab extends Tab {
 | 
			
		||||
  webview: Promise<WebView>;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import type {TabRole} from "../../../common/types";
 | 
			
		||||
import type {TabRole} from "../../../common/types.js";
 | 
			
		||||
 | 
			
		||||
export interface TabProps {
 | 
			
		||||
export type TabProps = {
 | 
			
		||||
  role: TabRole;
 | 
			
		||||
  icon?: string;
 | 
			
		||||
  name: string;
 | 
			
		||||
@@ -12,15 +12,12 @@ export interface TabProps {
 | 
			
		||||
  onHoverOut?: () => void;
 | 
			
		||||
  materialIcon?: string;
 | 
			
		||||
  onDestroy?: () => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default abstract class Tab {
 | 
			
		||||
  props: TabProps;
 | 
			
		||||
  abstract $el: Element;
 | 
			
		||||
 | 
			
		||||
  constructor(props: TabProps) {
 | 
			
		||||
    this.props = props;
 | 
			
		||||
  }
 | 
			
		||||
  constructor(readonly props: TabProps) {}
 | 
			
		||||
 | 
			
		||||
  registerListeners(): void {
 | 
			
		||||
    this.$el.addEventListener("click", this.props.onClick);
 | 
			
		||||
 
 | 
			
		||||
@@ -6,20 +6,20 @@ import process from "node:process";
 | 
			
		||||
import * as remote from "@electron/remote";
 | 
			
		||||
import {app, dialog} from "@electron/remote";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../../../common/config-util";
 | 
			
		||||
import type {Html} from "../../../common/html";
 | 
			
		||||
import {html} from "../../../common/html";
 | 
			
		||||
import type {RendererMessage} from "../../../common/typed-ipc";
 | 
			
		||||
import type {TabRole} from "../../../common/types";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import * as SystemUtil from "../utils/system-util";
 | 
			
		||||
import * as ConfigUtil from "../../../common/config-util.js";
 | 
			
		||||
import type {Html} from "../../../common/html.js";
 | 
			
		||||
import {html} from "../../../common/html.js";
 | 
			
		||||
import type {RendererMessage} from "../../../common/typed-ipc.js";
 | 
			
		||||
import type {TabRole} from "../../../common/types.js";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
import * as SystemUtil from "../utils/system-util.js";
 | 
			
		||||
 | 
			
		||||
import {generateNodeFromHtml} from "./base";
 | 
			
		||||
import {contextMenu} from "./context-menu";
 | 
			
		||||
import {generateNodeFromHtml} from "./base.js";
 | 
			
		||||
import {contextMenu} from "./context-menu.js";
 | 
			
		||||
 | 
			
		||||
const shouldSilentWebview = ConfigUtil.getConfigItem("silent", false);
 | 
			
		||||
 | 
			
		||||
interface WebViewProps {
 | 
			
		||||
type WebViewProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
  rootWebContents: WebContents;
 | 
			
		||||
  index: number;
 | 
			
		||||
@@ -32,7 +32,7 @@ interface WebViewProps {
 | 
			
		||||
  preload?: string;
 | 
			
		||||
  onTitleChange: () => void;
 | 
			
		||||
  hasPermission?: (origin: string, permission: string) => boolean;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default class WebView {
 | 
			
		||||
  static templateHtml(props: WebViewProps): Html {
 | 
			
		||||
@@ -42,7 +42,7 @@ export default class WebView {
 | 
			
		||||
        src="${props.url}"
 | 
			
		||||
        ${props.preload === undefined
 | 
			
		||||
          ? html``
 | 
			
		||||
          : html`preload="${props.preload}"`}
 | 
			
		||||
          : html`preload="${props.preload}" webpreferences="sandbox=no"`}
 | 
			
		||||
        partition="persist:webviewsession"
 | 
			
		||||
        allowpopups
 | 
			
		||||
      >
 | 
			
		||||
@@ -92,7 +92,6 @@ export default class WebView {
 | 
			
		||||
    return new WebView(props, $element, webContentsId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  props: WebViewProps;
 | 
			
		||||
  zoomFactor: number;
 | 
			
		||||
  badgeCount: number;
 | 
			
		||||
  loading: boolean;
 | 
			
		||||
@@ -102,11 +101,10 @@ export default class WebView {
 | 
			
		||||
  webContentsId: number;
 | 
			
		||||
 | 
			
		||||
  private constructor(
 | 
			
		||||
    props: WebViewProps,
 | 
			
		||||
    readonly props: WebViewProps,
 | 
			
		||||
    $element: HTMLElement,
 | 
			
		||||
    webContentsId: number,
 | 
			
		||||
  ) {
 | 
			
		||||
    this.props = props;
 | 
			
		||||
    this.zoomFactor = 1;
 | 
			
		||||
    this.loading = true;
 | 
			
		||||
    this.badgeCount = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
import {EventEmitter} from "node:events";
 | 
			
		||||
 | 
			
		||||
import type {ClipboardDecrypter} from "./clipboard-decrypter";
 | 
			
		||||
import {ClipboardDecrypterImpl} from "./clipboard-decrypter";
 | 
			
		||||
import type {NotificationData} from "./notification";
 | 
			
		||||
import {newNotification} from "./notification";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer";
 | 
			
		||||
import type {ClipboardDecrypter} from "./clipboard-decrypter.js";
 | 
			
		||||
import {ClipboardDecrypterImpl} from "./clipboard-decrypter.js";
 | 
			
		||||
import type {NotificationData} from "./notification/index.js";
 | 
			
		||||
import {newNotification} from "./notification/index.js";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
type ListenerType = (...args: any[]) => void;
 | 
			
		||||
 | 
			
		||||
export interface ElectronBridge {
 | 
			
		||||
export type ElectronBridge = {
 | 
			
		||||
  send_event: (eventName: string | symbol, ...args: unknown[]) => boolean;
 | 
			
		||||
  on_event: (eventName: string, listener: ListenerType) => void;
 | 
			
		||||
  new_notification: (
 | 
			
		||||
@@ -21,7 +21,7 @@ export interface ElectronBridge {
 | 
			
		||||
  get_send_notification_reply_message_supported: () => boolean;
 | 
			
		||||
  set_send_notification_reply_message_supported: (value: boolean) => void;
 | 
			
		||||
  decrypt_clipboard: (version: number) => ClipboardDecrypter;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let notificationReplySupported = false;
 | 
			
		||||
// Indicates if the user is idle or not
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
type ElectronBridge = import("./electron-bridge").ElectronBridge;
 | 
			
		||||
type ElectronBridge = import("./electron-bridge.js").ElectronBridge;
 | 
			
		||||
 | 
			
		||||
interface CompatElectronBridge extends ElectronBridge {
 | 
			
		||||
type CompatElectronBridge = {
 | 
			
		||||
  readonly idle_on_system: boolean;
 | 
			
		||||
  readonly last_active_on_system: number;
 | 
			
		||||
  send_notification_reply_message_supported: boolean;
 | 
			
		||||
}
 | 
			
		||||
} & ElectronBridge;
 | 
			
		||||
 | 
			
		||||
(() => {
 | 
			
		||||
  const zulipWindow = window as typeof window & {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,25 +6,25 @@ import {Menu, app, dialog, session} from "@electron/remote";
 | 
			
		||||
import * as remote from "@electron/remote";
 | 
			
		||||
import * as Sentry from "@sentry/electron";
 | 
			
		||||
 | 
			
		||||
import type {Config} from "../../common/config-util";
 | 
			
		||||
import * as ConfigUtil from "../../common/config-util";
 | 
			
		||||
import * as DNDUtil from "../../common/dnd-util";
 | 
			
		||||
import type {DndSettings} from "../../common/dnd-util";
 | 
			
		||||
import * as EnterpriseUtil from "../../common/enterprise-util";
 | 
			
		||||
import * as LinkUtil from "../../common/link-util";
 | 
			
		||||
import Logger from "../../common/logger-util";
 | 
			
		||||
import * as Messages from "../../common/messages";
 | 
			
		||||
import type {NavItem, ServerConf, TabData} from "../../common/types";
 | 
			
		||||
import type {Config} from "../../common/config-util.js";
 | 
			
		||||
import * as ConfigUtil from "../../common/config-util.js";
 | 
			
		||||
import * as DNDUtil from "../../common/dnd-util.js";
 | 
			
		||||
import type {DndSettings} from "../../common/dnd-util.js";
 | 
			
		||||
import * as EnterpriseUtil from "../../common/enterprise-util.js";
 | 
			
		||||
import * as LinkUtil from "../../common/link-util.js";
 | 
			
		||||
import Logger from "../../common/logger-util.js";
 | 
			
		||||
import * as Messages from "../../common/messages.js";
 | 
			
		||||
import type {NavItem, ServerConf, TabData} from "../../common/types.js";
 | 
			
		||||
 | 
			
		||||
import FunctionalTab from "./components/functional-tab";
 | 
			
		||||
import ServerTab from "./components/server-tab";
 | 
			
		||||
import WebView from "./components/webview";
 | 
			
		||||
import {AboutView} from "./pages/about";
 | 
			
		||||
import {PreferenceView} from "./pages/preference/preference";
 | 
			
		||||
import {initializeTray} from "./tray";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer";
 | 
			
		||||
import * as DomainUtil from "./utils/domain-util";
 | 
			
		||||
import ReconnectUtil from "./utils/reconnect-util";
 | 
			
		||||
import FunctionalTab from "./components/functional-tab.js";
 | 
			
		||||
import ServerTab from "./components/server-tab.js";
 | 
			
		||||
import WebView from "./components/webview.js";
 | 
			
		||||
import {AboutView} from "./pages/about.js";
 | 
			
		||||
import {PreferenceView} from "./pages/preference/preference.js";
 | 
			
		||||
import {initializeTray} from "./tray.js";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer.js";
 | 
			
		||||
import * as DomainUtil from "./utils/domain-util.js";
 | 
			
		||||
import ReconnectUtil from "./utils/reconnect-util.js";
 | 
			
		||||
 | 
			
		||||
Sentry.init({});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
export interface NotificationData {
 | 
			
		||||
export type NotificationData = {
 | 
			
		||||
  close: () => void;
 | 
			
		||||
  title: string;
 | 
			
		||||
  dir: NotificationDirection;
 | 
			
		||||
@@ -9,7 +9,7 @@ export interface NotificationData {
 | 
			
		||||
  tag: string;
 | 
			
		||||
  icon: string;
 | 
			
		||||
  data: unknown;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function newNotification(
 | 
			
		||||
  title: string,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import {app} from "@electron/remote";
 | 
			
		||||
 | 
			
		||||
import {html} from "../../../common/html";
 | 
			
		||||
import {html} from "../../../common/html.js";
 | 
			
		||||
 | 
			
		||||
export class AboutView {
 | 
			
		||||
  readonly $view: HTMLElement;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
export function init(
 | 
			
		||||
  $reconnectButton: Element,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
import type {Html} from "../../../../common/html";
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import type {Html} from "../../../../common/html.js";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base.js";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
interface BaseSectionProps {
 | 
			
		||||
type BaseSectionProps = {
 | 
			
		||||
  $element: HTMLElement;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
  value: boolean;
 | 
			
		||||
  clickHandler: () => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function generateSettingOption(props: BaseSectionProps): void {
 | 
			
		||||
  const {$element, disabled, value, clickHandler} = props;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import * as DomainUtil from "../../utils/domain-util";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
import * as DomainUtil from "../../utils/domain-util.js";
 | 
			
		||||
 | 
			
		||||
import {reloadApp} from "./base-section";
 | 
			
		||||
import {initFindAccounts} from "./find-accounts";
 | 
			
		||||
import {initServerInfoForm} from "./server-info-form";
 | 
			
		||||
import {reloadApp} from "./base-section.js";
 | 
			
		||||
import {initFindAccounts} from "./find-accounts.js";
 | 
			
		||||
import {initServerInfoForm} from "./server-info-form.js";
 | 
			
		||||
 | 
			
		||||
interface ConnectedOrgSectionProps {
 | 
			
		||||
type ConnectedOrgSectionProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function initConnectedOrgSection({
 | 
			
		||||
  $root,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,11 @@
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as LinkUtil from "../../../../common/link-util";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as LinkUtil from "../../../../common/link-util.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base.js";
 | 
			
		||||
 | 
			
		||||
interface FindAccountsProps {
 | 
			
		||||
type FindAccountsProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
async function findAccounts(url: string): Promise<void> {
 | 
			
		||||
  if (!url) {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,20 +9,20 @@ import Tagify from "@yaireo/tagify";
 | 
			
		||||
import ISO6391 from "iso-639-1";
 | 
			
		||||
import * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../../../../common/config-util";
 | 
			
		||||
import * as EnterpriseUtil from "../../../../common/enterprise-util";
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import * as ConfigUtil from "../../../../common/config-util.js";
 | 
			
		||||
import * as EnterpriseUtil from "../../../../common/enterprise-util.js";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import supportedLocales from "../../../../translations/supported-locales.json";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
import {generateSelectHtml, generateSettingOption} from "./base-section";
 | 
			
		||||
import {generateSelectHtml, generateSettingOption} from "./base-section.js";
 | 
			
		||||
 | 
			
		||||
const currentBrowserWindow = remote.getCurrentWindow();
 | 
			
		||||
 | 
			
		||||
interface GeneralSectionProps {
 | 
			
		||||
type GeneralSectionProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function initGeneralSection({$root}: GeneralSectionProps): void {
 | 
			
		||||
  $root.innerHTML = html`
 | 
			
		||||
@@ -616,7 +616,7 @@ export function initGeneralSection({$root}: GeneralSectionProps): void {
 | 
			
		||||
      const availableLanguages = session.fromPartition(
 | 
			
		||||
        "persist:webviewsession",
 | 
			
		||||
      ).availableSpellCheckerLanguages;
 | 
			
		||||
      let languagePairs: Map<string, string> = new Map();
 | 
			
		||||
      let languagePairs = new Map<string, string>();
 | 
			
		||||
      for (const l of availableLanguages) {
 | 
			
		||||
        if (ISO6391.validate(l)) {
 | 
			
		||||
          languagePairs.set(ISO6391.getName(l), l);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,18 @@
 | 
			
		||||
import type {Html} from "../../../../common/html";
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import type {NavItem} from "../../../../common/types";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base";
 | 
			
		||||
import type {Html} from "../../../../common/html.js";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import type {NavItem} from "../../../../common/types.js";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base.js";
 | 
			
		||||
 | 
			
		||||
interface PreferenceNavProps {
 | 
			
		||||
type PreferenceNavProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
  onItemSelected: (navItem: NavItem) => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default class PreferenceNav {
 | 
			
		||||
  props: PreferenceNavProps;
 | 
			
		||||
  navItems: NavItem[];
 | 
			
		||||
  $el: Element;
 | 
			
		||||
  constructor(props: PreferenceNavProps) {
 | 
			
		||||
    this.props = props;
 | 
			
		||||
  constructor(private readonly props: PreferenceNavProps) {
 | 
			
		||||
    this.navItems = [
 | 
			
		||||
      "General",
 | 
			
		||||
      "Network",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
import * as ConfigUtil from "../../../../common/config-util";
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import * as ConfigUtil from "../../../../common/config-util.js";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
import {generateSettingOption} from "./base-section";
 | 
			
		||||
import {generateSettingOption} from "./base-section.js";
 | 
			
		||||
 | 
			
		||||
interface NetworkSectionProps {
 | 
			
		||||
type NetworkSectionProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function initNetworkSection({$root}: NetworkSectionProps): void {
 | 
			
		||||
  $root.innerHTML = html`
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,16 @@
 | 
			
		||||
import {dialog} from "@electron/remote";
 | 
			
		||||
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as LinkUtil from "../../../../common/link-util";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import * as DomainUtil from "../../utils/domain-util";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as LinkUtil from "../../../../common/link-util.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base.js";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
import * as DomainUtil from "../../utils/domain-util.js";
 | 
			
		||||
 | 
			
		||||
interface NewServerFormProps {
 | 
			
		||||
type NewServerFormProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
  onChange: () => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function initNewServerForm({$root, onChange}: NewServerFormProps): void {
 | 
			
		||||
  const $newServerForm = generateNodeFromHtml(html`
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,16 @@
 | 
			
		||||
import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import type {DndSettings} from "../../../../common/dnd-util";
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import type {NavItem} from "../../../../common/types";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import type {DndSettings} from "../../../../common/dnd-util.js";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import type {NavItem} from "../../../../common/types.js";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
import {initConnectedOrgSection} from "./connected-org-section";
 | 
			
		||||
import {initGeneralSection} from "./general-section";
 | 
			
		||||
import Nav from "./nav";
 | 
			
		||||
import {initNetworkSection} from "./network-section";
 | 
			
		||||
import {initServersSection} from "./servers-section";
 | 
			
		||||
import {initShortcutsSection} from "./shortcuts-section";
 | 
			
		||||
import {initConnectedOrgSection} from "./connected-org-section.js";
 | 
			
		||||
import {initGeneralSection} from "./general-section.js";
 | 
			
		||||
import Nav from "./nav.js";
 | 
			
		||||
import {initNetworkSection} from "./network-section.js";
 | 
			
		||||
import {initServersSection} from "./servers-section.js";
 | 
			
		||||
import {initShortcutsSection} from "./shortcuts-section.js";
 | 
			
		||||
 | 
			
		||||
export class PreferenceView {
 | 
			
		||||
  readonly $view: HTMLElement;
 | 
			
		||||
@@ -63,29 +63,33 @@ export class PreferenceView {
 | 
			
		||||
    this.navItem = navItem;
 | 
			
		||||
    this.nav.select(navItem);
 | 
			
		||||
    switch (navItem) {
 | 
			
		||||
      case "AddServer":
 | 
			
		||||
      case "AddServer": {
 | 
			
		||||
        initServersSection({
 | 
			
		||||
          $root: this.$settingsContainer,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      case "General":
 | 
			
		||||
      case "General": {
 | 
			
		||||
        initGeneralSection({
 | 
			
		||||
          $root: this.$settingsContainer,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      case "Organizations":
 | 
			
		||||
      case "Organizations": {
 | 
			
		||||
        initConnectedOrgSection({
 | 
			
		||||
          $root: this.$settingsContainer,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      case "Network":
 | 
			
		||||
      case "Network": {
 | 
			
		||||
        initNetworkSection({
 | 
			
		||||
          $root: this.$settingsContainer,
 | 
			
		||||
        });
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      case "Shortcuts": {
 | 
			
		||||
        initShortcutsSection({
 | 
			
		||||
@@ -94,9 +98,10 @@ export class PreferenceView {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      default:
 | 
			
		||||
      default: {
 | 
			
		||||
        ((n: never) => n)(navItem);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    window.location.hash = `#${navItem}`;
 | 
			
		||||
  };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,19 @@
 | 
			
		||||
import {dialog} from "@electron/remote";
 | 
			
		||||
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as Messages from "../../../../common/messages";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import type {ServerConf} from "../../../../common/types";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer";
 | 
			
		||||
import * as DomainUtil from "../../utils/domain-util";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as Messages from "../../../../common/messages.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
import type {ServerConf} from "../../../../common/types.js";
 | 
			
		||||
import {generateNodeFromHtml} from "../../components/base.js";
 | 
			
		||||
import {ipcRenderer} from "../../typed-ipc-renderer.js";
 | 
			
		||||
import * as DomainUtil from "../../utils/domain-util.js";
 | 
			
		||||
 | 
			
		||||
interface ServerInfoFormProps {
 | 
			
		||||
type ServerInfoFormProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
  server: ServerConf;
 | 
			
		||||
  index: number;
 | 
			
		||||
  onChange: () => void;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function initServerInfoForm(props: ServerInfoFormProps): void {
 | 
			
		||||
  const $serverInfoForm = generateNodeFromHtml(html`
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
 | 
			
		||||
import {reloadApp} from "./base-section";
 | 
			
		||||
import {initNewServerForm} from "./new-server-form";
 | 
			
		||||
import {reloadApp} from "./base-section.js";
 | 
			
		||||
import {initNewServerForm} from "./new-server-form.js";
 | 
			
		||||
 | 
			
		||||
interface ServersSectionProps {
 | 
			
		||||
type ServersSectionProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function initServersSection({$root}: ServersSectionProps): void {
 | 
			
		||||
  $root.innerHTML = html`
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import {html} from "../../../../common/html";
 | 
			
		||||
import * as LinkUtil from "../../../../common/link-util";
 | 
			
		||||
import * as t from "../../../../common/translation-util";
 | 
			
		||||
import {html} from "../../../../common/html.js";
 | 
			
		||||
import * as LinkUtil from "../../../../common/link-util.js";
 | 
			
		||||
import * as t from "../../../../common/translation-util.js";
 | 
			
		||||
 | 
			
		||||
interface ShortcutsSectionProps {
 | 
			
		||||
type ShortcutsSectionProps = {
 | 
			
		||||
  $root: Element;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line complexity
 | 
			
		||||
export function initShortcutsSection({$root}: ShortcutsSectionProps): void {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
import {contextBridge, webFrame} from "electron/renderer";
 | 
			
		||||
import fs from "node:fs";
 | 
			
		||||
 | 
			
		||||
import electron_bridge, {bridgeEvents} from "./electron-bridge";
 | 
			
		||||
import * as NetworkError from "./pages/network";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer";
 | 
			
		||||
import electron_bridge, {bridgeEvents} from "./electron-bridge.js";
 | 
			
		||||
import * as NetworkError from "./pages/network.js";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
contextBridge.exposeInMainWorld("raw_electron_bridge", electron_bridge);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,11 @@ import process from "node:process";
 | 
			
		||||
 | 
			
		||||
import {BrowserWindow, Menu, Tray} from "@electron/remote";
 | 
			
		||||
 | 
			
		||||
import * as ConfigUtil from "../../common/config-util";
 | 
			
		||||
import type {RendererMessage} from "../../common/typed-ipc";
 | 
			
		||||
import * as ConfigUtil from "../../common/config-util.js";
 | 
			
		||||
import type {RendererMessage} from "../../common/typed-ipc.js";
 | 
			
		||||
 | 
			
		||||
import type {ServerManagerView} from "./main";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer";
 | 
			
		||||
import type {ServerManagerView} from "./main.js";
 | 
			
		||||
import {ipcRenderer} from "./typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
let tray: ElectronTray | null = null;
 | 
			
		||||
 | 
			
		||||
@@ -36,15 +36,22 @@ let unread = 0;
 | 
			
		||||
 | 
			
		||||
const trayIconSize = (): number => {
 | 
			
		||||
  switch (process.platform) {
 | 
			
		||||
    case "darwin":
 | 
			
		||||
    case "darwin": {
 | 
			
		||||
      return 20;
 | 
			
		||||
    case "win32":
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case "win32": {
 | 
			
		||||
      return 100;
 | 
			
		||||
    case "linux":
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case "linux": {
 | 
			
		||||
      return 100;
 | 
			
		||||
    default:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default: {
 | 
			
		||||
      return 80;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  Default config for Icon we might make it OS specific if needed like the size
 | 
			
		||||
@@ -236,5 +243,3 @@ export function initializeTray(serverManagerView: ServerManagerView) {
 | 
			
		||||
    createTray();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {};
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ import type {
 | 
			
		||||
  MainCall,
 | 
			
		||||
  MainMessage,
 | 
			
		||||
  RendererMessage,
 | 
			
		||||
} from "../../common/typed-ipc";
 | 
			
		||||
} from "../../common/typed-ipc.js";
 | 
			
		||||
 | 
			
		||||
type RendererListener<Channel extends keyof RendererMessage> =
 | 
			
		||||
  RendererMessage[Channel] extends (...args: infer Args) => void
 | 
			
		||||
 
 | 
			
		||||
@@ -7,11 +7,11 @@ import {JsonDB} from "node-json-db";
 | 
			
		||||
import {DataError} from "node-json-db/dist/lib/Errors";
 | 
			
		||||
import * as z from "zod";
 | 
			
		||||
 | 
			
		||||
import * as EnterpriseUtil from "../../../common/enterprise-util";
 | 
			
		||||
import Logger from "../../../common/logger-util";
 | 
			
		||||
import * as Messages from "../../../common/messages";
 | 
			
		||||
import type {ServerConf} from "../../../common/types";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import * as EnterpriseUtil from "../../../common/enterprise-util.js";
 | 
			
		||||
import Logger from "../../../common/logger-util.js";
 | 
			
		||||
import * as Messages from "../../../common/messages.js";
 | 
			
		||||
import type {ServerConf} from "../../../common/types.js";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
const logger = new Logger({
 | 
			
		||||
  file: "domain-util.log",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,20 @@
 | 
			
		||||
import * as backoff from "backoff";
 | 
			
		||||
 | 
			
		||||
import {html} from "../../../common/html";
 | 
			
		||||
import Logger from "../../../common/logger-util";
 | 
			
		||||
import type WebView from "../components/webview";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import {html} from "../../../common/html.js";
 | 
			
		||||
import Logger from "../../../common/logger-util.js";
 | 
			
		||||
import type WebView from "../components/webview.js";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
const logger = new Logger({
 | 
			
		||||
  file: "domain-util.log",
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default class ReconnectUtil {
 | 
			
		||||
  webview: WebView;
 | 
			
		||||
  url: string;
 | 
			
		||||
  alreadyReloaded: boolean;
 | 
			
		||||
  fibonacciBackoff: backoff.Backoff;
 | 
			
		||||
 | 
			
		||||
  constructor(webview: WebView) {
 | 
			
		||||
    this.webview = webview;
 | 
			
		||||
    this.url = webview.props.url;
 | 
			
		||||
    this.alreadyReloaded = false;
 | 
			
		||||
    this.fibonacciBackoff = backoff.fibonacci({
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer";
 | 
			
		||||
import {ipcRenderer} from "../typed-ipc-renderer.js";
 | 
			
		||||
 | 
			
		||||
export const connectivityError: string[] = [
 | 
			
		||||
  "ERR_INTERNET_DISCONNECTED",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 | 
			
		||||
<plist version="1.0">
 | 
			
		||||
  <dict>
 | 
			
		||||
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
 | 
			
		||||
    <true/>
 | 
			
		||||
  </dict>
 | 
			
		||||
</plist>
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 | 
			
		||||
<plist version="1.0">
 | 
			
		||||
<dict>
 | 
			
		||||
	<key>com.apple.security.app-sandbox</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
	<key>com.apple.security.network.client</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
	<key>com.apple.security.files.user-selected.read-only</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
	<key>com.apple.security.files.user-selected.read-write</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
	<key>com.apple.security.files.downloads.read-write</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
</dict>
 | 
			
		||||
</plist>
 | 
			
		||||
							
								
								
									
										22
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								changelog.md
									
									
									
									
									
								
							@@ -2,6 +2,28 @@
 | 
			
		||||
 | 
			
		||||
All notable changes to the Zulip desktop app are documented in this file.
 | 
			
		||||
 | 
			
		||||
### v5.9.4 --2023-01-04
 | 
			
		||||
 | 
			
		||||
**Fixes**:
 | 
			
		||||
 | 
			
		||||
- The `com.apple.quarantine` extended attribute is now correctly set for downloaded files on macOS.
 | 
			
		||||
- The external link handler ignores invalid URLs.
 | 
			
		||||
 | 
			
		||||
**Dependencies**:
 | 
			
		||||
 | 
			
		||||
- Upgraded all dependencies, including Electron 22.0.0.
 | 
			
		||||
 | 
			
		||||
### v5.9.3 --2022-04-28
 | 
			
		||||
 | 
			
		||||
**Fixes**:
 | 
			
		||||
 | 
			
		||||
- Fixed a bug in the automatic updater that would sometimes close the application instead of updating it.
 | 
			
		||||
  (As with most updater fixes, this fix will take effect when updating _from_ 5.9.3. If you're having trouble updating _to_ 5.9.3, a workaround is to click **Install Later** rather than **Install and Relaunch**, then **Quit** from the menu bar and re-open the application manually.)
 | 
			
		||||
 | 
			
		||||
**Dependencies**:
 | 
			
		||||
 | 
			
		||||
- Upgraded all dependencies, including Electron 18.2.0.
 | 
			
		||||
 | 
			
		||||
### v5.9.2 --2022-04-20
 | 
			
		||||
 | 
			
		||||
**Dependencies**:
 | 
			
		||||
 
 | 
			
		||||
@@ -53,20 +53,20 @@
 | 
			
		||||
 | 
			
		||||
- First download our signing key to make sure the deb you download is correct:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
sudo apt-key adv --keyserver pool.sks-keyservers.net --recv 69AD12704E71A4803DCA3A682424BE5AE9BD10D9
 | 
			
		||||
```bash
 | 
			
		||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 69AD12704E71A4803DCA3A682424BE5AE9BD10D9
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- Add the repo to your apt source list :
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
echo "deb https://dl.bintray.com/zulip/debian/ beta main" |
 | 
			
		||||
```bash
 | 
			
		||||
echo "deb https://download.zulip.com/desktop/apt stable main" |
 | 
			
		||||
  sudo tee -a /etc/apt/sources.list.d/zulip.list
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- Now install the client :
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
sudo apt-get update
 | 
			
		||||
sudo apt-get install zulip
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7735
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7735
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										39
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								package.json
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "zulip",
 | 
			
		||||
  "productName": "Zulip",
 | 
			
		||||
  "version": "5.9.2",
 | 
			
		||||
  "version": "5.9.4",
 | 
			
		||||
  "main": "./app/main",
 | 
			
		||||
  "description": "Zulip Desktop App",
 | 
			
		||||
  "license": "Apache-2.0",
 | 
			
		||||
@@ -18,7 +18,7 @@
 | 
			
		||||
    "url": "https://github.com/zulip/zulip-desktop/issues"
 | 
			
		||||
  },
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": ">=12.10.0"
 | 
			
		||||
    "node": ">=16.13.2"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "start": "tsc && electron .",
 | 
			
		||||
@@ -69,11 +69,7 @@
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "darkModeSupport": true,
 | 
			
		||||
      "artifactName": "${productName}-${version}-${arch}.${ext}",
 | 
			
		||||
      "hardenedRuntime": true,
 | 
			
		||||
      "entitlements": "build/entitlements.mac.plist",
 | 
			
		||||
      "entitlementsInherit": "build/entitlements.mac.plist",
 | 
			
		||||
      "gatekeeperAssess": false
 | 
			
		||||
      "artifactName": "${productName}-${version}-${arch}.${ext}"
 | 
			
		||||
    },
 | 
			
		||||
    "linux": {
 | 
			
		||||
      "category": "Chat;GNOME;GTK;Network;InstantMessaging",
 | 
			
		||||
@@ -147,7 +143,7 @@
 | 
			
		||||
  ],
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@electron/remote": "^2.0.8",
 | 
			
		||||
    "@sentry/electron": "^3.0.3",
 | 
			
		||||
    "@sentry/electron": "^4.1.2",
 | 
			
		||||
    "@yaireo/tagify": "^4.5.0",
 | 
			
		||||
    "adm-zip": "^0.5.5",
 | 
			
		||||
    "auto-launch": "^5.0.5",
 | 
			
		||||
@@ -156,8 +152,9 @@
 | 
			
		||||
    "electron-updater": "^5.0.1",
 | 
			
		||||
    "electron-window-state": "^5.0.3",
 | 
			
		||||
    "escape-goat": "^3.0.0",
 | 
			
		||||
    "gatemaker": "^1.0.0",
 | 
			
		||||
    "get-stream": "^6.0.1",
 | 
			
		||||
    "i18n": "^0.14.1",
 | 
			
		||||
    "i18n": "^0.15.1",
 | 
			
		||||
    "iso-639-1": "^2.1.9",
 | 
			
		||||
    "node-json-db": "^1.3.0",
 | 
			
		||||
    "semver": "^7.3.5",
 | 
			
		||||
@@ -172,22 +169,21 @@
 | 
			
		||||
    "@types/requestidlecallback": "^0.3.4",
 | 
			
		||||
    "@types/yaireo__tagify": "^4.3.2",
 | 
			
		||||
    "dotenv": "^16.0.0",
 | 
			
		||||
    "electron": "^18.0.1",
 | 
			
		||||
    "electron": "^22.0.0",
 | 
			
		||||
    "electron-builder": "^23.0.3",
 | 
			
		||||
    "electron-notarize": "^1.0.0",
 | 
			
		||||
    "eslint-import-resolver-typescript": "^2.4.0",
 | 
			
		||||
    "htmlhint": "^1.1.2",
 | 
			
		||||
    "medium": "^1.2.0",
 | 
			
		||||
    "playwright-core": "^1.19.1",
 | 
			
		||||
    "playwright-core": "^1.30.0-alpha-jan-3-2023",
 | 
			
		||||
    "pre-commit": "^1.2.2",
 | 
			
		||||
    "prettier": "^2.3.2",
 | 
			
		||||
    "rimraf": "^3.0.2",
 | 
			
		||||
    "stylelint": "^14.5.3",
 | 
			
		||||
    "stylelint-config-prettier": "^9.0.3",
 | 
			
		||||
    "stylelint-config-standard": "^25.0.0",
 | 
			
		||||
    "stylelint-config-standard": "^29.0.0",
 | 
			
		||||
    "tape": "^5.2.2",
 | 
			
		||||
    "typescript": "^4.3.5",
 | 
			
		||||
    "xo": "^0.48.0"
 | 
			
		||||
    "xo": "^0.53.1"
 | 
			
		||||
  },
 | 
			
		||||
  "prettier": {
 | 
			
		||||
    "bracketSpacing": false,
 | 
			
		||||
@@ -199,15 +195,6 @@
 | 
			
		||||
    "rules": {
 | 
			
		||||
      "@typescript-eslint/no-dynamic-delete": "off",
 | 
			
		||||
      "arrow-body-style": "error",
 | 
			
		||||
      "import/extensions": [
 | 
			
		||||
        "error",
 | 
			
		||||
        "always",
 | 
			
		||||
        {
 | 
			
		||||
          "pattern": {
 | 
			
		||||
            "ts": "never"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "import/no-restricted-paths": [
 | 
			
		||||
        "error",
 | 
			
		||||
        {
 | 
			
		||||
@@ -285,7 +272,8 @@
 | 
			
		||||
      ],
 | 
			
		||||
      "strict": "error",
 | 
			
		||||
      "unicorn/prefer-json-parse-buffer": "off",
 | 
			
		||||
      "unicorn/prefer-module": "off"
 | 
			
		||||
      "unicorn/prefer-module": "off",
 | 
			
		||||
      "unicorn/prefer-top-level-await": "off"
 | 
			
		||||
    },
 | 
			
		||||
    "envs": [
 | 
			
		||||
      "node",
 | 
			
		||||
@@ -312,9 +300,6 @@
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
          "unicorn/no-await-expression-member": "off"
 | 
			
		||||
        },
 | 
			
		||||
        "settings": {
 | 
			
		||||
          "import/resolver": "typescript"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# Link to the binary
 | 
			
		||||
ln -sf '/opt/${productFilename}/${executable}' '/usr/bin/${executable}'
 | 
			
		||||
ln -sf '/opt/${sanitizedProductName}/${executable}' '/usr/bin/${executable}'
 | 
			
		||||
 | 
			
		||||
# SUID chrome-sandbox for Electron 5+
 | 
			
		||||
chmod 4755 '/opt/${productFilename}/chrome-sandbox' || true
 | 
			
		||||
chmod 4755 '/opt/${sanitizedProductName}/chrome-sandbox' || true
 | 
			
		||||
 | 
			
		||||
update-mime-database /usr/share/mime || true
 | 
			
		||||
update-desktop-database /usr/share/applications || true
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const process = require("process");
 | 
			
		||||
const path = require("node:path");
 | 
			
		||||
const process = require("node:process");
 | 
			
		||||
 | 
			
		||||
const dotenv = require("dotenv");
 | 
			
		||||
const {notarize} = require("electron-notarize");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "version": "5.9.3",
 | 
			
		||||
  "productName": "ZulipTest",
 | 
			
		||||
  "main": "../app/main/index.js"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
const path = require("path");
 | 
			
		||||
const process = require("process");
 | 
			
		||||
const path = require("node:path");
 | 
			
		||||
const process = require("node:process");
 | 
			
		||||
 | 
			
		||||
const {_electron} = require("playwright-core");
 | 
			
		||||
const rimraf = require("rimraf");
 | 
			
		||||
@@ -30,20 +30,26 @@ function getAppDataDir() {
 | 
			
		||||
  let base;
 | 
			
		||||
 | 
			
		||||
  switch (process.platform) {
 | 
			
		||||
    case "darwin":
 | 
			
		||||
    case "darwin": {
 | 
			
		||||
      base = path.join(process.env.HOME, "Library", "Application Support");
 | 
			
		||||
      break;
 | 
			
		||||
    case "linux":
 | 
			
		||||
      base = process.env.XDG_CONFIG_HOME
 | 
			
		||||
        ? process.env.XDG_CONFIG_HOME
 | 
			
		||||
        : path.join(process.env.HOME, ".config");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case "linux": {
 | 
			
		||||
      base =
 | 
			
		||||
        process.env.XDG_CONFIG_HOME ?? path.join(process.env.HOME, ".config");
 | 
			
		||||
      break;
 | 
			
		||||
    case "win32":
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    case "win32": {
 | 
			
		||||
      base = process.env.APPDATA;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    default: {
 | 
			
		||||
      throw new Error("Could not detect app data dir base.");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  console.log("Detected App Data Dir base:", base);
 | 
			
		||||
  return path.join(base, testsPkg.productName);
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,10 @@ test("add-organization", async (t) => {
 | 
			
		||||
    const mainWindow = await take(windows);
 | 
			
		||||
    t.equal(await mainWindow.title(), "Zulip");
 | 
			
		||||
 | 
			
		||||
    await mainWindow.fill(".setting-input-value", "chat.zulip.org");
 | 
			
		||||
    await mainWindow.fill(
 | 
			
		||||
      ".setting-input-value",
 | 
			
		||||
      "zulip-desktop-test.zulipchat.com",
 | 
			
		||||
    );
 | 
			
		||||
    await mainWindow.click("#connect");
 | 
			
		||||
 | 
			
		||||
    const orgWebview = await take(windows);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								typings.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								typings.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
declare namespace Electron {
 | 
			
		||||
  // https://github.com/electron/typescript-definitions/issues/170
 | 
			
		||||
  // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
 | 
			
		||||
  interface IncomingMessage extends NodeJS.ReadableStream {}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user