From 3b9c16779de9e74db72b8fc2f763faae21235e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20H=C3=A4usler?= Date: Sun, 28 Apr 2019 19:23:42 +0200 Subject: [PATCH] fix: #878 select existing tab (#986) --- .github/CHANGELOG.md | 1 + src/renderer/store/editor.js | 14 +++++++++++++- src/renderer/util/fileSystem.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index bb83dbc6..1fdf927d 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -16,6 +16,7 @@ - Fixed some commonmark failed examples and add test case (#943) - Fixed some bugs after press `backspace` (#934, #938) - Change `inline math` vertical align to `top` (#977) +- Prevent to open the same file twice, instead select the existing tab (#878) ### 0.14.0 diff --git a/src/renderer/store/editor.js b/src/renderer/store/editor.js index 23955ec5..c617d6a7 100644 --- a/src/renderer/store/editor.js +++ b/src/renderer/store/editor.js @@ -2,6 +2,7 @@ import { clipboard, ipcRenderer, shell } from 'electron' import path from 'path' import bus from '../bus' import { hasKeys } from '../util' +import { isSameFileSync } from '../util/fileSystem' import listToTree from '../util/listToTree' import { createDocumentState, getOptionsFromState, getSingleFileState, getBlankFileState } from './help' import notice from '../services/notification' @@ -63,7 +64,7 @@ const mutations = { type: 'primary', time: 20000, showConfirm: false - }) + }) } let fileState = null @@ -392,6 +393,7 @@ const actions = { } }, + // This event is only used when loading a file during window creation. LISTEN_FOR_OPEN_SINGLE_FILE ({ commit, state, dispatch }) { ipcRenderer.on('AGANI::open-single-file', (e, { markdown, filename, pathname, options }) => { const fileState = getSingleFileState({ markdown, filename, pathname, options }) @@ -410,6 +412,7 @@ const actions = { }) }, + // Open a new tab, optionally with content. LISTEN_FOR_NEW_TAB ({ dispatch }) { ipcRenderer.on('AGANI::new-tab', (e, markdownDocument) => { if (markdownDocument) { @@ -457,6 +460,15 @@ const actions = { return } + // Check if tab already exist and select existing tab if so. + const { tabs } = state + const { pathname } = markdownDocument + const existingTab = tabs.find(t => isSameFileSync(t.pathname, pathname)) + if (existingTab) { + dispatch('UPDATE_CURRENT_FILE', existingTab) + return + } + dispatch('SHOW_TAB_VIEW', false) const { markdown, isMixedLineEndings } = markdownDocument diff --git a/src/renderer/util/fileSystem.js b/src/renderer/util/fileSystem.js index 77b52175..7f086141 100644 --- a/src/renderer/util/fileSystem.js +++ b/src/renderer/util/fileSystem.js @@ -1,3 +1,4 @@ +import path from 'path' import fse from 'fs-extra' export const create = (pathname, type) => { @@ -15,3 +16,30 @@ export const paste = ({ src, dest, type }) => { export const rename = (src, dest) => { return fse.move(src, dest) } + +/** + * Check if the both paths point to the same file. + * + * @param {*} pathA The first path. + * @param {*} pathB The second path. + * @param {*} isNormalized Are both paths already normalized. + */ +export const isSameFileSync = (pathA, pathB, isNormalized=false) => { + if (!pathA || !pathB) return false + const a = isNormalized ? pathA : path.normalize(pathA) + const b = isNormalized ? pathB : path.normalize(pathB) + if (a.length !== b.length) { + return false + } else if (a === b) { + return true + } else if (a.toLowerCase() === b.toLowerCase()) { + try { + const fiA = fse.statSync(a) + const fiB = fse.statSync(b) + return fiA.ino === fiB.ino + } catch (_) { + // Ignore error + } + } + return false +}