@lvce-editor/explorer-view 1.29.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/explorerViewWorkerMain.js +600 -635
- package/package.json +1 -1
|
@@ -1802,7 +1802,108 @@ const focusPrevious = state => {
|
|
|
1802
1802
|
}
|
|
1803
1803
|
};
|
|
1804
1804
|
|
|
1805
|
-
const
|
|
1805
|
+
const commandIds = ['acceptEdit', 'cancelEdit', 'collapseAll', 'copyPath', 'copyRelativePath', 'expandAll', 'expandRecursively', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'getFocusedDirent', 'handleArrowLeft', 'handleArrowLeft', 'handleArrowRight', 'handleArrowRight', 'handleBlur', 'handleClick', 'handleClickAt', 'handleClickCurrent', 'handleClickCurrentButKeepFocus', 'handleClickOpenFolder', 'handleContextMenu', 'handleCopy', 'handleDragOver', 'handleDrop', 'handleFocus', 'handleIconThemeChange', 'handleLanguagesChanged', 'handleMouseEnter', 'handleMouseLeave', 'handlePaste', 'handlePointerDown', 'handleUpload', 'handleWheel', 'handleWorkspaceChange', 'hotReload', 'newFile', 'newFolder', 'openContainingFolder', 'refresh', 'refresh', 'relealItem', 'removeDirent', 'rename', 'renameDirent', 'revealItem', 'scrollDown', 'scrollUp', 'setDeltaY', 'renderEventListeners', 'updateEditingValue', 'updateIcons'];
|
|
1806
|
+
|
|
1807
|
+
const getCommandIds = () => {
|
|
1808
|
+
return commandIds;
|
|
1809
|
+
};
|
|
1810
|
+
|
|
1811
|
+
const Enter = 3;
|
|
1812
|
+
const Escape = 8;
|
|
1813
|
+
const Space = 9;
|
|
1814
|
+
const End = 255;
|
|
1815
|
+
const Home = 12;
|
|
1816
|
+
const LeftArrow = 13;
|
|
1817
|
+
const UpArrow = 14;
|
|
1818
|
+
const RightArrow = 15;
|
|
1819
|
+
const DownArrow = 16;
|
|
1820
|
+
const Delete$1 = 18;
|
|
1821
|
+
const KeyC = 31;
|
|
1822
|
+
const KeyV = 50;
|
|
1823
|
+
const F2 = 58;
|
|
1824
|
+
const Star = 131;
|
|
1825
|
+
|
|
1826
|
+
const CtrlCmd = 1 << 11 >>> 0;
|
|
1827
|
+
const Alt = 1 << 9 >>> 0;
|
|
1828
|
+
|
|
1829
|
+
const FocusExplorer = 13;
|
|
1830
|
+
const FocusExplorerEditBox = 14;
|
|
1831
|
+
|
|
1832
|
+
const getKeyBindings = () => {
|
|
1833
|
+
return [{
|
|
1834
|
+
key: RightArrow,
|
|
1835
|
+
command: 'Explorer.handleArrowRight',
|
|
1836
|
+
when: FocusExplorer
|
|
1837
|
+
}, {
|
|
1838
|
+
key: LeftArrow,
|
|
1839
|
+
command: 'Explorer.handleArrowLeft',
|
|
1840
|
+
when: FocusExplorer
|
|
1841
|
+
}, {
|
|
1842
|
+
key: Home,
|
|
1843
|
+
command: 'Explorer.focusFirst',
|
|
1844
|
+
when: FocusExplorer
|
|
1845
|
+
}, {
|
|
1846
|
+
key: End,
|
|
1847
|
+
command: 'Explorer.focusLast',
|
|
1848
|
+
when: FocusExplorer
|
|
1849
|
+
}, {
|
|
1850
|
+
key: UpArrow,
|
|
1851
|
+
command: 'Explorer.focusPrevious',
|
|
1852
|
+
when: FocusExplorer
|
|
1853
|
+
}, {
|
|
1854
|
+
key: DownArrow,
|
|
1855
|
+
command: 'Explorer.focusNext',
|
|
1856
|
+
when: FocusExplorer
|
|
1857
|
+
}, {
|
|
1858
|
+
key: CtrlCmd | Star,
|
|
1859
|
+
command: 'Explorer.expandAll',
|
|
1860
|
+
when: FocusExplorer
|
|
1861
|
+
}, {
|
|
1862
|
+
key: Alt | RightArrow,
|
|
1863
|
+
command: 'Explorer.expandRecursively',
|
|
1864
|
+
when: FocusExplorer
|
|
1865
|
+
}, {
|
|
1866
|
+
key: CtrlCmd | LeftArrow,
|
|
1867
|
+
command: 'Explorer.collapseAll',
|
|
1868
|
+
when: FocusExplorer
|
|
1869
|
+
}, {
|
|
1870
|
+
key: CtrlCmd | KeyV,
|
|
1871
|
+
command: 'Explorer.handlePaste',
|
|
1872
|
+
when: FocusExplorer
|
|
1873
|
+
}, {
|
|
1874
|
+
key: CtrlCmd | KeyC,
|
|
1875
|
+
command: 'Explorer.handleCopy',
|
|
1876
|
+
when: FocusExplorer
|
|
1877
|
+
}, {
|
|
1878
|
+
key: F2,
|
|
1879
|
+
command: 'Explorer.rename',
|
|
1880
|
+
when: FocusExplorer
|
|
1881
|
+
}, {
|
|
1882
|
+
key: Escape,
|
|
1883
|
+
command: 'Explorer.cancelEdit',
|
|
1884
|
+
when: FocusExplorerEditBox
|
|
1885
|
+
}, {
|
|
1886
|
+
key: Enter,
|
|
1887
|
+
command: 'Explorer.acceptEdit',
|
|
1888
|
+
when: FocusExplorerEditBox
|
|
1889
|
+
}, {
|
|
1890
|
+
key: Delete$1,
|
|
1891
|
+
command: 'Explorer.removeDirent',
|
|
1892
|
+
when: FocusExplorer
|
|
1893
|
+
}, {
|
|
1894
|
+
key: Escape,
|
|
1895
|
+
command: 'Explorer.focusNone',
|
|
1896
|
+
when: FocusExplorer
|
|
1897
|
+
}, {
|
|
1898
|
+
key: Space,
|
|
1899
|
+
command: 'Explorer.handleClickCurrentButKeepFocus',
|
|
1900
|
+
when: FocusExplorer
|
|
1901
|
+
}, {
|
|
1902
|
+
key: Enter,
|
|
1903
|
+
command: 'Explorer.handleClickCurrent',
|
|
1904
|
+
when: FocusExplorer
|
|
1905
|
+
}];
|
|
1906
|
+
};
|
|
1806
1907
|
|
|
1807
1908
|
const emptyObject = {};
|
|
1808
1909
|
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
@@ -1826,7 +1927,7 @@ const Paste = 'Paste';
|
|
|
1826
1927
|
const CopyPath = 'Copy Path';
|
|
1827
1928
|
const CopyRelativePath = 'Copy Relative Path';
|
|
1828
1929
|
const Rename = 'Rename';
|
|
1829
|
-
const Delete
|
|
1930
|
+
const Delete = 'Delete';
|
|
1830
1931
|
const RefreshExplorer = 'Refresh Explorer';
|
|
1831
1932
|
const CollapseAllFoldersInExplorer = 'Collapse All Folders in Explorer';
|
|
1832
1933
|
const FilesExplorer = 'Files Explorer';
|
|
@@ -1864,7 +1965,7 @@ const rename = () => {
|
|
|
1864
1965
|
return i18nString(Rename);
|
|
1865
1966
|
};
|
|
1866
1967
|
const deleteItem = () => {
|
|
1867
|
-
return i18nString(Delete
|
|
1968
|
+
return i18nString(Delete);
|
|
1868
1969
|
};
|
|
1869
1970
|
const refresh = () => {
|
|
1870
1971
|
return i18nString(RefreshExplorer);
|
|
@@ -1882,391 +1983,58 @@ const openFolder$1 = () => {
|
|
|
1882
1983
|
return i18nString(OpenFolder);
|
|
1883
1984
|
};
|
|
1884
1985
|
|
|
1885
|
-
const
|
|
1886
|
-
const
|
|
1887
|
-
const
|
|
1888
|
-
const Refresh = 'Refresh';
|
|
1889
|
-
|
|
1890
|
-
const getActions = root => {
|
|
1891
|
-
if (!root) {
|
|
1892
|
-
return [];
|
|
1893
|
-
}
|
|
1894
|
-
return [{
|
|
1895
|
-
type: Button$2,
|
|
1896
|
-
id: newFile$1(),
|
|
1897
|
-
icon: NewFile,
|
|
1898
|
-
command: 'newFile'
|
|
1899
|
-
}, {
|
|
1900
|
-
type: Button$2,
|
|
1901
|
-
id: newFolder$1(),
|
|
1902
|
-
icon: NewFolder,
|
|
1903
|
-
command: 'newFolder'
|
|
1904
|
-
}, {
|
|
1905
|
-
type: Button$2,
|
|
1906
|
-
id: refresh(),
|
|
1907
|
-
icon: Refresh,
|
|
1908
|
-
command: 'refresh'
|
|
1909
|
-
}, {
|
|
1910
|
-
type: Button$2,
|
|
1911
|
-
id: collapseAll(),
|
|
1912
|
-
icon: CollapseAll,
|
|
1913
|
-
command: 'collapseAll'
|
|
1914
|
-
}];
|
|
1915
|
-
};
|
|
1916
|
-
|
|
1917
|
-
const commandIds = ['acceptEdit', 'cancelEdit', 'collapseAll', 'copyPath', 'copyRelativePath', 'expandAll', 'expandRecursively', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusNone', 'focusPrevious', 'getFocusedDirent', 'handleArrowLeft', 'handleArrowLeft', 'handleArrowRight', 'handleArrowRight', 'handleBlur', 'handleClick', 'handleClickAt', 'handleClickCurrent', 'handleClickCurrentButKeepFocus', 'handleClickOpenFolder', 'handleContextMenu', 'handleCopy', 'handleDragOver', 'handleDrop', 'handleFocus', 'handleIconThemeChange', 'handleLanguagesChanged', 'handleMouseEnter', 'handleMouseLeave', 'handlePaste', 'handlePointerDown', 'handleUpload', 'handleWheel', 'handleWorkspaceChange', 'hotReload', 'newFile', 'newFolder', 'openContainingFolder', 'refresh', 'refresh', 'relealItem', 'removeDirent', 'rename', 'renameDirent', 'revealItem', 'scrollDown', 'scrollUp', 'setDeltaY', 'renderEventListeners', 'updateEditingValue', 'updateIcons'];
|
|
1986
|
+
const Separator = 1;
|
|
1987
|
+
const None$4 = 0;
|
|
1988
|
+
const RestoreFocus = 6;
|
|
1918
1989
|
|
|
1919
|
-
const
|
|
1920
|
-
|
|
1990
|
+
const menuEntrySeparator = {
|
|
1991
|
+
id: 'separator',
|
|
1992
|
+
label: '',
|
|
1993
|
+
flags: Separator,
|
|
1994
|
+
command: ''
|
|
1921
1995
|
};
|
|
1922
1996
|
|
|
1923
|
-
const
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
const Actions = 'Actions';
|
|
1929
|
-
const Button$1 = 'Button';
|
|
1930
|
-
const ButtonNarrow = 'ButtonNarrow';
|
|
1931
|
-
const ButtonPrimary = 'ButtonPrimary';
|
|
1932
|
-
const ButtonWide = 'ButtonWide';
|
|
1933
|
-
const Chevron = 'Chevron';
|
|
1934
|
-
const Explorer$1 = 'Explorer';
|
|
1935
|
-
const FileIcon = 'FileIcon';
|
|
1936
|
-
const FocusOutline = 'FocusOutline';
|
|
1937
|
-
const IconButton = 'IconButton';
|
|
1938
|
-
const InputBox = 'InputBox';
|
|
1939
|
-
const Label = 'Label';
|
|
1940
|
-
const MaskIconChevronDown = 'MaskIconChevronDown';
|
|
1941
|
-
const MaskIconChevronRight = 'MaskIconChevronRight';
|
|
1942
|
-
const TreeItem = 'TreeItem';
|
|
1943
|
-
const TreeItemActive = 'TreeItemActive';
|
|
1944
|
-
const Viewlet = 'Viewlet';
|
|
1945
|
-
const Welcome = 'Welcome';
|
|
1946
|
-
const WelcomeMessage = 'WelcomeMessage';
|
|
1947
|
-
|
|
1948
|
-
// TODO add option to make classnames numeric
|
|
1949
|
-
// once at start, send all classnames to renderer process
|
|
1950
|
-
// then, components uses numeric classname
|
|
1951
|
-
// when a component uses multiple classnames, it is a new number
|
|
1952
|
-
// representing the concatenated strings for example
|
|
1953
|
-
// 0 = 'Button'
|
|
1954
|
-
// 1 = 'IconButton'
|
|
1955
|
-
// 2 = 'Button IconButton'
|
|
1956
|
-
// it could make dom diffing faster, since for classname,
|
|
1957
|
-
// only numbers are compared. it could also make rendering faster,
|
|
1958
|
-
// since less data is transferred to renderer process
|
|
1959
|
-
|
|
1960
|
-
const HandleClick = 'handleClick';
|
|
1961
|
-
const HandleClickOpenFolder = 'handleClickOpenFolder';
|
|
1962
|
-
const HandleContextMenu = 'handleContextMenu';
|
|
1963
|
-
const HandleEditingInput = 'handleEditingInput';
|
|
1964
|
-
const HandleListBlur = 'handleListBlur';
|
|
1965
|
-
const HandleListFocus = 'handleListFocus';
|
|
1966
|
-
const HandlePointerDown = 'handlePointerDown';
|
|
1967
|
-
const HandleWheel = 'handleWheel';
|
|
1968
|
-
|
|
1969
|
-
const mergeClassNames = (...classNames) => {
|
|
1970
|
-
return classNames.filter(Boolean).join(' ');
|
|
1997
|
+
const menuEntryNewFile = {
|
|
1998
|
+
id: 'newFile',
|
|
1999
|
+
label: newFile$1(),
|
|
2000
|
+
flags: None$4,
|
|
2001
|
+
command: 'Explorer.newFile'
|
|
1971
2002
|
};
|
|
1972
|
-
const
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
childCount: 0
|
|
1978
|
-
};
|
|
2003
|
+
const menuEntryNewFolder = {
|
|
2004
|
+
id: 'newFolder',
|
|
2005
|
+
label: newFolder$1(),
|
|
2006
|
+
flags: None$4,
|
|
2007
|
+
command: 'Explorer.newFolder'
|
|
1979
2008
|
};
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
const P = 50;
|
|
1986
|
-
|
|
1987
|
-
const chevronDownVirtualDom = {
|
|
1988
|
-
type: Div,
|
|
1989
|
-
className: mergeClassNames(Chevron, MaskIconChevronDown),
|
|
1990
|
-
childCount: 0
|
|
2009
|
+
const menuEntryOpenContainingFolder = {
|
|
2010
|
+
id: 'openContainingFolder',
|
|
2011
|
+
label: openContainingFolder$1(),
|
|
2012
|
+
flags: RestoreFocus,
|
|
2013
|
+
command: 'Explorer.openContainingFolder'
|
|
1991
2014
|
};
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2015
|
+
const menuEntryOpenInIntegratedTerminal = {
|
|
2016
|
+
id: 'openInIntegratedTerminal',
|
|
2017
|
+
label: openInIntegratedTerminal(),
|
|
2018
|
+
flags: None$4,
|
|
2019
|
+
command: /* TODO */'-1'
|
|
1997
2020
|
};
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2021
|
+
const menuEntryCut = {
|
|
2022
|
+
id: 'cut',
|
|
2023
|
+
label: cut(),
|
|
2024
|
+
flags: RestoreFocus,
|
|
2025
|
+
command: /* TODO */'-1'
|
|
2002
2026
|
};
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
src: icon,
|
|
2009
|
-
role: None$4,
|
|
2010
|
-
childCount: 0
|
|
2011
|
-
};
|
|
2027
|
+
const menuEntryCopy = {
|
|
2028
|
+
id: 'copy',
|
|
2029
|
+
label: copy(),
|
|
2030
|
+
flags: RestoreFocus,
|
|
2031
|
+
command: 'Explorer.handleCopy'
|
|
2012
2032
|
};
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
className: Label,
|
|
2019
|
-
childCount: 1
|
|
2020
|
-
};
|
|
2021
|
-
const getInputOrLabelDom = (isEditing, name) => {
|
|
2022
|
-
if (isEditing) {
|
|
2023
|
-
return [{
|
|
2024
|
-
type: Input,
|
|
2025
|
-
className: InputBox,
|
|
2026
|
-
id: 'ExplorerInput',
|
|
2027
|
-
onInput: HandleEditingInput,
|
|
2028
|
-
childCount: 0,
|
|
2029
|
-
name: ExplorerInput
|
|
2030
|
-
}];
|
|
2031
|
-
}
|
|
2032
|
-
return [label, text(name)];
|
|
2033
|
-
};
|
|
2034
|
-
|
|
2035
|
-
const getExplorerItemVirtualDom = item => {
|
|
2036
|
-
const {
|
|
2037
|
-
posInSet,
|
|
2038
|
-
setSize,
|
|
2039
|
-
icon,
|
|
2040
|
-
name,
|
|
2041
|
-
path,
|
|
2042
|
-
depth,
|
|
2043
|
-
indent,
|
|
2044
|
-
chevron,
|
|
2045
|
-
id,
|
|
2046
|
-
className,
|
|
2047
|
-
isEditing,
|
|
2048
|
-
ariaExpanded
|
|
2049
|
-
} = item;
|
|
2050
|
-
const chevronDom = getChevronVirtualDom(chevron);
|
|
2051
|
-
const dom = [{
|
|
2052
|
-
type: Div,
|
|
2053
|
-
role: TreeItem$1,
|
|
2054
|
-
className,
|
|
2055
|
-
draggable: true,
|
|
2056
|
-
title: path,
|
|
2057
|
-
ariaPosInSet: posInSet,
|
|
2058
|
-
ariaSetSize: setSize,
|
|
2059
|
-
ariaLevel: depth,
|
|
2060
|
-
childCount: 2 + chevronDom.length,
|
|
2061
|
-
paddingLeft: indent,
|
|
2062
|
-
ariaLabel: name,
|
|
2063
|
-
ariaExpanded,
|
|
2064
|
-
ariaDescription: '',
|
|
2065
|
-
id
|
|
2066
|
-
}, ...chevronDom, getFileIconVirtualDom(icon), ...getInputOrLabelDom(isEditing, name)];
|
|
2067
|
-
return dom;
|
|
2068
|
-
};
|
|
2069
|
-
|
|
2070
|
-
const getExplorerWelcomeVirtualDom = isWide => {
|
|
2071
|
-
return [{
|
|
2072
|
-
type: Div,
|
|
2073
|
-
className: mergeClassNames(Viewlet, Explorer$1),
|
|
2074
|
-
tabIndex: 0,
|
|
2075
|
-
childCount: 1
|
|
2076
|
-
}, {
|
|
2077
|
-
type: Div,
|
|
2078
|
-
className: Welcome,
|
|
2079
|
-
childCount: 2
|
|
2080
|
-
}, {
|
|
2081
|
-
type: P,
|
|
2082
|
-
className: WelcomeMessage,
|
|
2083
|
-
childCount: 1
|
|
2084
|
-
}, text(youHaveNotYetOpenedAFolder()), {
|
|
2085
|
-
type: Button,
|
|
2086
|
-
className: mergeClassNames(Button$1, ButtonPrimary, isWide ? ButtonWide : ButtonNarrow),
|
|
2087
|
-
childCount: 1,
|
|
2088
|
-
onClick: HandleClickOpenFolder
|
|
2089
|
-
}, text(openFolder$1())];
|
|
2090
|
-
};
|
|
2091
|
-
|
|
2092
|
-
const getActiveDescendant = focusedIndex => {
|
|
2093
|
-
if (focusedIndex >= 0) {
|
|
2094
|
-
return 'TreeItemActive';
|
|
2095
|
-
}
|
|
2096
|
-
return undefined;
|
|
2097
|
-
};
|
|
2098
|
-
const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide, focused) => {
|
|
2099
|
-
if (!root) {
|
|
2100
|
-
return getExplorerWelcomeVirtualDom(isWide);
|
|
2101
|
-
}
|
|
2102
|
-
const extraClass = focused && focusedIndex === -1 ? FocusOutline : '';
|
|
2103
|
-
const dom = [{
|
|
2104
|
-
type: Div,
|
|
2105
|
-
className: mergeClassNames(Viewlet, Explorer$1, extraClass),
|
|
2106
|
-
tabIndex: 0,
|
|
2107
|
-
role: Tree,
|
|
2108
|
-
ariaLabel: filesExplorer(),
|
|
2109
|
-
childCount: visibleItems.length,
|
|
2110
|
-
ariaActiveDescendant: getActiveDescendant(focusedIndex),
|
|
2111
|
-
onFocus: HandleListFocus,
|
|
2112
|
-
onBlur: HandleListBlur,
|
|
2113
|
-
onContextMenu: HandleContextMenu,
|
|
2114
|
-
onPointerDown: HandlePointerDown,
|
|
2115
|
-
onWheel: HandleWheel,
|
|
2116
|
-
onClick: HandleClick
|
|
2117
|
-
}, ...visibleItems.flatMap(getExplorerItemVirtualDom)];
|
|
2118
|
-
return dom;
|
|
2119
|
-
};
|
|
2120
|
-
|
|
2121
|
-
const Enter = 3;
|
|
2122
|
-
const Escape = 8;
|
|
2123
|
-
const Space = 9;
|
|
2124
|
-
const End = 255;
|
|
2125
|
-
const Home = 12;
|
|
2126
|
-
const LeftArrow = 13;
|
|
2127
|
-
const UpArrow = 14;
|
|
2128
|
-
const RightArrow = 15;
|
|
2129
|
-
const DownArrow = 16;
|
|
2130
|
-
const Delete = 18;
|
|
2131
|
-
const KeyC = 31;
|
|
2132
|
-
const KeyV = 50;
|
|
2133
|
-
const F2 = 58;
|
|
2134
|
-
const Star = 131;
|
|
2135
|
-
|
|
2136
|
-
const CtrlCmd = 1 << 11 >>> 0;
|
|
2137
|
-
const Alt = 1 << 9 >>> 0;
|
|
2138
|
-
|
|
2139
|
-
const FocusExplorer = 13;
|
|
2140
|
-
const FocusExplorerEditBox = 14;
|
|
2141
|
-
|
|
2142
|
-
const getKeyBindings = () => {
|
|
2143
|
-
return [{
|
|
2144
|
-
key: RightArrow,
|
|
2145
|
-
command: 'Explorer.handleArrowRight',
|
|
2146
|
-
when: FocusExplorer
|
|
2147
|
-
}, {
|
|
2148
|
-
key: LeftArrow,
|
|
2149
|
-
command: 'Explorer.handleArrowLeft',
|
|
2150
|
-
when: FocusExplorer
|
|
2151
|
-
}, {
|
|
2152
|
-
key: Home,
|
|
2153
|
-
command: 'Explorer.focusFirst',
|
|
2154
|
-
when: FocusExplorer
|
|
2155
|
-
}, {
|
|
2156
|
-
key: End,
|
|
2157
|
-
command: 'Explorer.focusLast',
|
|
2158
|
-
when: FocusExplorer
|
|
2159
|
-
}, {
|
|
2160
|
-
key: UpArrow,
|
|
2161
|
-
command: 'Explorer.focusPrevious',
|
|
2162
|
-
when: FocusExplorer
|
|
2163
|
-
}, {
|
|
2164
|
-
key: DownArrow,
|
|
2165
|
-
command: 'Explorer.focusNext',
|
|
2166
|
-
when: FocusExplorer
|
|
2167
|
-
}, {
|
|
2168
|
-
key: CtrlCmd | Star,
|
|
2169
|
-
command: 'Explorer.expandAll',
|
|
2170
|
-
when: FocusExplorer
|
|
2171
|
-
}, {
|
|
2172
|
-
key: Alt | RightArrow,
|
|
2173
|
-
command: 'Explorer.expandRecursively',
|
|
2174
|
-
when: FocusExplorer
|
|
2175
|
-
}, {
|
|
2176
|
-
key: CtrlCmd | LeftArrow,
|
|
2177
|
-
command: 'Explorer.collapseAll',
|
|
2178
|
-
when: FocusExplorer
|
|
2179
|
-
}, {
|
|
2180
|
-
key: CtrlCmd | KeyV,
|
|
2181
|
-
command: 'Explorer.handlePaste',
|
|
2182
|
-
when: FocusExplorer
|
|
2183
|
-
}, {
|
|
2184
|
-
key: CtrlCmd | KeyC,
|
|
2185
|
-
command: 'Explorer.handleCopy',
|
|
2186
|
-
when: FocusExplorer
|
|
2187
|
-
}, {
|
|
2188
|
-
key: F2,
|
|
2189
|
-
command: 'Explorer.rename',
|
|
2190
|
-
when: FocusExplorer
|
|
2191
|
-
}, {
|
|
2192
|
-
key: Escape,
|
|
2193
|
-
command: 'Explorer.cancelEdit',
|
|
2194
|
-
when: FocusExplorerEditBox
|
|
2195
|
-
}, {
|
|
2196
|
-
key: Enter,
|
|
2197
|
-
command: 'Explorer.acceptEdit',
|
|
2198
|
-
when: FocusExplorerEditBox
|
|
2199
|
-
}, {
|
|
2200
|
-
key: Delete,
|
|
2201
|
-
command: 'Explorer.removeDirent',
|
|
2202
|
-
when: FocusExplorer
|
|
2203
|
-
}, {
|
|
2204
|
-
key: Escape,
|
|
2205
|
-
command: 'Explorer.focusNone',
|
|
2206
|
-
when: FocusExplorer
|
|
2207
|
-
}, {
|
|
2208
|
-
key: Space,
|
|
2209
|
-
command: 'Explorer.handleClickCurrentButKeepFocus',
|
|
2210
|
-
when: FocusExplorer
|
|
2211
|
-
}, {
|
|
2212
|
-
key: Enter,
|
|
2213
|
-
command: 'Explorer.handleClickCurrent',
|
|
2214
|
-
when: FocusExplorer
|
|
2215
|
-
}];
|
|
2216
|
-
};
|
|
2217
|
-
|
|
2218
|
-
const Separator = 1;
|
|
2219
|
-
const None$3 = 0;
|
|
2220
|
-
const RestoreFocus = 6;
|
|
2221
|
-
|
|
2222
|
-
const menuEntrySeparator = {
|
|
2223
|
-
id: 'separator',
|
|
2224
|
-
label: '',
|
|
2225
|
-
flags: Separator,
|
|
2226
|
-
command: ''
|
|
2227
|
-
};
|
|
2228
|
-
|
|
2229
|
-
const menuEntryNewFile = {
|
|
2230
|
-
id: 'newFile',
|
|
2231
|
-
label: newFile$1(),
|
|
2232
|
-
flags: None$3,
|
|
2233
|
-
command: 'Explorer.newFile'
|
|
2234
|
-
};
|
|
2235
|
-
const menuEntryNewFolder = {
|
|
2236
|
-
id: 'newFolder',
|
|
2237
|
-
label: newFolder$1(),
|
|
2238
|
-
flags: None$3,
|
|
2239
|
-
command: 'Explorer.newFolder'
|
|
2240
|
-
};
|
|
2241
|
-
const menuEntryOpenContainingFolder = {
|
|
2242
|
-
id: 'openContainingFolder',
|
|
2243
|
-
label: openContainingFolder$1(),
|
|
2244
|
-
flags: RestoreFocus,
|
|
2245
|
-
command: 'Explorer.openContainingFolder'
|
|
2246
|
-
};
|
|
2247
|
-
const menuEntryOpenInIntegratedTerminal = {
|
|
2248
|
-
id: 'openInIntegratedTerminal',
|
|
2249
|
-
label: openInIntegratedTerminal(),
|
|
2250
|
-
flags: None$3,
|
|
2251
|
-
command: /* TODO */'-1'
|
|
2252
|
-
};
|
|
2253
|
-
const menuEntryCut = {
|
|
2254
|
-
id: 'cut',
|
|
2255
|
-
label: cut(),
|
|
2256
|
-
flags: RestoreFocus,
|
|
2257
|
-
command: /* TODO */'-1'
|
|
2258
|
-
};
|
|
2259
|
-
const menuEntryCopy = {
|
|
2260
|
-
id: 'copy',
|
|
2261
|
-
label: copy(),
|
|
2262
|
-
flags: RestoreFocus,
|
|
2263
|
-
command: 'Explorer.handleCopy'
|
|
2264
|
-
};
|
|
2265
|
-
const menuEntryPaste = {
|
|
2266
|
-
id: 'paste',
|
|
2267
|
-
label: paste(),
|
|
2268
|
-
flags: None$3,
|
|
2269
|
-
command: 'Explorer.handlePaste'
|
|
2033
|
+
const menuEntryPaste = {
|
|
2034
|
+
id: 'paste',
|
|
2035
|
+
label: paste(),
|
|
2036
|
+
flags: None$4,
|
|
2037
|
+
command: 'Explorer.handlePaste'
|
|
2270
2038
|
};
|
|
2271
2039
|
const menuEntryCopyPath = {
|
|
2272
2040
|
id: 'copyPath',
|
|
@@ -2283,13 +2051,13 @@ const menuEntryCopyRelativePath = {
|
|
|
2283
2051
|
const menuEntryRename = {
|
|
2284
2052
|
id: 'rename',
|
|
2285
2053
|
label: rename(),
|
|
2286
|
-
flags: None$
|
|
2054
|
+
flags: None$4,
|
|
2287
2055
|
command: 'Explorer.renameDirent'
|
|
2288
2056
|
};
|
|
2289
2057
|
const menuEntryDelete = {
|
|
2290
2058
|
id: 'delete',
|
|
2291
2059
|
label: deleteItem(),
|
|
2292
|
-
flags: None$
|
|
2060
|
+
flags: None$4,
|
|
2293
2061
|
command: 'Explorer.removeDirent'
|
|
2294
2062
|
};
|
|
2295
2063
|
const ALL_ENTRIES = [menuEntryNewFile, menuEntryNewFolder, menuEntryOpenContainingFolder, menuEntryOpenInIntegratedTerminal, menuEntrySeparator, menuEntryCut, menuEntryCopy, menuEntryPaste, menuEntrySeparator, menuEntryCopyPath, menuEntryCopyRelativePath, menuEntrySeparator, menuEntryRename, menuEntryDelete];
|
|
@@ -2330,116 +2098,19 @@ const getMenuEntries = state => {
|
|
|
2330
2098
|
}
|
|
2331
2099
|
};
|
|
2332
2100
|
|
|
2333
|
-
const
|
|
2334
|
-
const
|
|
2335
|
-
|
|
2101
|
+
const getParentStartIndex = (dirents, index) => {
|
|
2102
|
+
const dirent = dirents[index];
|
|
2103
|
+
let startIndex = index - 1;
|
|
2104
|
+
while (startIndex >= 0 && dirents[startIndex].depth >= dirent.depth) {
|
|
2105
|
+
startIndex--;
|
|
2106
|
+
}
|
|
2107
|
+
return startIndex;
|
|
2108
|
+
};
|
|
2336
2109
|
|
|
2337
|
-
const
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
switch (type) {
|
|
2342
|
-
case Directory:
|
|
2343
|
-
return Right;
|
|
2344
|
-
case DirectoryExpanded:
|
|
2345
|
-
case DirectoryExpanding:
|
|
2346
|
-
return Down;
|
|
2347
|
-
default:
|
|
2348
|
-
return None$2;
|
|
2349
|
-
}
|
|
2350
|
-
};
|
|
2351
|
-
|
|
2352
|
-
const None$1 = 0;
|
|
2353
|
-
const Expanded = 1;
|
|
2354
|
-
const Collapsed = 2;
|
|
2355
|
-
|
|
2356
|
-
const getExpandedType = type => {
|
|
2357
|
-
switch (type) {
|
|
2358
|
-
case Directory:
|
|
2359
|
-
return Collapsed;
|
|
2360
|
-
case DirectoryExpanding:
|
|
2361
|
-
case DirectoryExpanded:
|
|
2362
|
-
return Expanded;
|
|
2363
|
-
default:
|
|
2364
|
-
return None$1;
|
|
2365
|
-
}
|
|
2366
|
-
};
|
|
2367
|
-
|
|
2368
|
-
const defaultIndent$1 = 1;
|
|
2369
|
-
const getTreeItemIndent = depth => {
|
|
2370
|
-
return `${depth * defaultIndent$1}rem`;
|
|
2371
|
-
};
|
|
2372
|
-
|
|
2373
|
-
// TODO make all of these variable configurable
|
|
2374
|
-
const defaultPaddingLeft = 4;
|
|
2375
|
-
const defaultIndent = 8;
|
|
2376
|
-
|
|
2377
|
-
// TODO make chevron size configurable
|
|
2378
|
-
const chevronSize = 22;
|
|
2379
|
-
const getTreeItemIndentWithChevron = (depth, chevron) => {
|
|
2380
|
-
// TODO use numeric value here, convert to string value in renderer process
|
|
2381
|
-
const extraSpace = chevron ? 0 : chevronSize;
|
|
2382
|
-
return `${depth * defaultIndent + extraSpace + defaultPaddingLeft}px`;
|
|
2383
|
-
};
|
|
2384
|
-
|
|
2385
|
-
const ariaExpandedValues = [undefined, 'true', 'false'];
|
|
2386
|
-
const getVisibleExplorerItems = (items, minLineY, maxLineY, focusedIndex, editingIndex, editingType, editingValue, icons, useChevrons) => {
|
|
2387
|
-
const visible = [];
|
|
2388
|
-
const indentFn = useChevrons ? getTreeItemIndentWithChevron : getTreeItemIndent;
|
|
2389
|
-
let iconIndex = 0;
|
|
2390
|
-
for (let i = minLineY; i < Math.min(maxLineY, items.length); i++) {
|
|
2391
|
-
const item = items[i];
|
|
2392
|
-
const icon = icons[iconIndex++];
|
|
2393
|
-
const chevron = getChevronType(item.type, useChevrons);
|
|
2394
|
-
const indent = indentFn(item.depth, chevron);
|
|
2395
|
-
const isFocused = i === focusedIndex;
|
|
2396
|
-
const id = isFocused ? 'TreeItemActive' : undefined;
|
|
2397
|
-
const className = isFocused ? TreeItem + ' ' + TreeItemActive : TreeItem;
|
|
2398
|
-
const expanded = getExpandedType(item.type);
|
|
2399
|
-
const ariaExpanded = ariaExpandedValues[expanded];
|
|
2400
|
-
visible.push({
|
|
2401
|
-
...item,
|
|
2402
|
-
isEditing: i === editingIndex,
|
|
2403
|
-
icon,
|
|
2404
|
-
indent,
|
|
2405
|
-
ariaExpanded,
|
|
2406
|
-
chevron,
|
|
2407
|
-
id,
|
|
2408
|
-
className
|
|
2409
|
-
});
|
|
2410
|
-
}
|
|
2411
|
-
if (editingType !== None$5 && editingIndex === -1) {
|
|
2412
|
-
visible.push({
|
|
2413
|
-
depth: 3,
|
|
2414
|
-
posInSet: 1,
|
|
2415
|
-
setSize: 1,
|
|
2416
|
-
icon: '',
|
|
2417
|
-
name: 'new',
|
|
2418
|
-
path: '/test/new',
|
|
2419
|
-
isEditing: true,
|
|
2420
|
-
indent: '',
|
|
2421
|
-
ariaExpanded: undefined,
|
|
2422
|
-
chevron: 0,
|
|
2423
|
-
id: undefined,
|
|
2424
|
-
className: TreeItem
|
|
2425
|
-
});
|
|
2426
|
-
}
|
|
2427
|
-
return visible;
|
|
2428
|
-
};
|
|
2429
|
-
|
|
2430
|
-
const getParentStartIndex = (dirents, index) => {
|
|
2431
|
-
const dirent = dirents[index];
|
|
2432
|
-
let startIndex = index - 1;
|
|
2433
|
-
while (startIndex >= 0 && dirents[startIndex].depth >= dirent.depth) {
|
|
2434
|
-
startIndex--;
|
|
2435
|
-
}
|
|
2436
|
-
return startIndex;
|
|
2437
|
-
};
|
|
2438
|
-
|
|
2439
|
-
const focusParentFolder = state => {
|
|
2440
|
-
const parentStartIndex = getParentStartIndex(state.items, state.focusedIndex);
|
|
2441
|
-
if (parentStartIndex === -1) {
|
|
2442
|
-
return state;
|
|
2110
|
+
const focusParentFolder = state => {
|
|
2111
|
+
const parentStartIndex = getParentStartIndex(state.items, state.focusedIndex);
|
|
2112
|
+
if (parentStartIndex === -1) {
|
|
2113
|
+
return state;
|
|
2443
2114
|
}
|
|
2444
2115
|
return focusIndex(state, parentStartIndex);
|
|
2445
2116
|
};
|
|
@@ -2789,7 +2460,7 @@ const show = async (x, y, id, ...args) => {
|
|
|
2789
2460
|
return invoke('ContextMenu.show', x, y, id, ...args);
|
|
2790
2461
|
};
|
|
2791
2462
|
|
|
2792
|
-
const Explorer = 4;
|
|
2463
|
+
const Explorer$1 = 4;
|
|
2793
2464
|
|
|
2794
2465
|
const handleContextMenuKeyboard = async state => {
|
|
2795
2466
|
const {
|
|
@@ -2801,7 +2472,7 @@ const handleContextMenuKeyboard = async state => {
|
|
|
2801
2472
|
} = state;
|
|
2802
2473
|
const menuX = x;
|
|
2803
2474
|
const menuY = y + (focusedIndex - minLineY + 1) * itemHeight;
|
|
2804
|
-
await show(menuX, menuY, Explorer);
|
|
2475
|
+
await show(menuX, menuY, Explorer$1);
|
|
2805
2476
|
return state;
|
|
2806
2477
|
};
|
|
2807
2478
|
|
|
@@ -2809,7 +2480,7 @@ const handleContextMenuMouseAt = async (state, x, y) => {
|
|
|
2809
2480
|
number(x);
|
|
2810
2481
|
number(y);
|
|
2811
2482
|
const focusedIndex = getIndexFromPosition(state, x, y);
|
|
2812
|
-
await show(x, y, Explorer);
|
|
2483
|
+
await show(x, y, Explorer$1);
|
|
2813
2484
|
return {
|
|
2814
2485
|
...state,
|
|
2815
2486
|
focusedIndex,
|
|
@@ -3182,7 +2853,7 @@ const handlePasteNone = async (state, nativeFiles) => {
|
|
|
3182
2853
|
return state;
|
|
3183
2854
|
};
|
|
3184
2855
|
|
|
3185
|
-
const None = 'none';
|
|
2856
|
+
const None$3 = 'none';
|
|
3186
2857
|
const Copy = 'copy';
|
|
3187
2858
|
const Cut = 'cut';
|
|
3188
2859
|
|
|
@@ -3200,7 +2871,7 @@ const getPasteHandler = type => {
|
|
|
3200
2871
|
// TODO but will it work if the folder is a symlink?
|
|
3201
2872
|
// TODO handle error gracefully when copy fails
|
|
3202
2873
|
switch (type) {
|
|
3203
|
-
case None:
|
|
2874
|
+
case None$3:
|
|
3204
2875
|
return handlePasteNone;
|
|
3205
2876
|
case Copy:
|
|
3206
2877
|
return handlePasteCopy;
|
|
@@ -3514,113 +3185,408 @@ const newFolder = state => {
|
|
|
3514
3185
|
return newDirent(state, CreateFolder);
|
|
3515
3186
|
};
|
|
3516
3187
|
|
|
3517
|
-
const getContaingingFolder = (root, dirents, focusedIndex, pathSeparator) => {
|
|
3518
|
-
if (focusedIndex < 0) {
|
|
3519
|
-
return root;
|
|
3188
|
+
const getContaingingFolder = (root, dirents, focusedIndex, pathSeparator) => {
|
|
3189
|
+
if (focusedIndex < 0) {
|
|
3190
|
+
return root;
|
|
3191
|
+
}
|
|
3192
|
+
const dirent = dirents[focusedIndex];
|
|
3193
|
+
const direntPath = dirent.path;
|
|
3194
|
+
const direntParentPath = direntPath.slice(0, -(dirent.name.length + 1));
|
|
3195
|
+
const path = `${direntParentPath}`;
|
|
3196
|
+
return path;
|
|
3197
|
+
};
|
|
3198
|
+
const openContainingFolder = async state => {
|
|
3199
|
+
const {
|
|
3200
|
+
focusedIndex,
|
|
3201
|
+
root,
|
|
3202
|
+
items} = state;
|
|
3203
|
+
const path = getContaingingFolder(root, items, focusedIndex);
|
|
3204
|
+
await invoke('OpenNativeFolder.openNativeFolder', /* path */path);
|
|
3205
|
+
return state;
|
|
3206
|
+
};
|
|
3207
|
+
|
|
3208
|
+
// TODO support multiselection and removing multiple dirents
|
|
3209
|
+
const removeDirent = async state => {
|
|
3210
|
+
if (state.focusedIndex < 0) {
|
|
3211
|
+
return state;
|
|
3212
|
+
}
|
|
3213
|
+
const dirent = getFocusedDirent$1(state);
|
|
3214
|
+
const absolutePath = dirent.path;
|
|
3215
|
+
try {
|
|
3216
|
+
// TODO handle error
|
|
3217
|
+
await remove(absolutePath);
|
|
3218
|
+
} catch {
|
|
3219
|
+
// TODO vscode shows error as alert (no stacktrace) and retry button
|
|
3220
|
+
// maybe should show alert as well, but where to put stacktrace?
|
|
3221
|
+
// on web should probably show notification (dialog)
|
|
3222
|
+
// ErrorHandling.handleError(error)
|
|
3223
|
+
// await ErrorHandling.showErrorDialog(error)
|
|
3224
|
+
return state;
|
|
3225
|
+
}
|
|
3226
|
+
// TODO avoid state mutation
|
|
3227
|
+
// @ts-ignore
|
|
3228
|
+
const newVersion = ++state.version;
|
|
3229
|
+
// TODO race condition
|
|
3230
|
+
// const newState = await loadContent(state:any)
|
|
3231
|
+
// @ts-ignore
|
|
3232
|
+
if (state.version !== newVersion || state.disposed) {
|
|
3233
|
+
return state;
|
|
3234
|
+
}
|
|
3235
|
+
// TODO is it possible to make this more functional instead of mutating state?
|
|
3236
|
+
// maybe every function returns a new state?
|
|
3237
|
+
const index = state.items.indexOf(dirent);
|
|
3238
|
+
let deleteEnd = index + 1;
|
|
3239
|
+
for (; deleteEnd < state.items.length; deleteEnd++) {
|
|
3240
|
+
if (state.items[deleteEnd].depth <= dirent.depth) {
|
|
3241
|
+
break;
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
const deleteCount = deleteEnd - index;
|
|
3245
|
+
const newDirents = [...state.items];
|
|
3246
|
+
newDirents.splice(index, deleteCount);
|
|
3247
|
+
let indexToFocus = -1;
|
|
3248
|
+
if (newDirents.length === 0) {
|
|
3249
|
+
indexToFocus = -1;
|
|
3250
|
+
} else if (index < state.focusedIndex) {
|
|
3251
|
+
indexToFocus = state.focusedIndex - 1;
|
|
3252
|
+
} else if (index === state.focusedIndex) {
|
|
3253
|
+
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3254
|
+
} else {
|
|
3255
|
+
indexToFocus = Math.max(state.focusedIndex - 1, 0);
|
|
3256
|
+
}
|
|
3257
|
+
const visible = newDirents.slice(state.minLineY, state.maxLineY);
|
|
3258
|
+
const {
|
|
3259
|
+
icons,
|
|
3260
|
+
newFileIconCache
|
|
3261
|
+
} = await getFileIcons(visible, state.fileIconCache);
|
|
3262
|
+
return {
|
|
3263
|
+
...state,
|
|
3264
|
+
items: newDirents,
|
|
3265
|
+
icons,
|
|
3266
|
+
fileIconCache: newFileIconCache,
|
|
3267
|
+
focusedIndex: indexToFocus
|
|
3268
|
+
};
|
|
3269
|
+
};
|
|
3270
|
+
|
|
3271
|
+
const renameDirent = state => {
|
|
3272
|
+
const {
|
|
3273
|
+
focusedIndex,
|
|
3274
|
+
items
|
|
3275
|
+
} = state;
|
|
3276
|
+
const item = items[focusedIndex];
|
|
3277
|
+
// Focus.setFocus(FocusKey.ExplorerEditBox)
|
|
3278
|
+
return {
|
|
3279
|
+
...state,
|
|
3280
|
+
editingIndex: focusedIndex,
|
|
3281
|
+
editingType: Rename$1,
|
|
3282
|
+
editingValue: item.name
|
|
3283
|
+
};
|
|
3284
|
+
};
|
|
3285
|
+
|
|
3286
|
+
const renderEditingIndex = (oldState, newState) => {
|
|
3287
|
+
return ['focusInput', 'ExplorerInput'];
|
|
3288
|
+
};
|
|
3289
|
+
|
|
3290
|
+
const renderFocus = (oldState, newState) => {
|
|
3291
|
+
// TODO
|
|
3292
|
+
// 1. when focused, focus the outer list element
|
|
3293
|
+
// 2. when focused, set focus context in renderer worker
|
|
3294
|
+
return [];
|
|
3295
|
+
};
|
|
3296
|
+
|
|
3297
|
+
const None$2 = 'none';
|
|
3298
|
+
const ToolBar = 'toolbar';
|
|
3299
|
+
const Tree = 'tree';
|
|
3300
|
+
const TreeItem$1 = 'treeitem';
|
|
3301
|
+
|
|
3302
|
+
const Actions = 'Actions';
|
|
3303
|
+
const Button$2 = 'Button';
|
|
3304
|
+
const ButtonNarrow = 'ButtonNarrow';
|
|
3305
|
+
const ButtonPrimary = 'ButtonPrimary';
|
|
3306
|
+
const ButtonWide = 'ButtonWide';
|
|
3307
|
+
const Chevron = 'Chevron';
|
|
3308
|
+
const Explorer = 'Explorer';
|
|
3309
|
+
const FileIcon = 'FileIcon';
|
|
3310
|
+
const FocusOutline = 'FocusOutline';
|
|
3311
|
+
const IconButton = 'IconButton';
|
|
3312
|
+
const InputBox = 'InputBox';
|
|
3313
|
+
const Label = 'Label';
|
|
3314
|
+
const MaskIconChevronDown = 'MaskIconChevronDown';
|
|
3315
|
+
const MaskIconChevronRight = 'MaskIconChevronRight';
|
|
3316
|
+
const TreeItem = 'TreeItem';
|
|
3317
|
+
const TreeItemActive = 'TreeItemActive';
|
|
3318
|
+
const Viewlet = 'Viewlet';
|
|
3319
|
+
const Welcome = 'Welcome';
|
|
3320
|
+
const WelcomeMessage = 'WelcomeMessage';
|
|
3321
|
+
|
|
3322
|
+
// TODO add option to make classnames numeric
|
|
3323
|
+
// once at start, send all classnames to renderer process
|
|
3324
|
+
// then, components uses numeric classname
|
|
3325
|
+
// when a component uses multiple classnames, it is a new number
|
|
3326
|
+
// representing the concatenated strings for example
|
|
3327
|
+
// 0 = 'Button'
|
|
3328
|
+
// 1 = 'IconButton'
|
|
3329
|
+
// 2 = 'Button IconButton'
|
|
3330
|
+
// it could make dom diffing faster, since for classname,
|
|
3331
|
+
// only numbers are compared. it could also make rendering faster,
|
|
3332
|
+
// since less data is transferred to renderer process
|
|
3333
|
+
|
|
3334
|
+
const HandleClick = 'handleClick';
|
|
3335
|
+
const HandleClickOpenFolder = 'handleClickOpenFolder';
|
|
3336
|
+
const HandleContextMenu = 'handleContextMenu';
|
|
3337
|
+
const HandleEditingInput = 'handleEditingInput';
|
|
3338
|
+
const HandleListBlur = 'handleListBlur';
|
|
3339
|
+
const HandleListFocus = 'handleListFocus';
|
|
3340
|
+
const HandlePointerDown = 'handlePointerDown';
|
|
3341
|
+
const HandleWheel = 'handleWheel';
|
|
3342
|
+
|
|
3343
|
+
const mergeClassNames = (...classNames) => {
|
|
3344
|
+
return classNames.filter(Boolean).join(' ');
|
|
3345
|
+
};
|
|
3346
|
+
const Text = 12;
|
|
3347
|
+
const text = data => {
|
|
3348
|
+
return {
|
|
3349
|
+
type: Text,
|
|
3350
|
+
text: data,
|
|
3351
|
+
childCount: 0
|
|
3352
|
+
};
|
|
3353
|
+
};
|
|
3354
|
+
|
|
3355
|
+
const Button$1 = 1;
|
|
3356
|
+
const Div = 4;
|
|
3357
|
+
const Input = 6;
|
|
3358
|
+
const Img = 17;
|
|
3359
|
+
const P = 50;
|
|
3360
|
+
|
|
3361
|
+
const chevronDownVirtualDom = {
|
|
3362
|
+
type: Div,
|
|
3363
|
+
className: mergeClassNames(Chevron, MaskIconChevronDown),
|
|
3364
|
+
childCount: 0
|
|
3365
|
+
};
|
|
3366
|
+
|
|
3367
|
+
const chevronRightVirtualDom = {
|
|
3368
|
+
type: Div,
|
|
3369
|
+
className: mergeClassNames(Chevron, MaskIconChevronRight),
|
|
3370
|
+
childCount: 0
|
|
3371
|
+
};
|
|
3372
|
+
|
|
3373
|
+
const chevronDomNodes = [[], [chevronRightVirtualDom], [chevronDownVirtualDom]];
|
|
3374
|
+
const getChevronVirtualDom = chevronType => {
|
|
3375
|
+
return chevronDomNodes[chevronType];
|
|
3376
|
+
};
|
|
3377
|
+
|
|
3378
|
+
const getFileIconVirtualDom = icon => {
|
|
3379
|
+
return {
|
|
3380
|
+
type: Img,
|
|
3381
|
+
className: FileIcon,
|
|
3382
|
+
src: icon,
|
|
3383
|
+
role: None$2,
|
|
3384
|
+
childCount: 0
|
|
3385
|
+
};
|
|
3386
|
+
};
|
|
3387
|
+
|
|
3388
|
+
const ExplorerInput = 'ExplorerInput';
|
|
3389
|
+
|
|
3390
|
+
const label = {
|
|
3391
|
+
type: Div,
|
|
3392
|
+
className: Label,
|
|
3393
|
+
childCount: 1
|
|
3394
|
+
};
|
|
3395
|
+
const getInputOrLabelDom = (isEditing, name) => {
|
|
3396
|
+
if (isEditing) {
|
|
3397
|
+
return [{
|
|
3398
|
+
type: Input,
|
|
3399
|
+
className: InputBox,
|
|
3400
|
+
id: 'ExplorerInput',
|
|
3401
|
+
onInput: HandleEditingInput,
|
|
3402
|
+
childCount: 0,
|
|
3403
|
+
name: ExplorerInput
|
|
3404
|
+
}];
|
|
3405
|
+
}
|
|
3406
|
+
return [label, text(name)];
|
|
3407
|
+
};
|
|
3408
|
+
|
|
3409
|
+
const getExplorerItemVirtualDom = item => {
|
|
3410
|
+
const {
|
|
3411
|
+
posInSet,
|
|
3412
|
+
setSize,
|
|
3413
|
+
icon,
|
|
3414
|
+
name,
|
|
3415
|
+
path,
|
|
3416
|
+
depth,
|
|
3417
|
+
indent,
|
|
3418
|
+
chevron,
|
|
3419
|
+
id,
|
|
3420
|
+
className,
|
|
3421
|
+
isEditing,
|
|
3422
|
+
ariaExpanded
|
|
3423
|
+
} = item;
|
|
3424
|
+
const chevronDom = getChevronVirtualDom(chevron);
|
|
3425
|
+
const dom = [{
|
|
3426
|
+
type: Div,
|
|
3427
|
+
role: TreeItem$1,
|
|
3428
|
+
className,
|
|
3429
|
+
draggable: true,
|
|
3430
|
+
title: path,
|
|
3431
|
+
ariaPosInSet: posInSet,
|
|
3432
|
+
ariaSetSize: setSize,
|
|
3433
|
+
ariaLevel: depth,
|
|
3434
|
+
childCount: 2 + chevronDom.length,
|
|
3435
|
+
paddingLeft: indent,
|
|
3436
|
+
ariaLabel: name,
|
|
3437
|
+
ariaExpanded,
|
|
3438
|
+
ariaDescription: '',
|
|
3439
|
+
id
|
|
3440
|
+
}, ...chevronDom, getFileIconVirtualDom(icon), ...getInputOrLabelDom(isEditing, name)];
|
|
3441
|
+
return dom;
|
|
3442
|
+
};
|
|
3443
|
+
|
|
3444
|
+
const getExplorerWelcomeVirtualDom = isWide => {
|
|
3445
|
+
return [{
|
|
3446
|
+
type: Div,
|
|
3447
|
+
className: mergeClassNames(Viewlet, Explorer),
|
|
3448
|
+
tabIndex: 0,
|
|
3449
|
+
childCount: 1
|
|
3450
|
+
}, {
|
|
3451
|
+
type: Div,
|
|
3452
|
+
className: Welcome,
|
|
3453
|
+
childCount: 2
|
|
3454
|
+
}, {
|
|
3455
|
+
type: P,
|
|
3456
|
+
className: WelcomeMessage,
|
|
3457
|
+
childCount: 1
|
|
3458
|
+
}, text(youHaveNotYetOpenedAFolder()), {
|
|
3459
|
+
type: Button$1,
|
|
3460
|
+
className: mergeClassNames(Button$2, ButtonPrimary, isWide ? ButtonWide : ButtonNarrow),
|
|
3461
|
+
childCount: 1,
|
|
3462
|
+
onClick: HandleClickOpenFolder
|
|
3463
|
+
}, text(openFolder$1())];
|
|
3464
|
+
};
|
|
3465
|
+
|
|
3466
|
+
const getActiveDescendant = focusedIndex => {
|
|
3467
|
+
if (focusedIndex >= 0) {
|
|
3468
|
+
return 'TreeItemActive';
|
|
3520
3469
|
}
|
|
3521
|
-
|
|
3522
|
-
const direntPath = dirent.path;
|
|
3523
|
-
const direntParentPath = direntPath.slice(0, -(dirent.name.length + 1));
|
|
3524
|
-
const path = `${direntParentPath}`;
|
|
3525
|
-
return path;
|
|
3470
|
+
return undefined;
|
|
3526
3471
|
};
|
|
3527
|
-
const
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
const
|
|
3533
|
-
|
|
3534
|
-
|
|
3472
|
+
const getExplorerVirtualDom = (visibleItems, focusedIndex, root, isWide, focused) => {
|
|
3473
|
+
if (!root) {
|
|
3474
|
+
return getExplorerWelcomeVirtualDom(isWide);
|
|
3475
|
+
}
|
|
3476
|
+
const extraClass = focused && focusedIndex === -1 ? FocusOutline : '';
|
|
3477
|
+
const dom = [{
|
|
3478
|
+
type: Div,
|
|
3479
|
+
className: mergeClassNames(Viewlet, Explorer, extraClass),
|
|
3480
|
+
tabIndex: 0,
|
|
3481
|
+
role: Tree,
|
|
3482
|
+
ariaLabel: filesExplorer(),
|
|
3483
|
+
childCount: visibleItems.length,
|
|
3484
|
+
ariaActiveDescendant: getActiveDescendant(focusedIndex),
|
|
3485
|
+
onFocus: HandleListFocus,
|
|
3486
|
+
onBlur: HandleListBlur,
|
|
3487
|
+
onContextMenu: HandleContextMenu,
|
|
3488
|
+
onPointerDown: HandlePointerDown,
|
|
3489
|
+
onWheel: HandleWheel,
|
|
3490
|
+
onClick: HandleClick
|
|
3491
|
+
}, ...visibleItems.flatMap(getExplorerItemVirtualDom)];
|
|
3492
|
+
return dom;
|
|
3535
3493
|
};
|
|
3536
3494
|
|
|
3537
|
-
|
|
3538
|
-
const
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
try {
|
|
3545
|
-
// TODO handle error
|
|
3546
|
-
await remove(absolutePath);
|
|
3547
|
-
} catch {
|
|
3548
|
-
// TODO vscode shows error as alert (no stacktrace) and retry button
|
|
3549
|
-
// maybe should show alert as well, but where to put stacktrace?
|
|
3550
|
-
// on web should probably show notification (dialog)
|
|
3551
|
-
// ErrorHandling.handleError(error)
|
|
3552
|
-
// await ErrorHandling.showErrorDialog(error)
|
|
3553
|
-
return state;
|
|
3554
|
-
}
|
|
3555
|
-
// TODO avoid state mutation
|
|
3556
|
-
// @ts-ignore
|
|
3557
|
-
const newVersion = ++state.version;
|
|
3558
|
-
// TODO race condition
|
|
3559
|
-
// const newState = await loadContent(state:any)
|
|
3560
|
-
// @ts-ignore
|
|
3561
|
-
if (state.version !== newVersion || state.disposed) {
|
|
3562
|
-
return state;
|
|
3495
|
+
const None$1 = 0;
|
|
3496
|
+
const Right = 1;
|
|
3497
|
+
const Down = 2;
|
|
3498
|
+
|
|
3499
|
+
const getChevronType = (type, useChevrons) => {
|
|
3500
|
+
if (!useChevrons) {
|
|
3501
|
+
return None$1;
|
|
3563
3502
|
}
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3503
|
+
switch (type) {
|
|
3504
|
+
case Directory:
|
|
3505
|
+
return Right;
|
|
3506
|
+
case DirectoryExpanded:
|
|
3507
|
+
case DirectoryExpanding:
|
|
3508
|
+
return Down;
|
|
3509
|
+
default:
|
|
3510
|
+
return None$1;
|
|
3572
3511
|
}
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3512
|
+
};
|
|
3513
|
+
|
|
3514
|
+
const None = 0;
|
|
3515
|
+
const Expanded = 1;
|
|
3516
|
+
const Collapsed = 2;
|
|
3517
|
+
|
|
3518
|
+
const getExpandedType = type => {
|
|
3519
|
+
switch (type) {
|
|
3520
|
+
case Directory:
|
|
3521
|
+
return Collapsed;
|
|
3522
|
+
case DirectoryExpanding:
|
|
3523
|
+
case DirectoryExpanded:
|
|
3524
|
+
return Expanded;
|
|
3525
|
+
default:
|
|
3526
|
+
return None;
|
|
3585
3527
|
}
|
|
3586
|
-
const visible = newDirents.slice(state.minLineY, state.maxLineY);
|
|
3587
|
-
const {
|
|
3588
|
-
icons,
|
|
3589
|
-
newFileIconCache
|
|
3590
|
-
} = await getFileIcons(visible, state.fileIconCache);
|
|
3591
|
-
return {
|
|
3592
|
-
...state,
|
|
3593
|
-
items: newDirents,
|
|
3594
|
-
icons,
|
|
3595
|
-
fileIconCache: newFileIconCache,
|
|
3596
|
-
focusedIndex: indexToFocus
|
|
3597
|
-
};
|
|
3598
3528
|
};
|
|
3599
3529
|
|
|
3600
|
-
const
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
items
|
|
3604
|
-
} = state;
|
|
3605
|
-
const item = items[focusedIndex];
|
|
3606
|
-
// Focus.setFocus(FocusKey.ExplorerEditBox)
|
|
3607
|
-
return {
|
|
3608
|
-
...state,
|
|
3609
|
-
editingIndex: focusedIndex,
|
|
3610
|
-
editingType: Rename$1,
|
|
3611
|
-
editingValue: item.name
|
|
3612
|
-
};
|
|
3530
|
+
const defaultIndent$1 = 1;
|
|
3531
|
+
const getTreeItemIndent = depth => {
|
|
3532
|
+
return `${depth * defaultIndent$1}rem`;
|
|
3613
3533
|
};
|
|
3614
3534
|
|
|
3615
|
-
|
|
3616
|
-
|
|
3535
|
+
// TODO make all of these variable configurable
|
|
3536
|
+
const defaultPaddingLeft = 4;
|
|
3537
|
+
const defaultIndent = 8;
|
|
3538
|
+
|
|
3539
|
+
// TODO make chevron size configurable
|
|
3540
|
+
const chevronSize = 22;
|
|
3541
|
+
const getTreeItemIndentWithChevron = (depth, chevron) => {
|
|
3542
|
+
// TODO use numeric value here, convert to string value in renderer process
|
|
3543
|
+
const extraSpace = chevron ? 0 : chevronSize;
|
|
3544
|
+
return `${depth * defaultIndent + extraSpace + defaultPaddingLeft}px`;
|
|
3617
3545
|
};
|
|
3618
3546
|
|
|
3619
|
-
const
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3547
|
+
const ariaExpandedValues = [undefined, 'true', 'false'];
|
|
3548
|
+
const getVisibleExplorerItems = (items, minLineY, maxLineY, focusedIndex, editingIndex, editingType, editingValue, icons, useChevrons) => {
|
|
3549
|
+
const visible = [];
|
|
3550
|
+
const indentFn = useChevrons ? getTreeItemIndentWithChevron : getTreeItemIndent;
|
|
3551
|
+
let iconIndex = 0;
|
|
3552
|
+
for (let i = minLineY; i < Math.min(maxLineY, items.length); i++) {
|
|
3553
|
+
const item = items[i];
|
|
3554
|
+
const icon = icons[iconIndex++];
|
|
3555
|
+
const chevron = getChevronType(item.type, useChevrons);
|
|
3556
|
+
const indent = indentFn(item.depth, chevron);
|
|
3557
|
+
const isFocused = i === focusedIndex;
|
|
3558
|
+
const id = isFocused ? 'TreeItemActive' : undefined;
|
|
3559
|
+
const className = isFocused ? TreeItem + ' ' + TreeItemActive : TreeItem;
|
|
3560
|
+
const expanded = getExpandedType(item.type);
|
|
3561
|
+
const ariaExpanded = ariaExpandedValues[expanded];
|
|
3562
|
+
visible.push({
|
|
3563
|
+
...item,
|
|
3564
|
+
isEditing: i === editingIndex,
|
|
3565
|
+
icon,
|
|
3566
|
+
indent,
|
|
3567
|
+
ariaExpanded,
|
|
3568
|
+
chevron,
|
|
3569
|
+
id,
|
|
3570
|
+
className
|
|
3571
|
+
});
|
|
3572
|
+
}
|
|
3573
|
+
if (editingType !== None$5 && editingIndex === -1) {
|
|
3574
|
+
visible.push({
|
|
3575
|
+
depth: 3,
|
|
3576
|
+
posInSet: 1,
|
|
3577
|
+
setSize: 1,
|
|
3578
|
+
icon: '',
|
|
3579
|
+
name: 'new',
|
|
3580
|
+
path: '/test/new',
|
|
3581
|
+
isEditing: true,
|
|
3582
|
+
indent: '',
|
|
3583
|
+
ariaExpanded: undefined,
|
|
3584
|
+
chevron: 0,
|
|
3585
|
+
id: undefined,
|
|
3586
|
+
className: TreeItem
|
|
3587
|
+
});
|
|
3588
|
+
}
|
|
3589
|
+
return visible;
|
|
3624
3590
|
};
|
|
3625
3591
|
|
|
3626
3592
|
const renderItems = (oldState, newState) => {
|
|
@@ -3665,31 +3631,45 @@ const render2 = (uid, diffResult) => {
|
|
|
3665
3631
|
return commands;
|
|
3666
3632
|
};
|
|
3667
3633
|
|
|
3668
|
-
const
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
const
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
const commands = renderInternal(oldState, newState);
|
|
3679
|
-
return commands;
|
|
3634
|
+
const Button = 1;
|
|
3635
|
+
|
|
3636
|
+
const CollapseAll = 'CollapseAll';
|
|
3637
|
+
const NewFile = 'NewFile';
|
|
3638
|
+
const NewFolder = 'NewFolder';
|
|
3639
|
+
const Refresh = 'Refresh';
|
|
3640
|
+
|
|
3641
|
+
const getActions = root => {
|
|
3642
|
+
if (!root) {
|
|
3643
|
+
return [];
|
|
3680
3644
|
}
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3645
|
+
return [{
|
|
3646
|
+
type: Button,
|
|
3647
|
+
id: newFile$1(),
|
|
3648
|
+
icon: NewFile,
|
|
3649
|
+
command: 'newFile'
|
|
3650
|
+
}, {
|
|
3651
|
+
type: Button,
|
|
3652
|
+
id: newFolder$1(),
|
|
3653
|
+
icon: NewFolder,
|
|
3654
|
+
command: 'newFolder'
|
|
3655
|
+
}, {
|
|
3656
|
+
type: Button,
|
|
3657
|
+
id: refresh(),
|
|
3658
|
+
icon: Refresh,
|
|
3659
|
+
command: 'refresh'
|
|
3660
|
+
}, {
|
|
3661
|
+
type: Button,
|
|
3662
|
+
id: collapseAll(),
|
|
3663
|
+
icon: CollapseAll,
|
|
3664
|
+
command: 'collapseAll'
|
|
3665
|
+
}];
|
|
3686
3666
|
};
|
|
3687
3667
|
|
|
3688
3668
|
const getIconVirtualDom = (icon, type = Div) => {
|
|
3689
3669
|
return {
|
|
3690
3670
|
type,
|
|
3691
3671
|
className: `MaskIcon MaskIcon${icon}`,
|
|
3692
|
-
role: None$
|
|
3672
|
+
role: None$2,
|
|
3693
3673
|
childCount: 0
|
|
3694
3674
|
};
|
|
3695
3675
|
};
|
|
@@ -3701,7 +3681,7 @@ const getActionButtonVirtualDom = action => {
|
|
|
3701
3681
|
command
|
|
3702
3682
|
} = action;
|
|
3703
3683
|
return [{
|
|
3704
|
-
type: Button,
|
|
3684
|
+
type: Button$1,
|
|
3705
3685
|
className: IconButton,
|
|
3706
3686
|
title: id,
|
|
3707
3687
|
'data-command': command,
|
|
@@ -3711,7 +3691,7 @@ const getActionButtonVirtualDom = action => {
|
|
|
3711
3691
|
|
|
3712
3692
|
const getActionVirtualDom = action => {
|
|
3713
3693
|
switch (action.type) {
|
|
3714
|
-
case Button
|
|
3694
|
+
case Button:
|
|
3715
3695
|
return getActionButtonVirtualDom(action);
|
|
3716
3696
|
default:
|
|
3717
3697
|
return [];
|
|
@@ -3727,7 +3707,7 @@ const getActionsVirtualDom = actions => {
|
|
|
3727
3707
|
}, ...actions.flatMap(getActionVirtualDom)];
|
|
3728
3708
|
};
|
|
3729
3709
|
|
|
3730
|
-
const renderActions
|
|
3710
|
+
const renderActions = uid => {
|
|
3731
3711
|
const {
|
|
3732
3712
|
newState
|
|
3733
3713
|
} = get(uid);
|
|
@@ -3736,12 +3716,6 @@ const renderActions$1 = uid => {
|
|
|
3736
3716
|
return dom;
|
|
3737
3717
|
};
|
|
3738
3718
|
|
|
3739
|
-
const renderActions = state => {
|
|
3740
|
-
const actions = getActions(state.root);
|
|
3741
|
-
const dom = getActionsVirtualDom(actions);
|
|
3742
|
-
return dom;
|
|
3743
|
-
};
|
|
3744
|
-
|
|
3745
3719
|
const renderEventListeners = () => {
|
|
3746
3720
|
return [{
|
|
3747
3721
|
name: HandleListBlur,
|
|
@@ -4072,17 +4046,15 @@ const updateEditingValue = (state, value) => {
|
|
|
4072
4046
|
|
|
4073
4047
|
const wrapCommand = fn => {
|
|
4074
4048
|
const wrapped = async (uid, ...args) => {
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
} else {
|
|
4082
|
-
// deprecated
|
|
4083
|
-
const newerState = await fn(uid, ...args);
|
|
4084
|
-
return newerState;
|
|
4049
|
+
const {
|
|
4050
|
+
newState
|
|
4051
|
+
} = get(uid);
|
|
4052
|
+
const newerState = await fn(newState, ...args);
|
|
4053
|
+
if (newState === newerState) {
|
|
4054
|
+
return;
|
|
4085
4055
|
}
|
|
4056
|
+
const latest = get(uid);
|
|
4057
|
+
set(uid, latest.oldState, newerState);
|
|
4086
4058
|
};
|
|
4087
4059
|
return wrapped;
|
|
4088
4060
|
};
|
|
@@ -4136,17 +4108,10 @@ const commandMap = {
|
|
|
4136
4108
|
'Explorer.getKeyBindings': getKeyBindings,
|
|
4137
4109
|
'Explorer.getMenuEntries': getMenuEntries,
|
|
4138
4110
|
'Explorer.render2': render2,
|
|
4139
|
-
'Explorer.renderActions2': renderActions
|
|
4111
|
+
'Explorer.renderActions2': renderActions,
|
|
4140
4112
|
'Explorer.renderEventListeners': renderEventListeners,
|
|
4141
4113
|
'Explorer.saveState': saveState,
|
|
4142
|
-
'Explorer.terminate': terminate
|
|
4143
|
-
// deprecated
|
|
4144
|
-
'Explorer.getVirtualDom': getExplorerVirtualDom,
|
|
4145
|
-
'Explorer.getVisibleItems': getVisibleExplorerItems,
|
|
4146
|
-
'Explorer.getActions': getActions,
|
|
4147
|
-
'Explorer.renderActions': renderActions,
|
|
4148
|
-
'Explorer.render': doRender,
|
|
4149
|
-
'Explorer.diff': diff
|
|
4114
|
+
'Explorer.terminate': terminate
|
|
4150
4115
|
};
|
|
4151
4116
|
|
|
4152
4117
|
const listen = async () => {
|