Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
linonetwo committed Aug 11, 2024
2 parents fe3e948 + 4684683 commit af8107a
Show file tree
Hide file tree
Showing 13 changed files with 1,752 additions and 2,802 deletions.
39 changes: 20 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,35 @@
]
},
"devDependencies": {
"@modern-js/eslint-config": "^2.49.4",
"@modern-js/tsconfig": "^2.49.4",
"@types/lodash": "^4.17.4",
"@types/node": "^20.12.12",
"@modern-js/eslint-config": "^2.58.0",
"@modern-js/tsconfig": "^2.58.0",
"@types/lodash": "^4.17.7",
"@types/node": "^22.2.0",
"@types/pinyin": "^2.10.2",
"@types/react": "^18.3.2",
"dprint": "^0.45.1",
"@types/react": "^18.3.3",
"dprint": "^0.47.2",
"eslint-config-tidgi": "^1.2.3",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"postcss": "^8.4.38",
"rimraf": "^5.0.7",
"husky": "^9.1.4",
"lint-staged": "^15.2.8",
"postcss": "^8.4.41",
"rimraf": "^6.0.1",
"ts-node": "^10.9.2",
"tw5-typed": "^0.5.11",
"typescript": "^5.4.5"
"typescript": "^5.5.4"
},
"dependencies": {
"@algolia/autocomplete-core": "^1.17.1",
"@algolia/autocomplete-js": "^1.17.1",
"@algolia/autocomplete-shared": "^1.17.1",
"@algolia/autocomplete-theme-classic": "^1.17.1",
"@algolia/autocomplete-core": "^1.17.4",
"@algolia/autocomplete-js": "^1.17.4",
"@algolia/autocomplete-plugin-recent-searches": "^1.17.4",
"@algolia/autocomplete-shared": "^1.17.4",
"@algolia/autocomplete-theme-classic": "^1.17.4",
"@seznam/visibility-observer": "^1.1.0",
"fuse.js": "^7.0.0",
"lodash": "^4.17.21",
"npm-check-updates": "^16.14.20",
"pinyin": "4.0.0-alpha.0",
"npm-check-updates": "^17.0.6",
"pinyin": "4.0.0-alpha.2",
"segmentit": "^2.0.3",
"tiddlywiki": "^5.3.3",
"tiddlywiki-plugin-dev": "^0.2.0"
"tiddlywiki": "^5.3.5",
"tiddlywiki-plugin-dev": "^0.2.1"
}
}
4,368 changes: 1,594 additions & 2,774 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/commandpalette/language/en-GB/Translations.multids
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ UserTitle: Title of user tiddler
UserTitlePinyin: Title Pinyin of user tiddler
UserText: Text of user tiddler
StoryHistory: Story history
SearchHistory: Search history
Filter: Pick build-in filters
UnderFilter: Further search based on filters
Tagging: User tiddlers with tags
Expand Down
1 change: 1 addition & 0 deletions src/commandpalette/language/zh-Hans/Translations.multids
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SystemTitle: 系统条目标题
UserTitlePinyin: 用户条目标题拼音
UserText: 用户条目内容文本
StoryHistory: 故事流浏览历史
SearchHistory: 搜索历史
Filter: 选择预置筛选器
UnderFilter: 基于筛选器进一步搜索
Tagging: 带标签的用户条目
Expand Down
2 changes: 1 addition & 1 deletion src/commandpalette/plugin.info
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"title": "$:/plugins/linonetwo/commandpalette",
"description": "Best Command Palette, search everything, extensible, delightful.",
"author": "LinOnetwo",
"version": "1.6.0",
"version": "1.7.0",
"core-version": ">=5.0.8",
"source": "https://github.com/tiddly-gittly/tiddlywiki-plugins",
"dependents": "$:/plugins/Gk0Wk/focused-tiddler",
Expand Down
26 changes: 26 additions & 0 deletions src/commandpalette/widgets/build-in-sub-plugins/search-recent.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.tw-commandpalette-search-recent-item {
position: relative;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.tw-commandpalette-search-recent-item
.tw-commandpalette-search-recent-item-delete {
position: absolute;
right: 1em;
opacity: 0.3;
padding: 5px;
}
.tw-commandpalette-search-recent-item
.tw-commandpalette-search-recent-item-delete:hover {
opacity: 0.7;
}
.tw-commandpalette-search-recent-item
.tw-commandpalette-search-recent-item-delete:active {
opacity: 1;
}
.tw-commandpalette-search-recent-item
.tw-commandpalette-search-recent-item-delete svg {
width: 20px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title: $:/plugins/linonetwo/commandpalette/widget/build-in-sub-plugins/search-recent.css
type: text/css
tags: $:/tags/Stylesheet
67 changes: 67 additions & 0 deletions src/commandpalette/widgets/build-in-sub-plugins/search-recent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { StateUpdater } from '@algolia/autocomplete-core';
import type { AutocompletePlugin } from '@algolia/autocomplete-js';
import { createLocalStorageRecentSearchesPlugin, RecentSearchesPluginData } from '@algolia/autocomplete-plugin-recent-searches';
import { RecentSearchesItem } from '@algolia/autocomplete-plugin-recent-searches/dist/esm/types';
import { IContext } from '../utils/context';
import { getIconSvg } from '../utils/getIconSvg';
import { lingo } from '../utils/lingo';

export const plugin = (id: string): AutocompletePlugin<RecentSearchesItem, RecentSearchesPluginData<RecentSearchesItem>> => {
let setContext: StateUpdater<IContext> | undefined;
let refresh: () => Promise<void> | undefined;
const deleteIcon = getIconSvg('$:/core/images/delete-button', undefined);
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
key: `recent-${id}`,
subscribe(parameters) {
parameters.setContext?.({ addHistoryItem: (text: string) => recentSearchesPlugin.data?.addItem({ id: text, label: text }) } satisfies IContext);
setContext = parameters.setContext as unknown as StateUpdater<IContext>;
refresh = parameters.refresh.bind(parameters);
},
transformSource({ source }) {
const onSelect = (text: string) => {
setContext?.({ newQuery: text, noClose: true, noNavigate: true } satisfies IContext);
};
return {
...source,
getItemUrl({ item }) {
return item.id;
},
async getItems(parameters) {
if (parameters.query.length > 0) return [];
const items = source.getItems(parameters);
return await items;
},
onSelect({ item }) {
onSelect(item.id);
},
templates: {
...source.templates,
header() {
return lingo('SearchHistory');
},
item({ item, createElement }) {
return createElement(
'div',
{
class: 'tw-commandpalette-search-recent-item',
onclick: onSelect,
},
createElement('span', {}, item.id),
createElement('span', {
class: 'tw-commandpalette-search-recent-item-delete',
onclick: () => {
recentSearchesPlugin.data?.removeItem(item.id);
void refresh?.()?.catch?.(error => {
console.error('Error in search-recent refresh', error);
});
},
innerHTML: deleteIcon,
}),
);
},
},
};
},
});
return recentSearchesPlugin;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
title: $:/plugins/linonetwo/commandpalette/widget/build-in-sub-plugins/search-recent.js
tags: $:/tags/CommandPalettePlugin
type: application/javascript
module-type: library
priority: 1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const plugin = {
return [];
}
const onSelect = (item: ITiddlerFields) => {
(parameters.state.context as IContext).addHistoryItem?.(parameters.query);
const filter = `[[${item.title}]] [tag[${item.title}]]`;
parameters.setContext({ newQuery: '', noClose: true, noNavigate: true, filter, applyExclusion: applyIgnoreFilterToTag() } satisfies IContext);
};
Expand Down
4 changes: 4 additions & 0 deletions src/commandpalette/widgets/utils/context.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { Widget } from 'tiddlywiki';

export interface IContext {
/**
* Add a history item to the autocomplete-plugin-recent-searches.
*/
addHistoryItem?: (text: string) => void;
/**
* Apply the `TitleTextIgnoreFilter` to the filter.
*/
Expand Down
13 changes: 10 additions & 3 deletions src/commandpalette/widgets/utils/getSubPlugins.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AutocompletePlugin } from '@algolia/autocomplete-js';
import { ITiddlerFields } from 'tiddlywiki';

export function getSubPlugins() {
export function getSubPlugins(id: string) {
const plugins: Array<AutocompletePlugin<ITiddlerFields, unknown>> = [];
/**
* Try loading plugins. Plugin should add tag `$:/tags/CommandPalettePlugin` and export a `plugin` object.
Expand All @@ -13,8 +13,15 @@ export function getSubPlugins() {
.sort((a, b) => (b.priority as number | undefined ?? 0) - (a.priority as number | undefined ?? 0))
.forEach((tiddlerField) => {
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access, security/detect-non-literal-require, security-node/detect-non-literal-require-calls
plugins.push(require(tiddlerField.title).plugin);
// @ts-expect-error Cannot find name 'require'
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access, security/detect-non-literal-require, security-node/detect-non-literal-require-calls, @typescript-eslint/no-unsafe-assignment
let plugin = require(tiddlerField.title).plugin;
if (typeof plugin === 'function') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
plugin = plugin(id);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
plugins.push(plugin);
} catch (error) {
console.error(`Failed to load command palette plugin ${tiddlerField.title}`, error);
}
Expand Down
24 changes: 19 additions & 5 deletions src/commandpalette/widgets/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class CommandPaletteWidget extends Widget {
/** Can't get state from its instance, so use this as a way to get state */
autoCompleteState?: OnStateChangeProps<ITiddlerFields>;
historyMode = false;
autoFocus = true;

render(parent: Element, nextSibling: Element) {
this.parentDomNode = parent;
Expand All @@ -36,11 +37,12 @@ class CommandPaletteWidget extends Widget {
// params are get from `$:/plugins/linonetwo/commandpalette/DefaultCommandPalette` using transclusion from `$:/temp/commandpalette/default/opened`
const initialPrefix = this.getAttribute('prefix', '');
this.historyMode = this.getAttribute('historyMode', 'no') === 'yes';
this.autoFocus = this.getAttribute('autoFocus', 'yes') === 'yes';
const titlePriorityText = this.wiki.getTiddlerText('$:/plugins/linonetwo/commandpalette/configs/TitlePriorityText', 'no') === 'yes';
const containerElement = $tw.utils.domMaker('nav', {
class: 'tw-commandpalette-container',
});
parent.insertBefore(containerElement, nextSibling);
this.parentDomNode.insertBefore(containerElement, nextSibling);
this.domNodes.push(containerElement);

handleDarkMode();
Expand All @@ -52,6 +54,9 @@ class CommandPaletteWidget extends Widget {
this.autoCompleteInstance = autocomplete<ITiddlerFields>({
id: this.id,
container: containerElement,
classNames: {
panel: `tw-commandpalette-panel-${this.id}`,
},
placeholder: 'Search for tiddlers',
initialState: {
query: initialPrefix,
Expand All @@ -60,15 +65,15 @@ class CommandPaletteWidget extends Widget {
onStateChange(nextState) {
updateState(nextState);
},
autoFocus: true,
openOnFocus: true,
autoFocus: this.autoFocus,
openOnFocus: this.autoFocus,
ignoreCompositionEvents: true,
navigator: {
navigate: this.onEnter.bind(this) satisfies AutocompleteNavigator<ITiddlerFields>['navigate'],
navigateNewTab: this.onCtrlEnter.bind(this) satisfies AutocompleteNavigator<ITiddlerFields>['navigateNewTab'],
navigateNewWindow: this.onShiftEnter.bind(this) satisfies AutocompleteNavigator<ITiddlerFields>['navigateNewWindow'],
},
plugins: getSubPlugins(),
plugins: getSubPlugins(this.id),
reshape({ sourcesBySourceId }) {
const {
'title': titleSource,
Expand Down Expand Up @@ -105,6 +110,9 @@ class CommandPaletteWidget extends Widget {
itemUrl: string;
state: AutocompleteState<ITiddlerFields>;
}): void {
if (state.query.trim() !== '') {
(state.context as IContext).addHistoryItem?.(state.query);
}
if (state.context.newQuery !== undefined) {
this.autoCompleteInstance?.setQuery?.((state.context as IContext).newQuery!);
this.autoCompleteInstance?.setContext({ newQuery: undefined } satisfies IContext);
Expand Down Expand Up @@ -184,7 +192,9 @@ class CommandPaletteWidget extends Widget {
observe(containerElement, this.onVisibilityChange.bind(this));
this.registerHistoryKeyboardHandlers(inputElement);
// autoFocus param is not working, focus manually.
inputElement.focus();
if (this.autoFocus) {
inputElement.focus();
}
// no API to listen esc, listen manually
inputElement.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
Expand Down Expand Up @@ -251,7 +261,11 @@ class CommandPaletteWidget extends Widget {

destroy() {
this.setCloseState();
const containerElement = this.parentDomNode?.querySelector('.tw-commandpalette-container');
this.autoCompleteInstance?.destroy();
containerElement?.remove?.();
const panelElement = (this.document as unknown as Document)?.querySelector?.(`.tw-commandpalette-panel-${this.id}`);
panelElement?.remove?.();
this.autoCompleteInstance = undefined;
/* eslint-disable @typescript-eslint/unbound-method */
window.removeEventListener('resize', fixPanelPosition);
Expand Down

0 comments on commit af8107a

Please sign in to comment.