Examples for SettingsService

Do you have a simple example of how this looks with a Settings Tab class?
Sing the tab will already extend PluginSettingTab it cannot be a service, how will it get context to pull the SettingsService out from the container?

The idea is that different services have their own settings which together form the overall plugin settings, and the same for the tabs.  Each service performs its own useSettings() call and gets the same SettingsService, but the defaults and types from each are combined.
For the settings UI, each service does useSettingsTab() and adds a showSettings() method to actually create the settings UI via the builder.
So there is no PluginSettingTab - that's handled by the builder service (SettingsTabBuilder).  An example from some work in progress for one of my plugins:
class GlobalHotkeys extends Service {
    settingsTab   = useSettingsTab(this);
    settings      = useSettings(
        this,
        {globalHotkeys: [] as CmdCfg[]},
        ({globalHotkeys: g}) => this.updateHotkeys(g)
    );
    showSettings() {
        const tab = this.settingsTab, {settings} = this;
        tab.field().setName("Global Hotkeys").setHeading();
        const addNew = tab.field()
            .setName("Add new Command").addButton(b => b
                .setButtonText("Add command").setCta().onClick(async () => {
                    // ...
                    await settings.update(({globalHotkeys: g}) => {
                        g.push(cmd);
                    })
                    new CommandField(this, cmd, addNew.settingEl);
                })
            );
        this.globalHotkeys.forEach(c => new CommandField(this, c, addNew.settingEl));
        tab.field();
    }
}

Basically, there is no one place where you define all your plugins or settings tab UI - it's distributed among the services.  The order in which the services are initialized determines the order of the settings in the plugin's (auto-generated) settings tab.
This allows you to concentrate everything for a given feature in one place.
Since the plugin itself is also effectively a service, you can also have it define defaults and UI via the same method; the placement in the list will be determined by where useSettingsTab occurs in the setup, e.g.:
export default class MyPlugin extends Plugin {
    use = use.plugin(this);
    someService = this.use(SomeService);
    settingsTab = useSettingsTab(this, ...);
    otherService = this.use(OtherService);
}

In this example, any settings defined by SomeService will appear first in the plugin's settings, followed by those defined by the plugin class' showSettings() method, followed by any defined by OtherService.  So you can organize the settings groups any way you like, and in effect the PluginSettingTab gets generated for you.

By the way, in case it's not clear from the above, there is a single namespace for the plugin settings, but it's the intersection of all the individual types defined by the services.  So service A might use {serviceASetting1, serviceASetting2}, and service B might have {globalHotKeys}.  As long as the names don't overlap (or if they do, are a shared setting), it's fine - all the settings are still saved in the normal way, as a combined {serviceASetting1, serviceASetting2, globalHotkeys} type (with combined defaults, too).
But this way, each service only needs to know about its own types and defaults, without needing to manually combine them into a single set of types and defaults for the plugin as a whole.

Oh, also... to answer your original question, a class does not have to extend Service (or use use.service) in order to be able to look things up.  It just needs a use context, which you can pass into its constructor.  Or, it can capture use.this if it has a zero-argument constructor, e.g.:
class MyPlugin extends Plugin {
    use = use.plugin(this);
    onload() {
        this.addSettingTab(this.use(MyPluginSettings));
    }
}

class MyPluginSettings extends PluginSettingTab {
    settings = use(SomeService)
    constructor() {
        super(use(App), use(MyPlugin));
    }
}

Basically, any object that is created via a use() call can call use() to get other services.  If that object needs to call it after the constructor is finished, it needs to save it via this.use = use.this (or use = use.this in the class body).
The only reason that Plugin and Services are different on this point is that 1) Plugin is constructed by Obsidian, so there isn't a use() call active (and there is special setup to be done as well), and 2) Services are Components that get registered to load() and unload() with the plugin.
So anything that isn't a component that loads/unloads with the plugin does not have to be a Service.  You can also use() anything that has a zero-argument constructor, and it can call use() in the constructor (and any initializers), and it can save use.this (via constructor or initializer) to keep a reference to the context.

Thanks for the detailed response! I will re-read it again later today and look at how I have my plugin structured. Currently my settings are generated by a json configuration file that is processed to generate the UI dynamically. I will look to see how to break it up as the UI creation has a lot of repedative code that I was trying to avoid.
I should be able to make the generation seperate and then have a json file per service to keep it cleaner.
If you want I will make a PR in the next week or so to make this part of the documentation for this library.
I had tried to implement a DI in the past to break up my app but I just do not have enough working experience with typescript to be effective so this project is great as it gets me moving faster. Just have to refactor my code to the service model a bit. I'm sure there would be better ways but I have the rendering working locally now using your framework. Took a bit to sort out how to get the context though for the post code block rendering.
I'll make a PR for my plugin so you can see and comment on my mistakes if you are interested. Thank you for putting all this together.

Don't worry about the doc PR - the settings API (both the storage and UI parts) are too unstable at the moment, as I have not actually published any plugin updates using them.  I'm still exploring the use of them to see if the APIs are actually good.    The final API probably won't change a ton, but...  I don't feel it's stable enough to document at the moment.
You can ping me on your plugin PR, though, and I'll have a look.
I'm going to leave this issue open though as a reminder for me to write some documentation from this eventually.  :wink:

Oh, now I remembered one of the specific things that's most likely to change when useSettings/SettingsService finalizes API is that I may want to require settings to be immutable.  The current implementation is based on JSON comparison of the overall settings object rather than equality checking, which is super convenient in some ways but bad for others (e.g. if I rip out Events as the basis of distribution).  This is relevant to the API in that I would like to be able to convert the settings "data source" to be something you can functionally derive parts of it as properties, as in FRP systems.
What I mean is, it should be possible to take a settings object, give it two functions (an accessor and mutator for some aspect of settings) and then get a new "subsetting" with the same ability to observe changes and the like.  This would make complex settings UI easier if you have settings that need sub-dialogs to pop up with more settings.
Anyway, all of that is hard to do in the current setup - each subsetting would need its own Events instance at present.  I'm thinking about using @preact/signals-core instead, but it has the problem that signals always have an initial value, and Obsidian plugin settings don't have a value until they're loaded from disk...  which can't happen till plugin load, which screws up the necessary initialization order of services.  (I really wish Obsidian would just load the plugin data automatically before instantiating the plugin instance... it'd save so many headaches.)
So, yeah, the biggest holdup to finalizing the settings API is having a clean way of creating monitorable value streams without needing to write my own rxjs replacement, too...  though my local copy of ophidian/core has a draft or two of such.  :wink:  The new html module I'm working on in core right now is a redom-inspired Obsidian-specific HTML framework for use w/JSX, and I want to support binding it to some kind of value streams as well.
Unfortunately most tiny FRP libs seem to lack critical features somewhere:

Preact Signals lack the ability to have a signal with a delayed initial value (also doesn't have on-demand upstream pull but I can extend it to add that)
Callbags would be fantastic if they weren't all CommonJS modules using a calling convention that's essentially impossible to write code in Typescript for without constantly casting things.
Flyd doesn't do lazy upstreams and I can't hack it in without using proxies, getting a PR accepted (seems unlikely in this stage of its development), or just forking it. (Also its extensions are mostly CommonJS and lacking in typings.)  Oh, and though you can technically have a stream without an initial value, you can still read the nonexistent initial value, which is the thing I want to avoid for settings.

And the big ones are, well, big.  As in bigger than many Obsidian plugins' entire built main.js files.  most.js's minified code is larger than the source of my drafts for a tiny FRP, including lots of doc comments.  :grin:  (And rxjs is an order of magnitude larger, bigger than most Obsidian plugins.)
So if you happen to know of a good tiny FRP lib with decent performance and typings, that can do lazy, on-demand subscriptions and value streams with no initial value, packaged as ES modules and implemented as operator functions so it can be tree-shaken down to what a given plugin needs... please do share.  As much fun as I have writing draft FRP libs, getting them production-ready with docs and tests and such is more of a chore.  :wink:
If I don't find one, my likely next approach is to just bail on delayed-start as part of the FRP framework itself, and use Promise<Signal<T>> as SettingService's main event source, and augmenting Preact signals with the other bits Ophidian needs for general-purpose FRP and HTML rendering.  This won't likely change useSettings(), though, except that setting mutators will have to return new objects instead of mutating in place.  But some direct access stuff for SettingsService might change, and I might need to make it so that the PluginSettingTab doesn't get registered with Obsidian until after the SettingService finishes the data load.

This is where I know I am going the wrong way. I wanted to move the rendering logic to a separate service and then have the QueryRenderChild added as child of the  MarkdownPostProcessorContext. That class needs to extend MarkdownRenderChild.
I tried to get the use functions to load the object and not pass them through but kept on getting no context errors. Assing it directly works but looks like it is not cleaning it self up when pages load so need to look at how all the unloads work.
MarkdownRenderChild

Yeah, one thing there is that you don't want Service for things that aren't singletons you want to have hang around for the life of the plugin being loaded.  That's what inheriting from Service or using use.service() does -- make it load() and unload() with the Bootloader, which in turn is tied to the Plugin.
Second, you don't have to fork context to create things if you just want them to have a context.  You can just pass the context as a constructor argument, or send in a Useful thing.  That is, like this:
class AThing {
    use: Context
    constructor(ctx: Useful = use.this) {
        this.use = ctx.use;
    }
}

Now AThing will discover its own context when created by use(), but you can also create it manually by passing it any other object with a use property.  (e.g. new AThing(this) if this is a service or plugin or another Useful thing - i.e. a thing with a use: Context property.
You should use this approach for your render child stuff: just keep your existing Component subclasses but add a constructor argument you can pass the context into.  No need to fork or use services for components like this -- the examples in to-use of forking for requests are intended for a web server architecture where lots of different components might need to be request-specific and live and die by that request.  Per-request singletons, as it were.
But Obsidian doesn't have anything like that, just stuff like renderChild where it's not really a new context - just a thing that lives in the existing context and doesn't have any new, context-specific singletons that need to be shared among a bunch of things.
Another tip -- if you want to simplify stuff like access to Workspace, you can just do stuff like this in your main.ts:
use.def(Workspace, () =>use(Plugin).app.workspace);

And then you can just this.use(Workspace).on(...) and the like.  Or set ws = this.use(Workspace) as an instance property or whatever.

Come to think of it you can use use.def(Workspace, () =>use(App).workspace); too, since Ophidian now supplies a use.def for App as well.  (Honestly I'm thinking of adding an app export to Ophidian so that you can just import app anywhere you need it.)

ok, I just played around with something similar where I passed the service into the render child that extends MarkdownRenderChild. From that I called use off that service and got the instances of the classes I needed.
I tried to just use 'use' off the class via the base functionality of to-use but it kept complaining there was no context, which I know there was as the parent class definitely had it and was able to find the services.

Yeah, I thought I was clear on the distinction in the to-use docs, but maybe I wasn't:

Singletons created by to-use get the context automatically
Non-singletons need to be given a context so they can look up the singletons with it

That's what the Useful interface is for: the idea is that you can make a generic class or function that accepts any Useful object to get context from, without needing to know anything else about that object.
There's really no such thing as a "parent" class in to-use: just a context you can get configuration and singletons from.  If you have more than one of a thing and they're not scoped to some sort of execution context (like a web request), it's not something you'd look up via use().
Take for example PerWindowComponent in Ophidian.  PerWindowComponent is not a singleton or a service - it takes a context object as its first constructor parameter, and is created by a WindowManager service.  Code that needs to get a per window component ask the WindowManager, which then makes one or returns an existing one.  This is a handy approach when you have more than one of a thing, but they are still well-known in some way (i.e. as the instance of a thing "for" a particular window or whatever).
I wouldn't take that approach with a renderChild, though, because they're disposable one-offs, not well-known instances.  I jsut bring it up to show you there are many ways to manage things between "one-off with a context" and "total singleton".
If you have any suggestions on how to clear this up in the to-use docs, I would appreciate it.  I recall briefly referencing some of this stuff in it, but I was mostly focused on singletons providing services rather than classes that consume services but don't provide them.

ok, so one the plugin is set in the global container via use = use.plugin(this); calls to this.use will be using the global context/plugin context and all services are singletons in this container, correct?

Yep.  In to-use terms, it's just the plugin context, as the global context can't be used except to define defaults.  But from the point of view of everything in the plugin, it's definitely "global" in that sense.  In services.ts, it's also captured as rootCtx, and you can get access to it by calling getContext() with an object that might have a .use property.  If the passed in object doesn't have a use property and the plugin has been initialized, it returns the root (plugin) context.
Sorry this stuff isn't documented, but it's very much in motion -- I think I only added getContext() a month ago.

The returned Logger class will be independent in this case and it does not need any context as the parent class (LoggingService) which is the singleton handles it all.

Yeah, if an object doesn't use any other singletons it doesn't need a context.

For the rendering approach, in plugin I set a private property to the QueryRendererV2Service by using this.queryRendererService = this.use(QueryRendererV2Service); This would mean it is now in the context for the plugin and avaliable for services. In this case it is not really used by other classes

Yep.  You can also just call this.use(Whatever) in the plugin onload() without keeping a reference to it, if the service just does its own thing and you don't need to talk to it from the plugin.
And you may not even need to do that much, see below...

So reading through what you have said instead of the service being passed, I can pass the context that QueryRendererV2Service has to the child objects? So instead of passing the service over via this I should pass this.use which should be the Context object and from that I can get the singletons already registered in the plugins context.

Yes.  Exactly.  This lets you make things more loosely-coupled, as the parent doesn't have to "spoon feed" the child everything it needs.  In fact, you can write things the other way around, by making the child depend on the renderer service, instead of needing the service to create the child.
That is, you could just register a postprocessor that creates an instance of QueryRenderChildV2 and gives it a context, and then lets it look up the render service from there.  At which point the plugin would not need to create the rendering service at all!
That's the true freedom of dependency injection - it lets you work "bottom up" instead of "top down".  By default Obsidian architecture is sort of paternalistic, you have parents needing to know all their children's business and manage their lives.  In the Ophidian model, you just let the kids do their own thing, and they have a context they can call on for whatever shared resources they need -- without the parents needing to know or care about the details.
In the limit case, an Ophidian based plugin need not do anything except kickstart any services that represent user-visible features, and the services shouldn't need to reference the plugin except to access Obsidian plugin-level APIs (like view, postprocessor and command registration), and thus only use the raw Plugin interface without needing to import the plugin class from main.
The ideal really is that the plugin can import services or utility classes and depend on what features they have, but the services and utility classes should never need to depend on the plugin except as an access point for those plugin APIs (or as a place to getContext() from, I suppose).

This commit actually showcases a bit how some of the above is supposed to work, actually:
https://github.com/ophidian-lib/core/commit/03dd418c9c1761fb5392c62c052dc74fb3d750d1#diff-5536dabb3779843c6bc44bccbbbf02dc58b5c7fb4071b74f933a52119f52ce3eR46
If you look at how useSettings is implemented, it takes an owner argument, but doesn't do anything with it except use it to register an event and get the context (and it falls back to the root context if the owner doesn't have one).  It then does stuff with the SettingsManager behind the scenes.  This is an example of how you can create nice APIs that don't require explicit service management.  If you useSettings() the settings service comes along for the ride, but you don't have to create it, put it in a property, remember what property you put it on, etc. etc.  All you care about is that the return value of useSettings() has onChange() and update() methods.
In the same way, you could define a function like, "createQueryRenderChild()" or something, that takes an owner plus any needed parameters, and do the same thing without needing the consuming component to know anything about the underlying details.  Or you can just include an owner as a class constructor argument.  Or heck, you can just call getContext(null) and get the plugin context as long as the plugin constructor has already run.
When I was first writing Ophidian I thought it might be useful to have child use() contexts for some things...  but the more experience I get the more I see those are extreme specialty cases.  Like for example, I have considered doing some note indexing stuff where a note would get a context to look up computed field data.  For any version of a note, there is always one answer to a question like, "what tags does this have" or "does this link to note X".  So a context where you're looking up functions for computing those things makes sense and is a valid reason to fork contexts.
But that's an extreme special case compared to normal plugin development.
Another possibility is that if you have something like a remote login connection to a database or something, and you don't want to cache things across connections, you want clean setup each time, so you want to have "per-connection" singletons, then that's another place where forking makes sense - any components that use() the connection would then be scoped there.  The tricky bit is that they couldn't be Services unless the connection had its own Bootloader so as to shut down when the connection unloaded.  But you could do something like that, certainly.
Anyway, these two examples are far less common than I thought forking would be when I did the initial design and wrote to-use.  That's why I've recently loosened up and added getContext(), as it makes life a lot easier in the extremely common case where there will only ever be one context.

ok, I managed to wrap my head around the settings and got a second settings tab up and running for some parts. Will look at making a custom SettingsTabBuilder that will use the JSON based configuration to reduce the noise creating all the text, toggles, buttons etc. Will let you know when I have it done.

This commit has the initial implementation. While doing it I noticed a bit of duplication around the value management as the class has the running value and then you have defaults. This may be ok but just wanted to see if I missed something obvious.
https://github.com/sytone/obsidian-queryallthethings/pull/4/commits/fa4447d4eb679d626d6b67a6c585b0850f6471e7

I'm a bit confused about the rewritten builder.  What does it do differently than the Ophidian one?
With regard to the value duplication, the intended use is that you use the applySettings callback (arg 3 of useSettings()) to do any settings-dependent setup, instead of using defaults first and then changing them later, or waiting for the data load in onload.  In practice, useSettingsTab is broken because it should 1) wait for the settings to load before registering the settings tab, and 2) pass the settings values along to the showSettings/hideSettings methods.  I think this would streamline things, as there would only be one place to apply settings (the onChange callback) and one place to change them (in the UI created by showSettings).
What do you think?
(Bear in mind, btw, that at this point I only have one (draft) plugin doing anything with settings at all so you are working with literally the least stable part of Ophidian that is stable enough to be checked into git at all.  :wink:)
Anyway, based on your feedback so far, my thoughts are that I should change Ophidian's SettingsTabBuilder to not register the tab until settings are available, and expose the settings via an auto-updated data property so show/hide settings can access it
I don't think this would break anything, but it should allow a single source of truth and updates for each settings consumer, as they will be guaranteed not to receive data callbacks (or show/hide settings callbacks) until the data is available.

Ok, I've fixed some things with settings.  The settings service now has a .current property that you can read while creating settings UI.  It's not guaranteed to be non-null, though, so you still need the applySettings callback in useSettings to actually apply the settings (as opposed to displaying them in showSettings).
It's also not using events under the hood any more, and you can now return a replacement value from an update() callback instead of modifying in-place.

I'm a bit confused about the rewritten builder. What does it do differently than the Ophidian one?

I had not checked in. It now has helpers so my settings are more consistent and I do not have to repeat the setup and classes. Probably a better way to do it but playing around with this is helping me learn how it works better. I do not have a good strong skill base in Typescript/JavaScript and the ecosystem.

With regard to the value duplication, the intended use is that you use the applySettings callback (arg 3 of useSettings()) to do any settings-dependent setup, instead of using defaults first and then changing them later, or waiting for the data load in onload. In practice, useSettingsTab is broken because it should 1) wait for the settings to load before registering the settings tab, and 2) pass the settings values along to the showSettings/hideSettings methods. I think this would streamline things, as there would only be one place to apply settings (the onChange callback) and one place to change them (in the UI created by showSettings).

That makes sense, in the case of useSettings in the plugin class onload would have fired so I would still need to have the defaults in place? For the rest would useSettings execute before the onload in the Service/Component. Not sure how to easily visualize the call tree in TS.

(Bear in mind, btw, that at this point I only have one (draft) plugin doing anything with settings at all so you are working with literally the least stable part of Ophidian that is stable enough to be checked into git at all. 😉)

Something about a sense of adventure? I hope I am helping and not hindering, I am finding the conversation to be pretty insightful on my side. So thanks for that.
I will look at the changes in the next few days to see how it looks but from what you have said it makes sense. It may also make it possible for me to enable the saving of the collapse data for folding the headings in settings as a part of the settings tab builder and not have to worry about it as part of a setting for the plugin/service/component

I just tried to use current in showSettings and it was not picking up the value that is set in the data.json. The settings tab is showing fine with the placeholder value but using current or the property off the class that has showSettings is not returning anything. Looking at the apply settings callback I can see the value is being read and is in the settings object.
May be a issue with timing? Checking in the change, the 'AlaSqlQuery' class was the one I was playing with to test this out.

Nope, I was a idiot and did not fix a variable reference

That makes sense, in the case of useSettings in the plugin class onload would have fired so I would still need to have the defaults in place?

You can just have the applySettings call do whatever you would've done with those settings in onload, though.  It's a bit like running an onLayoutReady callback to do stuff when it's safe.
I've just refactored the settings service and useSettings to make this easier for one-time setup, though:  the service now has each() and once() methods (and corresponding callback arguments in useSettings()).   So you can do one-time setup (like registering commands that depend on the settings) in a once callback, and apply active settings (like adding or removing classes to the dom, adding/removing event handlers, etc. that need to be done whenever the settings change) in an each callback.
each was previously the onChange() method and the applySettings callback - I've renamed these for consistency and simplicity.  (Also hopefully clarity as to the fact it's called with each value the settings have, starting with the initial loaded settings.)
I think this was the right thing to do because the settings tab was already hacking its own version of once to register the settings tab!
So, basically, if you need settings to be valid so that callbacks can happen (e.g. commands, postprocessors, etc.), set them up in the once callback, as that guarantees settings are loaded.  (Services should also follow this policy if they use settings.)  If you need to know when settings change because things in the environment need to be turned on or off or reconfigured, use the each callback to update them.
So for example, if I was doing something like the original sliding panes plugin, and had a settings toggle for it being active, the each() callback would add or remove CSS classes (or add/remove event handlers) depending on the settings it receives each time.  At startup it gets the value (with defaults if applicable) from the settings load.  After that it gets it every time the value is toggled, whether it's by a command, button, settings dialog, or whatever.  (And of course settings are saved based on that as well.)
Anyway, the overall setup is intended to allow one to avoid the misleading nature of async onload, which superficially appears to work but internally screws up initialization order (because child components can finish their onload() even before the parent does, if they are sync and the parent is async).  For monolithic plugins this isn't a big deal, but if you're assembling a plugin out of generic services and components, being able to rely on what order things happen in is a bit more important.

ok, that is much clearer to work with, I had added booleans to make sure only some actions would run one on start-up. I can now remove this and use the once call back.
An example for what I am doing is when the plugin starts it can run a set of SQL based queries to make/change in memory tables for later use if needed. This should only run once on startup/enable of the plugin. I added the boolean check so when the settings were updated in the settings table it would not just run again and break any existing data.
I can now move that to once so it will only execute once and then the users can disable/enable the plugin to force it or restart obsidian which makes it much simpler.
Ill update shortly and push an update to see how it rolls.

What's coming next is the ability to use signals and effects: Ophidian will re-export the preact/signals package, allowing you to manage settings like this:
import {calc, effect, useSettings} from "@ophidian/core"

class MyServiceOrPlugin  extends Whichever {

    settings = useSettings(this, {someSetting: something as SomeType});
    @calc get someSetting() { return this.settings.current?.someSetting; }

    onload() {
        this.register(effect, () => this.doSetupForSomeSetting())
    }

    doSetupForSomeSetting() {
        if (this.someSetting == Option1) {
            // code to set up for option 1...
            return () => {
                // code to UNDO setup for option 1...
            }
        }
        if (this.someSetting == Option2) {
            // code to set up for option 2...
            return () => {
                // code to UNDO setup for option 2...
            }
        }
    }
}

Basically, anything you register as an effect is a callback that can use computed values (e.g. via calc decorator) and will automatically get called again if they change.  settings.current is already effectively a calc value so anything that depends on it will be re-run when the settings change.  Anyway, "effects" can return "undo" or "cleanup' functions, and they will be called if any (monitored) data changed that the effect used during the last call to it.   (And also when the plugin exits, via the register part shown.)
This is going to make it super easy to have plugin settings with complex effects, without needing to restart in order to change them, as long as it is something that's actually reversible.
There are two small catches: First, it only detects !== changes to values that are either computed (using @calc or compute) and derive from a signal().  SettingsService, if you look at the code, is using a signal ("version") and a compute value ("cloned") under the hood to implement the .current property, so any @calc or compute or effect that accesses .current will be re-run when the underlying .version of the settings change.  So anything you want to monitor and update based on has to be defined in some way using the signals package.
The second catch is that effect functions should do as little calculation as possible in the body of them, i.e. anything that can be moved to a @calc/compute, the better.  That way, you won't be undoing and redoing stuff every time any setting changes.  That's why the @calc is in the example above: it isolates the effect so it will only re-run if that setting changes (or any other settings it uses.
Apart from these two things to watch for, it's a huge benefit for complex, dynamic features in plugins.  It's also hugely useful for rendering UI, like for example having an effect that adds an is-selected class to the current (computed or assigned) selection position, and returns a callback to remove it.  Instead of having to centralize that code with anything that updates the position, you just write an effect that basically says, "make sure the current item has this class and takes it off when it's not current".  Bam!
The thing I'm currently working on for Ophidian is a special kind of effect that will let you write things that act like a cross between an effect and an async function, where yield pauses the function until something changes (that the function read since the last yield) or until a promise settles.  (And you can yield undo functions.)  My Calibre plugin has some complex async remote data loading logic I want to replace with a task function that does something like:
while(true) {
    if (queryToString(currentlyLoaded) !== queryToString(currentSettings)) {
         const newResults = yield *waitFor(requestURL(....));
         // could have changed while we waited
         if (queryToString(justLoaded) === queryToString(currentSettings)) {
             // set the new results, triggering UI updates and changing `currentlyLoaded`
         }
    } else if (currentPosition > currentResults.length - 25 && canLoadMore()) {
         // load more results and extend the current result list, similarly checking results
         // are still valid after yield
    } else yield;   // nothing to do, so wait for something to change and trigger us again
}

Wrapping that in a "special effect" of the kind I'm writing will simplify a lot of logical flags I'm currently using to simulate all that.  Writing it this way automatically makes it "single-threaded" in a sense, automatically rate-limiting search calls to the response speed of the server, and doing infinite scroll loading...  but only if the user isn't in the middle of typing stuff in the search box.
Granted, this style has its own gotchas: you need to be careful not to double-yield, i.e. have two yields without checking any values in between, and the first draft of what I wrote above had them.  The if-else and yield only after all conditions fail was necessary to avoid it.  I think I need to think some more about how to write these effectively, so that there's a standard pattern or rules you can follow to get a "safe" task.  But roughly speaking, they need to be arranged as an event loop of this kind: checking for various conditions and potentially yielding in the middle to accomplish things, but eventually dropping back to check conditions again, and only yielding at the top level of the loop when no conditions match.
An easier-to-read version might be:
while(true) {
    if (queryToString(currentlyLoaded) !== queryToString(currentSettings)) {
         yield *this.loadNewResults();
    } else if (currentPosition > currentResults.length - 25 && canLoadMore()) {
         yield *this.loadMoreResults();
    } else yield;   // nothing to do, so wait for something to change and trigger us again
}

yield * lets you call other generator functions, which can then do their own nested event loops or wait for promises or whatever.  Doing it this way makes it easier to verify the correctness of the event loop structure as not double-yielding -- there is clearly only one yield per loop here.
Anyway, that about summarizes coming attractions, I guess.  😀 I've just pushed the @calc and @prop decorators too, if you want to play with them.  (Your tsconfig.json needs "experimentalDecorators": true and "useDefineForClassFields": false in order for them to be compiled correctly, though.)  If you want more background on the underlying signals concept/library, here's the API Guide.

I'm going to have to read that one a few times 😀

I'll look at signals to see how that maps to other callback models I know in my head and see if I can impliment in the next few weeks. Still cleaning up my plugin and refactoring items around. Also trying to get jest to work but the whole js version ecosystem of modules and requires is fighting against me.

You don't need to worry about signals if you're just using the once/each/useSettings API.  But, if you want to know, signals are basically spreadsheet cells - values are input cells, and computes/effects are cells with formulas.  Like a spreadsheet, when you change an input cell, the formulas get recalculated.
In the last few weeks I've realized that preact/signals isn't actually going to work for what I want to do, so it will ultimately get replaced; the API I'm going to end up with will use someSignal() and someSignal.set() instead of someSignal.value.  But, if you're just using the current settings API, you don't need to worry about that, because the once/each/useSettings APIs aren't really changing.  The only thing that might be changing is from .current to .current() to get the current settings.
There is one other thing I want to change, though -- I want to drop hideSettings() as a thing and just have showSettings() take a Component you can use to register() things to unload in place of hideSettings().  I've been meaning to take a look at your code to see if that'll break anything but haven't got around to it yet.  (Specifically, changing it so showSettings() is called with a Component as the first argument instead of the Builder.)

Ok, the latest commit drops hideSettings() and passes a Component to showSettings() instead, so you can .register() callbacks on it if you need to do stuff on closing of the tab.
There's also now a narrower set of exports for the signals API, and it's a bit different from the one provided by @preact/signals-core.  (At the moment it's just a thin wrapper over their implementation but it will eventually be replaced with an in-house version.)
That will hopefully be it for backwards-incompatible-ish changes to Ophidian for a little while at least -- I hope  :wink:.  (It probably will be, just because I will be mainly writing new stuff in the near future, like adding an indexing service base class to handle a lot of the boilerplate for managing live indexes in Obsidian.)
Anyway, please let me know if you have any further questions or feedback, or would like me to look something over.

    onload() {
        this.register(effect, () => this.doSetupForSomeSetting())
    }

Just noticed a small oversight in the example code. Here's the corrected version:

    onload() {
        this.register(effect(() => this.doSetupForSomeSetting()))
    }

That's weird...  I wonder how I could've typoed it that badly.  Good catch; I've updated the example.

That will hopefully be it for backwards-incompatible-ish changes to Ophidian for a little while at least -- I hope 😉. (It probably will be, just because I will be mainly writing new stuff in the near future, like adding an indexing service base class to handle a lot of the boilerplate for managing live indexes in Obsidian.)

What are you covering in the indexes? Interested as my plugin is all about querying data in obsidian and allowing it to be displayed/exported as you want.

The current draft indexing code is here: https://github.com/ophidian-lib/core/blob/master/src/indexing.ts
You subclass either AbstractIndexer or NoteMetaIndexer and add a parse() method, and the result is a Service.
Indexers have two type parameters: the type of "item" being indexed (e.g. TFile in the case of NoteMetaIndexer) and a map type of keys to value types.  For each item, the index can track an unlimited number of key-value pairs, where keys must be strings, symbols, or numbers, and values can in principle be anything.  (But in practice they'll usually need to be strings, symbols, or numbers, since objects would be compared by identity.)
So, as a simple example, you could make a NoteMetaIndexer for properties, that used property types as keys and property values as values.  (With multi-valued properties being treated as one key-value pair for each property value.)  You'd then be able to iterate over all notes with a particular property (key), or that have a specific key-value pair present.  (Or get counts of the same, or retrieve the first item with a specific key-value pair.)
You're not limited to using note metadata, you just have to have a synchronous parse() method that emits key-value pairs for some input item (which doesn't have to be a note or even a file).  If your index needs to parse markdown then you just need to set up logic to handle calling the index add() method after the data is (asynchronously) loaded.
Note, though, that if you're creating an index with an item type that isn't TFile, you need to understand a bit more about how the indexing works to use it properly.  Items are implicitly assumed to be mutable objects in the sense that they have a long-lasting identity but with changing keys and values.  So if you use an immutable value as an item type (e.g. file names), then a file being renamed means you would have to delete() the old name and add() the new one.  And if you're trying to do something like index individual tasks or some other in-document items parsed from markdown, you would need to save the objects you created on each parse so that you could delete() the old ones and add() the new ones.
None of these issues apply if you're just indexing TFiles as the "item", though, since TFile objects always represent the same file, even if they've been moved or renamed or deleted.  So the very simple approach shown in NoteMetaIndex should work fine for indexing files (as opposed to items generated from their contents).
Currently the only place I'm using the indexing code is in a draft version of my Calibre Connect plugin, to index which notes are linked to specific books in Calibre via a Calibre-URL or Calibre-ID property.  So it uses a NoteMetaIndexer with key value pairs representing Calibre library codes and book ID numbers extracted from the properties by parse().  It then adds plugin-specific methods to look up, open, or create "book notes", using the inherited index methods.
Anyway, indexing is currently for unordered values only.  If you want to do something like iterating over files in last-modified order or something like that, you'd currently need to iterate over the values for the key and then sort them or put them in some other kind of index.  I may eventually add the ability to have ordered keys, and/or add more classes to make async indexing or parsed-item indexing easier, but I don't have a need for either one myself at the moment.

Just a heads-up for anyone following this...  Ophidian/core is going to have a bit of minor upheaval soon.  I've just released the first version of a new library (Uneventful), which will be used to upgrade certain internal parts of ophidian/core.
Specifically, the contents of internal modules cleanups, signify, and eventful will be mostly gutted and replaced with their better equivalents from Uneventful.
If you're not using anything that comes from inside those submodules you probably won't be affected.  I do intend to try to leave a fair amount of (deprecated) wrappers in place even there, to minimize disruption and ease migration, though.  (Especially since some of my plugins use them currently.)  And I'll be aiming to not disrupt anything else either (preferably at all), though there may be some changes in how the newer Settings UI stuff ends up working.
At this point, I've bumped the npm release of core to 0.0.22, to have a stable version number you can stick with for things as they are now, and not get surprised by anything that gets pushed to master in the future.
So, tl;dr: pin to 0.0.22 for now if you don't want to mess with this, there will be some later 0.0.x releases with deprecated wrappers that keep (hopefully almost entirely) the same outward API, and then some 0.1.x releases that will drop all the deprecated stuff and just use the newer APIs from Uneventful.  There will also be a ton of new functionality coming down the road based on Uneventful, that will make interacting with certain Obsidian APIs a lot easier, much of it in the area of settings and settings UI.
No timelines on any of this yet -- there are a few more things I want to do with Uneventful before I start any of this work, and it may be a while before I start checking any new stuff in to core, so hopefully that gives y'all plenty of time to switch from the github version to the npm version, or at least make a note of what git version you're currently using.  :wink:
Let me know if you have any questions or concerns.


Manual entry is rejected if client time (Date.now()) is ahead of data service time (Date.now())

Describe the bug
Manual entry is rejected if client time (Date.now()) is ahead of data service time (Date.now()).
To Reproduce
I can't repro, but there's a recording (soon) available for the curator UXR session in which this came up. This error message won't be visible, but I cross-checked against our cluster logs:
data: 'Case validation failed: revisionMetadata.creationMetadata.date: Path `date` (Thu Jul 16 2020 16:40:51 GMT+0000 (Coordinated Universal Time)) is after maximum allowed value (Date.now())., revisionMetadata.creationMetadata: Validation failed: date: Path `date` (Thu Jul 16 2020 16:40:51 GMT+0000 (Coordinated Universal Time)) is after maximum allowed value (Date.now())., revisionMetadata: Validation failed: creationMetadata.date: Path `date` (Thu Jul 16 2020 16:40:51 GMT+0000 (Coordinated Universal Time)) is after maximum allowed value (Date.now())., creationMetadata: Validation failed: date: Path `date` (Thu Jul 16 2020 16:40:51 GMT+0000 (Coordinated Universal Time)) is after maximum allowed value (Date.now()).'

Expected behavior
New cases shouldn't be susceptible to this time of error.
Relatedly, there should have been a better error message on the client. The message just listed the code (422) -- it should be treated and presented as 500 (~"System error"). The user wasn't sure whether it was a system issue or their entered info was somehow invalid.
Environment (please complete the following information):

OS: Unsure -- probably either Windows or CrOS.
Browser: Chrome
Version: Unsure

Bizarrely, this reoccurred (consistently) in today's UXR session. Logs excerpt is ~identical.

 Dataserver should populate (most) version data


An error occurred while training the custom dataset

Hi @mikeqzy  ,I want to run this project with custom dataset, but I got this error during training:
File "/home/WLY/3dgs-avatar-release/train.py", line 330, in main
    training(config)
  File "/home/WLY/3dgs-avatar-release/train.py", line 110, in training
    render_pkg = render(data, iteration, scene, pipe, background, compute_loss=True, return_opacity=use_mask)
File "/home/WLY/3dgs-avatar-release/gaussian_renderer/__init__.py", line 30, in render
    pc, loss_reg, colors_precomp = scene.convert_gaussians(data, iteration, compute_loss)
 File "/home/WLY/3dgs-avatar-release/scene/__init__.py", line 63, in convert_gaussians
    return self.converter(self.gaussians, viewpoint_camera, iteration, compute_loss)
File "/home/ubuntu/anaconda3/envs/3dgsa/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
File "/home/ubuntu/anaconda3/envs/3dgsa/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl
    return forward_call(*args, **kwargs)
File "/home/WLY/3dgs-avatar-release/models/gaussian_converter.py", line 51, in forward
    deformed_gaussians, loss_reg_deformer = self.deformer(gaussians, camera, iteration, compute_loss)
File "/home/ubuntu/anaconda3/envs/3dgsa/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
 File "/home/ubuntu/anaconda3/envs/3dgsa/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl
    return forward_call(*args, **kwargs)
File "/home/WLY/3dgs-avatar-release/models/deformer/deformer.py", line 15, in forward
    deformed_gaussians, loss_non_rigid = self.non_rigid(gaussians, iteration, camera, compute_loss)
File "/home/ubuntu/anaconda3/envs/3dgsa/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
File "/home/ubuntu/anaconda3/envs/3dgsa/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl
    return forward_call(*args, **kwargs)
File "/home/WLY/3dgs-avatar-release/models/deformer/non_rigid.py", line 268, in forward
    q1[0] = 1.  # [1,0,0,0] represents identity rotation
IndexError: index 0 is out of bounds for dimension 0 with size 0

I tried to find the source of the error, and I found that the error came from the anomaly of xyz variable:
none_grid.py line 239
xyz = gaussians.get_xyz

When the training goes smoothly, its output is:
xyz Parameter containing:

tensor([[-0.1932, -0.4575,  0.0899],
        [-0.4046,  0.2553,  0.0019],
        [ 0.2209, -0.5344, -0.0030],
        ...,
        [-0.0292,  0.0988, -0.1477],
        [ 0.1344,  0.1966, -0.0502],
        [ 0.1247,  0.2166, -0.0616]], device='cuda:0', requires_grad=True)

But then its shape changed, and its dimension was reduced to this:

xyz Parameter containing:

tensor([[ 0.4639,  0.1237, -0.0043]], device='cuda:0', requires_grad=True)

At the same time, the calculated Loss also turns to NAN.
Finally, the value of xyz disappears, which causes the error of the code:

xyz Parameter containing:

tensor([], device='cuda:0', size=(0, 3), requires_grad=True)

This has been bothering me for a long time. I want to know what caused this abnormal situation. Could you give me some suggestions on how to solve these mistakes?

If it runs well in the start and then the shape of xyz shrinks, I would suspect the Gaussians are pruned during density controls. You can verify it by turning off densification. If this is the case, maybe there's something wrong with the dataset


Clicking isn't always working for injected text

Testing #129383
There's a certain beat of clicking that allows me to click twice and the 2nd click is ignored. I think I'm clicking right as the text is changing or right before the text is changing.
This gif demonstrates:

In the gif, if I clicked faster or slower the text changed. It's only when I clicked at a specific speed that the text didn't change.
I don't think this will affect anyone but something I noticed.

I was in a diff editor if that matters.

@Tyriar it seems that this is caused by the hover updating after some delay:

You click next

The next inline completion is shown
The decoration is updated
A delayed hover update is scheduled

After the delay:

The hover is updated

I think this hover update interfers with clicks.
Do you have ideas how I can fix that?

ModesContentHoverWidget._renderMessages is called when the decoration changes.
This line is also not called everytime I click on "next":
https://github.com/microsoft/vscode/blob/401fffe5d6edc76f62344a817940c082b7604348/src/vs/base/browser/ui/hover/hoverWidget.ts#L67
I'm out of ideas how this can be fixed.

@hediet Is it possible that the HoverAction code is looking for the click event, while @TylerLeonhardt is actually doing a double click? If two clicks occur on the same element, browsers emit a dblclick event.

If two clicks occur on the same element, browsers emit a dblclick event.

It works if you do the double click faster (or slower), so I doubt the dblclick event is at fault here.

@hediet I haven't tried to reproduce, just reading off the thread:

This line is also not called everytime I click on "next":
https://github.com/microsoft/vscode/blob/401fffe5d6edc76f62344a817940c082b7604348/src/vs/base/browser/ui/hover/hoverWidget.ts#L67

What if you change the listener to be for mousedown? Does that line run every time you press the mouse button?

Alex is right, it works if the listener listens on mousedown rather than click.
Closing as duplicate of #133517.


Find reputation by a given source

As it is possible to call
@question.add_evaluation(:votes, 1, @user)
it would be great to also be able to call
@question.reputation_for(:votes, @user) which will return 1.
In this way you could find only the reputation from a given source instance.

I see that you have added it here, but it is still not evailable at the gem at https://rubygems.org/gems/activerecord-reputation-system

You can use evaluation_by method.
Expect the new version released next week, until then you can use github source in Gemfile:
gem 'activerecord-reputation-system', github: 'twitter/activerecord-reputation-system'


Actuator endpoint is not created when quickfixj.client.concurrent is set to true

Setting the property quickfixj.client.concurrent or quickfixj.server.concurrent prevents the actuator endpoint to be exposed

Fixed on version 2.7.0


All: Consider GitHub issue creation via go-github or alternative

https://github.com/google/go-github read up and consider implementing this alongside haste-it  for reporting git issues fast and concisely.

What's this about?

There are a few projects that I've run into over time where theres been a system in place to sanitize and report any logs along with create a github issue all with one command.  It's something that would be nice so that we could shortcut any Q&A during issue reporting and RCA's.


Multiple overlays using same overlay image

I am trying to re-use a red arrow SVG image to mark several positions onto a deepzoom pyramid.
I can do this just fine when I mark only one item, but if I try to add another location to the overlays array, it is ignored.  Any help is appreciated.
Example that works:

var viewer = OpenSeadragon({
    id: "openseadragon1",
    prefixUrl: "/openseadragon/images/",
    tileSources: "/dzdata/deepzoomr.dzi",
    overlays: [{
        id: 'right-arrow-overlay',
        x: 0.1968,
        y: 0.1262,
        placement: 'RIGHT'
    }]
});

Example that does not work: I see only the second location marked by the red arrow

var viewer = OpenSeadragon({
    id: "openseadragon1",
    prefixUrl: "/openseadragon/images/",
    tileSources: "/dzdata/deepzoomr.dzi",
    overlays: [
        {id: 'right-arrow-overlay',
        x: 0.1968,
        y: 0.1262,
        placement: 'RIGHT'}
        {id: 'right-arrow-overlay',
        x: 0.0968,
        y: 0.0262,
        placement: 'RIGHT'}
    ]
});

Apologies for the svg image being shown.  How can I remove that?

In my case I use multiple divs

and
var viewer = OpenSeadragon({
    id: "openseadragon1",
    prefixUrl: "/openseadragon/images/",
    tileSources: "/dzdata/deepzoomr.dzi",
    overlays: [
        {id: 'right-arrow-overlay-1',
        x: 0.1968,
        y: 0.1262,
        placement: 'RIGHT'}
        {id: 'right-arrow-overlay-2',
        x: 0.0968,
        y: 0.0262,
        placement: 'RIGHT'}
    ]
});

will work for sure. The div element is moved from the previous location to the overlay layer in OSD, therefore there is nothing to add for the second overlay.

Thanks, boskar!
I also found another way.  Someone posted that you can create a function that returns the same image to the overlays array as below:
    function newpushPin() {
        var img = document.createElement("img");
        img.src = "http://upload.wikimedia.org/wikipedia/commons/7/7a/Red_Arrow_Right.svg";
        img.width = 20
        return img
    }

    var viewer = OpenSeadragon({
        id: "openseadragon1",
        prefixUrl: "/openseadragon/images/",
        tileSources: "/dzdata/deepzoomr.dzi",
        overlays: [
            {id: newpushPin(),
            x: 0.1968,
            y: 0.1262,
            placement: 'RIGHT'},
            {id: newpushPin(),
            x: 0.0968,
            y: 0.0262,
            placement: 'RIGHT'}
        ]
    });

I like this solution!
Although the drawback is they are anonymous, therefore it's impossible to update nor remove them. It's not important here as they are "static" anyway - they are added on viewer initialization.

Right. They are anonymous... while that works for me, I see how that could be a problem for other use cases.


Style message

Very big text (but careful with mobile) and centered

:tada: This issue has been resolved in version 1.0.0 :tada:
The release is available on:

npm package (@latest dist-tag)
GitHub release

Your semantic-release bot :package::rocket:


chore(wash-cli, wash-lib) remove async nats 033

Feature or Problem

Related Issues

Release Information

Consumer Impact

Testing

Unit Test(s)

Acceptance or Integration

Manual Verification

Note: this PR is held up by a release of wadm-types that is the last bastion of async nats 0.33.0 usage in our codebase!

@vados-cosmonic heads up I removed this, because the test was failing

Blocked on https://github.com/wasmCloud/wasmCloud/pull/3209


track storage tier in SegmentMetadata object as server loads segment

Extending SegmentMetadata interface a bit to track segment's storage tier, following up on https://github.com/apache/pinot/issues/8844. Using SegmentMetadata to carry it, as all kinds of segments (implementing IndexSegment) is supposed to have its SegmentMetadata object.

Codecov Report

Merging #8865 (62d8e64) into master (d1d2ddb) will decrease coverage by 6.66%.
The diff coverage is 70.82%.

:exclamation: Current head 62d8e64 differs from pull request most recent head a8b2210. Consider uploading reports for the commit a8b2210 to get more accurate results

@@             Coverage Diff              @@
##             master    #8865      +/-   ##
============================================
- Coverage     69.80%   63.13%   -6.67%
- Complexity     4659     4974     +315
============================================
  Files          1741     1756      +15
  Lines         91476    91711     +235
  Branches      13677    13707      +30
============================================
- Hits          63854    57904    -5950
- Misses        23199    29667    +6468
+ Partials       4423     4140     -283

Flag
Coverage Δ

integration1
?

integration2
?

unittests1
66.55% <74.03%> (+0.32%)
:arrow_up:

unittests2
15.47% <68.14%> (+1.33%)
:arrow_up:

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files
Coverage Δ

...roker/requesthandler/BaseBrokerRequestHandler.java
33.02% <ø> (-40.23%)
:arrow_down:

...roker/requesthandler/GrpcBrokerRequestHandler.java
0.00% <0.00%> (-80.00%)
:arrow_down:

...requesthandler/MultiStageBrokerRequestHandler.java
0.00% <0.00%> (ø)

...pinot/common/utils/fetcher/HttpSegmentFetcher.java
7.69% <0.00%> (-53.85%)
:arrow_down:

...e/pinot/plugin/stream/kinesis/KinesisConsumer.java
33.33% <0.00%> (-1.33%)
:arrow_down:

...ache/pinot/segment/local/utils/IngestionUtils.java
28.07% <0.00%> (-0.17%)
:arrow_down:

.../org/apache/pinot/segment/spi/SegmentMetadata.java
100.00% <ø> (ø)

...egment/spi/index/metadata/SegmentMetadataImpl.java
72.19% <0.00%> (-1.18%)
:arrow_down:

...not/spi/ingestion/batch/BatchConfigProperties.java
0.00% <ø> (ø)

...va/org/apache/pinot/spi/utils/CommonConstants.java
28.57% <ø> (+6.34%)
:arrow_up:

... and 502 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d1d2ddb...a8b2210. Read the comment docs.


Breaking changes in error page

Description
Moved from Discord:

There are some changes to error pages that break my Vue project. Presumably because I have an _error.page.vue, _error.page.client.ts and _error.page.server.ts and the new error pages use a different architecture it seems.
Am I using error pages wrong, or is the current release WIP, or is a migration planned
— or should I open a bug for this? 😄

Error Message + Error Stack
No response

@[discord]schneefux What's the error? Yes, there are some WIP going on but these shouldn't affect current apps, so it's a bug if it does.

I created a reproduction here: https://github.com/schneefux/vps-errorpage-reproduction
It is based on the vue-full example, but it adds _error.page.client.ts and _error.page.server.ts which in this case are copies of the default files.
On dev or build, it outputs this error:
Error<EMAIL_ADDRESS>Usage] Only one `_error.page.js` is allowed. Found several: /renderer/_error /renderer/_error /renderer/_error
    at getErrorPageId (/Users/timo/projekte/vps-errorpage-reproduction/node_modules/vite-plugin-ssr/dist/cjs/shared/route/error-page.js:15:29)
    at prerender404Page (/Users/timo/projekte/vps-errorpage-reproduction/node_modules/vite-plugin-ssr/dist/cjs/node/runtime/renderPage/renderPageContext.js:98:52)
    at prerender404 (/Users/timo/projekte/vps-errorpage-reproduction/node_modules/vite-plugin-ssr/dist/cjs/node/prerender/runPrerender.js:446:71)

The reproduction works fine if you downgrade, e.g. yarn add<EMAIL_ADDRESS>My use case is that I built an error page which loads only the bare minimum and none of the plugins and business components of the main app (which could have triggered the error during SSR).

I'll release the fix later today.

Fix released in 0.4.87.


Bluetooth: Mesh: Add Option config unprov beacon interval

1 Add Option to specifies the second interval when device
send Unprovisioned Beacon.
2 Move BT_MESH_LPN_SUB_ALL_NODES_ADDR to LPN subgroup.
Signed-off-by: Lingao Meng<EMAIL_ADDRESS>

@LingaoM I think it would be best to have "2 Move BT_MESH_LPN_SUB_ALL_NODES_ADDR to LPN subgroup." as it's own commit.

@LingaoM It would be best to have "2 Move BT_MESH_LPN_SUB_ALL_NODES_ADDR to LPN subgroup." as it's own commit.
Can you please split it?

Done

@LingaoM Please check buildkite, there are compilation issues.

@LingaoM Please check buildkite, there are compilation issues.

Done

@LingaoM I pushed a third patch on top of your two patches, which eliminates a bunch of unnecessary #ifdefs from the code (in favour of using IS_ENABLED). Could you take a look and confirm that it's fine with you?

@LingaoM I pushed a third patch on top of your two patches, which eliminates a bunch of unnecessary #ifdefs from the code (in favour of using IS_ENABLED). Could you take a look and confirm that it's fine with you?

LGTM


Auth changes - this is against feature/gg-auth branch...

(Because that part has already been reviewed but not yet merged, so to avoid confusion...)
Auth stuff. Here is how it works (this should be part of some documentation but not sure where... Better to put it in the wiki, I think?)

Root service, at /auth URL, provides authentication service. Currently it
is username/password based but can be key-based in the future. Also,
currently username/password is checked against a SQL database, but
we can easily add other authentication backends.

Each other service is provided username and password on the command line.

As a first thing, as part of GetClientConfig(), each service sends
its credential to the auth url from (1), and, if successful, gets a
JWT (Jason Web Token) with roles (for now; they are unused) that this
user has, signed with the private key (specified in the YAML config file).
RestClient saves this information and uses it for subsequent requests
(this is sent in Authorization header).

Each service also provides authentication middleware that checks
this token (with public key specified in YAML config file).

Submitted comments and questions. Otherwise, done for now.


Fix chainex_tests/unit_tests/routines_tests/test_linalg.py::Inverse

Fix matrix generation to prevent divide by zero-like matrices, which have high error rates.
Fixes #8034
Error reproduced, and solved with this PR. 4000 trials. Previously 8 errors, none after fix.

Squashed!

Jenkins, test this please

Jenkins CI test (for commit 624b011602c0192304c6a2b01b9306574dd968d0, target branch master) failed with status FAILURE.

Jenkins, test this please

Jenkins CI test (for commit 624b011602c0192304c6a2b01b9306574dd968d0, target branch master) succeeded!

Jenkins CI test (for commit 624b011602c0192304c6a2b01b9306574dd968d0, target branch master) succeeded!


docs(tt_um_fstolzcode): stop tinyZuse docs from breaking pandoc

Wrapped python strings into code backticks

Thanks! looks like this fixed the issue: https://github.com/TinyTapeout/tinytapeout-06/actions/runs/11877726814


Node.js snippet: "ParseError: Unexpected token"

I have the following gulp task:
var browserify = require('browserify');
var riotify = require('riotify');
var source = require('vinyl-source-stream');
var transform = require('vinyl-transform'); // I tried without this, too

gulp.task('clientJs', [], function () {
    browserify({ entries: ['game/Client.js'] })
        .transform(riotify, {}) // pass options if you need
        .bundle()
        .on('error', gutil.log) // Show errors
        .pipe(source('misthavenClient.js'))
        .pipe(gulp.dest('public/js'));
});

And in the Client.js that i'm browserifying, I have:
var riot = require('riot');
var loginScreen = require('RiotTags/login-screen.tag');

riot.mount(loginScreen);

The login-screen.tag's contents are:
<login-screen></login-screen>
And yet Gulp throws the following error:
/var/www/project/game/node_modules/RiotTags/login-screen.tag:1
<login-screen></login-screen>
^
ParseError: Unexpected token

Why is this? Google has brought zero information to light on this.
My riot Node package version is 2.3.17, Riotify is 1.0.0.

Hi @ividyon. Can you compile the tag with riot cli command? It looks invalid tag definition:
<login-screen></login-screen>

Hey @cognitom,
thanks for the help!
-> % riot game/node_modules/RiotTags/login-screen.tag
game/node_modules/RiotTags/login-screen.tag -> game/node_modules/RiotTags/login-screen.js

The tag file compiles just fine to the following:
riot.tag2('login-screen', '', '', '', function(opts) {
});

@ividyon, this line seems a bit strange:
var loginScreen = require('RiotTags/login-screen.tag');

If you have your private npm repo, it might be ok, but if not, you got to tell Browserify which dir should be included:
browserify({
  entries: ['game/Client.js'],
  paths: ['./RiotTags']
})

This line doesn't make sense. Just remove it:
var transform = require('vinyl-transform')

Hey again @cognitom,

@ividyon, this line seems a bit strange:
var loginScreen = require('RiotTags/login-screen.tag');
If you have your private npm repo, it might be ok, but if not, you got to tell Browserify which dir should be included:

This sounds like it makes sense, but I have taken the approach straight from the riotify readme:
var riot = require('riot')
var todo = require('./todo.tag')
riot.mount(todo)

In my case, RiotTags is simply a module in the project's node_modules folder. So, I don't really see why that line might seem strange.
When I get home, I will try the alternate approach with the paths option for Browserify, but I don't think that I should need it, right?

Update:
I managed to get it to compile by putting the login-screen.tag file in the same folder as my JS, and requiring it like so:
require('./login-screen.tag');
But why won't anything else work? Surely I can't keep all my tags in the root folder. Even trying to locate the RiotTags folder with
require('./node_modules/RiotTags/login-screen.tag');
already fails, despite the path being correct. Something is very wrong here.

Update 2:
I believe I solved it. The issue seems to be that Browserify transforms apparently ignore files in node_modules, as module files are generally expected to be compiled, finished code. I did not know that, and put most of my code into node_modules, which is the wrong approach.
Moving the tag files anywhere outside of node_modules gets rid of the error.
I'm still pretty annoyed by how unclear the error was, though. The syntax was not invalid anywhere, and "Parse error: Unexpected token" does not communicate to me that files within node_modules are ignored.

I'm confused by this resolution.  I'm having the same Syntax Error issue, and I keep my tag files in a folder which -- though it's not IN node_modules -- has a symbolic link leading to it in node_modules
This is how I've always handled this and it's never given me any problems -- I've always used at least brfs as a transform.  So how can it be that transforms won't work this way?

I can confirm this issue. If you are putting yuor tags into a node_modules folder to simply require with no dot reference, it does not work. To made this work, you have to use -g instead of -t:
NODE_PATH=app/client browserify -g riotify ...

The node_modules folder is intended exclusively for external packages/dependencies you install via NPM. The folder is often ignored by packages due to its sheer size, therefore it is logical and intended that riotify wouldn't locate any tags you put into the node_modules folder.
I had forgotten to close this issue.

This is true for small projects only.
Il Ven 19 Ago 2016 13:10 ividyon<EMAIL_ADDRESS>ha scritto:

Closed #29 https://github.com/jhthorsen/riotify/issues/29.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jhthorsen/riotify/issues/29#event-761127822, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ACpwB-CO0X8bDrLZIHXkkZbNGygMtsPIks5qhY8ggaJpZM4Hxa_H
.


Put a link in the Readme to the rationale behind this template

Hi Ken,
Thanks again for this template. I have been using it with my PhD thesis and I plan to explore its use on other publications.
I would suggest to link A 1.5 column layout in LaTeX in the readme, because it shows the rationale behind this template and also from that page to this repository to appreciate better the relationship between both.

Hi Offray,
Good idea. I've added links to this blog post and a few other related ones.
Thanks!


Workspace - Workspace in the workspace list is misaligned when deleted offline

If you haven’t already, check out our contributing guidelines for onboarding and email<EMAIL_ADDRESS>to request to join our Slack channel!

Version Number: <IP_ADDRESS>
Reproducible in staging?: y
Reproducible in production?: n
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: Applause - Internal Team
Slack conversation:
Action Performed:

Go to staging.new.expensify.com
Go offline.
Go to Settings > Workspaces > Create a new workspace.
Click on the three-dot menu > Delete workspace > Delete.

Expected Result:
The deleted workspace in the workspace list will not be misaligned.
Actual Result:
The deleted workspace in the workspace list is misaligned.
Workaround:
Unknown
Platforms:

Which of our officially supported platforms is this issue occurring on?

[x] Android: Native
[x] Android: mWeb Chrome
[ ] iOS: Native
[x] iOS: mWeb Safari
[x] MacOS: Chrome / Safari
[x] MacOS: Desktop

Screenshots/Videos
Add any screenshot/video evidence
https://github.com/Expensify/App/assets/93399543/6d16d6b2-43c7-4557-b99c-023ba46e6b61
View all open jobs on GitHub

Problem related with this PR
https://github.com/Expensify/App/pull/31728

Hi, I’m Michael (Mykhailo) from Callstack and I would like to work on this issue, because I am author of the broken PR.

Commented with root cause and solution on offending PR

I am preparing a PR, will open it soon.

Happy to review PR if @puneetlath agrees

I've opened the PR for review.


Test Suite Refactor

[Low priority] Currently running our test suite locally runs into several hundreds of warnings, which needs investigating. Also, profiling our test execution duration will also help identify any hotspots (likely not many but it'll be good to flesh them out).

================================================================================= warnings summary ==================================================================================
causal_testing/specification/causal_dag.py:142: 1 warning
examples/covasim_/doubling_beta/example_beta.py: 7 warnings
examples/lr91/example_max_conductances.py: 66 warnings
examples/lr91/example_max_conductances_test_suite.py: 1 warning
examples/poisson/example_run_causal_tests.py: 1 warning
tests/json_front_tests/test_json_class.py: 18 warnings
tests/specification_tests/test_causal_dag.py: 27 warnings
tests/specification_tests/test_metamorphic_relations.py: 14 warnings
tests/surrogate_tests/test_causal_surrogate_assisted.py: 5 warnings
tests/testing_tests/test_causal_test_adequacy.py: 5 warnings
tests/testing_tests/test_causal_test_case.py: 8 warnings
tests/testing_tests/test_causal_test_suite.py: 3 warnings


COPOD Explainability on unseen data

COPOD explain_outlier() function works only for a given data point within the dataset. Is there any approach for explainability on unseen data( data on which model has not been trained) ?

I have a similar issue. I would like to 1) have a method by which I can predict or 'explain' the individual scores of each feature, and I would like to do that predictively too. Is there a way I can contribute that feature? I notice that the decision_functgion sums the results. A simple flag to not do that would already be awesome!
    def decision_function(self, X):
        """Predict raw anomaly score of X using the fitted detector.
         For consistency, outliers are assigned with larger anomaly scores.
        Parameters
        ----------
        X : numpy array of shape (n_samples, n_features)
            The training input samples. Sparse matrices are accepted only
            if they are supported by the base estimator.
        Returns
        -------
        anomaly_scores : numpy array of shape (n_samples,)
            The anomaly score of the input samples.
        """
        # use multi-thread execution
        if self.n_jobs != 1:
            return self._decision_function_parallel(X)

        if hasattr(self, 'X_train'):
            original_size = X.shape[0]
            X = np.concatenate((self.X_train, X), axis=0)

        self.U_l = pd.DataFrame(-1 * np.log(np.apply_along_axis(ecdf, 0, X)))
        self.U_r = pd.DataFrame(-1 * np.log(np.apply_along_axis(ecdf, 0, -X)))
        skewness = np.sign(skew(X, axis=0))
        self.U_skew = self.U_l * -1 * np.sign(
            skewness - 1) + self.U_r * np.sign(skewness + 1)
        self.O = np.maximum(self.U_skew, np.add(self.U_l, self.U_r) / 2)
        if hasattr(self, 'X_train'):
            decision_scores_ = self.O.sum(axis=1).to_numpy()[-original_size:]
        else:
            decision_scores_ = self.O.sum(axis=1).to_numpy()
        return decision_scores_.ravel()

Am I correct in the statement that the data for all the individual scores is stored in the attribute 'O'? This would already provide me with access to the individual scores of the trained data at least..

COPOD explain_outlier() function works only for a given data point within the dataset. Is there any approach for explainability on unseen data( data on which model has not been trained) ?

The current functionality does not support it...but you could combine your test dataset with train to achieve this, indirectly.

I have a similar issue. I would like to 1) have a method by which I can predict or 'explain' the individual scores of each feature, and I would like to do that predictively too. Is there a way I can contribute that feature? I notice that the decision_functgion sums the results. A simple flag to not do that would already be awesome!
    def decision_function(self, X):
        """Predict raw anomaly score of X using the fitted detector.
         For consistency, outliers are assigned with larger anomaly scores.
        Parameters
        ----------
        X : numpy array of shape (n_samples, n_features)
            The training input samples. Sparse matrices are accepted only
            if they are supported by the base estimator.
        Returns
        -------
        anomaly_scores : numpy array of shape (n_samples,)
            The anomaly score of the input samples.
        """
        # use multi-thread execution
        if self.n_jobs != 1:
            return self._decision_function_parallel(X)

        if hasattr(self, 'X_train'):
            original_size = X.shape[0]
            X = np.concatenate((self.X_train, X), axis=0)

        self.U_l = pd.DataFrame(-1 * np.log(np.apply_along_axis(ecdf, 0, X)))
        self.U_r = pd.DataFrame(-1 * np.log(np.apply_along_axis(ecdf, 0, -X)))
        skewness = np.sign(skew(X, axis=0))
        self.U_skew = self.U_l * -1 * np.sign(
            skewness - 1) + self.U_r * np.sign(skewness + 1)
        self.O = np.maximum(self.U_skew, np.add(self.U_l, self.U_r) / 2)
        if hasattr(self, 'X_train'):
            decision_scores_ = self.O.sum(axis=1).to_numpy()[-original_size:]
        else:
            decision_scores_ = self.O.sum(axis=1).to_numpy()
        return decision_scores_.ravel()

Am I correct in the statement that the data for all the individual scores is stored in the attribute 'O'? This would already provide me with access to the individual scores of the trained data at least..

That is true. self.O is a numpy matrix with shape (n_samples, n_features), so it stores each individual scores.

@yzhao062 would this be a feature that we could add? I dont mind doing the leg-work for it :)

I prepped a pull-request with the appropiate changes. Please check whether I did a good job at making the request, as it is my first time. https://github.com/yzhao062/pyod/pull/309

@thewall27 , my approach should give you all the functionality that you would need over the decision_function function, by adding the flag scores_per_feature. What this be acceptable to you?

So greater the score of a feature, more chance that it is contributing for an observation to be an anomaly. Right? @psmgeelen

@thewall27 , exactly! And this can be done with new data and old data. I still want to look at the predict_proba method that is stored in the base.py, but this contains a lot of data-formatting that I am not 100% comfortable yet with. The simple proba method is based on a MinMax scaler however, so outside of the library it could be wrapped as follows:
### Train model and scaler first
model = COPOD().fit(X)
predictions = COPOD.decision_boundaries(X, scores_per_feature=True)
scaler = MinMax().fit(predictions)

### How to get the proba's
probas =  scaler.transform(model.decision_boundaries(X, scores_per_feature=True)).clip(0,1)

Clip is a kewl method from Numpy (I found out 10 mins ago) that makes sure that values do not exceed (in this case) zero or 1.

So it should be
### Train model and scaler first
model = COPOD().fit(X)
predictions = model.decision_boundaries(X, scores_per_feature=True)
scaler = MinMax().fit(predictions)

### How to get the proba's
probas =  scaler.transform(model.decision_boundaries(X, scores_per_feature=True)).clip(0,1)

But for some reason I cannot change prior comment..

COPOD explain_outlier() function works only for a given data point within the dataset. Is there any approach for explainability on unseen data( data on which model has not been trained) ?

it is, in general, the case for all models because of all scaling/normalization functions... what to do if the plan is to make predictions on live data which surely will not always fit into recalculated scales of training set?
thanks!

@cherepanovic, so there are a couple of tricks that can be applied, but lets start at the basics. By definition one could argue that data that is out of range of the training data, is an anomaly. Also note how all scalers can be used to rescale all other data. This is never a problem in itself, as 'trained' scalers are simple arithmetic. Of course there are algorithms that need the data in a particular fashion, and 'test' can end up being out of range of that algorithm. This is seldomly the case though because the estimation processes are often based on 'distance' between 'common' and less 'common' data-points. For this reason it tends to measurable too. Please take a deep dive in what anomaly detection is; this library is an excellent example what common approaches are used. Its really worthwhile!


This is a new issue

title
Item.

Resolved.

The text formatting looks good. Maybe that could be used?

This still needs work.


[BUG] docker compose build fails with unresolved packages

=> ERROR [ 4/12] RUN echo '    - pyvirtualdisplay' >> /tmp/environment.  14.1s

[ 4/12] RUN echo '    - pyvirtualdisplay' >> /tmp/environment.yml     && conda env create -f /tmp/environment.yml     && conda clean -afy     && find /opt/conda/ -follow -type f -name '.a' -delete     && find /opt/conda/ -follow -type f -name '.pyc' -delete     && find /opt/conda/ -follow -type f -name '*.js.map' -delete     && rm /tmp/environment.yml:
#8 0.444 Collecting package metadata (repodata.json): ...working... done
#8 12.95 Solving environment: ...working... failed
#8 12.96
#8 12.96 ResolvePackageNotFound:
#8 12.96   - pyglet=1.5
#8 12.96   - box2d-py
#8 12.96

executor failed running [/bin/sh -c echo '    - pyvirtualdisplay' >> /tmp/environment.yml     && conda env create -f /tmp/environment.yml     && conda clean -afy     && find /opt/conda/ -follow -type f -name '.a' -delete     && find /opt/conda/ -follow -type f -name '.pyc' -delete     && find /opt/conda/ -follow -type f -name '*.js.map' -delete     && rm /tmp/environment.yml]: exit code: 1
ERROR: Service 'handson-ml3' failed to build : Build failed

Hi @sinharahul ,
Thanks for your feedback, and my apologies for the late response.
I've updated the Dockerfile, and I successfully built ageron/handson-ml3. Could you please give it another try?


Stop the false claims

This is a response to some false claims made which use the respected word "Engineering" in it.
Hey
@bisqwit  just wanted to say that Engineering has nothing to do with sitting behind a keyboard and writing code. There is no such thing as "reverse" "engineering". Engineering is a real subject. Engineering means designing and building real mechanical systems, like vehicular engines and turbojets. Software devs are claiming the most ridiculous of false claims these days.
Software dev is easy and for kids, and has absolutely nothing to do with a real and serious complex subject like engineering.Death to open source mindset. Open source also makes no sense and is a very salty and backwards mindset. Death to "universities" [dumpsterversities].
Mechanical Engineering is the only Engineering.
bye bye

Ideology spam.


Take picture does not work on emulator

When opened on a mobile device, picture taking works and goes to the Journal Entry screen. Opening in the Android emulator, the app freezes after clicking the take picture button and does not move on to the Journal Entry screen

Turns out that this is a known issue. The camera plugin does not function on Emulated Google Pixel phones, particularly those running Andriod 12. See this issue on the flutter github for more info. Marking as closed.

Camera does not work in non-Pixel emulator. Reopening issue so that we can look further into whether or not the issue is related to the issue that flutter has, or whether it is a problem with our project. If anyone finds an emulator that works, please let us know.


Question with gen_mpy

I am wanting to have the esp_lcd component added to the espidf module that gets created for micropython. I have gotten the component added to the build and I added the includes into the esp_idf.h file so the code will be generated. I am running into an issue with the output C code from gen_mpy.
There is a lot of this seen in the generated lv_espidf.c file
/*
 * Function NOT generated:
 * Missing 'user_data' as a field of the first parameter of the callback function 'esp_lcd_panel_t_reset_callback'
 * esp_err_t (*reset)(esp_lcd_panel_t *panel)
 */

/*
 * Function NOT generated:
 * Missing 'user_data' as a field of the first parameter of the callback function 'esp_lcd_panel_t_init_callback'
 * esp_err_t (*init)(esp_lcd_panel_t *panel)
 */

/*
 * Function NOT generated:
 * Missing 'user_data' as a field of the first parameter of the callback function 'esp_lcd_panel_t_del_callback'
 * esp_err_t (*del)(esp_lcd_panel_t *panel)
 */

and I am getting this as a compilation error
lv_espidf.c: In function 'mp_esp_lcd_panel_io_t_attr':
lv_espidf.c:9738:92: error: 'struct esp_lcd_panel_io_t' has no member named '_del'; did you mean 'del'?
             case MP_QSTR__del: dest[0] = mp_lv_funcptr(&mp_funcptr_del_mpobj, (void*)data->_del, NULL ,MP_QSTR_esp_lcd_panel_io_t__del, NULL); break; // converting from callback esp_err_t (*)(esp_lcd_panel_io_t *io);
                                                                                ^~~~
                                                                                del
lv_espidf.c:9750:42: error: 'struct esp_lcd_panel_io_t' has no member named '_del'; did you mean 'del'?
                 case MP_QSTR__del: data->_del = (void*)mp_lv_callback(dest[1], NULL ,MP_QSTR_esp_lcd_panel_io_t__del, NULL); break; // converting to callback esp_err_t (*)(esp_lcd_panel_io_t *io);
                                          ^~~~
                                          del
lv_espidf.c: In function 'mp_esp_lcd_panel_t_attr':
lv_espidf.c:10134:94: error: 'struct esp_lcd_panel_t' has no member named '_del'; did you mean 'del'?
             case MP_QSTR__del: dest[0] = mp_lv_funcptr(&mp_funcptr_reset_mpobj, (void*)data->_del, NULL ,MP_QSTR_esp_lcd_panel_t__del, NULL); break; // converting from callback esp_err_t (*)(esp_lcd_panel_t *panel);
                                                                                ^~~~
                                                                                del
lv_espidf.c:10151:42: error: 'struct esp_lcd_panel_t' has no member named '_del'; did you mean 'del'?
                 case MP_QSTR__del: data->_del = (void*)mp_lv_callback(dest[1], NULL ,MP_QSTR_esp_lcd_panel_t__del, NULL); break; // converting to callback esp_err_t (*)(esp_lcd_panel_t *panel);
                                          ^~~~
                                          del

I have attached the generated lv_espidf.c file so it can be looked at of needed. I am thinking that there is improper handling of "del" being used as a field name in a struct and I am not sure why there is a requirement for a field name of user_data to be in the structure for the first parameter of a callback
I am using idf version 4.4
I can fix the _del issue pretty easily by writing a script to handle changing the _ del field names in the generated functions and add that script to be executed by make. The functions that are not getting generated is beyond my knowledge on how to fix and a point in the direction needed to fix it would be a HUGE help.
Thanks
--Kevin

@kdschlosser OFF_TOPIC and desparate attempt: but since this is your most recent action here on github - Eventghost server and forum are dead and nobody is able to contact you. could you have a look.

Hi @kdschlosser ,
The Micropython Binding Script was created to automatically generate Micropython API from LVGL C API.
As such, it expects from the C API certain structure and assumes it follows certain conventions.
You can use the Micropython Binding Script to generate Micropython API for additional functions and libraries other than LVGL, but this needs to be done with care.
For example, we use it to provide Micropython API for parts of the ESP-IDF, and some other libraries.
Please read the documentation for all the details. Specifically the explanation about Callback Conventions.
In your case, your component does not follow these conventions. You can consider wrapping it with a thin API layer that does follow the conventions, and let the script process that layer instead.


Doesn't react to controller being turned on

When the app is turned on before the controller, it will never start working (unless perhaps quitSDLGamepad and initSDLGamepad will be called). Calling ControllerManager.update does nothing.

It is working for gdx-controllers desktop (which uses this lib), please check the implementation: https://github.com/libgdx/gdx-controllers/tree/master/gdx-controllers-desktop/src/main/java/com/badlogic/gdx/controllers/desktop

In my case getNumControllers always returns 0, and checking ControllerIndex like JamepadControllerMonitor (used by JamepadControllerManager) to maxNumControllers shows all are always disconnected. I have a wireless Xbox pad with adapter.

I'm trying to use this in a non-gdx project.
Issue number 1: had to manually specify gdx-jnigen-loader version in my pom, because the pom for Jamepad <IP_ADDRESS> wants gdx-jnigen-loader 2.0.0-SNAPSHOT, and by default SNAPSHOTs are not downloaded by Maven.
Issue number 2: had to extend ControllerManager and provide gamecontrollerdb.txt inside my jar for the mappings to load correctly (I think jamepad relies on the file from gdx-controllers-desktop). Luckily it uses getClass() do get the resource, so a workaround is possible.
Issue number 3: getLastNativeError from initSDLGamepad returns Couldn't find mapping for device (3), but I think it's a minor problem for some device that can be ignored. It exists whether the gamepad works (turned before app is started) or not (turned after the app is started).
Tried to find if the issue is in nativeControllerConnectedOrDisconnected, by manually calling reconnectController for all ControllerIndex objects, but it doesn't help. Simply put, when the pad is turned on after the app starts, getNumControllers will always return 0, and all ControllerIndex will return false from isConnected, even after calling reconnectController. When the pad is turned on before the app starts, getNumControllers returns 1, and ControllerIndex at index 0 is connected.

Likewise, turning the controller off when it works in the app will make no effect on the app - it will still show it as connected.

It makes no difference whether it's the actual pad that is turned on or off, or the wireless dongle that is plugged in or out of an USB port. It seems like the library recognizes only the at-app-start status of the controller(s), and nothing can change this later.

I can safely say this is not a general problem as hot plugging is possible with this lib on Mac, Windows and Linux. Either there is a device problem or an implementation problem. I get that you don't want to use the lib with gdx, but using the test application gdx-controllers provides can give you a hint if you have a device problem or implementation problem.

Issue number 4: after using quitSDLGamepad it's impossible to reuse the object by calling initSDLGamepad, because controllers array will stay at 0 length.
I got it working by destroying the controller manager object in every loop.
          cm.quitSDLGamepad();
          cm = new GamePadControllerManager(configuration);
          cm.initSDLGamepad();
          cm.update();

Only in this case will it detect connected/disconnected controller. So somehow the SDL is not refreshing correctly.

The API is simple so it's not an implementation problem. The device is working.
Hotplugging works for me when using the https://github.com/electronstudio/sdl2gdx library, but it has its own set of problems.
IMHO somethings wrong with the SDL layer when this library is used without GDX.

Perhaps GDX does some SDL_refresh (if there is such a thing, I'm just imaginig this), while this app when standalone doesn't.

Maybe it's about SDL_PumpEvents?

It seems sdl2gdx uses SDL_PumpEvents instead of SDL_JoystickUpdate (though documentation says SDL_PollEvent uses SDL_PumpEvents internally).

It also adds some more hints to SDL:
https://wiki.libsdl.org/SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
https://wiki.libsdl.org/SDL_HINT_MAC_BACKGROUND_APP

Perhaps GDX does some SDL_refresh (if there is such a thing, I'm just imaginig this), while this app when standalone doesn't.

I would suggest you to check the code, it is open source in the linked repo :)

This library is advertised as being able to work without gdx ("The following information is only needed for non-gdx Java projects"), but it doesn't. Refering to gdx and their examples is not helpful in that case, I think there is place for a Jamepad-only example. The core way to use the API is:
ControllerManager cm = new GamePadControllerManager();
cm.initSDLGamepad();
while (doWork) {
  cm.update();
  ...
}
cm.quitSDLGamepad();

and it doesn't work when it comes to detecting connected/disconnected controllers while the app is running. It only works when used this way:
ControllerManager cm = new GamePadControllerManager();
cm.initSDLGamepad();
while (doWork) {
  cm.quitSDLGamepad();
  cm = new GamePadControllerManager();
  cm.initSDLGamepad();
  cm.update();
  ...
}
cm.quitSDLGamepad();

which means full SDL re-init is needed to get a snapshot of the controllers connected to the system. Something doesn't work correcty in the cm.update(); (at least when not using GDX).

The library does as it should when used within the libgdx convinience wrapper gdx-controllers. If it does not work for you, compare where your code differs from that wrapper and track down what's the problem.  If you find that there's a problem in Jamepad that needs to be fixed, feel free to open a PR with the changes.


catppuccin-fcitx5: 0-unstable-2022-10-05 -> 0-unstable-2024-09-01

Automatic update generated by nixpkgs-update tools. This update was made based on information from passthru.updateScript.
meta.description for catppuccin-fcitx5 is: Soothing pastel theme for Fcitx5
meta.homepage for catppuccin-fcitx5 is: https://github.com/catppuccin/fcitx5
Updates performed

Ran passthru.UpdateScript

To inspect upstream changes

Compare changes on GitHub

Impact
Checks done

built on NixOS
fcitx result is not automatically checked because some binaries stick around

Rebuild report (if merged into master) (click to expand)

2 total rebuild path(s)

2 package rebuild(s)

First fifty rebuilds by attrpath

catppuccin-fcitx5

Instructions to test this update (click to expand)

Either download from Cachix:
nix-store -r /nix/store/5z94pj17gv84m7fw2513in0rm6grcfqn-catppuccin-fcitx5-0-unstable-2024-09-01 \
  --option binary-caches 'https://cache.nixos.org/ https://nix-community.cachix.org/' \
  --option trusted-public-keys '
  nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=
  cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
  '

(The Cachix cache is only trusted for this store-path realization.)
For the Cachix download to work, your user must be in the trusted-users list or you can use sudo since root is effectively trusted.
Or, build yourself:
nix-build -A catppuccin-fcitx5 https://github.com/r-ryantm/nixpkgs/archive/02d5cde9d218297e87446db6fc1bbc7aada1c1c8.tar.gz

Or:
nix build github:r-ryantm/nixpkgs/02d5cde9d218297e87446db6fc1bbc7aada1c1c8#catppuccin-fcitx5

After you've downloaded or built it, look at the files and if there are any, run the binaries:
ls -la /nix/store/5z94pj17gv84m7fw2513in0rm6grcfqn-catppuccin-fcitx5-0-unstable-2024-09-01
ls -la /nix/store/5z94pj17gv84m7fw2513in0rm6grcfqn-catppuccin-fcitx5-0-unstable-2024-09-01/bin

Pre-merge build results
We have automatically built all packages that will get rebuilt due to
this change.
This gives evidence on whether the upgrade will break dependent packages.
Note sometimes packages show up as failed to build independent of the
change, simply because they are already broken on the target branch.
Result of nixpkgs-review run on x86_64-linux 1

1 package built:

catppuccin-fcitx5

Maintainer pings
cc @pluiedev @Guanran928 for testing.

[!TIP]
As a maintainer, if your package is located under pkgs/by-name/*, you can comment @NixOS/nixpkgs-merge-bot merge to automatically merge this update using the nixpkgs-merge-bot.

Add a :+1: reaction to pull requests you find important.

Result of nixpkgs-review pr 340571 run on x86_64-linux 1

1 package built:

catppuccin-fcitx5