Changed custom dict scrollbar and fixed suggestion dropdown

This commit is contained in:
c-degni 2025-05-12 04:15:20 -04:00
parent 525f3f207e
commit 9a34f12aa7
6 changed files with 46 additions and 158 deletions

View file

@ -2,6 +2,6 @@ import { Trie } from './trie';
import { DEFAULT_WORDS } from './words'
let DEFAULT_TRIE = new Trie();
DEFAULT_WORDS.forEach(word => DEFAULT_TRIE.insert(word.toLowerCase()));
DEFAULT_WORDS.forEach(word => DEFAULT_TRIE.insert(word));
export { DEFAULT_TRIE };

155
main.ts
View file

@ -41,7 +41,7 @@ export default class TAPlugin extends Plugin {
destroyTAUI();
}
// Load respective settings
// Load respective plugin data
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
@ -51,15 +51,10 @@ export default class TAPlugin extends Plugin {
this.settings.customDict.forEach(word => this.wordTrie.insert(word));
}
// Save respective settings
// Save settings
async saveSettings() {
await this.saveData(this.settings);
}
// // Save word trie
// async saveWordTrie() {
// await this.saveData(this.wordTrie);
// }
// Handles event of text being typed in document
handleEditorChange(editor: Editor) {
@ -77,17 +72,16 @@ export default class TAPlugin extends Plugin {
return;
}
const match = beforeCursor.match(/(\b\w+)$/); // Match contains word at the end of string
const match = beforeCursor.match(/(\b[\w']+)$/);; // Match contains word at the end of string
// No matches (word at the end of the string)
if (!match) {
destroyTAUI();
return;
}
const word: string = match[1].toLowerCase();
const word: string = match[1];
const suggestions: string[] = this.wordTrie.findWordsWithPrefix(word, this.settings.maxSuggestions)
.filter((w: string) => w !== word);
// const suggestions = WORDS.filter(w => w.startsWith(word) && w !== word).slice(0, this.settings.maxSuggestions);
if (suggestions.length > 0) {
updateSuggestions(suggestions, editor, match[1]);
@ -122,143 +116,4 @@ export default class TAPlugin extends Plugin {
items.forEach((item, i) => item.classList.toggle('active', i === index)); // Updates which suggestion is tagged active
}
}
}
// import { App, DropdownComponent, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
// // Remember to rename these classes and interfaces!
// interface PluginSettings {
// mySetting: string;
// }
// const DEFAULT_SETTINGS: PluginSettings = {
// mySetting: 'default'
// }
// export default class TAPlugin extends Plugin {
// settings: PluginSettings;
// async onload() {
// await this.loadSettings();
// // This creates an icon in the left ribbon.
// const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => {
// // Called when the user clicks the icon.
// new Notice('This is a notice!');
// });
// // Perform additional things with the ribbon
// ribbonIconEl.addClass('my-plugin-ribbon-class');
// // This adds a status bar item to the bottom of the app. Does not work on mobile apps.
// const statusBarItemEl = this.addStatusBarItem();
// statusBarItemEl.setText('Status Bar Text');
// // This adds a simple command that can be triggered anywher
// this.addCommand({
// id: 'open-sample-modal-simple',
// name: 'Open sample modal (simple)',
// callback: () => {
// new SampleModal(this.app).open();
// }
// });
// // This adds an editor command that can perform some operation on the current editor instance
// this.addCommand({
// id: 'sample-editor-command',
// name: 'Sample editor command',
// editorCallback: (editor: Editor, view: MarkdownView) => {
// console.log(editor.getSelection());
// editor.replaceSelection('Sample Editor Command');
// }
// });
// // This adds a complex command that can check whether the current state of the app allows execution of the command
// this.addCommand({
// id: 'open-sample-modal-complex',
// name: 'Open sample modal (complex)',
// checkCallback: (checking: boolean) => {
// // Conditions to check
// const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
// if (markdownView) {
// // If checking is true, we're simply "checking" if the command can be run.
// // If checking is false, then we want to actually perform the operation.
// if (!checking) {
// new SampleModal(this.app).open();
// }
// // This command will only show up in Command Palette when the check function returns true
// return true;
// }
// }
// });
// // This adds a settings tab so the user can configure various aspects of the plugin
// this.addSettingTab(new SampleSettingTab(this.app, this));
// // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
// // Using this function will automatically remove the event listener when this plugin is disabled.
// this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
// console.log('click', evt);
// });
// // When registering intervals, this function will automatically clear the interval when the plugin is disabled.
// this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
// }
// onunload() {
// }
// async loadSettings() {
// this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
// }
// async saveSettings() {
// await this.saveData(this.settings);
// }
// }
// class SuggestedWordDropdown extends DropdownComponent {
// }
// class SampleModal extends Modal {
// constructor(app: App) {
// super(app);
// }
// onOpen() {
// const {contentEl} = this;
// contentEl.setText('Woah!');
// }
// onClose() {
// const {contentEl} = this;
// contentEl.empty();
// }
// }
// class SampleSettingTab extends PluginSettingTab {
// plugin: TAPlugin;
// constructor(app: App, plugin: TAPlugin) {
// super(app, plugin);
// this.plugin = plugin;
// }
// display(): void {
// const {containerEl} = this;
// containerEl.empty();
// new Setting(containerEl)
// .setName('Setting #1')
// .setDesc('It\'s a secret')
// .addText(text => text
// .setPlaceholder('Enter your secret')
// .setValue(this.plugin.settings.mySetting)
// .onChange(async (value) => {
// this.plugin.settings.mySetting = value;
// await this.plugin.saveSettings();
// }));
// }
// }
}

View file

@ -36,7 +36,7 @@ export class TASettingsTab extends PluginSettingTab {
// Autocomplete setting
new Setting(containerEl)
.setName('Autocomplete')
.setDesc('Enable/disable autocomplete feature.')
.setDesc('Enable/disable the autocomplete feature.')
.addToggle(toggle =>
toggle.setValue(this.plugin.settings.enabled)
.onChange(async val => {
@ -47,7 +47,7 @@ export class TASettingsTab extends PluginSettingTab {
// Language setting
new Setting(containerEl)
.setName('Language')
.setDesc('Specify text language support.')
.setDesc('Specify text language support (only English is supported at the moment).')
.addDropdown(dropdown =>
dropdown.addOption('English', 'English')
.setValue(this.plugin.settings.language)
@ -77,7 +77,7 @@ export class TASettingsTab extends PluginSettingTab {
text.setPlaceholder('e.g. tiktok');
text.inputEl.addEventListener('keydown', async (e) => {
if (e.key === 'Enter') {
const word = text.getValue().trim().toLowerCase();
const word = text.getValue().trim();
if (word && !this.plugin.settings.customDict.includes(word)) {
this.plugin.settings.customDict.push(word);
this.plugin.wordTrie.insert(word);
@ -91,8 +91,15 @@ export class TASettingsTab extends PluginSettingTab {
// Manage custom dictionary subsetting
if (this.plugin.settings.customDict.length > 0) {
// containerEl.createEl('h3', { text: 'Custom Dictionary Contents' });
const scrollContainer = containerEl.createDiv({ cls: 'custom-word-scroll' });
scrollContainer.addEventListener('scroll', () => {
scrollContainer.classList.add('show');
clearTimeout((scrollContainer as any).scrollTimeout);
(scrollContainer as any).scrollTimeout = setTimeout(() => {
scrollContainer.classList.remove('show');
}, 1000);
});
this.plugin.settings.customDict.forEach((word, index) => {
const row = new Setting(scrollContainer)

View file

@ -12,3 +12,29 @@
.autocomplete-dropdown li:hover {
background-color: var(--background-modifier-hover);
}
.custom-word-scroll {
max-height: 200px;
overflow-y: auto;
padding-left: 10px;
padding-right: 15px;
}
.custom-word-scroll::-webkit-scrollbar {
background-color: transparent;
width: 5px;
}
.custom-word-scroll.show::-webkit-scrollbar-thumb {
background-color: rgba(100, 100, 100, 0.5);
border-radius: 5px;
}
.custom-word-scroll:not(.show)::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 5px;
}
.custom-word-scroll::-webkit-scrollbar-track {
background: transparent;
}

4
ui.ts
View file

@ -30,7 +30,7 @@ export function updateSuggestions(suggestions: string[], editor: Editor, baseWor
const cursor = editor.getCursor();
const line = editor.getLine(cursor.line);
const beforeCursor = line.substring(0, cursor.ch);
const match = beforeCursor.match(/(\b\w+)$/);
const match = beforeCursor.match(/(\b[\w']+)$/);
if (match) {
editor.replaceRange(
suggestion,
@ -49,7 +49,7 @@ export function updateSuggestions(suggestions: string[], editor: Editor, baseWor
position: 'absolute',
top: `${coords.bottom + window.scrollY}px`,
left: `${coords.left + window.scrollX}px`,
zIndex: 1000,
zIndex: 50,
backgroundColor: 'var(--background-primary)',
border: '1px solid var(--divider-color)',
borderRadius: '4px',

View file

@ -4,7 +4,7 @@ const DEFAULT_WORDS : string[] = [
"and",
"to",
"in",
"i",
"I",
"that",
"was",
"his",