TiddlyWiki / TiddlyWiki5

A self-contained JavaScript wiki for the browser, Node.js, AWS Lambda etc.
https://tiddlywiki.com/
Other
8.02k stars 1.19k forks source link

[IDEA] Should tm-close-tiddler (optionally) navigate to the previous tiddler? #7262

Open yaisog opened 1 year ago

yaisog commented 1 year ago

After tm-close-tiddler, the tiddler referenced in the current-tiddler field in $:/HistoryList is no longer in the story. That seems a bit contradictory. An easy solution would be to navigate back to the last tiddler in tv-history-list that is also in tv-story-list -- but only if the closed tiddler was the current-tiddler. If the last open tiddler was closed, clear current-tiddler. If tv-history-list and tv-story-list do not intersect, navigate to the tiddler either following or preceding the closed tiddler.

That would change the default behavior of the story, though, and I can already see some people running for their pitchforks. So maybe make that an option, via a parameter to the message?

yaisog commented 1 year ago

In WikiText, it might look a bit like this:

<$list filter="[all[current]match{$:/HistoryList!!current-tiddler}]">
    <$let previousItem={{{ [{$:/HistoryList}jsonindexes[]] :map[{$:/HistoryList}jsonget<currentTiddler>,[title]] :intersection[list<tv-story-list>] +[!match<currentTiddler>reverse[]first[]] :else[list<tv-story-list>before<currentTiddler>] :else[list<tv-story-list>after<currentTiddler>]" }}}>
        <$action-navigate $to=<<previousItem>> />
    </$let>
</$list>

where I wasn't really consistent with the source of the history list. 😊 Also, current-tiddler is not cleared when the story is empty, because somewhere in the back of my mind something's yelling "Never mess with $:/HistoryList!"

yaisog commented 1 year ago

Same goes for tm-delete-tiddler...?

pmario commented 1 year ago

IMO similar to: When closing, navigate to previous tiddler #2776 .. which has been closed lately because of a comment form Saq at Talk

Implementing anything like this is intricately tied with the work of opening up the core to be expressed more so in wikitext and thus hackable. In particular we need to provide affordances to replace the current JavaScript only hooks 1 with equivalent wikitext based affordances. This is a non-trivial amount of work. Parameterized transclusions are the first step in this direction.

Trying to address the expressed needs independently of implementing wikitext affordances for hooks would likely lead to two similar but conflicting mechanisms for customizing core behaviour.

yaisog commented 1 year ago

@pmario: Not only similar, but pretty much congruent. I did search before opening the issue, but only through open PRs...

It's unfortunate that @twMat was not able to garner enough developer support to get this (as a selectable option) into the core. The code was there and could have been made optionally activatable. My proposal of going back in history instead of up through the story is slightly different, but would probably yield similar behavior with the classic storyview.

My reason for opening this is different, though. I have created a single-tiddler storyview in order for everything to remain responsive with a large TW. That storyview shows the current-tiddler from $:/HistoryList. Without navigation after close or delete, this doesn't work. I, too, have overwritten the close and delete buttons, but it would be cleaner to have it in the code for the tm-messages.

Reading through #2776, I get the feeling that there are many out there who'd prefer an option for the changed behavior. Pity. I understand that people are loathe to implement things now in the core that they might have to re-do later in a parameterized transclusion version of it. That couldn't have been the reason 6 years ago, though.

Also, by checking if the closed tiddler is the current one, the code above gets rid of almost all possible issues with closing tiddlers from the Open sidebar. Only the case that the current tiddler is scrolled out of view and then closed via Open (I think it was mentioned by Jeremy) remains as a nuisance. Compare this to being annoyed nearly every time a tiddler is closed.

Maybe related, but does anyone know the history of this code in $:/core/modules/story.js:

Story.prototype.storyCloseTiddler = function(targetTitle) {
// TBD
};

Story.prototype.storyCloseAllTiddlers = function() {
// TBD
};
pmario commented 1 year ago

Maybe related, but does anyone know the history of this code in $:/core/modules/story.js:

Yes. ... IMO the main problem is, that there is no clear separation of concerns between several elements in the core. The story.js module should have handled those actions, but they are handled in the navigator.js code, most of them, that's why story.js is so empty.

The navigator-widget is the "main" authority which is responsible to handle all the tm-xx messages. see: navigator.js, because it adds all the event-listeners.

The widget defines the basic behaviour of navigation for the PageTemplate

So it defines the $:/StoryList and which $:/HistoryList state tiddlers it wants to use. Like so:

<$navigator story="$:/StoryList" history="$:/HistoryList" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>

It also defines the tv-story-list and tv-history-list variables in the .execute function., where it also initiates the this.stroy = new $tw.Story() object ... Like so.

/*
Compute the internal state of the widget
*/
NavigatorWidget.prototype.execute = function() {
    // Get our parameters
    this.storyTitle = this.getAttribute("story");
    this.historyTitle = this.getAttribute("history");
    this.setVariable("tv-story-list",this.storyTitle);
    this.setVariable("tv-history-list",this.historyTitle);
    this.story = new $tw.Story({
        wiki: this.wiki,
        storyTitle: this.storyTitle,
        historyTitle: this.historyTitle
    });
    // Construct the child widgets
    this.makeChildWidgets();
};

BUT then for eg: tm-close-tiddler it does all the work on its own.

// Close a specified tiddler
NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
    event = $tw.hooks.invokeHook("th-closing-tiddler",event);
    var title = event.param || event.tiddlerTitle,
        storyList = this.getStoryList();     // <-- it should be this.story.getStoryList()
    // Look for tiddlers with this title to close
    this.removeTitleFromStory(storyList,title);   
    this.saveStoryList(storyList);                 // <-- here too. the work is done in navigator.js
    return false;
};

eg: this.getStoryList() in navigator.js is implemented like so:

NavigatorWidget.prototype.getStoryList = function() {
    return this.storyTitle ? this.wiki.getTiddlerList(this.storyTitle) : null;
};

this.getStoryList() in story.js is implemented like so:

Story.prototype.getStoryList = function() {
    return this.wiki.getTiddlerList(this.storyTitle) || [];
};

There is a slight difference, because the navigator needs to check if this.storyTitle exists becuase it doesn't initialize a default value.

BUT the initialisation in the story.js uses a default value, so the code can be sure there is a valid this.storyTitle

So there clearly is an unnecessary duplication of code and it makes it impossible for other widgets to use new $tw.Story(options) since it does not contain the functions needed to actually manage a story.

IMO this should be fixed ...


There is an other widget, that also adds to the complexity of the history-handling. .. The list-widget, because it's responsible to trigger page-refresh if HistorList changes.

The list-widget in the PageTemplate should also be the authority for the "storyviews" like "classic, pop, zoomin" ... It gets the history="$:/HistoryList parameter.

This info is needed to trigger the animation cycle for the storyviews, if the history has been changed. also see: ListWidget.prototype.handleListChanges which is right below the link.

The storyview modules: classic.js, pop.js and zoomin.js are responsible for the story animations.


I hope, that's not too confusing.

yaisog commented 1 year ago

I hope, that's not too confusing.

Not at all. It helped that I've looked into this before, albeit with much less attention to the specifics you describe above. Thank you for taking the time to explain it. I am not completely sure, though, if that is an argument for or against change of the closing behavior. What you do argue is that the story handling itself should be fixed first. From the examples you show, I'd have to agree with that point.

yaisog commented 1 year ago

This is a point I wanted to make separately, hence a new comment: A similar concept that most users are familiar with are browser tabs, and opening links in new tabs. Browser tabs are akin to the Open sidebar. Now - at least with Firefox - when I close a tab that has been opened from another tab, the browser will go back to the previous tab, not the next one (unless you install an extension to override this). Firefox probably doesn't keep a history list, but rather assigns an opened from x property to the new tab, but the effect is very similar to going backwards through the tab display history when closing tabs. It has been that way since versions were in the 20s, I think. This might be the reason that many stumble over the TW way of doing things.

Yes, I am aware of the differences (e.g. classic storyview lets you scroll through tiddlers without changing the current one, which browser tabs cannot; the same tiddler can be "opened" multiple times from different source tiddlers, etc.). Nevertheless, my expectations on the closing behavior are based on what I am familiar with, while at the same time expecting that there be slight differences...

pmario commented 1 year ago

Thank you for taking the time to explain it. I am not completely sure, though, if that is an argument for or against change of the closing behaviour. What you do argue is that the story handling itself should be fixed first. From the examples you show, I'd have to agree with that point.

TLDR, I think you need to be more specific, what you expect and why. See my workflow description below. I am fine with the default behaviour. Probably because I did follow the development of TW from the beginning and I did help to define it.


I'm fine with the current behaviour of the "classic" stoyview.

I don't ever use a different view. If a page uses a different default setting I do change it back to classic. If that's not possible, I let the author know that I want to have "classic" story view. If they don't change it, I don't visit the page.

So the description below is about "classic" story view with the default settings from tiddlywiki.com

That's how I'm used to work with tiddlywiki.com. I know I could change the order how tiddlers are opened, for my own wikis, but then I would have to remember, which wiki has which settings. So I use the defaults. No change of behaviour needed.




yaisog commented 1 year ago

Thanks again, for this thorough description. I see that the current behavior makes sense for you (but also that your way of interacting with the TW maybe stems from exactly that behavior). No matter how much sense it makes to you, you'll have to admit that other people will do things differently. Often, in a tiddler with multiple links of interest, I would open one, read it, close it, open the next. It depends, though, how the text is structured - is it a list of links or are these links interspersed throughout the text copy (then I'd do it closer to your way).

Anyway, realizing that not everyone interacts the same way (and the comments in the previous issue show that there is a significant number of "deviants"), I'd propose to make any changes optional via a switch in the control panel. To me, it is very much akin to the preference of opening new tiddlers above or below the story. You like it one way, but others do not - that's why that preference is in there.

I also don't use classic much, and if I used it I would not open many tiddlers at the same time. In a large wiki with complex tiddler structures, this can really slow things down unbearably.

My proposal for change is two-part:

  1. After your comments how all the messages are handled by the navigator widget, I propose to put a configurable message catcher just inside the navigator in $:/core/ui/PageTemplate. To be flexible, it would be implemented with the $genesis widget. Its attributes could thus be set via filters and it would be able to intercept a variable number of messages. This should be exactly what $genesis was designed for. Any overrides for actions would be controlled by tiddlers with a special tag like $:/tags/PageMessageOverride. A tiddler would contain one message to override and the actions to override it with.
  2. Create override tiddlers for tm-close-tiddler and tm-delete-tiddler. Both would check the control panel setting for handling the closing of tiddlers, and either simply pass the original message and its parameters (default), or do some extra handling, e.g. like in post 2. The details of that handling would be up for debate. Users or plugins could override the handling with their own.

This would also enable adding additional actions on tm-navigate events, as is requested on TWTalk every now and then. Shipping the two overrides from 2. will also show users how to pass the original messages correctly.

Advantages:

Open questions:

pmario commented 1 year ago

No matter how much sense it makes to you, you'll have to admit that other people will do things differently. Often, in a tiddler with multiple links of interest, I would open one, read it, close it, open the next. It depends, though, how the text is structured - is it a list of links or are these links interspersed throughout the text copy (then I'd do it closer to your way).

So that's a "workflow" which is important for you.

That makes sense. I usually never scroll .. so I didn't see that.

To me, it is very much akin to the preference of opening new tiddlers above or below the story. You like it one way, but others do not

Yes ... there is a setting, but I think it is way to slow to change it. ... That's one reason, why I use the defaults. .. I don't want to change settings, because it's way to slow. We have CTRL click, but there could be more.

I also don't use classic much, and if I used it I would not open many tiddlers at the same time. In a large wiki with complex tiddler structures, this can really slow things down unbearably.

I think that's a different problem with slow filters and slow back-references. There are wikis out there with 30 000 tiddlers that work well ... but that's way to off-topic

  1. After your comments how all the messages are handled by the navigator widget, I propose to put a configurable message catcher just inside the navigator in $:/core/ui/PageTemplate. To be flexible, it would be implemented with the $genesis widget.

I would need to have a closer look if I could think about an implementation with the $genesis widget. ... But in general it seems to be the way, which Jeremy wants to go

yaisog commented 1 year ago

I would need to have a closer look if I could think about an implementation with the $genesis widget

If you want to, I'm not going to stop you, of course. But you could let me try first, and then "optimize" my proposal. Since I do have a direct need for this, I'll do it anyway, and it may not be efficient if we both do it simultaneously (even though I usually learn something in the process)...

I would also like to hear @Jermolene's thoughts on this. If he's gonna shoot it down immediately, I might not make it as pretty as I would otherwise... 😉

twMat commented 1 year ago

@yaisog , I am very happy to see you push for this (and with superior a understanding of the core compared to me!) but also for the mere confirmation from yet one more individual that this UX idea is sensible and there is a need for it.

yaisog commented 1 year ago

This turned out to be simpler than I thought.

We only have to insert this line just inside the $navigator widget in $:/mwi/ui/PageTemplate:

<$genesis $type="$messagecatcher"
          $names="[tag[$:/tags/PageTemplateMessageHandler]!is[draft]has[message]get[message]addprefix[$]]"
          $values="[tag[$:/tags/PageTemplateMessageHandler]!is[draft]has[message]get[text]]">

and the corresponding closing tag. Now we can create a tiddler with the tag $:/tags/PageTemplateMessageHandler like this

title: $:/yaisog/ui/PageTemplate/tm-notify
tags: $:/tags/PageTemplateMessageHandler
message: tm-notify

<$genesis $type="$action-sendmessage" 
          $$message=<<event-type>>
      $$param={{{ [<event-param>!is[blank]else<event-tiddlerTitle>] }}}
      $names="[enlist<list-event-paramObject>]"
      $values="[enlist<list-event-paramObject>addprefix[event-paramObject-]getvariable[]]" />

This will pass the original message though, including param and the whole paramObject hashmap, here as an example for tm-notify. I could now go ahead and e.g. make changes to the paramObject variables by adding the corresponding WikiText code to the tiddler.

In the case of tm-close-tiddler and tm-delete-tiddler I don't have to worry about the paramObject and thus do not need $genesis:

title: $:/yaisog/ui/PageTemplate/tm-close-tiddler
tags: $:/tags/PageTemplateMessageHandler
message: tm-close-tiddler

<$let targetTiddler={{{ [<event-param>!is[blank]else<event-tiddlerTitle>] }}} history={{{ [<tv-history-list>get[text]] }}}>
    <$list filter="[<tv-history-list>get[current-tiddler]match<targetTiddler>">
        <$let previousItem={{{ [<history>jsonindexes[]] :map[<history>jsonget<currentTiddler>,[title]] :intersection[list<tv-story-list>] +[!match<targetTiddler>reverse[]first[]] :else[list<tv-story-list>before<targetTiddler>] :else[list<tv-story-list>after<targetTiddler>]" }}}>
            <$action-navigate $to=<<previousItem>> />
        </$let>
    </$list>
    <$action-sendmessage $message=<<event-type>> $param=<<targetTiddler>> />
</$let>

This basically adds the going-back-to-the-previous-tiddler operation (or the tiddler above if no tiddler from the history is open in the story) from post 2 before passing the message along. It would be trivial to wrap this in a check for a control panel setting whether to use this. The tiddler for tm-delete-tiddler would look identical except for the title and message fields.

PS: Like I said over on TWTalk: I for one welcome our new genesis overlords. 😄

pmario commented 1 year ago

This turned out to be simpler than I thought.

yaisog commented 1 year ago

Oh, sorry. You have to send a message to see how it works.

Try creating a tiddler "Tiddler 1":

Button Clicked with one=<<one>> and two=<<two>>.

and a tiddler "Tiddler 2":

<$button actions="""<$action-sendmessage $message="tm-notify" $param="Tiddler 1" one="1" two="2" />""">Click</$button>

This should display a notification which uses the hashmap variables when you click on the button in Tiddler 2.

If I wasn't so giddy to get this out, I might have prepared a JSON tiddler bundle for importing... 🙄

Also, in the example in my previous post, I got the message in the "close" tiddler wrong. That is corrected now.

yaisog commented 1 year ago

I don't want to get too far ahead of myself, but by the same method one could add a generic $eventcatcher to the page template which uses another tag to collect events to listen to.

This could be used e.g. for displaying a context menu by binding the corresponding mouse event. The only drawback here is that all catchable events would have to share the same selector, and the selectors for multiple events would have to be aggregated for the corresponding $eventcatcher attribute. In principle, each so-defined action could check if its own selector matches, but $eventviewer does not pass information about which selector from the selector attribute triggered the action.

pmario commented 1 year ago

Sorry for my ignorance. I did create the message example tiddler too. It shows the message. But how does title: $:/yaisog/ui/PageTemplate/tm-notify change it. I can not see a difference.

Sorry -- again. What exactly do I need to click to see a different behaviour for the tm-close-tiddler message between tiddlywiki.com and the new "messagecatcher"

The only thing I can see is that it creates an "animation stutter if a tiddler is closed at the top of the story river" and there is a tiddler below it. Can be best seen if animation time is 2000 or higher.

pmario commented 1 year ago

I found a problem in the code snippet. The following snippet does not show an error in the action-log

title: $:/yaisog/ui/PageTemplate/tm-close-tiddler
tags: $:/tags/PageTemplateMessageHandler
message: tm-close-tiddler

<$let targetTiddler={{{ [<event-param>!is[blank]else<event-tiddlerTitle>] }}} history={{{ [<tv-history-list>get[text]] }}}>
    <$list filter="[<tv-history-list>get[current-tiddler]match<targetTiddler>]"> <!-- the last closing ] bracket was missing ->
        <$let previousItem={{{ [<history>jsonindexes[]] :map[<history>jsonget<currentTiddler>,[title]] :intersection[list<tv-story-list>] +[!match<targetTiddler>reverse[]first[]] :else[list<tv-story-list>before<targetTiddler>] :else[list<tv-story-list>after<targetTiddler>] }}}>
            <$action-navigate $to=<<previousItem>> />
<$action-log/>   <!-- your code snippet shows a problem with the currentTiddler variable -->
        </$let>
    </$list>
    <$action-sendmessage $message=<<event-type>> $param=<<targetTiddler>> />
</$let>
yaisog commented 1 year ago

But how does $:/yaisog/ui/PageTemplate/tm-notify change it. I can not see a difference.

Exactly! 😁 That example was just to show how to pass everything through unchanged, i.e. the fallback. Any changes you want have still to be put in there. You could e.g. change this line:

$values="[enlist<list-event-paramObject>addprefix[event-paramObject-]getvariable[]add[10]]" />

Note the add[10] near the end. Now the notification will read "one=11 and two=12". You could also change the param, i.e. the tiddler that is shown, based on some condition.

The following snippet does not show an error in the action-log.

I'm not quite sure what you mean. The currentTiddler is not defined since we're in the page template outside the story $list. Its use in the code example is only inside :map where it gets a different meaning...

pmario commented 1 year ago

See the $list filter in this snippet and compare it with your snippet. Yours creates a error message for the currentTiddler if the $action-log is added.

The snippet below works, but it may change the behaviour of the function since there is a valid jsonget<currentTiddler>, now.

<$let targetTiddler={{{ [<event-param>!is[blank]else<event-tiddlerTitle>] }}} history={{{ [<tv-history-list>get[text]] }}}>
    <$list filter="[<tv-history-list>get[current-tiddler]match<targetTiddler>]"> <!-- the last closing ] bracket was missing ->
yaisog commented 1 year ago

I got distracted and didn't come back to this still open discussion.

@pmario: You did find a typo in the filter expression. Correcting it made it actually work correctly. Thank you.

I feel that we'll never get the necessary changes into the NavigatorWidget (i.e. NavigatorWidget.prototype.handleCloseTiddlerEvent function), especially if there's a check of a ControlPanel option involved. So how about then we integrate the customizable message interceptor as outlined above into the PageTemplate? Especially if combined with $genesis, it will not even add an element to the DOM in the default configuration when no custom MessageHandlers are defined, if done right. Then, with the infrastructure in place, the handling of back-in-history navigation upon close / delete -- among many others -- could be outsourced to a plugin, if maintainers don't want it in the core. Isn't this a step into the direction that Saq wanted to go? The WikiText equivalent of JavaScript hooks? I don't think it would be impossible to make it optional to pass along the original message, via a field in the custom MessageHandler, to make it less error-prone.

@Jermolene @saqimtiaz: Thoughts?

saqimtiaz commented 1 year ago

So how about then we integrate the customizable message interceptor as outlined above into the PageTemplate? Especially if combined with $genesis, it will not even add an element to the DOM in the default configuration when no custom MessageHandlers are defined, if done right.

I have been investigating along similar lines to allow the MessageCatcher and EventCatcher widgets to be used within the page template without needing to overwrite the shadow tiddlers. There are a few aspects of this that need to be considered. Firstly, it isn't necessarily clear where users might want to wrap the catcher widgets, it could just as easily be just around the sidebar as around the entire page template.

Secondly, the best architectural approach isn't necessarily clear at this time. I have been considering a few approaches for this, all of which have their own caveats.

The first is similar to what you are proposing here using $genesis. However, while this works well for the MessageCatcher widget which only needs key value pairs to be assigned as attributes, the EventCatcher has more attributes not all of which are common for the events captured and thus a single widget cannot necessarily be used to capture multiple events.

Another approach would be define the catcher widgets to be used in the page template via tagged tiddlers and create a widget for each such tagged tiddlers. However, this would lead to a variable number of DOM nodes being injected into the page template and ideally the DOM structure should not change at all with the injection of catcher widgets, let alone change in a variable manner.

Lastly, we could extend or have a widget similar to $importvariables that can import widget definitions defined in tiddlers into a template. However, the issue with creating extra DOM nodes would remain, and it might be that this cannot be avoided.

Isn't this a step into the direction that Saq wanted to go? The WikiText equivalent of JavaScript hooks?

The long term goal is to deprecate the $navigator widget and move the entire logic for navigation into wikitext, much as Jeremy has done in the TW pub work. This will also require providing a wikitext affordance in place of the current JavaScript hooks provided by $navigator. However, the risk we face by introducing a wikitext based hooks mechanism in advance of the navigator refactoring to wikitext is that the two may not be consistent.

In closing, I think this is definitely something we need to work towards and it deserves further exploration. If we don't already have one, we should create an issue for the refactoring of $navigator into wikitext.

pmario commented 1 year ago

However, the risk we face by introducing a wikitext based hooks mechanism in advance of the navigator refactoring to wikitext is that the two may not be consistent.

In closing, I think this is definitely something we need to work towards and it deserves further exploration.

I also have a big concern about users manipulating $:/StoryList and $:/HistoryList on their own. At the moment the navigator-widget watches a whole bunch of extra configurations, that are important to also work after installing a pluign.

But if the plugin does directly manipulate current-tiddler in the $:/HustoryList, without setting those variables right, the navigation mechanism will be broken.

My second concern is that the whole handling will be very brittle, since it's way to easy to create endless loops if user-defined actions are called with "hook-replacements".

Just my thoughts. ...


I do have a branch that removes all the "story-related" functions from the navigator and moves them to the "story.js" module. Which should give us a better separation of concerns.

This should make it possible for plugin authors to manage as many stories as they want without the need of the navigator widget, if they which to do so. ... BUT with all the existing navigation configuration variables observed and respected.

For backwards compatibility reasons it's needed that all the functions defined in navigator.js keep their function-signature. ... Which makes the whole process cumbersome. ... Nothing to share yet.

yaisog commented 1 year ago

EventCatcher has more attributes not all of which are common for the events captured and thus a single widget cannot necessarily be used to capture multiple events.

Hi @saqimtiaz, I've run across this also. Catching multiple (individually configured) events would require to concatenate their selectors and upon firing match the selector again and forward to the correct event(s), in WikiText. It would be less messy to extend the $eventcatcher in some way for each event to have its own selector and matchSelector attributes. Though I don't know how that would work.

How are keyboard shortcuts implemented with respect to additional DOM nodes? Does each shortcut create its own $keyboard widget? I don't see too much of a problem with variable numbers of DOM elements. Isn't that the whole concept of TW?

@pmario: Users can already directly manipulate the Story and History Lists. My example uses the $action-navigate widget to explicitly avoid messing directly with these lists. Since I think that intercepting messages is a topic for somewhat advanced users, I believe we could get away with a corresponding warning text in the description of the mechanism. A loop detector for these hooks might be a good idea, though.

I'm not sure we should shy away from useful features only because they could be misused. That is already easily done, as I have painfully experienced. But each time this happened I learned something new about TW, so in the end it was worth it. 😉

Jermolene commented 1 year ago

I've no objection to fixing the OP; I think the reason that #2776 was closed was just because we didn't have a viable implementation.

yaisog commented 1 year ago

Another approach would be define the catcher widgets to be used in the page template via tagged tiddlers and create a widget for each such tagged tiddlers.

Is this something that is possible in WikiText, @saqimtiaz? How would you call $genesis a variable number of times?

yaisog commented 1 year ago

I have another use for the configurable message catcher in the PageTemplate: With this it would be possible to add actions upon tm-save-tiddler, such as making an in-wiki backup (preferrably with the new makepatches filter to save space). Otherwise one would have to edit $:/core/ui/Buttons/save (for the button) and $:/core/ui/EditTemplate (for the keyboard shortcut) to get additional actions in.

I will make a draft PR based on the above discussed code. This will not include an $eventcatcher as the path to its configurability via tagged tiddlers is not clear at the moment. This could easily be independently added later.

Jermolene commented 1 year ago

I have another use for the configurable message catcher in the PageTemplate: With this it would be possible to add actions upon tm-save-tiddler, such as making an in-wiki backup (preferrably with the new makepatches filter to save space). Otherwise one would have to edit $:/core/ui/Buttons/save (for the button) and $:/core/ui/EditTemplate (for the keyboard shortcut) to get additional actions in.

At the moment the <$navigator> widget absorbs tm-save-tiddler messages, making them invisible to ancestor widgets. We could get around it by inserting a dynamic, tag-driven message catcher immediately inside the <$navigator> widget.

I will make a draft PR based on the above discussed code. This will not include an $eventcatcher as the path to its configurability via tagged tiddlers is not clear at the moment. This could easily be independently added later.