@lvce-editor/file-search-worker 5.9.0 → 5.11.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.
@@ -940,7 +940,7 @@ const create$1 = ({
940
940
  scrollBarActive: false
941
941
  };
942
942
  };
943
- const getListHeight = (height, headerHeight) => {
943
+ const getListHeight$1 = (height, headerHeight) => {
944
944
  if (headerHeight) {
945
945
  return height - headerHeight;
946
946
  }
@@ -955,7 +955,7 @@ const setDeltaY = (state, deltaY) => {
955
955
  height,
956
956
  headerHeight
957
957
  } = state;
958
- const listHeight = getListHeight(height, headerHeight);
958
+ const listHeight = getListHeight$1(height, headerHeight);
959
959
  const itemsLength = items.length;
960
960
  const finalDeltaY = itemsLength * itemHeight - listHeight;
961
961
  if (deltaY < 0) {
@@ -1003,7 +1003,7 @@ const create = (uid, uri, listItemHeight, x, y, width, height, platform, args, w
1003
1003
  width: 600,
1004
1004
  ...create$1({
1005
1005
  itemHeight: listItemHeight,
1006
- headerHeight: 30,
1006
+ headerHeight: 38,
1007
1007
  minimumSliderSize: minimumSliderSize
1008
1008
  }),
1009
1009
  inputSource: User,
@@ -1084,19 +1084,19 @@ const focusPick$1 = async pick => {
1084
1084
  };
1085
1085
 
1086
1086
  const ColorTheme$1 = 0;
1087
- const Commands$1 = 2;
1088
- const Custom = 3;
1089
- const EveryThing$1 = 4;
1090
- const File$2 = 5;
1091
- const GoToLine$2 = 6;
1092
- const Help$2 = 7;
1093
- const Recent$1 = 8;
1094
- const Symbol$2 = 9;
1095
- const View$3 = 10;
1096
- const WorkspaceSymbol$2 = 11;
1087
+ const Commands$1 = 1;
1088
+ const Custom = 2;
1089
+ const File$2 = 3;
1090
+ const GoToLine$2 = 4;
1091
+ const Help$2 = 5;
1092
+ const Recent$1 = 6;
1093
+ const Symbol$2 = 7;
1094
+ const View$3 = 8;
1095
+ const WorkspaceSymbol$2 = 9;
1096
+ const EveryThing$1 = 100;
1097
1097
 
1098
1098
  const noop$2 = async () => {};
1099
- const getFn$2 = id => {
1099
+ const getFn$3 = id => {
1100
1100
  switch (id) {
1101
1101
  case ColorTheme$1:
1102
1102
  return focusPick$1;
@@ -1105,7 +1105,7 @@ const getFn$2 = id => {
1105
1105
  }
1106
1106
  };
1107
1107
  const focusPick = (id, pick) => {
1108
- const fn = getFn$2(id);
1108
+ const fn = getFn$3(id);
1109
1109
  return fn(pick);
1110
1110
  };
1111
1111
 
@@ -1695,7 +1695,7 @@ const getFilterValueEverything = value => {
1695
1695
  const prefixLength = prefix.length;
1696
1696
  return value.slice(prefixLength).trim();
1697
1697
  };
1698
- const getFn$1 = id => {
1698
+ const getFn$2 = id => {
1699
1699
  switch (id) {
1700
1700
  case EveryThing$1:
1701
1701
  return getFilterValueEverything;
@@ -1704,1307 +1704,1369 @@ const getFn$1 = id => {
1704
1704
  }
1705
1705
  };
1706
1706
  const getFilterValue = (id, value) => {
1707
- const fn = getFn$1(id);
1707
+ const fn = getFn$2(id);
1708
1708
  const filterValue = fn(value);
1709
1709
  return filterValue;
1710
1710
  };
1711
1711
 
1712
- const select = Object.create(null);
1713
- const getPick$1 = Object.create(null);
1714
- const registerSelect = modules => {
1715
- Object.assign(select, modules);
1712
+ const getFinalDeltaY = (height, itemHeight, itemsLength) => {
1713
+ const contentHeight = itemsLength * itemHeight;
1714
+ const finalDeltaY = Math.max(contentHeight - height, 0);
1715
+ return finalDeltaY;
1716
1716
  };
1717
- const registerGetPick = modules => {
1718
- Object.assign(getPick$1, modules);
1717
+
1718
+ const getListHeight = (itemsLength, itemHeight, maxHeight) => {
1719
+ number(itemsLength);
1720
+ number(itemHeight);
1721
+ number(maxHeight);
1722
+ if (itemsLength === 0) {
1723
+ return itemHeight;
1724
+ }
1725
+ const totalHeight = itemsLength * itemHeight;
1726
+ return Math.min(totalHeight, maxHeight);
1719
1727
  };
1720
- const getPicks$d = id => {
1721
- const fn = getPick$1[id];
1722
- return fn;
1728
+
1729
+ const getColorThemeNames = async () => {
1730
+ return invoke$1(/* Ajax.getJson */'ColorTheme.getColorThemeNames');
1723
1731
  };
1724
- const getSelect = id => {
1725
- const fn = select[id];
1726
- return fn;
1732
+
1733
+ const toProtoVisibleItem$2 = name => {
1734
+ const pick = {
1735
+ label: name,
1736
+ description: '',
1737
+ fileIcon: '',
1738
+ icon: '',
1739
+ matches: [],
1740
+ direntType: 0,
1741
+ uri: ''
1742
+ };
1743
+ return pick;
1744
+ };
1745
+ const getPicks$c = async searchValue => {
1746
+ const colorThemeNames = await getColorThemeNames();
1747
+ const picks = colorThemeNames.map(toProtoVisibleItem$2);
1748
+ return picks;
1727
1749
  };
1728
1750
 
1729
- const getPicks$c = (id, searchValue) => {
1730
- const fn = getPicks$d(id);
1731
- return fn(searchValue);
1751
+ const handleError = async (error, notify = true, prefix = '') => {
1752
+ console.error(error);
1753
+ };
1754
+ const showErrorDialog = async error => {
1755
+ const code = error.code;
1756
+ const message = error.message;
1757
+ const stack = error.stack;
1758
+ const name = error.name;
1759
+ const errorInfo = {
1760
+ code,
1761
+ message,
1762
+ stack,
1763
+ name
1764
+ };
1765
+ await invoke$1('ErrorHandling.showErrorDialog', errorInfo);
1766
+ };
1767
+ const warn = (...args) => {
1768
+ console.warn(...args);
1732
1769
  };
1733
1770
 
1734
- const getQuickPickSubProviderId = prefix => {
1735
- switch (prefix) {
1736
- case Command:
1737
- return Commands$1;
1738
- case Symbol$1:
1739
- return Symbol$2;
1740
- case WorkspaceSymbol$1:
1741
- return WorkspaceSymbol$2;
1742
- case GoToLine$1:
1743
- return GoToLine$2;
1744
- case View$2:
1745
- return View$3;
1746
- case Help$1:
1747
- return Help$2;
1748
- default:
1749
- return File$2;
1750
- }
1771
+ const state$2 = {
1772
+ menuEntries: []
1773
+ };
1774
+ const getAll = () => {
1775
+ return state$2.menuEntries;
1776
+ };
1777
+ const add = menuEntries => {
1778
+ state$2.menuEntries = [...state$2.menuEntries, ...menuEntries];
1751
1779
  };
1752
1780
 
1753
- // TODO when user types letters -> no need to query provider again -> just filter existing results
1754
- const setValue = async (state, newValue) => {
1755
- const {
1756
- providerId,
1757
- value,
1758
- minLineY,
1759
- maxLineY,
1760
- fileIconCache
1761
- } = state;
1762
- if (value === newValue) {
1763
- return state;
1781
+ // TODO combine Ajax with cache (specify strategy: cacheFirst, networkFirst)
1782
+ const getBuiltinPicks = async () => {
1783
+ const builtinPicks = getAll();
1784
+ return builtinPicks;
1785
+ };
1786
+ const prefixIdWithExt = item => {
1787
+ if (!item.label) {
1788
+ warn('[QuickPick] item has missing label', item);
1789
+ }
1790
+ if (!item.id) {
1791
+ warn('[QuickPick] item has missing id', item);
1764
1792
  }
1765
- const prefix = getQuickPickPrefix(newValue);
1766
- const subId = getQuickPickSubProviderId(prefix);
1767
- const newPicks = await getPicks$c(subId, newValue);
1768
- const filterValue = getFilterValue(providerId, newValue);
1769
- const items = filterQuickPickItems(newPicks, filterValue);
1770
- const focusedIndex = items.length === 0 ? -1 : 0;
1771
- const sliced = items.slice(minLineY, maxLineY);
1772
- const {
1773
- newFileIconCache,
1774
- icons
1775
- } = await getQuickPickFileIcons(sliced, fileIconCache);
1776
1793
  return {
1777
- ...state,
1778
- picks: newPicks,
1779
- items,
1780
- focusedIndex,
1781
- inputSource: Script,
1782
- value: newValue,
1783
- icons,
1784
- fileIconCache: newFileIconCache
1794
+ ...item,
1795
+ id: `ext.${item.id}`,
1796
+ label: item.label || item.id
1785
1797
  };
1786
1798
  };
1787
-
1788
- // TODO when user types letters -> no need to query provider again -> just filter existing results
1789
- const handleInput = async (state, newValue, cursorOffset, inputSource = Script) => {
1790
- if (state.value === newValue) {
1791
- return state;
1799
+ const getExtensionPicks = async () => {
1800
+ try {
1801
+ // TODO don't call this every time
1802
+ const extensionPicks = await invoke$1('ExtensionHost.getCommands');
1803
+ if (!extensionPicks) {
1804
+ return [];
1805
+ }
1806
+ const mappedPicks = extensionPicks.map(prefixIdWithExt);
1807
+ return mappedPicks;
1808
+ } catch (error) {
1809
+ console.error(`Failed to get extension picks: ${error}`);
1810
+ return [];
1792
1811
  }
1793
- const newState = await setValue(state, newValue);
1794
- return {
1795
- ...newState,
1796
- cursorOffset,
1797
- inputSource
1812
+ };
1813
+ const toProtoVisibleItem$1 = item => {
1814
+ const pick = {
1815
+ label: item.label,
1816
+ description: '',
1817
+ fileIcon: '',
1818
+ icon: '',
1819
+ matches: [],
1820
+ direntType: 0,
1821
+ uri: ''
1798
1822
  };
1823
+ // @ts-ignore
1824
+ pick.id = item.id;
1825
+ return pick;
1799
1826
  };
1800
-
1801
- const handleBeforeInput = (state, inputType, data, selectionStart, selectionEnd) => {
1802
- string(inputType);
1803
- number(selectionStart);
1804
- number(selectionEnd);
1805
- const {
1806
- value
1807
- } = state;
1808
- const {
1809
- newValue,
1810
- cursorOffset
1811
- } = getNewValue(value, inputType, data, selectionStart, selectionEnd);
1812
- return handleInput(state, newValue, cursorOffset, User);
1827
+ const getPicks$b = async () => {
1828
+ // TODO get picks in parallel
1829
+ const builtinPicks = await getBuiltinPicks();
1830
+ const extensionPicks = await getExtensionPicks();
1831
+ const allPicks = [...builtinPicks, ...extensionPicks];
1832
+ const converted = allPicks.map(toProtoVisibleItem$1);
1833
+ return converted;
1813
1834
  };
1814
1835
 
1815
- const handleBlur = async state => {
1816
- // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
1817
- // await CloseWidget.closeWidget(state.uid)
1818
- return state;
1836
+ const state$1 = {
1837
+ args: []
1819
1838
  };
1820
1839
 
1821
- const getPick = (items, index) => {
1822
- array(items);
1823
- number(index);
1824
- // if (index < state.recentPicks.length) {
1825
- // return state.recentPicks[index]
1826
- // }
1827
- // index -= state.recentPicks.length
1828
- if (index < items.length) {
1829
- return items[index];
1830
- }
1831
- console.warn('no pick matching index', index);
1832
- return undefined;
1840
+ const getPicks$a = async searchValue => {
1841
+ const items = state$1.args[1] || [];
1842
+ return items;
1833
1843
  };
1834
1844
 
1835
- const Hide = 'hide';
1836
- const KeepOpen = '';
1837
-
1838
- const selectIndex = async (state, index, button = /* left */0) => {
1839
- const {
1840
- minLineY,
1841
- items,
1842
- value
1843
- } = state;
1844
- const actualIndex = index + minLineY;
1845
- const pick = getPick(items, actualIndex);
1846
- if (!pick) {
1847
- return state;
1848
- }
1849
- const prefix = getQuickPickPrefix(value);
1850
- const subId = getQuickPickSubProviderId(prefix);
1851
- const fn = getSelect(subId);
1852
- const selectPickResult = await fn(pick);
1853
- object(selectPickResult);
1854
- string(selectPickResult.command);
1855
- const {
1856
- command
1857
- } = selectPickResult;
1858
- switch (command) {
1859
- case Hide:
1860
- await closeWidget(state.uid);
1861
- return state;
1862
- default:
1863
- return state;
1864
- }
1845
+ const emptyMatches = [];
1865
1846
 
1866
- // TODO recent picks should be per provider
1867
- // if (!state.recentPickIds.has(pick.id)) {
1868
- // state.recentPicks.unshift(pick)
1869
- // state.recentPickIds.add(pick.id)
1870
- // }
1871
- // if (state.recentPicks.length > RECENT_PICKS_MAX_SIZE) {
1872
- // const last = state.recentPicks.pop()
1873
- // state.recentPickIds.delete(last.id)
1874
- // }
1847
+ const getWorkspacePath = async () => {
1848
+ return invoke$1('Workspace.getPath');
1875
1849
  };
1876
1850
 
1877
- const handleClickAt = (state, x, y) => {
1878
- const {
1879
- top,
1880
- headerHeight,
1881
- itemHeight
1882
- } = state;
1883
- const relativeY = y - top - headerHeight;
1884
- const index = Math.floor(relativeY / itemHeight);
1885
- return selectIndex(state, index);
1851
+ const RE_PROTOCOL = /^([a-z-]+):\/\//;
1852
+ const getProtocol = uri => {
1853
+ const protocolMatch = uri.match(RE_PROTOCOL);
1854
+ if (protocolMatch) {
1855
+ return protocolMatch[1];
1856
+ }
1857
+ return '';
1886
1858
  };
1887
1859
 
1888
- const setFocus = async focusKey => {
1889
- await invoke$1('Focus.setFocus', focusKey);
1860
+ const state = Object.create(null);
1861
+ const register = modules => {
1862
+ Object.assign(state, modules);
1863
+ };
1864
+ const getFn$1 = protocol => {
1865
+ return state[protocol];
1890
1866
  };
1891
1867
 
1892
- const handleFocus = async state => {
1893
- // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
1894
- await setFocus(FocusQuickPickInput);
1895
- // await CloseWidget.closeWidget(state.uid)
1896
- return state;
1868
+ const searchFile$5 = async (path, value, prepare, assetDir) => {
1869
+ const protocol = getProtocol(path);
1870
+ // TODO call different providers depending on protocol
1871
+ const fn = getFn$1(protocol);
1872
+ const result = await fn(path, value, prepare, assetDir);
1873
+ return result;
1897
1874
  };
1898
1875
 
1899
- const getDefaultValue = id => {
1900
- switch (id) {
1901
- case EveryThing$1:
1902
- return Command;
1903
- default:
1904
- return '';
1905
- }
1876
+ // TODO this should be in FileSystem module
1877
+ const pathBaseName = path => {
1878
+ return path.slice(path.lastIndexOf('/') + 1);
1906
1879
  };
1907
1880
 
1908
- const Commands = 'quickPick://commands';
1909
- const EveryThing = 'quickPick://everything';
1910
- const Recent = 'quickPick://recent';
1911
- const ColorTheme = 'quickPick://color-theme';
1912
- const Symbol = 'quickPick://symbol';
1913
- const View$1 = 'quickPick://view';
1914
- const Help = 'quickPick://help';
1915
- const WorkspaceSymbol = 'quickPick://workspace-symbol';
1916
- const GoToLine = 'quickPick://go-to-line';
1917
-
1918
- const getQuickPickProviderId = prefix => {
1919
- switch (prefix) {
1920
- case Commands:
1921
- case Symbol:
1922
- case WorkspaceSymbol:
1923
- case EveryThing:
1924
- case GoToLine:
1925
- case View$1:
1926
- case Help:
1927
- return EveryThing$1;
1928
- case ColorTheme:
1929
- return ColorTheme$1;
1930
- case Recent:
1931
- return Recent$1;
1932
- default:
1933
- return File$2;
1881
+ // TODO this should be in FileSystem module
1882
+ const pathDirName = path => {
1883
+ const pathSeparator = '/';
1884
+ const index = path.lastIndexOf(pathSeparator);
1885
+ if (index === -1) {
1886
+ return '';
1934
1887
  }
1888
+ return path.slice(0, index);
1935
1889
  };
1936
1890
 
1937
- const state$3 = {
1938
- args: []
1891
+ const searchFile$4 = async (path, value) => {
1892
+ const prepare = true;
1893
+ const files = await searchFile$5(/* path */path, /* searchTerm */value, prepare, '');
1894
+ return files;
1939
1895
  };
1940
-
1941
- const noop = args => {};
1942
- const setArgsCustom = args => {
1943
- state$3.args = args;
1896
+ const convertToPick = uri => {
1897
+ const baseName = pathBaseName(uri);
1898
+ const dirName = pathDirName(uri);
1899
+ return {
1900
+ description: dirName,
1901
+ direntType: File$1,
1902
+ fileIcon: '',
1903
+ icon: '',
1904
+ label: baseName,
1905
+ matches: emptyMatches,
1906
+ uri
1907
+ };
1944
1908
  };
1945
- const getFn = id => {
1946
- switch (id) {
1947
- case Custom:
1948
- return setArgsCustom;
1949
- default:
1950
- return noop;
1909
+
1910
+ // TODO handle files differently
1911
+ // e.g. when there are many files, don't need
1912
+ // to compute the fileIcon for all files
1913
+
1914
+ const getPicks$9 = async searchValue => {
1915
+ // TODO cache workspace path
1916
+ const workspace = await getWorkspacePath();
1917
+ if (!workspace) {
1918
+ return [];
1951
1919
  }
1920
+ const files = await searchFile$4(workspace, searchValue);
1921
+ const picks = files.map(convertToPick);
1922
+ return picks;
1952
1923
  };
1953
- const setArgs = (id, args) => {
1954
- const fn = getFn(id);
1955
- return fn(args);
1924
+
1925
+ const getPicks$8 = async () => {
1926
+ const picks = [{
1927
+ label: '1',
1928
+ description: '',
1929
+ icon: '',
1930
+ fileIcon: '',
1931
+ matches: [],
1932
+ direntType: None$2,
1933
+ uri: ''
1934
+ }, {
1935
+ label: '2',
1936
+ description: '',
1937
+ icon: '',
1938
+ fileIcon: '',
1939
+ matches: [],
1940
+ direntType: None$2,
1941
+ uri: ''
1942
+ }, {
1943
+ label: '3',
1944
+ description: '',
1945
+ icon: '',
1946
+ fileIcon: '',
1947
+ matches: [],
1948
+ direntType: None$2,
1949
+ uri: ''
1950
+ }, {
1951
+ label: '4',
1952
+ description: '',
1953
+ icon: '',
1954
+ fileIcon: '',
1955
+ matches: [],
1956
+ direntType: None$2,
1957
+ uri: ''
1958
+ }, {
1959
+ label: '5',
1960
+ description: '',
1961
+ icon: '',
1962
+ fileIcon: '',
1963
+ matches: [],
1964
+ direntType: None$2,
1965
+ uri: ''
1966
+ }, {
1967
+ label: '6',
1968
+ description: '',
1969
+ icon: '',
1970
+ fileIcon: '',
1971
+ matches: [],
1972
+ direntType: None$2,
1973
+ uri: ''
1974
+ }];
1975
+ return picks;
1956
1976
  };
1957
1977
 
1958
- const loadContent = async state => {
1959
- const {
1960
- uri,
1961
- args,
1962
- fileIconCache
1963
- } = state;
1964
- const id = getQuickPickProviderId(uri);
1965
- const value = getDefaultValue(id);
1966
- const prefix = getQuickPickPrefix(value);
1967
- const subId = getQuickPickSubProviderId(prefix);
1968
- setArgs(subId, args);
1969
- const newPicks = await getPicks$c(subId, value);
1970
- array(newPicks);
1971
- const filterValue = getFilterValue(id, value);
1972
- const items = filterQuickPickItems(newPicks, filterValue);
1973
- const minLineY = 0;
1974
- const maxLineY = Math.min(minLineY + state.maxVisibleItems, newPicks.length);
1975
- const sliced = newPicks.slice(minLineY, maxLineY);
1976
- const {
1977
- newFileIconCache,
1978
- icons
1979
- } = await getQuickPickFileIcons(sliced, fileIconCache);
1980
- return {
1981
- ...state,
1982
- picks: newPicks,
1983
- items,
1984
- focusedIndex: 0,
1985
- state: Finished,
1986
- minLineY,
1987
- maxLineY,
1988
- value,
1989
- cursorOffset: value.length,
1990
- inputSource: Script,
1991
- focused: true,
1992
- fileIconCache: newFileIconCache,
1993
- icons,
1994
- providerId: id
1978
+ const DotDotDot = '...';
1979
+ const Colon = ':';
1980
+ const Percent = '%';
1981
+ const AngleBracket = '>';
1982
+ const View$1 = 'view';
1983
+
1984
+ const emptyObject = {};
1985
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1986
+ const i18nString = (key, placeholders = emptyObject) => {
1987
+ if (placeholders === emptyObject) {
1988
+ return key;
1989
+ }
1990
+ const replacer = (match, rest) => {
1991
+ return placeholders[rest];
1995
1992
  };
1993
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
1996
1994
  };
1997
1995
 
1998
- const state$2 = {
1999
- menuEntries: []
1996
+ const GoToFile = 'Go to file';
1997
+ const GoToLineColumn = 'Go to Line / Column';
1998
+ const GoToSymbolInEditor = 'Go to Symbol in Editor';
1999
+ const NoResults = 'No Results';
2000
+ const OpenView = 'Open View';
2001
+ const QuickOpen = 'Quick open';
2002
+ const SearchForText = 'Search for text';
2003
+ const ShowAndRunCommands = 'Show And Run Commands';
2004
+ const TypeNameOfCommandToRun = 'Type the name of a command to run.';
2005
+
2006
+ const typeNameofCommandToRun = () => {
2007
+ return i18nString(TypeNameOfCommandToRun);
2000
2008
  };
2001
- const getAll = () => {
2002
- return state$2.menuEntries;
2009
+ const showAndRunCommands = () => {
2010
+ return i18nString(ShowAndRunCommands);
2003
2011
  };
2004
- const add = menuEntries => {
2005
- state$2.menuEntries = [...state$2.menuEntries, ...menuEntries];
2012
+ const goToFile = () => {
2013
+ return i18nString(GoToFile);
2006
2014
  };
2007
-
2008
- const getVisible$1 = (items, minLineY, maxLineY, icons) => {
2009
- const range = items.slice(minLineY, maxLineY);
2010
- const protoVisibleItems = range.map((item, index) => {
2011
- return {
2012
- ...item,
2013
- fileIcon: icons[index]
2014
- };
2015
- });
2016
- return protoVisibleItems;
2015
+ const noResults = () => {
2016
+ return i18nString(NoResults);
2017
+ };
2018
+ const quickOpen = () => {
2019
+ return i18nString(QuickOpen);
2020
+ };
2021
+ const goToLineColumn = () => {
2022
+ return i18nString(GoToLineColumn);
2023
+ };
2024
+ const goToSymbolInEditor = () => {
2025
+ return i18nString(GoToSymbolInEditor);
2026
+ };
2027
+ const searchForText = () => {
2028
+ return i18nString(SearchForText);
2029
+ };
2030
+ const openView = () => {
2031
+ return i18nString(OpenView);
2017
2032
  };
2018
2033
 
2019
- const emptyHighlightSections = [];
2020
-
2021
- const getHighlightSections = (highlights, label) => {
2022
- if (highlights.length === 0) {
2023
- return emptyHighlightSections;
2024
- }
2025
- const sections = [];
2026
- let position = 0;
2027
- for (let i = 0; i < highlights.length; i += 2) {
2028
- const highlightStart = highlights[i];
2029
- const highlightEnd = highlights[i + 1];
2030
- if (position < highlightStart) {
2031
- const beforeText = label.slice(position, highlightStart);
2032
- sections.push({
2033
- highlighted: false,
2034
- text: beforeText
2035
- });
2036
- }
2037
- const highlightText = label.slice(highlightStart, highlightEnd);
2038
- sections.push({
2039
- highlighted: true,
2040
- text: highlightText
2041
- });
2042
- position = highlightEnd;
2043
- }
2044
- if (position < label.length) {
2045
- const afterText = label.slice(position);
2046
- sections.push({
2047
- highlighted: false,
2048
- text: afterText
2049
- });
2050
- }
2051
- return sections;
2034
+ const getPicks$7 = async () => {
2035
+ return [{
2036
+ description: goToFile(),
2037
+ direntType: None$2,
2038
+ fileIcon: '',
2039
+ icon: '',
2040
+ label: DotDotDot,
2041
+ matches: [],
2042
+ uri: ''
2043
+ }, {
2044
+ description: goToLineColumn(),
2045
+ direntType: None$2,
2046
+ fileIcon: '',
2047
+ icon: '',
2048
+ label: ':',
2049
+ matches: [],
2050
+ uri: ''
2051
+ }, {
2052
+ description: goToSymbolInEditor(),
2053
+ direntType: None$2,
2054
+ fileIcon: '',
2055
+ icon: '',
2056
+ label: Colon,
2057
+ matches: [],
2058
+ uri: ''
2059
+ }, {
2060
+ description: searchForText(),
2061
+ direntType: None$2,
2062
+ fileIcon: '',
2063
+ icon: '',
2064
+ label: Percent,
2065
+ matches: [],
2066
+ uri: ''
2067
+ }, {
2068
+ description: showAndRunCommands(),
2069
+ direntType: None$2,
2070
+ fileIcon: '',
2071
+ icon: '',
2072
+ label: AngleBracket,
2073
+ matches: [],
2074
+ uri: ''
2075
+ }, {
2076
+ description: openView(),
2077
+ direntType: None$2,
2078
+ fileIcon: '',
2079
+ icon: '',
2080
+ label: View$1,
2081
+ matches: [],
2082
+ uri: ''
2083
+ }];
2052
2084
  };
2053
2085
 
2054
- const getVisible = (setSize, protoVisibleItems, minLineY, focusedIndex) => {
2055
- const visibleItems = protoVisibleItems.map((visibleItem, i) => {
2056
- const highlights = visibleItem.matches.slice(1);
2057
- const sections = getHighlightSections(highlights, visibleItem.label);
2058
- return {
2059
- ...visibleItem,
2060
- posInSet: minLineY + i + 1,
2061
- setSize,
2062
- isActive: i === focusedIndex,
2063
- highlights: sections
2064
- };
2065
- });
2066
- return visibleItems;
2086
+ const getRecentlyOpened = () => {
2087
+ return invoke$1(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
2067
2088
  };
2068
2089
 
2069
- const createQuickPickViewModel = (oldState, newState) => {
2070
- const protoVisibleItems = getVisible$1(newState.items, newState.minLineY, newState.maxLineY, newState.icons);
2071
- const visibleItems = getVisible(newState.items.length, protoVisibleItems, newState.minLineY, newState.focusedIndex);
2072
- const oldFocusedIndex = oldState.focusedIndex - oldState.minLineY;
2073
- const newFocusedIndex = newState.focusedIndex - newState.minLineY;
2074
- const maxLineY = Math.min(newState.maxLineY, newState.items.length);
2075
- const itemCount = maxLineY - newState.minLineY;
2076
- const height = itemCount * newState.itemHeight;
2090
+ const toProtoVisibleItem = uri => {
2077
2091
  return {
2078
- visibleItems,
2079
- value: newState.value,
2080
- cursorOffset: newState.cursorOffset,
2081
- focused: newState.focused,
2082
- height,
2083
- oldFocusedIndex,
2084
- newFocusedIndex,
2085
- uid: newState.uid
2092
+ label: uri,
2093
+ description: '',
2094
+ fileIcon: '',
2095
+ icon: '',
2096
+ matches: [],
2097
+ direntType: Directory,
2098
+ uri: uri
2086
2099
  };
2087
2100
  };
2088
-
2089
- const SetCursorOffset = 'setCursorOffset';
2090
- const SetFocusedIndex = 'setFocusedIndex';
2091
- const SetItemsHeight = 'setItemsHeight';
2092
- const SetValue = 'setValue';
2093
-
2094
- const renderCursorOffset = newState => {
2095
- return ['Viewlet.send', newState.uid, /* method */SetCursorOffset, /* cursorOffset */newState.cursorOffset];
2101
+ const getPicks$6 = async () => {
2102
+ const recentlyOpened = await getRecentlyOpened();
2103
+ const picks = recentlyOpened.map(toProtoVisibleItem);
2104
+ return picks;
2096
2105
  };
2097
2106
 
2098
- const QuickPickInput = 'QuickPickInput';
2099
-
2100
- const renderFocus = newState => {
2101
- return ['Viewlet.focusElementByName', QuickPickInput];
2107
+ const getPicks$5 = async () => {
2108
+ const picks = [];
2109
+ return picks;
2102
2110
  };
2103
2111
 
2104
- const renderFocusedIndex = newState => {
2105
- return ['Viewlet.send', newState.uid, /* method */SetFocusedIndex, /* oldFocusedIndex */newState.oldFocusedIndex, /* newFocusedIndex */newState.newFocusedIndex];
2112
+ const getPicks$4 = async () => {
2113
+ return [];
2106
2114
  };
2107
2115
 
2108
- const renderHeight = newState => {
2109
- if (newState.height === 0) {
2110
- return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */20];
2111
- }
2112
- return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */newState.height];
2116
+ const getPicks$3 = async () => {
2117
+ const picks = [];
2118
+ return picks;
2113
2119
  };
2114
2120
 
2115
- const ComboBox = 'combobox';
2116
- const ListBox = 'listbox';
2117
- const None = 'none';
2118
- const Option = 'option';
2119
-
2120
- const FileIcon = 'FileIcon';
2121
- const InputBox = 'InputBox';
2122
- const Label = 'Label';
2123
- const MaskIcon = 'MaskIcon';
2124
- const QuickPick$1 = 'QuickPick';
2125
- const QuickPickHeader = 'QuickPickHeader';
2126
- const QuickPickHighlight = 'QuickPickHighlight';
2127
- const QuickPickItem = 'QuickPickItem';
2128
- const QuickPickItemActive$1 = 'QuickPickItemActive';
2129
- const QuickPickItemDescription = 'QuickPickItemDescription';
2130
- const QuickPickItemLabel = 'QuickPickItemLabel';
2131
- const QuickPickItems$1 = 'QuickPickItems';
2132
- const QuickPickMaskIcon = 'QuickPickMaskIcon';
2133
- const QuickPickStatus = 'QuickPickStatus';
2134
- const Viewlet = 'Viewlet';
2135
-
2136
- const HandleBeforeInput = 'handleBeforeInput';
2137
- const HandleBlur = 'handleBlur';
2138
- const HandleFocus = 'handleFocus';
2139
- const HandleInput = 'handleInput';
2140
- const HandlePointerDown = 'handlePointerDown';
2141
- const HandleWheel = 'handleWheel';
2142
-
2143
- const QuickPick = 'QuickPick';
2144
- const QuickPickItems = 'QuickPickItems';
2145
- const QuickPickItemActive = 'QuickPickItemActive';
2121
+ const Hide = 'hide';
2122
+ const KeepOpen = '';
2146
2123
 
2147
- const emptyObject = {};
2148
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
2149
- const i18nString = (key, placeholders = emptyObject) => {
2150
- if (placeholders === emptyObject) {
2151
- return key;
2152
- }
2153
- const replacer = (match, rest) => {
2154
- return placeholders[rest];
2124
+ const selectPick$9 = async pick => {
2125
+ const id = pick.label;
2126
+ await setColorTheme(/* colorThemeId */id);
2127
+ return {
2128
+ command: Hide
2155
2129
  };
2156
- return key.replaceAll(RE_PLACEHOLDER, replacer);
2157
2130
  };
2158
2131
 
2159
- const GoToFile = 'Go to file';
2160
- const GoToLineColumn = 'Go to Line / Column';
2161
- const GoToSymbolInEditor = 'Go to Symbol in Editor';
2162
- const NoResults = 'No Results';
2163
- const OpenView = 'Open View';
2164
- const QuickOpen = 'Quick open';
2165
- const SearchForText = 'Search for text';
2166
- const ShowAndRunCommands = 'Show And Run Commands';
2167
- const TypeNameOfCommandToRun = 'Type the name of a command to run.';
2168
-
2169
- const typeNameofCommandToRun = () => {
2170
- return i18nString(TypeNameOfCommandToRun);
2171
- };
2172
- const showAndRunCommands = () => {
2173
- return i18nString(ShowAndRunCommands);
2174
- };
2175
- const goToFile = () => {
2176
- return i18nString(GoToFile);
2177
- };
2178
- const noResults = () => {
2179
- return i18nString(NoResults);
2132
+ const shouldHide = item => {
2133
+ if (item.id === 'Viewlet.openWidget' && item.args[0] === 'QuickPick') {
2134
+ return false;
2135
+ }
2136
+ return true;
2180
2137
  };
2181
- const quickOpen = () => {
2182
- return i18nString(QuickOpen);
2138
+ const selectPickBuiltin = async item => {
2139
+ const args = item.args || [];
2140
+ // TODO ids should be all numbers for efficiency -> also directly can call command
2141
+ await invoke$1(item.id, ...args);
2142
+ if (shouldHide(item)) {
2143
+ return {
2144
+ command: Hide
2145
+ };
2146
+ }
2147
+ return {
2148
+ command: KeepOpen
2149
+ };
2183
2150
  };
2184
- const goToLineColumn = () => {
2185
- return i18nString(GoToLineColumn);
2151
+ const selectPickExtension = async item => {
2152
+ const id = item.id.slice(4); // TODO lots of string allocation with 'ext.' find a better way to separate builtin commands from extension commands
2153
+ try {
2154
+ await invoke$1('ExtensionHost.executeCommand', id);
2155
+ } catch (error) {
2156
+ await handleError(error, false);
2157
+ await showErrorDialog(error);
2158
+ }
2159
+ return {
2160
+ command: Hide
2161
+ };
2186
2162
  };
2187
- const goToSymbolInEditor = () => {
2188
- return i18nString(GoToSymbolInEditor);
2163
+ const selectPick$8 = async item => {
2164
+ // @ts-ignore
2165
+ const id = item.id;
2166
+ if (id.startsWith('ext.')) {
2167
+ return selectPickExtension(item);
2168
+ }
2169
+ return selectPickBuiltin(item);
2189
2170
  };
2190
- const searchForText = () => {
2191
- return i18nString(SearchForText);
2171
+
2172
+ const selectPick$7 = async pick => {
2173
+ const {
2174
+ args
2175
+ } = state$1;
2176
+ const resolve = args[2];
2177
+ resolve(pick);
2178
+ return {
2179
+ command: Hide
2180
+ };
2192
2181
  };
2193
- const openView = () => {
2194
- return i18nString(OpenView);
2182
+
2183
+ const openUri = async uri => {
2184
+ await invoke$1(/* Main.openUri */'Main.openUri', /* uri */uri);
2195
2185
  };
2196
2186
 
2197
- const Div = 4;
2198
- const Input = 6;
2199
- const Span = 8;
2200
- const Img = 17;
2201
-
2202
- const getQuickPickInputVirtualDom = () => {
2203
- const ariaLabel = typeNameofCommandToRun();
2187
+ const selectPick$6 = async pick => {
2188
+ const description = pick.description;
2189
+ const fileName = pick.label;
2190
+ const workspace = await getWorkspacePath();
2191
+ const absolutePath = `${workspace}/${description}/${fileName}`;
2192
+ await openUri(absolutePath);
2204
2193
  return {
2205
- type: Input,
2206
- className: InputBox,
2207
- spellcheck: false,
2208
- autocapitalize: 'off',
2209
- inputType: 'text',
2210
- childCount: 0,
2211
- role: ComboBox,
2212
- name: QuickPickInput,
2213
- onBeforeInput: HandleBeforeInput,
2214
- onBlur: HandleBlur,
2215
- onInput: HandleInput,
2216
- onFocus: HandleFocus,
2217
- ariaLabel: ariaLabel,
2218
- ariaAutoComplete: 'list',
2219
- ariaExpanded: true,
2220
- autocomplete: 'off'
2194
+ command: Hide
2221
2195
  };
2222
2196
  };
2223
2197
 
2224
- const getQuickPickHeaderVirtualDom = () => {
2225
- return [{
2226
- type: Div,
2227
- className: QuickPickHeader,
2228
- childCount: 1
2229
- }, getQuickPickInputVirtualDom()];
2198
+ const execute = async (method, ...params) => {
2199
+ // TODO
2230
2200
  };
2231
2201
 
2232
- const getFileIconVirtualDom = icon => {
2202
+ const selectPick$5 = async item => {
2203
+ const rowIndex = Number.parseInt(item.label);
2204
+ const position = {
2205
+ rowIndex,
2206
+ columnIndex: 5
2207
+ };
2208
+ await execute(/* EditorSetCursor.editorSetCursor */'TODO', /* position */position);
2209
+ // TODO put cursor onto that line
2233
2210
  return {
2234
- type: Img,
2235
- className: FileIcon,
2236
- src: icon,
2237
- role: None,
2238
- childCount: 0
2211
+ command: Hide
2239
2212
  };
2240
2213
  };
2241
2214
 
2242
- const mergeClassNames = (...classNames) => {
2243
- return classNames.filter(Boolean).join(' ');
2244
- };
2245
- const Text = 12;
2246
- const text = data => {
2215
+ const selectPick$4 = async item => {
2216
+ // Command.execute(/* openView */ 549, /* viewName */ item.label)
2247
2217
  return {
2248
- type: Text,
2249
- text: data,
2250
- childCount: 0
2218
+ command: Hide
2251
2219
  };
2252
2220
  };
2253
2221
 
2254
- const quickPickHighlight = {
2255
- type: Span,
2256
- className: QuickPickHighlight,
2257
- childCount: 1
2222
+ const openWorkspaceFolder = uri => {
2223
+ return invoke$1(/* Workspace.setPath */'Workspace.setPath', /* path */uri);
2258
2224
  };
2259
- const getHighlights = (sections, label) => {
2260
- const labelDom = {
2261
- type: Div,
2262
- className: QuickPickItemLabel,
2263
- childCount: 0
2225
+
2226
+ // TODO selectPick should be independent of show/hide
2227
+ const selectPick$3 = async pick => {
2228
+ const path = `${pick.description}/${pick.label}`;
2229
+ await openWorkspaceFolder(path);
2230
+ return {
2231
+ command: Hide
2264
2232
  };
2265
- const nodes = [labelDom];
2266
- if (sections.length === 0) {
2267
- labelDom.childCount++;
2268
- nodes.push(text(label));
2269
- } else {
2270
- for (const section of sections) {
2271
- if (section.highlighted) {
2272
- labelDom.childCount++;
2273
- nodes.push(quickPickHighlight, text(section.text));
2274
- } else {
2275
- labelDom.childCount++;
2276
- nodes.push(text(section.text));
2277
- }
2278
- }
2279
- }
2280
- return nodes;
2281
2233
  };
2282
2234
 
2283
- const getQuickPickItemVirtualDom = visibleItem => {
2284
- const {
2285
- posInSet,
2286
- label,
2287
- setSize,
2288
- isActive,
2289
- description,
2290
- icon,
2291
- highlights,
2292
- fileIcon
2293
- } = visibleItem;
2294
- const dom = [];
2295
- dom.push({
2296
- type: Div,
2297
- className: QuickPickItem,
2298
- role: Option,
2299
- ariaPosInSet: posInSet,
2300
- ariaSetSize: setSize,
2301
- childCount: 1
2302
- });
2303
- const parent = dom[0];
2304
- if (isActive) {
2305
- // @ts-ignore
2306
- parent.id = QuickPickItemActive;
2307
- parent.className += ' ' + QuickPickItemActive$1;
2308
- }
2309
- if (fileIcon) {
2310
- parent.childCount++;
2311
- dom.push(getFileIconVirtualDom(fileIcon));
2312
- } else if (icon) {
2313
- parent.childCount++;
2314
- dom.push({
2315
- type: Div,
2316
- className: mergeClassNames(QuickPickMaskIcon, MaskIcon, `MaskIcon${icon}`),
2317
- childCount: 0
2318
- });
2319
- }
2320
- const highlightDom = getHighlights(highlights, label);
2321
- dom.push(...highlightDom);
2322
- if (description) {
2323
- parent.childCount++;
2324
- dom.push({
2325
- type: Div,
2326
- className: QuickPickItemDescription,
2327
- childCount: 1
2328
- }, text(description));
2329
- }
2330
- return dom;
2235
+ const selectPick$2 = async item => {
2236
+ return {
2237
+ command: Hide
2238
+ };
2331
2239
  };
2332
2240
 
2333
- const getQuickPickNoResultsVirtualDom = () => {
2334
- const noResults$1 = noResults();
2335
- return [{
2336
- type: Div,
2337
- className: mergeClassNames(QuickPickItem, QuickPickItemActive$1, QuickPickStatus),
2338
- childCount: 1
2339
- }, {
2340
- type: Div,
2341
- className: Label,
2342
- childCount: 1
2343
- }, text(noResults$1)];
2241
+ const selectPick$1 = async item => {
2242
+ // Command.execute(/* openView */ 549, /* viewName */ item.label)
2243
+ return {
2244
+ command: Hide
2245
+ };
2344
2246
  };
2345
2247
 
2346
- const getQuickPickItemsVirtualDom = visibleItems => {
2347
- if (visibleItems.length === 0) {
2348
- return getQuickPickNoResultsVirtualDom();
2349
- }
2350
- const dom = visibleItems.flatMap(getQuickPickItemVirtualDom);
2351
- return dom;
2248
+ const selectPick = async item => {
2249
+ return {
2250
+ command: Hide
2251
+ };
2352
2252
  };
2353
2253
 
2354
- const getQuickPickVirtualDom = visibleItems => {
2355
- const quickOpen$1 = quickOpen();
2356
- return [{
2357
- type: Div,
2358
- className: mergeClassNames(Viewlet, QuickPick$1),
2359
- childCount: 2,
2360
- id: QuickPick,
2361
- ariaLabel: quickOpen$1
2362
- }, ...getQuickPickHeaderVirtualDom(), {
2363
- type: Div,
2364
- className: QuickPickItems$1,
2365
- id: QuickPickItems,
2366
- role: ListBox,
2367
- ariaActivedescendant: QuickPickItemActive,
2368
- onWheel: HandleWheel,
2369
- childCount: visibleItems.length
2370
- }, ...getQuickPickItemsVirtualDom(visibleItems)];
2371
- };
2254
+ const selectPicks = [selectPick$9, selectPick$8, selectPick$7, selectPick$6, selectPick$5, selectPick$4, selectPick$3, selectPick$2, selectPick$1, selectPick];
2255
+ const getPicks$2 = [getPicks$c, getPicks$b, getPicks$a, getPicks$9, getPicks$8, getPicks$7, getPicks$6, getPicks$5, getPicks$4, getPicks$3];
2372
2256
 
2373
- const renderItems = newState => {
2374
- const dom = getQuickPickVirtualDom(newState.visibleItems);
2375
- return ['Viewlet.setDom2', dom];
2257
+ const select = selectPicks;
2258
+ const getPick$1 = getPicks$2;
2259
+ const getPicks$1 = id => {
2260
+ const fn = getPick$1[id];
2261
+ return fn;
2376
2262
  };
2377
-
2378
- const renderValue = newState => {
2379
- return ['Viewlet.send', newState.uid, /* method */SetValue, /* value */newState.value];
2263
+ const getSelect = id => {
2264
+ const fn = select[id];
2265
+ return fn;
2380
2266
  };
2381
2267
 
2382
- const getRenderer = diffType => {
2383
- switch (diffType) {
2384
- case RenderValue:
2385
- return renderValue;
2386
- case RenderCursorOffset:
2387
- return renderCursorOffset;
2388
- case RenderItems:
2389
- return renderItems;
2390
- case RenderFocusedIndex:
2391
- return renderFocusedIndex;
2392
- case Height:
2393
- return renderHeight;
2394
- case RenderFocus:
2395
- return renderFocus;
2396
- default:
2397
- throw new Error('unknown renderer');
2398
- }
2268
+ const getPicks = (id, searchValue) => {
2269
+ const fn = getPicks$1(id);
2270
+ return fn(searchValue);
2399
2271
  };
2400
2272
 
2401
- const applyRender = (oldState, newState, diffResult) => {
2402
- const commands = [];
2403
- const viewModel = createQuickPickViewModel(oldState, newState);
2404
- for (const item of diffResult) {
2405
- if (item === Height) {
2406
- continue;
2407
- }
2408
- if (item === RenderFocusedIndex) {
2409
- continue;
2410
- }
2411
- const fn = getRenderer(item);
2412
- commands.push(fn(viewModel));
2273
+ const getQuickPickSubProviderId = prefix => {
2274
+ switch (prefix) {
2275
+ case Command:
2276
+ return Commands$1;
2277
+ case Symbol$1:
2278
+ return Symbol$2;
2279
+ case WorkspaceSymbol$1:
2280
+ return WorkspaceSymbol$2;
2281
+ case GoToLine$1:
2282
+ return GoToLine$2;
2283
+ case View$2:
2284
+ return View$3;
2285
+ case Help$1:
2286
+ return Help$2;
2287
+ default:
2288
+ return File$2;
2413
2289
  }
2414
- return commands;
2415
2290
  };
2416
2291
 
2417
- const render2 = (uid, diffResult) => {
2292
+ // TODO when user types letters -> no need to query provider again -> just filter existing results
2293
+ const setValue = async (state, newValue) => {
2418
2294
  const {
2419
- oldState,
2420
- newState
2421
- } = get(uid);
2422
- if (oldState === newState) {
2423
- return [];
2424
- }
2425
- set(uid, newState, newState);
2426
- const commands = applyRender(oldState, newState, diffResult);
2427
- return commands;
2428
- };
2429
-
2430
- const renderEventListeners = () => {
2431
- return [{
2432
- name: HandlePointerDown,
2433
- params: ['handlePointerDown', 'event.clientX', 'event.clientY'],
2434
- preventDefault: true
2435
- }, {
2436
- name: HandleWheel,
2437
- params: ['handleWheel', 'event.deltaMode', 'event.deltaY']
2438
- }, {
2439
- name: HandleBlur,
2440
- params: ['handleBlur']
2441
- }, {
2442
- name: HandleBeforeInput,
2443
- params: ['handleBeforeInput']
2444
- }, {
2445
- name: HandleInput,
2446
- params: ['handleInput', 'event.target.value']
2447
- }, {
2448
- name: HandleFocus,
2449
- params: ['handleFocus']
2450
- }];
2451
- };
2452
-
2453
- const selectCurrentIndex = state => {
2454
- return selectIndex(state, state.focusedIndex);
2455
- };
2456
-
2457
- const findLabelIndex = (items, label) => {
2458
- for (let i = 0; i < items.length; i++) {
2459
- if (items[i].label === label) {
2460
- return i;
2461
- }
2295
+ providerId,
2296
+ value,
2297
+ minLineY,
2298
+ maxLineY,
2299
+ fileIconCache,
2300
+ itemHeight,
2301
+ height
2302
+ } = state;
2303
+ if (value === newValue) {
2304
+ return state;
2462
2305
  }
2463
- return -1;
2306
+ const prefix = getQuickPickPrefix(newValue);
2307
+ const subId = getQuickPickSubProviderId(prefix);
2308
+ const newPicks = await getPicks(subId, newValue);
2309
+ const filterValue = getFilterValue(providerId, newValue);
2310
+ const items = filterQuickPickItems(newPicks, filterValue);
2311
+ const focusedIndex = items.length === 0 ? -1 : 0;
2312
+ const sliced = items.slice(minLineY, maxLineY);
2313
+ const {
2314
+ newFileIconCache,
2315
+ icons
2316
+ } = await getQuickPickFileIcons(sliced, fileIconCache);
2317
+ const listHeight = getListHeight(items.length, itemHeight, height);
2318
+ const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, items.length);
2319
+ return {
2320
+ ...state,
2321
+ picks: newPicks,
2322
+ items,
2323
+ focusedIndex,
2324
+ inputSource: Script,
2325
+ value: newValue,
2326
+ icons,
2327
+ fileIconCache: newFileIconCache,
2328
+ finalDeltaY
2329
+ };
2464
2330
  };
2465
2331
 
2466
- const selectItem = async (state, label) => {
2467
- string(label);
2468
- const index = findLabelIndex(state.items, label);
2469
- if (index === -1) {
2332
+ // TODO when user types letters -> no need to query provider again -> just filter existing results
2333
+ const handleInput = async (state, newValue, cursorOffset, inputSource = Script) => {
2334
+ if (state.value === newValue) {
2470
2335
  return state;
2471
2336
  }
2472
- return selectIndex(state, index);
2473
- };
2474
-
2475
- const wrapCommand = fn => {
2476
- const wrapped = async (uid, ...args) => {
2477
- const {
2478
- newState
2479
- } = get(uid);
2480
- const newerState = await fn(newState, ...args);
2481
- if (newState === newerState) {
2482
- return;
2483
- }
2484
- const latest = get(uid);
2485
- set(uid, latest.oldState, newerState);
2337
+ const newState = await setValue(state, newValue);
2338
+ return {
2339
+ ...newState,
2340
+ cursorOffset,
2341
+ inputSource
2486
2342
  };
2487
- return wrapped;
2488
2343
  };
2489
2344
 
2490
- const commandMap = {
2491
- 'QuickPick.addMenuEntries': add,
2492
- 'QuickPick.close': close,
2493
- 'QuickPick.create2': create,
2494
- 'QuickPick.diff2': diff2,
2495
- 'QuickPick.dispose': dispose,
2496
- 'QuickPick.focusFirst': wrapCommand(focusFirst),
2497
- 'QuickPick.focusIndex': wrapCommand(focusIndex),
2498
- 'QuickPick.focusLast': wrapCommand(focusLast),
2499
- 'QuickPick.focusNext': wrapCommand(focusNext),
2500
- 'QuickPick.focusPrevious': wrapCommand(focusPrevious),
2501
- 'QuickPick.getCommandIds': getCommandIds,
2502
- 'QuickPick.getKeyBindings': getKeyBindings,
2503
- 'QuickPick.handleBeforeInput': wrapCommand(handleBeforeInput),
2504
- 'QuickPick.handleBlur': wrapCommand(handleBlur),
2505
- 'QuickPick.handleClickAt': wrapCommand(handleClickAt),
2506
- 'QuickPick.handleFocus': wrapCommand(handleFocus),
2507
- 'QuickPick.handleInput': wrapCommand(handleInput),
2508
- 'QuickPick.handleWheel': wrapCommand(handleWheel),
2509
- 'QuickPick.loadContent': wrapCommand(loadContent),
2510
- 'QuickPick.render2': render2,
2511
- 'QuickPick.renderEventListeners': renderEventListeners,
2512
- 'QuickPick.selectCurrentIndex': wrapCommand(selectCurrentIndex),
2513
- 'QuickPick.selectIndex': wrapCommand(selectIndex),
2514
- 'QuickPick.selectItem': wrapCommand(selectItem),
2515
- 'QuickPick.setDeltaY': wrapCommand(setDeltaY),
2516
- 'QuickPick.setValue': wrapCommand(setValue)
2345
+ const handleBeforeInput = (state, inputType, data, selectionStart, selectionEnd) => {
2346
+ string(inputType);
2347
+ number(selectionStart);
2348
+ number(selectionEnd);
2349
+ const {
2350
+ value
2351
+ } = state;
2352
+ const {
2353
+ newValue,
2354
+ cursorOffset
2355
+ } = getNewValue(value, inputType, data, selectionStart, selectionEnd);
2356
+ return handleInput(state, newValue, cursorOffset, User);
2517
2357
  };
2518
2358
 
2519
- const getColorThemeNames = async () => {
2520
- return invoke$1(/* Ajax.getJson */'ColorTheme.getColorThemeNames');
2359
+ const handleBlur = async state => {
2360
+ // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
2361
+ // await CloseWidget.closeWidget(state.uid)
2362
+ return state;
2521
2363
  };
2522
2364
 
2523
- const toProtoVisibleItem$2 = name => {
2524
- const pick = {
2525
- label: name,
2526
- description: '',
2527
- fileIcon: '',
2528
- icon: '',
2529
- matches: [],
2530
- direntType: 0,
2531
- uri: ''
2532
- };
2533
- return pick;
2365
+ const getIndex = (top, headerHeight, itemHeight, y) => {
2366
+ const relativeY = y - top - headerHeight;
2367
+ const index = Math.floor(relativeY / itemHeight);
2368
+ return index;
2534
2369
  };
2535
- const getPicks$b = async searchValue => {
2536
- const colorThemeNames = await getColorThemeNames();
2537
- const picks = colorThemeNames.map(toProtoVisibleItem$2);
2538
- return picks;
2370
+
2371
+ const getPick = (items, index) => {
2372
+ array(items);
2373
+ number(index);
2374
+ // if (index < state.recentPicks.length) {
2375
+ // return state.recentPicks[index]
2376
+ // }
2377
+ // index -= state.recentPicks.length
2378
+ if (index < items.length) {
2379
+ return items[index];
2380
+ }
2381
+ console.warn('no pick matching index', index);
2382
+ return undefined;
2539
2383
  };
2540
2384
 
2541
- const handleError = async (error, notify = true, prefix = '') => {
2542
- console.error(error);
2385
+ const selectIndex = async (state, index, button = /* left */0) => {
2386
+ const {
2387
+ minLineY,
2388
+ items,
2389
+ value
2390
+ } = state;
2391
+ const actualIndex = index + minLineY;
2392
+ const pick = getPick(items, actualIndex);
2393
+ if (!pick) {
2394
+ return state;
2395
+ }
2396
+ const prefix = getQuickPickPrefix(value);
2397
+ const subId = getQuickPickSubProviderId(prefix);
2398
+ const fn = getSelect(subId);
2399
+ const selectPickResult = await fn(pick);
2400
+ object(selectPickResult);
2401
+ string(selectPickResult.command);
2402
+ const {
2403
+ command
2404
+ } = selectPickResult;
2405
+ switch (command) {
2406
+ case Hide:
2407
+ await closeWidget(state.uid);
2408
+ return state;
2409
+ default:
2410
+ return state;
2411
+ }
2412
+
2413
+ // TODO recent picks should be per provider
2414
+ // if (!state.recentPickIds.has(pick.id)) {
2415
+ // state.recentPicks.unshift(pick)
2416
+ // state.recentPickIds.add(pick.id)
2417
+ // }
2418
+ // if (state.recentPicks.length > RECENT_PICKS_MAX_SIZE) {
2419
+ // const last = state.recentPicks.pop()
2420
+ // state.recentPickIds.delete(last.id)
2421
+ // }
2543
2422
  };
2544
- const showErrorDialog = async error => {
2545
- const code = error.code;
2546
- const message = error.message;
2547
- const stack = error.stack;
2548
- const name = error.name;
2549
- const errorInfo = {
2550
- code,
2551
- message,
2552
- stack,
2553
- name
2554
- };
2555
- await invoke$1('ErrorHandling.showErrorDialog', errorInfo);
2423
+
2424
+ const handleClickAt = (state, x, y) => {
2425
+ const {
2426
+ top,
2427
+ headerHeight,
2428
+ itemHeight
2429
+ } = state;
2430
+ const index = getIndex(top, headerHeight, itemHeight, y);
2431
+ return selectIndex(state, index);
2556
2432
  };
2557
- const warn = (...args) => {
2558
- console.warn(...args);
2433
+
2434
+ const setFocus = async focusKey => {
2435
+ await invoke$1('Focus.setFocus', focusKey);
2559
2436
  };
2560
2437
 
2561
- // TODO combine Ajax with cache (specify strategy: cacheFirst, networkFirst)
2562
- const getBuiltinPicks = async () => {
2563
- const builtinPicks = getAll();
2564
- return builtinPicks;
2438
+ const handleFocus = async state => {
2439
+ // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
2440
+ await setFocus(FocusQuickPickInput);
2441
+ // await CloseWidget.closeWidget(state.uid)
2442
+ return state;
2565
2443
  };
2566
- const prefixIdWithExt = item => {
2567
- if (!item.label) {
2568
- warn('[QuickPick] item has missing label', item);
2569
- }
2570
- if (!item.id) {
2571
- warn('[QuickPick] item has missing id', item);
2444
+
2445
+ const getDefaultValue = id => {
2446
+ switch (id) {
2447
+ case EveryThing$1:
2448
+ return Command;
2449
+ default:
2450
+ return '';
2572
2451
  }
2573
- return {
2574
- ...item,
2575
- id: `ext.${item.id}`,
2576
- label: item.label || item.id
2577
- };
2578
2452
  };
2579
- const getExtensionPicks = async () => {
2580
- try {
2581
- // TODO don't call this every time
2582
- const extensionPicks = await invoke$1('ExtensionHost.getCommands');
2583
- if (!extensionPicks) {
2584
- return [];
2585
- }
2586
- const mappedPicks = extensionPicks.map(prefixIdWithExt);
2587
- return mappedPicks;
2588
- } catch (error) {
2589
- console.error(`Failed to get extension picks: ${error}`);
2590
- return [];
2453
+
2454
+ const Commands = 'quickPick://commands';
2455
+ const EveryThing = 'quickPick://everything';
2456
+ const Recent = 'quickPick://recent';
2457
+ const ColorTheme = 'quickPick://color-theme';
2458
+ const Symbol = 'quickPick://symbol';
2459
+ const View = 'quickPick://view';
2460
+ const Help = 'quickPick://help';
2461
+ const WorkspaceSymbol = 'quickPick://workspace-symbol';
2462
+ const GoToLine = 'quickPick://go-to-line';
2463
+
2464
+ const getQuickPickProviderId = prefix => {
2465
+ switch (prefix) {
2466
+ case Commands:
2467
+ case Symbol:
2468
+ case WorkspaceSymbol:
2469
+ case EveryThing:
2470
+ case GoToLine:
2471
+ case View:
2472
+ case Help:
2473
+ return EveryThing$1;
2474
+ case ColorTheme:
2475
+ return ColorTheme$1;
2476
+ case Recent:
2477
+ return Recent$1;
2478
+ default:
2479
+ return File$2;
2591
2480
  }
2592
2481
  };
2593
- const toProtoVisibleItem$1 = item => {
2594
- const pick = {
2595
- label: item.label,
2596
- description: '',
2597
- fileIcon: '',
2598
- icon: '',
2599
- matches: [],
2600
- direntType: 0,
2601
- uri: ''
2602
- };
2603
- // @ts-ignore
2604
- pick.id = item.id;
2605
- return pick;
2482
+
2483
+ const noop = args => {};
2484
+ const setArgsCustom = args => {
2485
+ state$1.args = args;
2606
2486
  };
2607
- const getPicks$a = async () => {
2608
- // TODO get picks in parallel
2609
- const builtinPicks = await getBuiltinPicks();
2610
- const extensionPicks = await getExtensionPicks();
2611
- const allPicks = [...builtinPicks, ...extensionPicks];
2612
- const converted = allPicks.map(toProtoVisibleItem$1);
2613
- return converted;
2487
+ const getFn = id => {
2488
+ switch (id) {
2489
+ case Custom:
2490
+ return setArgsCustom;
2491
+ default:
2492
+ return noop;
2493
+ }
2614
2494
  };
2615
-
2616
- const getPicks$9 = async searchValue => {
2617
- const items = state$3.args[1] || [];
2618
- return items;
2495
+ const setArgs = (id, args) => {
2496
+ const fn = getFn(id);
2497
+ return fn(args);
2619
2498
  };
2620
2499
 
2621
- const state$1 = {
2622
- provider: File$2,
2623
- prefix: 'string-that-should-never-match-another-string'
2500
+ const loadContent = async state => {
2501
+ const {
2502
+ uri,
2503
+ args,
2504
+ fileIconCache,
2505
+ itemHeight,
2506
+ height
2507
+ } = state;
2508
+ const id = getQuickPickProviderId(uri);
2509
+ const value = getDefaultValue(id);
2510
+ const prefix = getQuickPickPrefix(value);
2511
+ const subId = getQuickPickSubProviderId(prefix);
2512
+ setArgs(subId, args);
2513
+ const newPicks = await getPicks(subId, value);
2514
+ array(newPicks);
2515
+ const filterValue = getFilterValue(id, value);
2516
+ const items = filterQuickPickItems(newPicks, filterValue);
2517
+ const minLineY = 0;
2518
+ const maxLineY = Math.min(minLineY + state.maxVisibleItems, newPicks.length);
2519
+ const sliced = newPicks.slice(minLineY, maxLineY);
2520
+ const {
2521
+ newFileIconCache,
2522
+ icons
2523
+ } = await getQuickPickFileIcons(sliced, fileIconCache);
2524
+ const listHeight = getListHeight(items.length, itemHeight, height);
2525
+ const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, items.length);
2526
+ return {
2527
+ ...state,
2528
+ picks: newPicks,
2529
+ items,
2530
+ focusedIndex: 0,
2531
+ state: Finished,
2532
+ minLineY,
2533
+ maxLineY,
2534
+ value,
2535
+ cursorOffset: value.length,
2536
+ inputSource: Script,
2537
+ focused: true,
2538
+ fileIconCache: newFileIconCache,
2539
+ icons,
2540
+ providerId: id,
2541
+ finalDeltaY
2542
+ };
2624
2543
  };
2625
2544
 
2626
- const getPicks$8 = async value => {
2627
- const prefix = getQuickPickPrefix(value);
2628
- const providerId = getQuickPickProviderId(prefix);
2545
+ const getVisible$1 = (items, minLineY, maxLineY, icons) => {
2546
+ const range = items.slice(minLineY, maxLineY);
2547
+ const protoVisibleItems = range.map((item, index) => {
2548
+ return {
2549
+ ...item,
2550
+ fileIcon: icons[index]
2551
+ };
2552
+ });
2553
+ return protoVisibleItems;
2554
+ };
2629
2555
 
2630
- // TODO race condition
2631
- if (state$1.prefix !== prefix) {
2632
- state$1.prefix = prefix;
2633
- state$1.provider = providerId;
2556
+ const getScrollBarSize = (size, contentSize, minimumSliderSize) => {
2557
+ if (size >= contentSize) {
2558
+ return 0;
2634
2559
  }
2635
- // TODO this line is a bit duplicated with getFilterValue
2636
- const slicedValue = value.slice(prefix.length).trimStart();
2637
- const picks = await getPicks$c(providerId, slicedValue);
2638
- return picks;
2560
+ return Math.max(Math.round(size ** 2 / contentSize), minimumSliderSize);
2639
2561
  };
2640
2562
 
2641
- const emptyMatches = [];
2642
-
2643
- const getWorkspacePath = async () => {
2644
- return invoke$1('Workspace.getPath');
2645
- };
2563
+ const emptyHighlightSections = [];
2646
2564
 
2647
- const RE_PROTOCOL = /^([a-z-]+):\/\//;
2648
- const getProtocol = uri => {
2649
- const protocolMatch = uri.match(RE_PROTOCOL);
2650
- if (protocolMatch) {
2651
- return protocolMatch[1];
2565
+ const getHighlightSections = (highlights, label) => {
2566
+ if (highlights.length === 0) {
2567
+ return emptyHighlightSections;
2652
2568
  }
2653
- return '';
2569
+ const sections = [];
2570
+ let position = 0;
2571
+ for (let i = 0; i < highlights.length; i += 2) {
2572
+ const highlightStart = highlights[i];
2573
+ const highlightEnd = highlights[i + 1];
2574
+ if (position < highlightStart) {
2575
+ const beforeText = label.slice(position, highlightStart);
2576
+ sections.push({
2577
+ highlighted: false,
2578
+ text: beforeText
2579
+ });
2580
+ }
2581
+ const highlightText = label.slice(highlightStart, highlightEnd);
2582
+ sections.push({
2583
+ highlighted: true,
2584
+ text: highlightText
2585
+ });
2586
+ position = highlightEnd;
2587
+ }
2588
+ if (position < label.length) {
2589
+ const afterText = label.slice(position);
2590
+ sections.push({
2591
+ highlighted: false,
2592
+ text: afterText
2593
+ });
2594
+ }
2595
+ return sections;
2654
2596
  };
2655
2597
 
2656
- const state = Object.create(null);
2657
- const register = modules => {
2658
- Object.assign(state, modules);
2659
- };
2660
- const getModule = protocol => {
2661
- return state[protocol];
2598
+ const getVisible = (setSize, protoVisibleItems, minLineY, focusedIndex) => {
2599
+ const visibleItems = protoVisibleItems.map((visibleItem, i) => {
2600
+ const highlights = visibleItem.matches.slice(1);
2601
+ const sections = getHighlightSections(highlights, visibleItem.label);
2602
+ return {
2603
+ ...visibleItem,
2604
+ posInSet: minLineY + i + 1,
2605
+ setSize,
2606
+ isActive: i === focusedIndex,
2607
+ highlights: sections
2608
+ };
2609
+ });
2610
+ return visibleItems;
2662
2611
  };
2663
2612
 
2664
- const searchFile$5 = async (path, value, prepare, assetDir) => {
2665
- const protocol = getProtocol(path);
2666
- // TODO call different providers depending on protocol
2667
- const fn = getModule(protocol);
2668
- const result = await fn(path, value, prepare, assetDir);
2669
- return result;
2613
+ const getScrollBarOffset = (delta, finalDelta, size, scrollBarSize) => {
2614
+ const scrollBarOffset = delta / finalDelta * (size - scrollBarSize);
2615
+ return scrollBarOffset;
2670
2616
  };
2617
+ const getScrollBarY = getScrollBarOffset;
2671
2618
 
2672
- // TODO this should be in FileSystem module
2673
- const pathBaseName = path => {
2674
- return path.slice(path.lastIndexOf('/') + 1);
2619
+ const createQuickPickViewModel = (oldState, newState) => {
2620
+ const protoVisibleItems = getVisible$1(newState.items, newState.minLineY, newState.maxLineY, newState.icons);
2621
+ const visibleItems = getVisible(newState.items.length, protoVisibleItems, newState.minLineY, newState.focusedIndex);
2622
+ const oldFocusedIndex = oldState.focusedIndex - oldState.minLineY;
2623
+ const newFocusedIndex = newState.focusedIndex - newState.minLineY;
2624
+ const itemCount = newState.items.length;
2625
+ const {
2626
+ itemHeight,
2627
+ deltaY,
2628
+ finalDeltaY,
2629
+ minimumSliderSize,
2630
+ headerHeight,
2631
+ height
2632
+ } = newState;
2633
+ const listHeight = getListHeight(itemCount, itemHeight, height);
2634
+ const contentHeight = itemCount * itemHeight;
2635
+ const scrollBarHeight = getScrollBarSize(listHeight, contentHeight, minimumSliderSize);
2636
+ const scrollBarY = getScrollBarY(deltaY, finalDeltaY, height - headerHeight, scrollBarHeight);
2637
+ const roundedScrollBarY = Math.round(scrollBarY);
2638
+ return {
2639
+ visibleItems,
2640
+ value: newState.value,
2641
+ cursorOffset: newState.cursorOffset,
2642
+ focused: newState.focused,
2643
+ height,
2644
+ oldFocusedIndex,
2645
+ newFocusedIndex,
2646
+ uid: newState.uid,
2647
+ scrollBarHeight,
2648
+ scrollBarTop: roundedScrollBarY
2649
+ };
2675
2650
  };
2676
2651
 
2677
- // TODO this should be in FileSystem module
2678
- const pathDirName = path => {
2679
- const pathSeparator = '/';
2680
- const index = path.lastIndexOf(pathSeparator);
2681
- if (index === -1) {
2682
- return '';
2683
- }
2684
- return path.slice(0, index);
2685
- };
2652
+ const SetCursorOffset = 'setCursorOffset';
2653
+ const SetFocusedIndex = 'setFocusedIndex';
2654
+ const SetItemsHeight = 'setItemsHeight';
2686
2655
 
2687
- const searchFile$4 = async (path, value) => {
2688
- const prepare = true;
2689
- const files = await searchFile$5(/* path */path, /* searchTerm */value, prepare, '');
2690
- return files;
2656
+ const renderCursorOffset = newState => {
2657
+ return ['Viewlet.send', newState.uid, /* method */SetCursorOffset, /* cursorOffset */newState.cursorOffset];
2691
2658
  };
2692
- const convertToPick = uri => {
2693
- const baseName = pathBaseName(uri);
2694
- const dirName = pathDirName(uri);
2695
- return {
2696
- description: dirName,
2697
- direntType: File$1,
2698
- fileIcon: '',
2699
- icon: '',
2700
- label: baseName,
2701
- matches: emptyMatches,
2702
- uri
2703
- };
2659
+
2660
+ const QuickPickInput = 'QuickPickInput';
2661
+
2662
+ const renderFocus = newState => {
2663
+ return ['Viewlet.focusElementByName', QuickPickInput];
2704
2664
  };
2705
2665
 
2706
- // TODO handle files differently
2707
- // e.g. when there are many files, don't need
2708
- // to compute the fileIcon for all files
2666
+ const renderFocusedIndex = newState => {
2667
+ return ['Viewlet.send', newState.uid, /* method */SetFocusedIndex, /* oldFocusedIndex */newState.oldFocusedIndex, /* newFocusedIndex */newState.newFocusedIndex];
2668
+ };
2709
2669
 
2710
- const getPicks$7 = async searchValue => {
2711
- // TODO cache workspace path
2712
- const workspace = await getWorkspacePath();
2713
- if (!workspace) {
2714
- return [];
2670
+ const renderHeight = newState => {
2671
+ if (newState.height === 0) {
2672
+ return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */20];
2715
2673
  }
2716
- const files = await searchFile$4(workspace, searchValue);
2717
- const picks = files.map(convertToPick);
2718
- return picks;
2674
+ return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */newState.height];
2719
2675
  };
2720
2676
 
2721
- const getPicks$6 = async () => {
2722
- const picks = [{
2723
- label: '1',
2724
- description: '',
2725
- icon: '',
2726
- fileIcon: '',
2727
- matches: [],
2728
- direntType: None$2,
2729
- uri: ''
2730
- }, {
2731
- label: '2',
2732
- description: '',
2733
- icon: '',
2734
- fileIcon: '',
2735
- matches: [],
2736
- direntType: None$2,
2737
- uri: ''
2738
- }, {
2739
- label: '3',
2740
- description: '',
2741
- icon: '',
2742
- fileIcon: '',
2743
- matches: [],
2744
- direntType: None$2,
2745
- uri: ''
2746
- }, {
2747
- label: '4',
2748
- description: '',
2749
- icon: '',
2750
- fileIcon: '',
2751
- matches: [],
2752
- direntType: None$2,
2753
- uri: ''
2754
- }, {
2755
- label: '5',
2756
- description: '',
2757
- icon: '',
2758
- fileIcon: '',
2759
- matches: [],
2760
- direntType: None$2,
2761
- uri: ''
2762
- }, {
2763
- label: '6',
2764
- description: '',
2765
- icon: '',
2766
- fileIcon: '',
2767
- matches: [],
2768
- direntType: None$2,
2769
- uri: ''
2770
- }];
2771
- return picks;
2772
- };
2677
+ const ComboBox = 'combobox';
2678
+ const ListBox = 'listbox';
2679
+ const None = 'none';
2680
+ const Option = 'option';
2773
2681
 
2774
- const DotDotDot = '...';
2775
- const Colon = ':';
2776
- const Percent = '%';
2777
- const AngleBracket = '>';
2778
- const View = 'view';
2682
+ const ContainContent = 'ContainContent';
2683
+ const FileIcon = 'FileIcon';
2684
+ const InputBox = 'InputBox';
2685
+ const Label = 'Label';
2686
+ const List = 'List';
2687
+ const ListItems = 'ListItems';
2688
+ const MaskIcon = 'MaskIcon';
2689
+ const QuickPick$1 = 'QuickPick';
2690
+ const QuickPickHeader = 'QuickPickHeader';
2691
+ const QuickPickHighlight = 'QuickPickHighlight';
2692
+ const QuickPickItem = 'QuickPickItem';
2693
+ const QuickPickItemActive$1 = 'QuickPickItemActive';
2694
+ const QuickPickItemDescription = 'QuickPickItemDescription';
2695
+ const QuickPickItemLabel = 'QuickPickItemLabel';
2696
+ const QuickPickMaskIcon = 'QuickPickMaskIcon';
2697
+ const QuickPickStatus = 'QuickPickStatus';
2698
+ const ScrollBar = 'ScrollBar';
2699
+ const ScrollBarSmall = 'ScrollBarSmall';
2700
+ const ScrollBarThumb = 'ScrollBarThumb';
2701
+ const Viewlet = 'Viewlet';
2779
2702
 
2780
- const getPicks$5 = async () => {
2703
+ const HandleWheel = 'handleWheel';
2704
+ const HandlePointerDown = 'handlePointerDown';
2705
+ const HandleBeforeInput = 'handleBeforeInput';
2706
+ const HandleBlur = 'handleBlur';
2707
+ const HandleFocus = 'handleFocus';
2708
+ const HandleInput = 'handleInput';
2709
+
2710
+ const QuickPick = 'QuickPick';
2711
+ const QuickPickItems = 'QuickPickItems';
2712
+ const QuickPickItemActive = 'QuickPickItemActive';
2713
+
2714
+ const Div = 4;
2715
+ const Input = 6;
2716
+ const Span = 8;
2717
+ const Img = 17;
2718
+
2719
+ const getQuickPickInputVirtualDom = () => {
2720
+ const ariaLabel = typeNameofCommandToRun();
2721
+ return {
2722
+ type: Input,
2723
+ className: InputBox,
2724
+ spellcheck: false,
2725
+ autocapitalize: 'off',
2726
+ inputType: 'text',
2727
+ childCount: 0,
2728
+ role: ComboBox,
2729
+ name: QuickPickInput,
2730
+ onBeforeInput: HandleBeforeInput,
2731
+ onBlur: HandleBlur,
2732
+ onInput: HandleInput,
2733
+ onFocus: HandleFocus,
2734
+ ariaLabel: ariaLabel,
2735
+ ariaAutoComplete: 'list',
2736
+ ariaExpanded: true,
2737
+ autocomplete: 'off'
2738
+ };
2739
+ };
2740
+
2741
+ const getQuickPickHeaderVirtualDom = () => {
2781
2742
  return [{
2782
- description: goToFile(),
2783
- direntType: None$2,
2784
- fileIcon: '',
2785
- icon: '',
2786
- label: DotDotDot,
2787
- matches: [],
2788
- uri: ''
2789
- }, {
2790
- description: goToLineColumn(),
2791
- direntType: None$2,
2792
- fileIcon: '',
2793
- icon: '',
2794
- label: ':',
2795
- matches: [],
2796
- uri: ''
2797
- }, {
2798
- description: goToSymbolInEditor(),
2799
- direntType: None$2,
2800
- fileIcon: '',
2801
- icon: '',
2802
- label: Colon,
2803
- matches: [],
2804
- uri: ''
2805
- }, {
2806
- description: searchForText(),
2807
- direntType: None$2,
2808
- fileIcon: '',
2809
- icon: '',
2810
- label: Percent,
2811
- matches: [],
2812
- uri: ''
2813
- }, {
2814
- description: showAndRunCommands(),
2815
- direntType: None$2,
2816
- fileIcon: '',
2817
- icon: '',
2818
- label: AngleBracket,
2819
- matches: [],
2820
- uri: ''
2821
- }, {
2822
- description: openView(),
2823
- direntType: None$2,
2824
- fileIcon: '',
2825
- icon: '',
2826
- label: View,
2827
- matches: [],
2828
- uri: ''
2829
- }];
2743
+ type: Div,
2744
+ className: QuickPickHeader,
2745
+ childCount: 1
2746
+ }, getQuickPickInputVirtualDom()];
2830
2747
  };
2831
2748
 
2832
- const getRecentlyOpened = () => {
2833
- return invoke$1(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
2749
+ const getFileIconVirtualDom = icon => {
2750
+ return {
2751
+ type: Img,
2752
+ className: FileIcon,
2753
+ src: icon,
2754
+ role: None,
2755
+ childCount: 0
2756
+ };
2834
2757
  };
2835
2758
 
2836
- const toProtoVisibleItem = uri => {
2759
+ const mergeClassNames = (...classNames) => {
2760
+ return classNames.filter(Boolean).join(' ');
2761
+ };
2762
+ const Text = 12;
2763
+ const text = data => {
2837
2764
  return {
2838
- label: uri,
2839
- description: '',
2840
- fileIcon: '',
2841
- icon: '',
2842
- matches: [],
2843
- direntType: Directory,
2844
- uri: uri
2765
+ type: Text,
2766
+ text: data,
2767
+ childCount: 0
2845
2768
  };
2846
2769
  };
2847
- const getPicks$4 = async () => {
2848
- const recentlyOpened = await getRecentlyOpened();
2849
- const picks = recentlyOpened.map(toProtoVisibleItem);
2850
- return picks;
2770
+
2771
+ const quickPickHighlight = {
2772
+ type: Span,
2773
+ className: QuickPickHighlight,
2774
+ childCount: 1
2775
+ };
2776
+ const getHighlights = (sections, label) => {
2777
+ const labelDom = {
2778
+ type: Div,
2779
+ className: QuickPickItemLabel,
2780
+ childCount: 0
2781
+ };
2782
+ const nodes = [labelDom];
2783
+ if (sections.length === 0) {
2784
+ labelDom.childCount++;
2785
+ nodes.push(text(label));
2786
+ } else {
2787
+ for (const section of sections) {
2788
+ if (section.highlighted) {
2789
+ labelDom.childCount++;
2790
+ nodes.push(quickPickHighlight, text(section.text));
2791
+ } else {
2792
+ labelDom.childCount++;
2793
+ nodes.push(text(section.text));
2794
+ }
2795
+ }
2796
+ }
2797
+ return nodes;
2851
2798
  };
2852
2799
 
2853
- const getPicks$3 = async () => {
2854
- const picks = [];
2855
- return picks;
2800
+ const getQuickPickItemVirtualDom = visibleItem => {
2801
+ const {
2802
+ posInSet,
2803
+ label,
2804
+ setSize,
2805
+ isActive,
2806
+ description,
2807
+ icon,
2808
+ highlights,
2809
+ fileIcon
2810
+ } = visibleItem;
2811
+ const dom = [];
2812
+ dom.push({
2813
+ type: Div,
2814
+ className: QuickPickItem,
2815
+ role: Option,
2816
+ ariaPosInSet: posInSet,
2817
+ ariaSetSize: setSize,
2818
+ childCount: 1
2819
+ });
2820
+ const parent = dom[0];
2821
+ if (isActive) {
2822
+ // @ts-ignore
2823
+ parent.id = QuickPickItemActive;
2824
+ parent.className += ' ' + QuickPickItemActive$1;
2825
+ }
2826
+ if (fileIcon) {
2827
+ parent.childCount++;
2828
+ dom.push(getFileIconVirtualDom(fileIcon));
2829
+ } else if (icon) {
2830
+ parent.childCount++;
2831
+ dom.push({
2832
+ type: Div,
2833
+ className: mergeClassNames(QuickPickMaskIcon, MaskIcon, `MaskIcon${icon}`),
2834
+ childCount: 0
2835
+ });
2836
+ }
2837
+ const highlightDom = getHighlights(highlights, label);
2838
+ dom.push(...highlightDom);
2839
+ if (description) {
2840
+ parent.childCount++;
2841
+ dom.push({
2842
+ type: Div,
2843
+ className: QuickPickItemDescription,
2844
+ childCount: 1
2845
+ }, text(description));
2846
+ }
2847
+ return dom;
2848
+ };
2849
+
2850
+ const getQuickPickNoResultsVirtualDom = () => {
2851
+ const noResults$1 = noResults();
2852
+ return [{
2853
+ type: Div,
2854
+ className: mergeClassNames(QuickPickItem, QuickPickItemActive$1, QuickPickStatus),
2855
+ childCount: 1
2856
+ }, {
2857
+ type: Div,
2858
+ className: Label,
2859
+ childCount: 1
2860
+ }, text(noResults$1)];
2856
2861
  };
2857
2862
 
2858
- const getPicks$2 = async () => {
2859
- return [];
2863
+ const getQuickPickItemsVirtualDom = visibleItems => {
2864
+ if (visibleItems.length === 0) {
2865
+ return getQuickPickNoResultsVirtualDom();
2866
+ }
2867
+ const dom = visibleItems.flatMap(getQuickPickItemVirtualDom);
2868
+ return dom;
2860
2869
  };
2861
2870
 
2862
- const getPicks$1 = async () => {
2863
- const picks = [];
2864
- return picks;
2871
+ const px = value => {
2872
+ return `${value}px`;
2865
2873
  };
2866
-
2867
- const selectPick$a = async pick => {
2868
- const id = pick.label;
2869
- await setColorTheme(/* colorThemeId */id);
2870
- return {
2871
- command: Hide
2872
- };
2874
+ const position = (x, y) => {
2875
+ return `${x}px ${y}px`;
2873
2876
  };
2874
2877
 
2875
- const shouldHide = item => {
2876
- if (item.id === 'Viewlet.openWidget' && item.args[0] === 'QuickPick') {
2877
- return false;
2878
- }
2879
- return true;
2880
- };
2881
- const selectPickBuiltin = async item => {
2882
- const args = item.args || [];
2883
- // TODO ids should be all numbers for efficiency -> also directly can call command
2884
- await invoke$1(item.id, ...args);
2885
- if (shouldHide(item)) {
2886
- return {
2887
- command: Hide
2888
- };
2889
- }
2890
- return {
2891
- command: KeepOpen
2892
- };
2893
- };
2894
- const selectPickExtension = async item => {
2895
- const id = item.id.slice(4); // TODO lots of string allocation with 'ext.' find a better way to separate builtin commands from extension commands
2896
- try {
2897
- await invoke$1('ExtensionHost.executeCommand', id);
2898
- } catch (error) {
2899
- await handleError(error, false);
2900
- await showErrorDialog(error);
2901
- }
2902
- return {
2903
- command: Hide
2904
- };
2905
- };
2906
- const selectPick$9 = async item => {
2907
- // @ts-ignore
2908
- const id = item.id;
2909
- if (id.startsWith('ext.')) {
2910
- return selectPickExtension(item);
2878
+ const getScrollBarVirtualDom = (scrollBarHeight, scrollBarTop) => {
2879
+ const shouldShowScrollbar = scrollBarHeight > 0;
2880
+ if (!shouldShowScrollbar) {
2881
+ return [];
2911
2882
  }
2912
- return selectPickBuiltin(item);
2883
+ const heightString = px(scrollBarHeight);
2884
+ const translateString = position(0, scrollBarTop);
2885
+ return [{
2886
+ type: Div,
2887
+ className: mergeClassNames(ScrollBar, ScrollBarSmall),
2888
+ childCount: 1
2889
+ }, {
2890
+ type: Div,
2891
+ className: ScrollBarThumb,
2892
+ childCount: 0,
2893
+ height: heightString,
2894
+ translate: translateString
2895
+ }];
2913
2896
  };
2914
2897
 
2915
- const selectPick$8 = async pick => {
2916
- const {
2917
- args
2918
- } = state$3;
2919
- const resolve = args[2];
2920
- resolve(pick);
2921
- return {
2922
- command: Hide
2923
- };
2898
+ const getQuickPickVirtualDom = (visibleItems, scrollBarHeight, scrollBarTop) => {
2899
+ const quickOpen$1 = quickOpen();
2900
+ const shouldShowScrollbar = scrollBarHeight > 0;
2901
+ return [{
2902
+ type: Div,
2903
+ className: mergeClassNames(Viewlet, QuickPick$1),
2904
+ childCount: 2,
2905
+ id: QuickPick,
2906
+ ariaLabel: quickOpen$1
2907
+ }, ...getQuickPickHeaderVirtualDom(), {
2908
+ type: Div,
2909
+ className: mergeClassNames(List, ContainContent),
2910
+ id: QuickPickItems,
2911
+ role: ListBox,
2912
+ ariaActivedescendant: QuickPickItemActive,
2913
+ onWheel: HandleWheel,
2914
+ onPointerDown: HandlePointerDown,
2915
+ childCount: shouldShowScrollbar ? 2 : 1
2916
+ }, {
2917
+ type: Div,
2918
+ className: mergeClassNames(ListItems, ContainContent),
2919
+ childCount: visibleItems.length
2920
+ }, ...getQuickPickItemsVirtualDom(visibleItems), ...getScrollBarVirtualDom(scrollBarHeight, scrollBarTop)];
2924
2921
  };
2925
2922
 
2926
- const selectPick$7 = item => {
2927
- const {
2928
- provider
2929
- } = state$1;
2930
- const fn = getSelect(provider);
2931
- return fn(item);
2923
+ const renderItems = newState => {
2924
+ const dom = getQuickPickVirtualDom(newState.visibleItems, newState.scrollBarHeight, newState.scrollBarTop);
2925
+ return ['Viewlet.setDom2', dom];
2932
2926
  };
2933
2927
 
2934
- const openUri = async uri => {
2935
- await invoke$1(/* Main.openUri */'Main.openUri', /* uri */uri);
2928
+ const renderValue = newState => {
2929
+ return ['Viewlet.setValueByName', QuickPickInput, /* value */newState.value];
2936
2930
  };
2937
2931
 
2938
- const selectPick$6 = async pick => {
2939
- const description = pick.description;
2940
- const fileName = pick.label;
2941
- const workspace = await getWorkspacePath();
2942
- const absolutePath = `${workspace}/${description}/${fileName}`;
2943
- await openUri(absolutePath);
2944
- return {
2945
- command: Hide
2946
- };
2932
+ const getRenderer = diffType => {
2933
+ switch (diffType) {
2934
+ case RenderValue:
2935
+ return renderValue;
2936
+ case RenderCursorOffset:
2937
+ return renderCursorOffset;
2938
+ case RenderItems:
2939
+ return renderItems;
2940
+ case RenderFocusedIndex:
2941
+ return renderFocusedIndex;
2942
+ case Height:
2943
+ return renderHeight;
2944
+ case RenderFocus:
2945
+ return renderFocus;
2946
+ default:
2947
+ throw new Error('unknown renderer');
2948
+ }
2947
2949
  };
2948
2950
 
2949
- const execute = async (method, ...params) => {
2950
- // TODO
2951
+ const applyRender = (oldState, newState, diffResult) => {
2952
+ const commands = [];
2953
+ const viewModel = createQuickPickViewModel(oldState, newState);
2954
+ for (const item of diffResult) {
2955
+ if (item === Height) {
2956
+ continue;
2957
+ }
2958
+ if (item === RenderFocusedIndex) {
2959
+ continue;
2960
+ }
2961
+ const fn = getRenderer(item);
2962
+ commands.push(fn(viewModel));
2963
+ }
2964
+ return commands;
2951
2965
  };
2952
2966
 
2953
- const selectPick$5 = async item => {
2954
- const rowIndex = Number.parseInt(item.label);
2955
- const position = {
2956
- rowIndex,
2957
- columnIndex: 5
2958
- };
2959
- await execute(/* EditorSetCursor.editorSetCursor */'TODO', /* position */position);
2960
- // TODO put cursor onto that line
2961
- return {
2962
- command: Hide
2963
- };
2967
+ const render2 = (uid, diffResult) => {
2968
+ const {
2969
+ oldState,
2970
+ newState
2971
+ } = get(uid);
2972
+ if (oldState === newState) {
2973
+ return [];
2974
+ }
2975
+ set(uid, newState, newState);
2976
+ const commands = applyRender(oldState, newState, diffResult);
2977
+ return commands;
2964
2978
  };
2965
2979
 
2966
- const selectPick$4 = async item => {
2967
- // Command.execute(/* openView */ 549, /* viewName */ item.label)
2968
- return {
2969
- command: Hide
2970
- };
2980
+ const renderEventListeners = () => {
2981
+ return [{
2982
+ name: HandlePointerDown,
2983
+ params: ['handleClickAt', 'event.clientX', 'event.clientY'],
2984
+ preventDefault: true
2985
+ }, {
2986
+ name: HandleWheel,
2987
+ params: ['handleWheel', 'event.deltaMode', 'event.deltaY'],
2988
+ passive: true
2989
+ }, {
2990
+ name: HandleBlur,
2991
+ params: ['handleBlur']
2992
+ }, {
2993
+ name: HandleBeforeInput,
2994
+ params: ['handleBeforeInput']
2995
+ }, {
2996
+ name: HandleInput,
2997
+ params: ['handleInput', 'event.target.value']
2998
+ }, {
2999
+ name: HandleFocus,
3000
+ params: ['handleFocus']
3001
+ }];
2971
3002
  };
2972
3003
 
2973
- const openWorkspaceFolder = uri => {
2974
- return invoke$1(/* Workspace.setPath */'Workspace.setPath', /* path */uri);
3004
+ const selectCurrentIndex = state => {
3005
+ return selectIndex(state, state.focusedIndex);
2975
3006
  };
2976
3007
 
2977
- // TODO selectPick should be independent of show/hide
2978
- const selectPick$3 = async pick => {
2979
- const path = `${pick.description}/${pick.label}`;
2980
- await openWorkspaceFolder(path);
2981
- return {
2982
- command: Hide
2983
- };
3008
+ const findLabelIndex = (items, label) => {
3009
+ for (let i = 0; i < items.length; i++) {
3010
+ if (items[i].label === label) {
3011
+ return i;
3012
+ }
3013
+ }
3014
+ return -1;
2984
3015
  };
2985
3016
 
2986
- const selectPick$2 = async item => {
2987
- return {
2988
- command: Hide
2989
- };
3017
+ const selectItem = async (state, label) => {
3018
+ string(label);
3019
+ const index = findLabelIndex(state.items, label);
3020
+ if (index === -1) {
3021
+ return state;
3022
+ }
3023
+ return selectIndex(state, index);
2990
3024
  };
2991
3025
 
2992
- const selectPick$1 = async item => {
2993
- // Command.execute(/* openView */ 549, /* viewName */ item.label)
2994
- return {
2995
- command: Hide
3026
+ const wrapCommand = fn => {
3027
+ const wrapped = async (uid, ...args) => {
3028
+ const {
3029
+ newState
3030
+ } = get(uid);
3031
+ const newerState = await fn(newState, ...args);
3032
+ if (newState === newerState) {
3033
+ return;
3034
+ }
3035
+ const latest = get(uid);
3036
+ set(uid, latest.oldState, newerState);
2996
3037
  };
3038
+ return wrapped;
2997
3039
  };
2998
3040
 
2999
- const selectPick = async item => {
3000
- return {
3001
- command: Hide
3002
- };
3041
+ const commandMap = {
3042
+ 'QuickPick.addMenuEntries': add,
3043
+ 'QuickPick.close': close,
3044
+ 'QuickPick.create2': create,
3045
+ 'QuickPick.diff2': diff2,
3046
+ 'QuickPick.dispose': dispose,
3047
+ 'QuickPick.focusFirst': wrapCommand(focusFirst),
3048
+ 'QuickPick.focusIndex': wrapCommand(focusIndex),
3049
+ 'QuickPick.focusLast': wrapCommand(focusLast),
3050
+ 'QuickPick.focusNext': wrapCommand(focusNext),
3051
+ 'QuickPick.focusPrevious': wrapCommand(focusPrevious),
3052
+ 'QuickPick.getCommandIds': getCommandIds,
3053
+ 'QuickPick.getKeyBindings': getKeyBindings,
3054
+ 'QuickPick.handleBeforeInput': wrapCommand(handleBeforeInput),
3055
+ 'QuickPick.handleBlur': wrapCommand(handleBlur),
3056
+ 'QuickPick.handleClickAt': wrapCommand(handleClickAt),
3057
+ 'QuickPick.handleFocus': wrapCommand(handleFocus),
3058
+ 'QuickPick.handleInput': wrapCommand(handleInput),
3059
+ 'QuickPick.handleWheel': wrapCommand(handleWheel),
3060
+ 'QuickPick.loadContent': wrapCommand(loadContent),
3061
+ 'QuickPick.render2': render2,
3062
+ 'QuickPick.renderEventListeners': renderEventListeners,
3063
+ 'QuickPick.selectCurrentIndex': wrapCommand(selectCurrentIndex),
3064
+ 'QuickPick.selectIndex': wrapCommand(selectIndex),
3065
+ 'QuickPick.selectItem': wrapCommand(selectItem),
3066
+ 'QuickPick.setDeltaY': wrapCommand(setDeltaY),
3067
+ 'QuickPick.setValue': wrapCommand(setValue)
3003
3068
  };
3004
3069
 
3005
- const selectPicks = [selectPick$a, selectPick$7, selectPick$9, selectPick$8, selectPick$7, selectPick$6, selectPick$5, selectPick$4, selectPick$3, selectPick$2, selectPick$1, selectPick];
3006
- const getPicks = [getPicks$b, getPicks$8, getPicks$a, getPicks$9, getPicks$8, getPicks$7, getPicks$6, getPicks$5, getPicks$4, getPicks$3, getPicks$2, getPicks$1];
3007
-
3008
3070
  const Memfs = 'memfs';
3009
3071
  const Html = 'html';
3010
3072
  const Fetch = 'fetch';
@@ -3066,8 +3128,6 @@ const searchModules = {
3066
3128
 
3067
3129
  const listen = async () => {
3068
3130
  register(searchModules);
3069
- registerSelect(selectPicks);
3070
- registerGetPick(getPicks);
3071
3131
  const rpc = await WebWorkerRpcClient.create({
3072
3132
  commandMap: commandMap
3073
3133
  });