diff --git a/dist/index.js b/dist/index.js index b1802203..b5383a78 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,10 +1,9 @@ (() => { - // node_modules/bloatless-react/index.ts + // ../bloatless-react/index.ts var State = class { - _value; - _bindings = /* @__PURE__ */ new Set(); // init constructor(initialValue) { + this._bindings = /* @__PURE__ */ new Set(); this._value = initialValue; } // value @@ -32,15 +31,17 @@ } }; var ListState = class extends State { - additionHandlers = /* @__PURE__ */ new Set(); - removalHandlers = /* @__PURE__ */ new Map(); // init constructor(initialItems) { super(new Set(initialItems)); + this.additionHandlers = /* @__PURE__ */ new Set(); + this.removalHandlers = /* @__PURE__ */ new Map(); + this.genericRemovalHandlers = /* @__PURE__ */ new Set(); } // list add(...items) { items.forEach((item) => { + if (this.value.has(item)) return; this.value.add(item); this.additionHandlers.forEach((handler) => handler(item)); }); @@ -49,6 +50,7 @@ remove(...items) { items.forEach((item) => { this.value.delete(item); + this.genericRemovalHandlers.forEach((handler) => handler(item)); if (!this.removalHandlers.has(item)) return; this.removalHandlers.get(item).forEach((handler) => handler(item)); this.removalHandlers.delete(item); @@ -68,6 +70,9 @@ this.removalHandlers.set(item, /* @__PURE__ */ new Set()); this.removalHandlers.get(item).add(handler); } + handleRemovals(handler) { + this.genericRemovalHandlers.add(handler); + } // stringification toString() { const array = [...this.value.values()]; @@ -76,11 +81,12 @@ } }; var MapState = class extends State { - additionHandlers = /* @__PURE__ */ new Set(); - removalHandlers = /* @__PURE__ */ new Map(); // init constructor(initialItems) { super(new Map(initialItems)); + this.additionHandlers = /* @__PURE__ */ new Set(); + this.removalHandlers = /* @__PURE__ */ new Map(); + this.genericRemovalHandlers = /* @__PURE__ */ new Set(); } // list set(key, item) { @@ -94,6 +100,7 @@ if (!item) return; this.value.delete(key); this.callSubscriptions(); + this.genericRemovalHandlers.forEach((handler) => handler(item)); if (!this.removalHandlers.has(item)) return; this.removalHandlers.get(item).forEach((handler) => handler(item)); this.removalHandlers.delete(item); @@ -111,6 +118,9 @@ this.removalHandlers.set(item, /* @__PURE__ */ new Set()); this.removalHandlers.get(item).add(handler); } + handleRemovals(handler) { + this.genericRemovalHandlers.add(handler); + } // stringification toString() { const array = [...this.value.entries()]; @@ -294,10 +304,13 @@ general: { deleteItemButtonAudioLabel: "delete item", searchButtonAudioLabel: "search", + searchButtonClearAudioLabel: "clear search query", abortButton: "Abort", + applyButton: "Apply", + backButton: "Back", cancelButton: "Cancel", closeButton: "Close", - backButton: "Back", + deleteButton: "Delete", continueButton: "Continue", confirmButton: "Confirm", saveButton: "Save", @@ -305,6 +318,7 @@ reloadAppButton: "Reload App", fileVersionLabel: "Version", searchLabel: "Search", + searchSuggestionsLabel: "Recent searches", waitingLabel: "Waiting...", restoreConnection: "Restore connection", noPageSelected: "No page selected" @@ -1260,7 +1274,7 @@ this.connectionModel = connectionModel2; this.chatListModel = chatListModel2; this.fileTransferModel = fileTransferModel2; - this.BUILD = "Build 26.09.21.B"; + this.BUILD = "Build 26.09.21.C"; // CONTEXT this.contextStack = /* @__PURE__ */ new Map(); this.closeContext = (contextId, fromHistoryEvent = false) => { @@ -1301,7 +1315,6 @@ this.draggedObject = new State(void 0); // SUGGESTIONS // boards & tasks - this.boardFilterStringSuggestions = new ListState(); this.taskCategorySuggestions = new ListState(); this.taskStatusSuggestions = new ListState(); this.translations = allTranslations[settingsModel2.language] || allTranslations.en; @@ -2988,6 +3001,10 @@ var SearchViewModel = class { // init constructor(allObjects, matchingObjects, getStringsOfObject, suggestions) { + this.allObjects = allObjects; + this.matchingObjects = matchingObjects; + this.getStringsOfObject = getStringsOfObject; + this.suggestions = suggestions; // state this.appliedQuery = new State(""); this.searchInput = new State(""); @@ -2996,6 +3013,11 @@ [this.searchInput, this.appliedQuery], () => this.searchInput.value == this.appliedQuery.value ); + this.cannotClear = createProxyState( + [this.searchInput], + () => this.searchInput.value == "" + ); + this.hasNoSuggestions = createProxyState([this.suggestions], () => this.suggestions.value.size == 0); // methods this.search = (searchTerm) => { this.searchInput.value = searchTerm; @@ -3010,6 +3032,12 @@ this.matchingObjects.add(object); } }; + this.clear = () => { + this.searchInput.value = ""; + }; + this.deleteSuggestion = (suggestion) => { + this.suggestions.remove(suggestion); + }; // utility this.checkDoesMatchSearch = (object) => { return checkDoesObjectMatchSearch( @@ -3018,10 +3046,6 @@ object ); }; - this.allObjects = allObjects; - this.matchingObjects = matchingObjects; - this.getStringsOfObject = getStringsOfObject; - this.suggestions = suggestions; this.allObjects.handleAddition((newObject) => { const doesMatch = this.checkDoesMatchSearch(newObject); if (doesMatch == false) { @@ -3056,6 +3080,7 @@ ); this.isPresentingSettingsModal = new State(false); this.isPresentingFilterModal = new State(false); + this.searchSuggestions = new ListState(); this.filteredTaskViewModels = new ListState(); // paths this.getBasePath = () => { @@ -3123,14 +3148,21 @@ searchTerm ]; this.coreViewModel.storageModel.write(suggestionPath, ""); - if (!this.coreViewModel.boardFilterStringSuggestions.value.has( + if (!this.searchSuggestions.value.has( searchTerm - )) { - this.coreViewModel.boardFilterStringSuggestions.add(searchTerm); + ) && searchTerm != "") { + this.searchSuggestions.add(searchTerm); } const lastSearchPath = this.getLastSearchPath(); this.coreViewModel.storageModel.write(lastSearchPath, searchTerm); }; + this.handleSearchRemoved = (searchTerm) => { + const suggestionPath = [ + ...this.getPreviousSearchesPath(), + searchTerm + ]; + this.coreViewModel.storageModel.remove(suggestionPath); + }; // view this.showTask = (taskFileContent) => { if (taskFileContent.boardId != this.boardInfo.fileId) { @@ -3209,7 +3241,7 @@ this.loadSearchSuggestions = () => { const dirPath = this.getPreviousSearchesPath(); const searches = this.coreViewModel.storageModel.list(dirPath); - this.coreViewModel.boardFilterStringSuggestions.add(...searches); + this.searchSuggestions.add(...searches.filter((x) => x != "")); }; this.restoreSearch = () => { const lastSearchPath = this.getLastSearchPath(); @@ -3255,12 +3287,13 @@ this.taskViewModels, this.filteredTaskViewModels, TaskViewModel.getStringsForFilter, - this.coreViewModel.boardFilterStringSuggestions + this.searchSuggestions ); this.searchViewModel.appliedQuery.subscribeSilent((newQuery) => { this.handleNewSearch(newQuery); }); this.restoreSearch(); + this.searchSuggestions.handleRemovals(this.handleSearchRemoved); this.isFilterActive = createProxyState( [this.searchViewModel.appliedQuery], () => this.searchViewModel.appliedQuery.value != "" @@ -5483,7 +5516,7 @@ } // src/View/Modals/searchModal.tsx - function SearchModal(coreViewModel2, searchViewModel, headline, converter, isOpen) { + function SearchModal(coreViewModel2, searchViewModel, headline, isOpen) { function close() { isOpen.value = false; } @@ -5492,10 +5525,11 @@ if (!isOpen2) return; ViewController.setFocusWithDelay(); }); - return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isOpen, extended: true }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, headline), /* @__PURE__ */ createElement("div", { class: "flex-row width-input" }, /* @__PURE__ */ createElement( + return /* @__PURE__ */ createElement("div", { class: "modal", "toggle:open": isOpen, extended: true }, /* @__PURE__ */ createElement("div", null, /* @__PURE__ */ createElement("main", null, /* @__PURE__ */ createElement("h2", null, headline), /* @__PURE__ */ createElement("div", { class: "flex-row" }, /* @__PURE__ */ createElement( "input", { id: "focused", + style: "max-width: unset", placeholder: coreViewModel2.translations.general.searchLabel, "bind:value": searchViewModel.searchInput, "on:enter": searchViewModel.applySearch, @@ -5511,6 +5545,15 @@ StringToOption ] } + ), /* @__PURE__ */ createElement( + "button", + { + class: "standard", + "aria-label": coreViewModel2.translations.general.searchButtonClearAudioLabel, + "on:click": searchViewModel.clear, + "toggle:disabled": searchViewModel.cannotClear + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "close") ), /* @__PURE__ */ createElement( "button", { @@ -5520,18 +5563,52 @@ "toggle:disabled": searchViewModel.cannotApplySearch }, /* @__PURE__ */ createElement("span", { class: "icon" }, "search") - )), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement( + )), /* @__PURE__ */ createElement( "div", { - class: "grid gap", - style: "grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr))", - "children:append": [ - searchViewModel.matchingObjects, - converter - ] - } + "toggle:hidden": searchViewModel.hasNoSuggestions + }, + /* @__PURE__ */ createElement("hr", null), + /* @__PURE__ */ createElement("h3", null, coreViewModel2.translations.general.searchSuggestionsLabel), + /* @__PURE__ */ createElement( + "div", + { + class: "flex-column gap", + "children:append": [ + searchViewModel.suggestions, + (suggestion) => SuggestionView(suggestion, searchViewModel, coreViewModel2) + ] + } + ) )), /* @__PURE__ */ createElement("button", { "on:click": close }, coreViewModel2.translations.general.closeButton, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))); } + function SuggestionView(suggestion, searchViewModel, coreViewModel2) { + const isApplied = createProxyState([searchViewModel.appliedQuery], () => searchViewModel.appliedQuery.value == suggestion); + function deleteSuggestion() { + searchViewModel.deleteSuggestion(suggestion); + } + function applySuggestion() { + searchViewModel.search(suggestion); + } + return /* @__PURE__ */ createElement("div", { class: "flex-row surface align-center" }, /* @__PURE__ */ createElement("span", { class: "width-100 flex-1 padding-h" }, suggestion), /* @__PURE__ */ createElement( + "button", + { + class: "danger", + "aria-label": coreViewModel2.translations.general.deleteButton, + "on:click": deleteSuggestion + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "delete") + ), /* @__PURE__ */ createElement( + "button", + { + class: "primary", + "aria-label": coreViewModel2.translations.general.applyButton, + "on:click": applySuggestion, + "toggle:disabled": isApplied + }, + /* @__PURE__ */ createElement("span", { class: "icon" }, "check") + )); + } // src/View/Components/colorPicker.tsx function ColorPicker(selectedColor) { @@ -5701,7 +5778,6 @@ coreViewModel2, boardViewModel.searchViewModel, coreViewModel2.translations.chatPage.task.filterTasksHeadline, - TaskViewModelToEntry, boardViewModel.isPresentingFilterModal ), /* @__PURE__ */ createElement("div", { "children:set": taskSettingsModal })); } diff --git a/src/View/.translations.ts.swp b/src/View/.translations.ts.swp deleted file mode 100644 index 5ff93499..00000000 Binary files a/src/View/.translations.ts.swp and /dev/null differ diff --git a/src/View/Modals/.searchModal.tsx.swp b/src/View/Modals/.searchModal.tsx.swp deleted file mode 100644 index 5a801363..00000000 Binary files a/src/View/Modals/.searchModal.tsx.swp and /dev/null differ diff --git a/src/View/Modals/taskSettingsModal.tsx b/src/View/Modals/taskSettingsModal.tsx index 10d71221..ae306460 100644 --- a/src/View/Modals/taskSettingsModal.tsx +++ b/src/View/Modals/taskSettingsModal.tsx @@ -113,7 +113,7 @@ export function TaskSettingsModal( hidden id={categorySuggestionId} children:append={[ - taskViewModel.coreViewModel.taskCategorySuggestions, + taskViewModel.containingViewModel.taskCategorySuggestions, StringToOption, ]} > @@ -137,7 +137,7 @@ export function TaskSettingsModal( hidden id={statusSuggestionId} children:append={[ - taskViewModel.coreViewModel.taskStatusSuggestions, + taskViewModel.containingViewModel.taskStatusSuggestions, StringToOption, ]} > diff --git a/src/ViewModel/Global/.coreViewModel.ts.swp b/src/ViewModel/Global/.coreViewModel.ts.swp deleted file mode 100644 index ade7e2ef..00000000 Binary files a/src/ViewModel/Global/.coreViewModel.ts.swp and /dev/null differ diff --git a/src/ViewModel/Global/coreViewModel.ts b/src/ViewModel/Global/coreViewModel.ts index 80e4bdf7..2f1d2f5d 100644 --- a/src/ViewModel/Global/coreViewModel.ts +++ b/src/ViewModel/Global/coreViewModel.ts @@ -9,7 +9,7 @@ import ConnectionModel from "../../Model/Global/connectionModel"; import ChatListModel from "../../Model/Chat/chatListModel"; export default class CoreViewModel { - readonly BUILD = "Build 26.09.21.B"; + readonly BUILD = "Build 26.09.21.C"; translations: Translations; @@ -81,11 +81,6 @@ export default class CoreViewModel { // DRAG & DROP draggedObject: React.State = new React.State(undefined); - // SUGGESTIONS - // boards & tasks - taskCategorySuggestions: React.ListState = new React.ListState(); - taskStatusSuggestions: React.ListState = new React.ListState(); - // init constructor( public readonly storageModel: StorageModel, diff --git a/src/ViewModel/Pages/.boardViewModel.ts.swp b/src/ViewModel/Pages/.boardViewModel.ts.swp deleted file mode 100644 index 05a6e037..00000000 Binary files a/src/ViewModel/Pages/.boardViewModel.ts.swp and /dev/null differ diff --git a/src/ViewModel/Pages/boardViewModel.ts b/src/ViewModel/Pages/boardViewModel.ts index fd0c412e..0c9c7b66 100644 --- a/src/ViewModel/Pages/boardViewModel.ts +++ b/src/ViewModel/Pages/boardViewModel.ts @@ -32,7 +32,7 @@ export default class BoardViewModel extends TaskContainingPageViewModel { filteredTaskViewModels: React.ListState = new React.ListState(); isFilterActive: React.State; - + // paths getBasePath = (): string[] => { return [ diff --git a/src/ViewModel/Pages/taskContainingPageViewModel.ts b/src/ViewModel/Pages/taskContainingPageViewModel.ts index 5fc5e676..8aec3d63 100644 --- a/src/ViewModel/Pages/taskContainingPageViewModel.ts +++ b/src/ViewModel/Pages/taskContainingPageViewModel.ts @@ -17,6 +17,10 @@ export default class TaskContainingPageViewModel extends Context { new React.State(undefined); taskViewModels: React.MapState = new React.MapState(); + + taskCategorySuggestions: React.ListState = new React.ListState(); + taskStatusSuggestions: React.ListState = new React.ListState(); + // methods createTaskFromBoardId = (boardId: string): void => { diff --git a/src/ViewModel/Pages/taskViewModel.ts b/src/ViewModel/Pages/taskViewModel.ts index 6578a7b2..1b923925 100644 --- a/src/ViewModel/Pages/taskViewModel.ts +++ b/src/ViewModel/Pages/taskViewModel.ts @@ -104,19 +104,19 @@ export default class TaskViewModel extends Context { updateSuggestions = (): void => { if ( - this.coreViewModel.taskCategorySuggestions.value.has( + this.containingViewModel.taskCategorySuggestions.value.has( this.category.value, ) == false ) { - this.coreViewModel.taskCategorySuggestions.add(this.category.value); + this.containingViewModel.taskCategorySuggestions.add(this.category.value); } if ( - this.coreViewModel.taskStatusSuggestions.value.has( + this.containingViewModel.taskStatusSuggestions.value.has( this.status.value, ) == false ) { - this.coreViewModel.taskStatusSuggestions.add(this.status.value); + this.containingViewModel.taskStatusSuggestions.add(this.status.value); } }; diff --git a/src/ViewModel/Utility/.searchViewModel.ts.swp b/src/ViewModel/Utility/.searchViewModel.ts.swp deleted file mode 100644 index adfc033c..00000000 Binary files a/src/ViewModel/Utility/.searchViewModel.ts.swp and /dev/null differ