implement uniform sorting on all views

This commit is contained in:
marlon-erler
2024-07-19 15:13:43 +02:00
parent 0704ca9e5b
commit 6990b5edc5
13 changed files with 157 additions and 102 deletions
+51 -35
View File
@@ -427,6 +427,19 @@
var stringToOptionTag = (value) => { var stringToOptionTag = (value) => {
return /* @__PURE__ */ createElement("option", null, value); return /* @__PURE__ */ createElement("option", null, value);
}; };
function getRawObjectIndex(latest) {
const dateString = latest.date || "0000-00-00";
const [year, month, date] = dateString.split("-");
const timeString = latest.time || "00:00";
const [hour, minute] = timeString.split(":");
const hourInMinutes = parseInt(hour) * 60;
const minutesTotal = parseInt(minute) + hourInMinutes;
const paddedMinutes = minutesTotal.toString().padStart(4, "0");
const priority = latest.priority ?? 0;
const priorityInverse = 100 - priority;
const paddedPriority = priorityInverse.toString().padStart(3, "0");
return `${year}${month}${date}${paddedMinutes}${paddedPriority}`;
}
// src/translations.ts // src/translations.ts
var englishTranslations = { var englishTranslations = {
@@ -760,6 +773,14 @@
var translation = allTranslations[language] ?? allTranslations.en; var translation = allTranslations[language] ?? allTranslations.en;
// src/Model/chatModel.ts // src/Model/chatModel.ts
var MessageObjectWithIndex = class {
constructor(messageObject, index = 0) {
this.id = messageObject.id;
this.title = messageObject.title;
this.contentVersions = messageObject.contentVersions;
this.index = new State(index);
}
};
var Chat = class { var Chat = class {
id; id;
viewType; viewType;
@@ -1582,7 +1603,7 @@
const [icon, value] = field; const [icon, value] = field;
return /* @__PURE__ */ createElement("span", { class: "flex-row control-gap flex align-center padding-right ellipsis" }, /* @__PURE__ */ createElement("span", { class: "icon" }, icon), /* @__PURE__ */ createElement("span", { class: "ellipsis" }, value)); return /* @__PURE__ */ createElement("span", { class: "flex-row control-gap flex align-center padding-right ellipsis" }, /* @__PURE__ */ createElement("span", { class: "icon" }, icon), /* @__PURE__ */ createElement("span", { class: "ellipsis" }, value));
}); });
return /* @__PURE__ */ createElement( const view = /* @__PURE__ */ createElement(
"button", "button",
{ {
class: "tile flex-no", class: "tile flex-no",
@@ -1599,6 +1620,10 @@
...fieldElements ...fieldElements
)) ))
); );
messageObject.index.subscribe((newIndex) => {
view.style.order = newIndex;
});
return view;
} }
// src/Views/Objects/objectGridView.tsx // src/Views/Objects/objectGridView.tsx
@@ -1652,22 +1677,12 @@
messageObjects.value.forEach(processObject); messageObjects.value.forEach(processObject);
}); });
const objectConverter = (messageObject) => { const objectConverter = (messageObject) => {
const latest = chat.getMostRecentContent(messageObject); return ObjectEntryView(
const timeString = latest.time || "00:00";
const [hour, minute] = timeString.split(":");
const hourInMinutes = parseInt(hour) * 60;
const minutesTotal = parseInt(minute) + hourInMinutes;
const priority = latest.priority ?? 0;
const priorityInverse = 100 - priority;
const order = `${minutesTotal}${priorityInverse}`;
const view = ObjectEntryView(
chat, chat,
messageObject, messageObject,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
); );
view.style.order = order;
return view;
}; };
return /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement(
"div", "div",
@@ -1701,16 +1716,10 @@
const isToday = today.getDate() == dateObject.getUTCDate() && today.getMonth() == dateObject.getUTCMonth() && today.getFullYear() == dateObject.getUTCFullYear(); const isToday = today.getDate() == dateObject.getUTCDate() && today.getMonth() == dateObject.getUTCMonth() && today.getFullYear() == dateObject.getUTCFullYear();
messageObjects.handleAddition(processObject); messageObjects.handleAddition(processObject);
const objectConverter = (messageObject) => { const objectConverter = (messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
const timeString = latest.time || "00:00";
const [hour, minute] = timeString.split(":");
const hourInMinutes = parseInt(hour) * 60;
const minutesTotal = parseInt(minute) + hourInMinutes;
const priority = latest.priority ?? 0;
const priorityInverse = 100 - priority;
const order = `${minutesTotal}${priorityInverse}`;
const view = /* @__PURE__ */ createElement("span", { class: "secondary ellipsis" }, chat.getObjectTitle(messageObject)); const view = /* @__PURE__ */ createElement("span", { class: "secondary ellipsis" }, chat.getObjectTitle(messageObject));
view.style.order = order; messageObject.index.subscribe((newIndex) => {
view.style.order = newIndex;
});
return view; return view;
}; };
return /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement(
@@ -1774,7 +1783,6 @@
monthGridCells.value = []; monthGridCells.value = [];
currentDate.setUTCDate(1); currentDate.setUTCDate(1);
currentDate.setUTCMonth(newSelectedDate.getMonth()); currentDate.setUTCMonth(newSelectedDate.getMonth());
console.log(currentDate);
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
monthGridCells.value.push( monthGridCells.value.push(
/* @__PURE__ */ createElement("b", { class: "secondary ellipsis width-100" }, translation.weekdays[i]) /* @__PURE__ */ createElement("b", { class: "secondary ellipsis width-100" }, translation.weekdays[i])
@@ -1917,14 +1925,12 @@
chat.addObjectAndSend(messageObject); chat.addObjectAndSend(messageObject);
} }
const itemToViewEntry = (kanbanBoardItem) => { const itemToViewEntry = (kanbanBoardItem) => {
const view = ObjectEntryView( return ObjectEntryView(
chat, chat,
kanbanBoardItem.messageObject, kanbanBoardItem.messageObject,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
); );
view.style.order = kanbanBoardItem.priority * -1;
return view;
}; };
return /* @__PURE__ */ createElement( return /* @__PURE__ */ createElement(
"div", "div",
@@ -2291,7 +2297,7 @@
[appliedFilter, resultCount], [appliedFilter, resultCount],
() => translation.searchTitleText(appliedFilter.value, resultCount.value) () => translation.searchTitleText(appliedFilter.value, resultCount.value)
); );
const showingMessageObjects = new MapState(); const visibleMessageObjects = new MapState();
const isFilterEmpty = createProxyState( const isFilterEmpty = createProxyState(
[appliedFilter], [appliedFilter],
() => appliedFilter.value == "" () => appliedFilter.value == ""
@@ -2305,21 +2311,21 @@
if (!previousObjectSearches.value.has(appliedFilter.value)) if (!previousObjectSearches.value.has(appliedFilter.value))
previousObjectSearches.add(appliedFilter.value); previousObjectSearches.add(appliedFilter.value);
const allObjects = [...chat.objects.value.values()]; const allObjects = [...chat.objects.value.values()];
allObjects.forEach((object, i) => { allObjects.forEach((messageObject, i) => {
const doesMatch = checkIfMatchesFilter(object); const doesMatch = checkIfMatchesFilter(messageObject);
if (doesMatch) { if (doesMatch) {
showingMessageObjects.set(object.id, object); visibleMessageObjects.set(messageObject.id, new MessageObjectWithIndex(messageObject));
} else { } else {
showingMessageObjects.remove(object.id); visibleMessageObjects.remove(messageObject.id);
} }
}); });
resultCount.value = showingMessageObjects.value.size; resultCount.value = visibleMessageObjects.value.size;
} }
chat.objects.handleAddition((messageObject) => { chat.objects.handleAddition((messageObject) => {
if (checkIfMatchesFilter(messageObject) == false) return; if (checkIfMatchesFilter(messageObject) == false) return;
showingMessageObjects.set(messageObject.id, messageObject); visibleMessageObjects.set(messageObject.id, new MessageObjectWithIndex(messageObject));
chat.objects.handleRemoval(messageObject, () => { chat.objects.handleRemoval(messageObject, () => {
showingMessageObjects.remove(messageObject.id); visibleMessageObjects.remove(messageObject.id);
}); });
}); });
function checkIfMatchesFilter(messageObject) { function checkIfMatchesFilter(messageObject) {
@@ -2347,6 +2353,16 @@
return true; return true;
} }
applyFilter(); applyFilter();
visibleMessageObjects.subscribe((visibleMessageObjects2) => {
let indices = [...visibleMessageObjects2.values()].map((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
return getRawObjectIndex(latest);
}).sort();
visibleMessageObjects2.forEach((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
messageObject.index.value = indices.indexOf(getRawObjectIndex(latest));
});
});
const objectModal = createProxyState( const objectModal = createProxyState(
[chat.objects, selectedObject], [chat.objects, selectedObject],
() => { () => {
@@ -2375,7 +2391,7 @@
} }
return getViewFunction()( return getViewFunction()(
chat, chat,
showingMessageObjects, visibleMessageObjects,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
); );
@@ -2432,7 +2448,7 @@
translation.reset translation.reset
), /* @__PURE__ */ createElement("button", { class: "width-50 flex primary", "on:click": applyFilter }, translation.search, /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward"))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("b", { class: "secondary", "subscribe:innerText": resultText }), ObjectGridView( ), /* @__PURE__ */ createElement("button", { class: "width-50 flex primary", "on:click": applyFilter }, translation.search, /* @__PURE__ */ createElement("span", { class: "icon" }, "arrow_forward"))), /* @__PURE__ */ createElement("hr", null), /* @__PURE__ */ createElement("b", { class: "secondary", "subscribe:innerText": resultText }), ObjectGridView(
chat, chat,
showingMessageObjects, visibleMessageObjects,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
)), /* @__PURE__ */ createElement("button", { "on:click": closeFilters }, translation.close, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))), /* @__PURE__ */ createElement("div", { "children:set": objectModal })); )), /* @__PURE__ */ createElement("button", { "on:click": closeFilters }, translation.close, /* @__PURE__ */ createElement("span", { class: "icon" }, "close")))), /* @__PURE__ */ createElement("div", { "children:set": objectModal }));
+13
View File
@@ -49,6 +49,19 @@ export interface MessageObjectContent {
time?: string; time?: string;
} }
export interface MessageObjectWithIndex extends MessageObject {
index: React.State<number>;
}
export class MessageObjectWithIndex implements MessageObjectWithIndex {
constructor(messageObject: MessageObject, index: number = 0) {
this.id = messageObject.id;
this.title = messageObject.title;
this.contentVersions = messageObject.contentVersions;
this.index = new React.State(index);
}
}
// chat // chat
export class Chat { export class Chat {
id: string; id: string;
+2 -2
View File
@@ -1,13 +1,13 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { ObjectGridView } from "./objectGridView"; import { ObjectGridView } from "./objectGridView";
import { translation } from "../../translations"; import { translation } from "../../translations";
export function AllObjectsView( export function AllObjectsView(
chat: Chat, chat: Chat,
messageObjects: React.MapState<MessageObject>, messageObjects: React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
+2 -2
View File
@@ -1,6 +1,6 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { DayView } from "./dayView"; import { DayView } from "./dayView";
import { MiniatureDayView } from "./miniatureDayView"; import { MiniatureDayView } from "./miniatureDayView";
@@ -9,7 +9,7 @@ import { translation } from "../../translations";
export function CalendarView( export function CalendarView(
chat: Chat, chat: Chat,
messageObjects: React.MapState<MessageObject>, messageObjects: React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
+7 -18
View File
@@ -1,6 +1,6 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { ObjectEntryView } from "./objectEntryView"; import { ObjectEntryView } from "./objectEntryView";
import { dayInCalendar } from "../../Model/model"; import { dayInCalendar } from "../../Model/model";
@@ -8,14 +8,14 @@ import { dayInCalendar } from "../../Model/model";
export function DayView( export function DayView(
chat: Chat, chat: Chat,
messageObjects: messageObjects:
| React.ListState<MessageObject> | React.ListState<MessageObjectWithIndex>
| React.MapState<MessageObject>, | React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
const objectsForDayView = new React.ListState<MessageObject>(); const objectsForDayView = new React.ListState<MessageObjectWithIndex>();
function processObject(messageObject: MessageObject) { function processObject(messageObject: MessageObjectWithIndex) {
const latest = chat.getMostRecentContent(messageObject); const latest = chat.getMostRecentContent(messageObject);
if (!latest.date || latest.date != dayInCalendar.value) return; if (!latest.date || latest.date != dayInCalendar.value) return;
@@ -31,26 +31,15 @@ export function DayView(
messageObjects.value.forEach(processObject); messageObjects.value.forEach(processObject);
}) })
const objectConverter: React.StateItemConverter<MessageObject> = ( const objectConverter: React.StateItemConverter<MessageObjectWithIndex> = (
messageObject messageObject
) => { ) => {
const latest = chat.getMostRecentContent(messageObject); return ObjectEntryView(
const timeString = latest.time || "00:00";
const [hour, minute] = timeString.split(":");
const hourInMinutes = parseInt(hour) * 60;
const minutesTotal = parseInt(minute) + hourInMinutes;
const priority = latest.priority ?? 0;
const priorityInverse = 100 - priority;
const order = `${minutesTotal}${priorityInverse}`;
const view = ObjectEntryView(
chat, chat,
messageObject, messageObject,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
); );
view.style.order = order;
return view;
}; };
return ( return (
+3 -5
View File
@@ -1,6 +1,6 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { ObjectEntryView } from "./objectEntryView"; import { ObjectEntryView } from "./objectEntryView";
import { RenameView } from "../renameView"; import { RenameView } from "../renameView";
@@ -17,7 +17,7 @@ interface KanbanBoardItem {
export function KanbanView( export function KanbanView(
chat: Chat, chat: Chat,
messageObjects: React.MapState<MessageObject>, messageObjects: React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
@@ -116,14 +116,12 @@ function KanbanBoardView(
const itemToViewEntry: React.StateItemConverter<KanbanBoardItem> = ( const itemToViewEntry: React.StateItemConverter<KanbanBoardItem> = (
kanbanBoardItem kanbanBoardItem
) => { ) => {
const view = ObjectEntryView( return ObjectEntryView(
chat, chat,
kanbanBoardItem.messageObject, kanbanBoardItem.messageObject,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
); );
view.style.order = kanbanBoardItem.priority * -1;
return view;
}; };
return ( return (
+9 -15
View File
@@ -1,21 +1,22 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { dayInCalendar } from "../../Model/model"; import { dayInCalendar } from "../../Model/model";
import { getRawObjectIndex } from "../../utility";
export function MiniatureDayView( export function MiniatureDayView(
chat: Chat, chat: Chat,
messageObjects: messageObjects:
| React.ListState<MessageObject> | React.ListState<MessageObjectWithIndex>
| React.MapState<MessageObject>, | React.MapState<MessageObjectWithIndex>,
dateObject: Date dateObject: Date
) { ) {
const objectsForDayView = new React.ListState<MessageObject>(); const objectsForDayView = new React.ListState<MessageObject>();
const dateString = dateObject.toISOString().split("T")[0]; const dateString = dateObject.toISOString().split("T")[0];
function processObject(messageObject: MessageObject) { function processObject(messageObject: MessageObjectWithIndex) {
const latest = chat.getMostRecentContent(messageObject); const latest = chat.getMostRecentContent(messageObject);
if (!latest.date || latest.date != dateString) return; if (!latest.date || latest.date != dateString) return;
@@ -41,24 +42,17 @@ export function MiniatureDayView(
messageObjects.handleAddition(processObject); messageObjects.handleAddition(processObject);
const objectConverter: React.StateItemConverter<MessageObject> = ( const objectConverter: React.StateItemConverter<MessageObjectWithIndex> = (
messageObject messageObject
) => { ) => {
const latest = chat.getMostRecentContent(messageObject);
const timeString = latest.time || "00:00";
const [hour, minute] = timeString.split(":");
const hourInMinutes = parseInt(hour) * 60;
const minutesTotal = parseInt(minute) + hourInMinutes;
const priority = latest.priority ?? 0;
const priorityInverse = 100 - priority;
const order = `${minutesTotal}${priorityInverse}`;
const view = ( const view = (
<span class="secondary ellipsis"> <span class="secondary ellipsis">
{chat.getObjectTitle(messageObject)} {chat.getObjectTitle(messageObject)}
</span> </span>
); );
view.style.order = order; messageObject.index.subscribe(newIndex => {
view.style.order = newIndex;
})
return view; return view;
}; };
+2 -2
View File
@@ -1,12 +1,12 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { ObjectGridView } from "./objectGridView"; import { ObjectGridView } from "./objectGridView";
export function NoteObjectsView( export function NoteObjectsView(
chat: Chat, chat: Chat,
messageObjects: React.MapState<MessageObject>, messageObjects: React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
+7 -2
View File
@@ -4,13 +4,14 @@ import {
Chat, Chat,
MessageObject, MessageObject,
MessageObjectContent, MessageObjectContent,
MessageObjectWithIndex,
} from "../../Model/chatModel"; } from "../../Model/chatModel";
import { icons } from "../../icons"; import { icons } from "../../icons";
export function ObjectEntryView( export function ObjectEntryView(
chat: Chat, chat: Chat,
messageObject: MessageObject, messageObject: MessageObjectWithIndex,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
@@ -54,7 +55,7 @@ export function ObjectEntryView(
); );
}); });
return ( const view = (
<button <button
class="tile flex-no" class="tile flex-no"
on:click={select} on:click={select}
@@ -73,4 +74,8 @@ export function ObjectEntryView(
</div> </div>
</button> </button>
); );
messageObject.index.subscribe(newIndex => {
view.style.order = newIndex;
})
return view;
} }
+4 -4
View File
@@ -1,18 +1,18 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { ObjectEntryView } from "./objectEntryView"; import { ObjectEntryView } from "./objectEntryView";
export function ObjectGridView( export function ObjectGridView(
chat: Chat, chat: Chat,
messageObjects: messageObjects:
| React.ListState<MessageObject> | React.ListState<MessageObjectWithIndex>
| React.MapState<MessageObject>, | React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
const objectConverter: React.StateItemConverter<MessageObject> = ( const objectConverter: React.StateItemConverter<MessageObjectWithIndex> = (
messageObject messageObject
) => { ) => {
return ObjectEntryView( return ObjectEntryView(
+31 -12
View File
@@ -1,6 +1,11 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import {
Chat,
MessageObject,
MessageObjectWithIndex,
} from "../../Model/chatModel";
import { getRawObjectIndex, stringToOptionTag } from "../../utility";
import { objectFilterInput, previousObjectSearches } from "../../Model/model"; import { objectFilterInput, previousObjectSearches } from "../../Model/model";
import { AllObjectsView } from "./allObjectsView"; import { AllObjectsView } from "./allObjectsView";
@@ -11,7 +16,6 @@ import { ObjectDetailModal } from "./objectDetailModal";
import { ObjectGridView } from "./objectGridView"; import { ObjectGridView } from "./objectGridView";
import { StatusView } from "./statusView"; import { StatusView } from "./statusView";
import { icons } from "../../icons"; import { icons } from "../../icons";
import { stringToOptionTag } from "../../utility";
import { translation } from "../../translations"; import { translation } from "../../translations";
export const viewTypes = { export const viewTypes = {
@@ -51,7 +55,7 @@ export function ObjectPane(chat: Chat) {
const resultText = React.createProxyState([appliedFilter, resultCount], () => const resultText = React.createProxyState([appliedFilter, resultCount], () =>
translation.searchTitleText(appliedFilter.value, resultCount.value) translation.searchTitleText(appliedFilter.value, resultCount.value)
); );
const showingMessageObjects = new React.MapState<MessageObject>(); const visibleMessageObjects = new React.MapState<MessageObjectWithIndex>();
const isFilterEmpty = React.createProxyState( const isFilterEmpty = React.createProxyState(
[appliedFilter], [appliedFilter],
() => appliedFilter.value == "" () => appliedFilter.value == ""
@@ -68,22 +72,22 @@ export function ObjectPane(chat: Chat) {
previousObjectSearches.add(appliedFilter.value); previousObjectSearches.add(appliedFilter.value);
const allObjects = [...chat.objects.value.values()]; const allObjects = [...chat.objects.value.values()];
allObjects.forEach((object, i) => { allObjects.forEach((messageObject, i) => {
const doesMatch = checkIfMatchesFilter(object); const doesMatch = checkIfMatchesFilter(messageObject);
if (doesMatch) { if (doesMatch) {
showingMessageObjects.set(object.id, object); visibleMessageObjects.set(messageObject.id, new MessageObjectWithIndex(messageObject));
} else { } else {
showingMessageObjects.remove(object.id); visibleMessageObjects.remove(messageObject.id);
} }
}); });
resultCount.value = showingMessageObjects.value.size; resultCount.value = visibleMessageObjects.value.size;
} }
chat.objects.handleAddition((messageObject) => { chat.objects.handleAddition((messageObject) => {
if (checkIfMatchesFilter(messageObject) == false) return; if (checkIfMatchesFilter(messageObject) == false) return;
showingMessageObjects.set(messageObject.id, messageObject); visibleMessageObjects.set(messageObject.id, new MessageObjectWithIndex(messageObject));
chat.objects.handleRemoval(messageObject, () => { chat.objects.handleRemoval(messageObject, () => {
showingMessageObjects.remove(messageObject.id); visibleMessageObjects.remove(messageObject.id);
}); });
}); });
@@ -122,6 +126,21 @@ export function ObjectPane(chat: Chat) {
applyFilter(); applyFilter();
// sorting
visibleMessageObjects.subscribe((visibleMessageObjects) => {
let indices = [...visibleMessageObjects.values()]
.map((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
return getRawObjectIndex(latest);
})
.sort();
visibleMessageObjects.forEach((messageObject) => {
const latest = chat.getMostRecentContent(messageObject);
messageObject.index.value = indices.indexOf(getRawObjectIndex(latest));
});
});
// view // view
const objectModal = React.createProxyState( const objectModal = React.createProxyState(
[chat.objects, selectedObject], [chat.objects, selectedObject],
@@ -154,7 +173,7 @@ export function ObjectPane(chat: Chat) {
return getViewFunction()( return getViewFunction()(
chat, chat,
showingMessageObjects, visibleMessageObjects,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
); );
@@ -238,7 +257,7 @@ export function ObjectPane(chat: Chat) {
{ObjectGridView( {ObjectGridView(
chat, chat,
showingMessageObjects, visibleMessageObjects,
selectedObject, selectedObject,
isShowingObjectModal isShowingObjectModal
)} )}
+2 -2
View File
@@ -1,6 +1,6 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { Chat, MessageObject } from "../../Model/chatModel"; import { Chat, MessageObject, MessageObjectWithIndex } from "../../Model/chatModel";
import { ObjectEntryView } from "./objectEntryView"; import { ObjectEntryView } from "./objectEntryView";
import { RenameView } from "../renameView"; import { RenameView } from "../renameView";
@@ -29,7 +29,7 @@ interface StatusData {
export function StatusView( export function StatusView(
chat: Chat, chat: Chat,
messageObjects: React.MapState<MessageObject>, messageObjects: React.MapState<MessageObjectWithIndex>,
selectedObject: React.State<MessageObject | undefined>, selectedObject: React.State<MessageObject | undefined>,
isShowingObjectModal: React.State<boolean> isShowingObjectModal: React.State<boolean>
) { ) {
+23 -2
View File
@@ -1,7 +1,6 @@
import * as React from "bloatless-react"; import * as React from "bloatless-react";
import { MessageObject } from "./Model/chatModel"; import { MessageObjectContent } from "./Model/chatModel";
import { ObjectEntryView } from "./Views/Objects/objectEntryView";
export const storageKeys = { export const storageKeys = {
viewType(id: string): string { viewType(id: string): string {
@@ -48,3 +47,25 @@ export const storageKeys = {
export const stringToOptionTag: React.StateItemConverter<string> = (value) => { export const stringToOptionTag: React.StateItemConverter<string> = (value) => {
return <option>{value}</option>; return <option>{value}</option>;
}; };
export function getRawObjectIndex(latest: MessageObjectContent): string {
// date
const dateString = latest.date || "0000-00-00";
const [year, month, date] = dateString.split("-")
// time
const timeString = latest.time || "00:00";
const [hour, minute] = timeString.split(":");
const hourInMinutes = parseInt(hour) * 60;
const minutesTotal = parseInt(minute) + hourInMinutes;
const paddedMinutes = minutesTotal.toString().padStart(4, "0")
// priority
const priority = latest.priority ?? 0;
const priorityInverse = 100 - priority;
const paddedPriority = priorityInverse.toString().padStart(3, "0");
// final
return `${year}${month}${date}${paddedMinutes}${paddedPriority}`;
}