"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fs_1 = require("fs");
const electron_1 = require("electron");
const electron_log_1 = require("electron-log");
const electron_updater_1 = require("electron-updater");
const electron_dl_1 = require("electron-dl");
const electronContextMenu = require("electron-context-menu");
const electronLocalshortcut = require("electron-localshortcut");
const electronDebug = require("electron-debug");
const electron_util_1 = require("electron-util");
const facebook_locales_1 = require("facebook-locales");
const menu_1 = require("./menu");
const config_1 = require("./config");
const tray_1 = require("./tray");
const util_1 = require("./util");
const emoji_1 = require("./emoji");
const ensure_online_1 = require("./ensure-online");
require("./touch-bar"); // eslint-disable-line import/no-unassigned-import
const menu_bar_mode_1 = require("./menu-bar-mode");
electron_1.ipcMain.setMaxListeners(100);
electronDebug({
    isEnabled: true,
    showDevTools: false
});
electron_dl_1.default();
electronContextMenu();
const domain = config_1.default.get('useWorkChat') ? 'facebook.com' : 'messenger.com';
electron_1.app.setAppUserModelId('com.sindresorhus.caprine');
if (!config_1.default.get('hardwareAcceleration')) {
    electron_1.app.disableHardwareAcceleration();
}
if (!electron_util_1.is.development && !electron_util_1.is.linux) {
    (async () => {
        electron_log_1.default.transports.file.level = 'info';
        electron_updater_1.autoUpdater.logger = electron_log_1.default;
        const FOUR_HOURS = 1000 * 60 * 60 * 4;
        setInterval(async () => {
            await electron_updater_1.autoUpdater.checkForUpdates();
        }, FOUR_HOURS);
        await electron_updater_1.autoUpdater.checkForUpdates();
    })();
}
let mainWindow;
let isQuitting = false;
let prevMessageCount = 0;
let dockMenu;
if (!electron_1.app.requestSingleInstanceLock()) {
    electron_1.app.quit();
}
electron_1.app.on('second-instance', () => {
    if (mainWindow) {
        if (mainWindow.isMinimized()) {
            mainWindow.restore();
        }
        mainWindow.show();
    }
});
function getMessageCount(conversations) {
    return conversations.filter(({ unread }) => unread).length;
}
function updateBadge(conversations) {
    // Ignore `Sindre messaged you` blinking
    if (!Array.isArray(conversations)) {
        return;
    }
    const messageCount = getMessageCount(conversations);
    if (electron_util_1.is.macos || electron_util_1.is.linux) {
        if (config_1.default.get('showUnreadBadge')) {
            electron_1.app.setBadgeCount(messageCount);
        }
        if (electron_util_1.is.macos && config_1.default.get('bounceDockOnMessage') && prevMessageCount !== messageCount) {
            electron_1.app.dock.bounce('informational');
            prevMessageCount = messageCount;
        }
    }
    if (electron_util_1.is.linux || electron_util_1.is.windows) {
        if (config_1.default.get('showUnreadBadge')) {
            tray_1.default.setBadge(messageCount > 0);
        }
        if (config_1.default.get('flashWindowOnMessage')) {
            mainWindow.flashFrame(messageCount !== 0);
        }
    }
    tray_1.default.update(messageCount);
    if (electron_util_1.is.windows) {
        if (config_1.default.get('showUnreadBadge')) {
            if (messageCount === 0) {
                mainWindow.setOverlayIcon(null, '');
            }
            else {
                // Delegate drawing of overlay icon to renderer process
                mainWindow.webContents.send('render-overlay-icon', messageCount);
            }
        }
    }
}
electron_1.ipcMain.on('update-overlay-icon', (_event, data, text) => {
    const img = electron_1.nativeImage.createFromDataURL(data);
    mainWindow.setOverlayIcon(img, text);
});
function updateTrayIcon() {
    if (!config_1.default.get('showTrayIcon') || config_1.default.get('quitOnWindowClose')) {
        tray_1.default.destroy();
    }
    else {
        tray_1.default.create(mainWindow);
    }
}
electron_1.ipcMain.on('update-tray-icon', updateTrayIcon);
function enableHiresResources() {
    const scaleFactor = Math.max(...electron_1.screen.getAllDisplays().map(display => display.scaleFactor));
    if (scaleFactor === 1) {
        return;
    }
    const filter = { urls: [`*://*.${domain}/`] };
    electron_1.session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
        let cookie = details.requestHeaders.Cookie;
        if (cookie && details.method === 'GET') {
            if (/(; )?dpr=\d/.test(cookie)) {
                cookie = cookie.replace(/dpr=\d/, `dpr=${scaleFactor}`);
            }
            else {
                cookie = `${cookie}; dpr=${scaleFactor}`;
            }
            details.requestHeaders.Cookie = cookie;
        }
        callback({
            cancel: false,
            requestHeaders: details.requestHeaders
        });
    });
}
function initRequestsFiltering() {
    const filter = {
        urls: [
            `*://*.${domain}/*typ.php*`,
            `*://*.${domain}/*change_read_status.php*`,
            `*://*.${domain}/*delivery_receipts*`,
            `*://*.${domain}/*unread_threads*`,
            '*://*.fbcdn.net/images/emoji.php/v9/*',
            '*://*.facebook.com/images/emoji.php/v9/*' // Emoji
        ]
    };
    electron_1.session.defaultSession.webRequest.onBeforeRequest(filter, async ({ url }, callback) => {
        if (url.includes('emoji.php')) {
            callback(await emoji_1.process(url));
        }
        else if (url.includes('typ.php')) {
            callback({ cancel: config_1.default.get('block.typingIndicator') });
        }
        else if (url.includes('change_read_status.php')) {
            callback({ cancel: config_1.default.get('block.chatSeen') });
        }
        else if (url.includes('delivery_receipts') || url.includes('unread_threads')) {
            callback({ cancel: config_1.default.get('block.deliveryReceipt') });
        }
    });
}
function setUserLocale() {
    const userLocale = facebook_locales_1.bestFacebookLocaleFor(electron_1.app.getLocale().replace('-', '_'));
    const cookie = {
        url: 'https://www.messenger.com/',
        name: 'locale',
        value: userLocale
    };
    electron_1.session.defaultSession.cookies.set(cookie);
}
function setNotificationsMute(status) {
    const label = 'Mute Notifications';
    const muteMenuItem = electron_1.Menu.getApplicationMenu().getMenuItemById('mute-notifications');
    config_1.default.set('notificationsMuted', status);
    muteMenuItem.checked = status;
    if (electron_util_1.is.macos) {
        const item = dockMenu.items.find(x => x.label === label);
        item.checked = status;
    }
}
function createMainWindow() {
    const lastWindowState = config_1.default.get('lastWindowState');
    const isDarkMode = config_1.default.get('darkMode');
    // Messenger or Work Chat
    const mainURL = config_1.default.get('useWorkChat')
        ? 'https://work.facebook.com/chat'
        : 'https://www.messenger.com/login/';
    const win = new electron_1.BrowserWindow({
        title: electron_1.app.getName(),
        show: false,
        x: lastWindowState.x,
        y: lastWindowState.y,
        width: lastWindowState.width,
        height: lastWindowState.height,
        icon: electron_util_1.is.linux ? path.join(__dirname, '..', 'static', 'Icon.png') : undefined,
        minWidth: 400,
        minHeight: 200,
        alwaysOnTop: config_1.default.get('alwaysOnTop'),
        titleBarStyle: 'hiddenInset',
        autoHideMenuBar: config_1.default.get('autoHideMenuBar'),
        darkTheme: isDarkMode,
        webPreferences: {
            preload: path.join(__dirname, 'browser.js'),
            contextIsolation: true,
            plugins: true
        }
    });
    setUserLocale();
    initRequestsFiltering();
    electron_util_1.darkMode.onChange(() => {
        win.webContents.send('set-dark-mode');
    });
    if (electron_util_1.is.macos) {
        win.setSheetOffset(40);
    }
    win.loadURL(mainURL);
    win.on('close', e => {
        if (config_1.default.get('quitOnWindowClose')) {
            electron_1.app.quit();
            return;
        }
        if (!isQuitting) {
            e.preventDefault();
            // Workaround for electron/electron#10023
            win.blur();
            win.hide();
        }
    });
    win.on('focus', () => {
        if (config_1.default.get('flashWindowOnMessage')) {
            // This is a security in the case where messageCount is not reset by page title update
            win.flashFrame(false);
        }
    });
    return win;
}
(async () => {
    await Promise.all([ensure_online_1.default(), electron_1.app.whenReady()]);
    const trackingUrlPrefix = `https://l.${domain}/l.php`;
    await menu_1.default();
    mainWindow = createMainWindow();
    // Workaround for https://github.com/electron/electron/issues/5256
    electronLocalshortcut.register(mainWindow, 'CommandOrControl+=', () => {
        util_1.sendAction('zoom-in');
    });
    // Start in menu bar mode if enabled, otherwise start normally
    menu_bar_mode_1.setUpMenuBarMode(mainWindow);
    if (electron_util_1.is.macos) {
        const firstItem = {
            label: 'Mute Notifications',
            type: 'checkbox',
            checked: config_1.default.get('notificationsMuted'),
            click() {
                mainWindow.webContents.send('toggle-mute-notifications');
            }
        };
        dockMenu = electron_1.Menu.buildFromTemplate([firstItem]);
        electron_1.app.dock.setMenu(dockMenu);
        // Dock icon is hidden initially on macOS
        if (config_1.default.get('showDockIcon')) {
            electron_1.app.dock.show();
        }
        electron_1.ipcMain.on('conversations', (_event, conversations) => {
            if (conversations.length === 0) {
                return;
            }
            const items = conversations.map(({ label, icon }, index) => {
                return {
                    label: `${label}`,
                    icon: electron_1.nativeImage.createFromDataURL(icon),
                    click: () => {
                        mainWindow.show();
                        util_1.sendAction('jump-to-conversation', index + 1);
                    }
                };
            });
            electron_1.app.dock.setMenu(electron_1.Menu.buildFromTemplate([firstItem, { type: 'separator' }, ...items]));
        });
    }
    // Update badge on conversations change
    electron_1.ipcMain.on('conversations', (_event, conversations) => {
        updateBadge(conversations);
    });
    enableHiresResources();
    const { webContents } = mainWindow;
    webContents.on('dom-ready', async () => {
        await menu_1.default();
        webContents.insertCSS(fs_1.readFileSync(path.join(__dirname, '..', 'css', 'browser.css'), 'utf8'));
        webContents.insertCSS(fs_1.readFileSync(path.join(__dirname, '..', 'css', 'dark-mode.css'), 'utf8'));
        webContents.insertCSS(fs_1.readFileSync(path.join(__dirname, '..', 'css', 'vibrancy.css'), 'utf8'));
        webContents.insertCSS(fs_1.readFileSync(path.join(__dirname, '..', 'css', 'code-blocks.css'), 'utf8'));
        webContents.insertCSS(fs_1.readFileSync(path.join(__dirname, '..', 'css', 'autoplay.css'), 'utf8'));
        if (config_1.default.get('useWorkChat')) {
            webContents.insertCSS(fs_1.readFileSync(path.join(__dirname, '..', 'css', 'workchat.css'), 'utf8'));
        }
        if (fs_1.existsSync(path.join(electron_1.app.getPath('userData'), 'custom.css'))) {
            webContents.insertCSS(fs_1.readFileSync(path.join(electron_1.app.getPath('userData'), 'custom.css'), 'utf8'));
        }
        if (config_1.default.get('launchMinimized') || electron_1.app.getLoginItemSettings().wasOpenedAsHidden) {
            mainWindow.hide();
        }
        else {
            mainWindow.show();
        }
        webContents.send('toggle-mute-notifications', config_1.default.get('notificationsMuted'));
        webContents.send('toggle-message-buttons', config_1.default.get('showMessageButtons'));
        await webContents.executeJavaScript(fs_1.readFileSync(path.join(__dirname, 'notifications-isolated.js'), 'utf8'));
    });
    webContents.on('new-window', (event, url, frameName, _disposition, options) => {
        event.preventDefault();
        if (url === 'about:blank') {
            if (frameName !== 'about:blank') {
                // Voice/video call popup
                options.show = true;
                options.titleBarStyle = 'default';
                options.webPreferences.nodeIntegration = false;
                options.webPreferences.preload = path.join(__dirname, 'browser-call.js');
                event.newGuest = new electron_1.BrowserWindow(options);
            }
        }
        else {
            if (url.startsWith(trackingUrlPrefix)) {
                url = new URL(url).searchParams.get('u');
            }
            electron_1.shell.openExternalSync(url);
        }
    });
    webContents.on('will-navigate', (event, url) => {
        const isMessengerDotCom = (url) => {
            const { hostname } = new URL(url);
            return hostname.endsWith('.messenger.com');
        };
        const isTwoFactorAuth = (url) => {
            const twoFactorAuthURL = 'https://www.facebook.com/checkpoint/start';
            return url.startsWith(twoFactorAuthURL);
        };
        const isWorkChat = (url) => {
            const { hostname, pathname } = new URL(url);
            if (hostname === 'work.facebook.com' || hostname === 'work.workplace.com') {
                return true;
            }
            if (
            // Example: https://company-name.facebook.com/login or
            //   		https://company-name.workplace.com/login
            (hostname.endsWith('.facebook.com') || hostname.endsWith('.workplace.com')) &&
                (pathname.startsWith('/login') || pathname.startsWith('/chat'))) {
                return true;
            }
            if (hostname === 'login.microsoftonline.com') {
                return true;
            }
            return false;
        };
        if (isMessengerDotCom(url) || isTwoFactorAuth(url) || isWorkChat(url)) {
            return;
        }
        event.preventDefault();
        electron_1.shell.openExternalSync(url);
    });
})();
if (electron_util_1.is.macos) {
    electron_1.ipcMain.on('set-vibrancy', () => {
        mainWindow.setVibrancy('sidebar');
        if (config_1.default.get('followSystemAppearance')) {
            electron_1.systemPreferences.setAppLevelAppearance(electron_1.systemPreferences.isDarkMode() ? 'dark' : 'light');
        }
        else {
            electron_1.systemPreferences.setAppLevelAppearance(config_1.default.get('darkMode') ? 'dark' : 'light');
        }
    });
}
electron_1.ipcMain.on('mute-notifications-toggled', (_event, status) => {
    setNotificationsMute(status);
});
electron_1.app.on('activate', () => {
    if (mainWindow) {
        mainWindow.show();
    }
});
electron_1.app.on('before-quit', () => {
    isQuitting = true;
    // Checking whether the window exists to work around an Electron race issue:
    // https://github.com/sindresorhus/caprine/issues/809
    if (mainWindow) {
        config_1.default.set('lastWindowState', mainWindow.getNormalBounds());
    }
});
const notifications = new Map();
electron_1.ipcMain.on('notification', (_event, { id, title, body, icon, silent }) => {
    const notification = new electron_1.Notification({
        title,
        body: config_1.default.get('notificationMessagePreview') ? body : `You have a new message`,
        hasReply: true,
        icon: electron_1.nativeImage.createFromDataURL(icon),
        silent
    });
    notifications.set(id, notification);
    notification.on('click', () => {
        util_1.sendAction('notification-callback', { callbackName: 'onclick', id });
        notifications.delete(id);
    });
    notification.on('reply', (_event, reply) => {
        // We use onclick event used by messenger to go to the right convo
        util_1.sendBackgroundAction('notification-reply-callback', { callbackName: 'onclick', id, reply });
        notifications.delete(id);
    });
    notification.on('close', () => {
        util_1.sendBackgroundAction('notification-callback', { callbackName: 'onclose', id });
        notifications.delete(id);
    });
    notification.show();
});
//# sourceMappingURL=index.js.map