aridevelopment-de / myanimetab

A highly customizable firefox startpage for weebs
https://aridevelopment-de.github.io/myanimetab.com
Mozilla Public License 2.0
5 stars 1 forks source link

[Widget Idea] Custom Searchengine for searchbar #121

Open Ari24-cb24 opened 1 year ago

Ari24-cb24 commented 1 year ago

Is your feature request related to a problem? Please describe. The serachbar ships with pre-defined search engines but the user is not able to use alternative search eninges such as https://searx.thegpm.org/ for example.

Describe the solution you'd like Let the user enter urls like https://searx.thegpm.org/ into a list (and also maybe an icon) so that they can use this searchengine.

Additional context May have to change how search engines are currently being saved (I think it was a string identifier)

lbirkert commented 1 year ago

It would be possible to just use the favicon provided by the URL directly (eventhough some favicons are heavily compressed and low resolution)

Ari24-cb24 commented 1 year ago

Currently working on a solution, but I think this won't be possible at the moment. Internally, I store those settings via nested objects

"settings": {
  "...": "...",
  "searchEngines": {
    "i-0": {
      "title": "...",
      "...": "..."
    }
  }
}

but I'm currently fighting with a recursion being created by a dependency array. The whole thing works fine, if you delete the searchbar entry and then add it again but not for migration (meaning the searchEngines key is missing). Here, the rendered component should use a registerDefault parameter in the useSetting hook so that there will always be at least one default value to work with. Used the following snippet to reproduce:

indexedDB.open("widgets").onsuccess = (event) => {
    var db = event.target.result;
    const objectStore = db.transaction(["widgets"], "readwrite").objectStore("widgets");
    objectStore.get("searchbar-0").onsuccess = (ev) => {
        const data = ev.target.result;
        delete data.settings.search_engines;
        objectStore.put(data);
    }
}

the whole concepts involves taking care of setting keys with dots in them, just I can access and modify nested settings. This is a whole other layer of code being involved. The current wrapper uses Table.update

setSetting(id: string, key: string, value: any) {
  key = `settings.${key}`;
  this.widgets.update(id, { [key]: value });
}

and it does seemingly not update nested objects that don't exist. I will probably contact the dexie maintainers and ask them for a possible solution but until then I couldn't get it working. Also, as seen from the useSetting hook, I already take care of nesting:

let key_split = key.split(".");
let current = data[0].settings;

for (let i = 0; i < key_split.length; i++) {
  if (current[key_split[i]] === undefined) {
    if (registerDefault !== undefined) {
      if (i === key_split.length - 1) {
        setState(registerDefault);
        widgetsDb.setSetting(id, key, registerDefault);
        return;
      } else {
        current[key_split[i]] = {};
      }
    } else {
      break;
    }
  }

  if (i === key_split.length - 1) {
    setState(current[key_split[i]]);
    return;
  }

  current = current[key_split[i]];
}

Here, the dependency array involves data, which is defined as the following:

const data = useLiveQuery(() =>
  widgetsDb.widgets.where("id").equals(id).toArray()
);

Now, it should be clear why the recursion happens. Whenever I call widgetsDb.setSetting, data is going to be updated as well. But as dexie does not change the value, the code above tries to call widgetsDb.setSetting again.

I also tried adding an empty object to indexed db but it seems like this doesn't have any effect at all and the recursion still occurs.

This is the current state of my work and I basically wrote this as a reminder of what went wrong. Thing is, if I let dexie take care of it, I won't have to bother with performance concerns.