Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
exhuma committed Jul 24, 2022
2 parents e643906 + 34cc846 commit ed99242
Show file tree
Hide file tree
Showing 45 changed files with 2,249 additions and 694 deletions.
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"recommendations": [
"runem.lit-plugin",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint"
"dbaeumer.vscode-eslint",
"bradlc.vscode-tailwindcss"
]
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"*.css": "tailwindcss"
}
}
265 changes: 47 additions & 218 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,247 +1,76 @@
# Schmackhaft

## Early Development
[![Add to Firefox](https://img.shields.io/badge/Firefox-Install-ff7139?logo=firefoxbrowser)][ff-page]
[![Add to Edge](https://img.shields.io/badge/Edge-Install-0078d7?logo=microsoftedge)][edge-page]

This is an early release for this extension which scratches my own itch.
Development will be slow, unless I notice public interest. In that case I might
shuffle around some priorities to invest more time in this extension.
![demo animation](docs/demo.gif "Demo animation")

Feedback is of course more than welcome, epecially in this early stage of the
project.
## The "What/Why/When/Where/Who"

The biggest shortcoming right now is the visual design and UX of the extension.
As this is, for now, dogfood-ware, this might remain basic as UI/UX design is
not my strength.
### What is "schmackhaft"?

## Installation

Except for Edge, the extension must be manually installed using [a release
generated on GitHub](https://github.com/exhuma/schmackhaft/releases). For Edge,
it should be available in the extension store.

Extension publishing to the different browser stores is cumbersome and
therefore, expect the extension to be available _only_ in Edge for now as this
is the most forgiving:

- The Mozilla store requires a simpler build process: The extension is manually
validated on the Mozilla store. This means, the build process must eliminate
human error to the best of its abilities. And this is currently not
guaranteed. Evidenced by the fact that I keep getting validation rejections
because the person validating it is not getting the correct build result.
- The Chrome web store is not allowing submissions from Luxembourg (at the time
of this writing).
- The Edge extension store has - so far - always verified and validated the
extension with no issue.

## Description

This extension allows the storage of bookmarks in a _non-hierarchical_
structure. Each bookmark is identified by the URL and has a collection of
_tags_. They can then be browsed by filtering according to those tags.

This in turn allows "drilling down" into tags without being forced to pick a
specific tag as "first level". So whether you pick "Python" first and _then_
"Programming" is going to be the same as picking "Programming" first followed by
"Python".

This reproduces a behaviour reminiscent to to https://del.icio.us from the early
2000s which has since completely changed its behaviour and has - to the best of
my knowledge - become effectively defunct.

## Screenshots

### Browser Button

The Browser Button gives access to the stored bookmarks. It also contains a
refresh button to force a reload. This can be useful if remote JSON URLs have
changed.

Clicking on the tag-chips at the top will cycle their filtering state. By
default they are "ignored" in filtering. Clicking once will set them to an
"inclusive" state. This will show _only_ links that have this tag. Clicking
again will set them to an "exclusive" state. This will _hide_ all links that
have this tag.

The state-transition is:

neutral -> included -> excluded -> neutral ...

Right-Clicking on a tag will set the state in reverse:

neutral -> excluded -> included -> neutral ...

The bottom panel will show the links with the tag-states applied.

![Page Action](docs/screenshots/browser-button.png "Browser Button")

### Preferences/Options

The extension currently has two main options:

- A list of external JSON URLs
- An option to include browser-stored bookmarks in the UI or not.

Each JSON URL can store bookmarks in the format described below. To remove a
URL, simply set it to the empty string.

Enabling the browser bookmarks will make them available. They will all have the
automatic tag "browser bookmark" and each folder-name is used as additional
tags.
Schmackhaft is a browser extension to navigate (and manage) browser bookmarks
based on tags. As of version "1.0", navigating is comfortable. The "manage" part
is still very limited.

![Preferences](docs/screenshots/options.png "Preferences")
Schmackhaft aggregates bookmarks from a configurable collection of "sources".
Whether these "sources" allow adding new bookmarks, depends on the source.

## Adding Bookmarks
The above screenshots shows the main interface. In the screenshot, the bookmarks are filtered to include everything with the tag "programming" and _exclude_ everything with the tag "YouTube Channel".

Currently it is _only_ possible to get bookmarks from an external JSON file. An
example use-case is to load it from a GitHub repository.
### Why "schmackhaft"?

An option to add bookmarks directly via the extension will be added in the
future.
This is twofold:

## Bookmark Collections
- Scratching my own itch: I loved using `del.icio.us` when it was still fully
functional. It made it really simple to save bookmarks and find them back
_efficiently_. `schmackhaft` intends to reproduce this efficient browsing.
- Sharing Bookmarks: At the office we (a team of sys-admins and developers)
would like to provide our users with a list of bookmarks to our applications.

The extension aims to provide support for multiple collections from which to
draw un when browsing the bookmarks. This currently (in version 0.3) only
supports external JSON files and the bookmarks stored in the browser.
Collection support is flexible in the source code and additional collections can
be added fairly easily.
### When/Where/Who?

### Web URL (JSON)
Development started in mid 2022 here on GitHub by Michel Albert.

The initially supported JSON collection is read-only and only simple HTTP-GET
requests are made. An example collection looks like this:

```javascript
[
{
href: "https://www.google.com",
tags: ["search", "google"],
title: "Google Search",
description: "An example description",
},
{
href: "https://news.ycombinator.com",
tags: ["news", "it"],
},
{
href: "https://duckduckgo.com",
tags: ["search"],
},
{
href: "https://bbc.com",
tags: ["news", "world"],
},
];
```

## Development, Building & Maintenance

Bug/Feature-tracker is over at [exhuma/schmackhaft](https://github.com/exhuma/schmackhaft).

The project provides a VS-Code "development container". This is optional
but provides a reproducible build environment with all required system
dependencies. When working with VS-Code (including the
`ms-vscode-remote.vscode-remote-extensionpack` extension) the development
container can be built manually by opening the command-pallette (CTRL-SHIFT-P)
and selecting `Remote-Containers: Rebuild Container` command. This can also be
used any time something in the container has changed.

1. Clone the Repository

```
git clone https://github.com/exhuma/schmackhaft
cd schmackhaft
```

1. Build

- With VS-Code using the "Remote Containers" extension

- Build the development container

Select "Remote-Containers: Rebuild Container" from the command-pallette
(CTRL-SHIFT-P)

- Build the extension

Open a terminal inside VS-Code and run:

```
make dist
```
- Without VS-Code
- Build the development container
```
docker build -t schmackhaft-dev-container -f .devcontainer/Dockerfile .
```
- Build the extension
- Fetch required npm dependencies:
```
docker run \
--rm \
-it \
-u $(id -u) \
-v $(pwd):/data \
-w /data \
schmackhaft-dev-container \
npm ci
```
- Build the extension:
```
docker run \
--rm \
-it \
-u $(id -u) \
-v $(pwd):/data \
-w /data \
schmackhaft-dev-container \
make dist
```
## Installation

This will create the following artifacts:
Distribution of the extension happens via the extension stores. With the
exception of Chrome (which does not allow publishing from Luxembourg) it should
be findable in the appropriate store.

- `dist/*.zip`
_Note for Firefox: At the time of this writing, Mozilla is a bit finnicky to accept the build. If you cannot find it, follow the manual instruction below_.

Zipped files, ready for distribution to the browser app stores
Use the following links to the store listings:

- `unpackaged/mozilla`
- [Firefox/Mozilla Addons][ff-page]
- [Edge Extensions][edge-page]

The generated source-code for Mozilla based browsers
## Manual Installation

- `unpackaged/chrome`
Prebuilt releases are available in [the GitHub releases
page](https://github.com/exhuma/schmackhaft/releases/latest). These releases are
_unofficial and unsigned by the browsers_. As unsigned release, they must be
installed as "unpackaged" (edge) or "from file" (Firefox). This may not be
possible in a corporate environment.

The generated source-code for Chromium based browsers
## Including/Excluding Tags

### Component Development
To change a tag from being "inclusive" or "exclusive", simply click on it repeatedly (not double-clicking).

For an easier development cycle, a lot of code is written in
[lit](https://lit.dev). This allows us to run a development server with `npm run
serve` and access `/demo/index.html` to try out the components. This makes it
possible to have a develop/test cycle without the need to reload the browser
extension. It also makes it a lot easier to use the browser development tools.
- Clicking one, will set it to "inclusive" (green).
- Clicking again will set it to "exclusive" (red).
- A third click reverts it to "neutral.

## Load the extension into the browser for testing
Right-clicking reverses the steps above. So you can simply right-click on a tag
to remove all links with that tag.

* Chromium based browsers
# Preferences/Options

Open the "extensions" page [chrome://extensions/](chrome://extensions/) and
drag/drop the generated `.zip` file onto that page
See [the configuration page](docs/configuration.md)

Alternatively, follow the instructions on
[Chrome: Loading unpacked
extensions](https://developer.chrome.com/docs/extensions/mv3/getstarted/#unpacked)
with the unzipped contents.
# Development, Building & Maintenance

* Mozilla based browsers
See [the development page](docs/development.md)

Either unzip the `.zip` file from the dist folder, or use the `dist/mozilla`
folder and follow the steps detailed on [Mozilla: Installing Web
Extensions](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension#installing)
[edge-page]: https://microsoftedge.microsoft.com/addons/detail/schmackhaft/aemjihidkhdjpelcgdokkpalbeejgdhi
[ff-page]: https://addons.mozilla.org/en-US/firefox/addon/schmackhaft
8 changes: 6 additions & 2 deletions TODO
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
- Remove Toolbar from HTML files
- Add a text-search for bookmarks
- Allow sources to be enabled/disabled
- Add default tags per source
- Replace arrays with sets where possible
- Centralise logging and update eslintrc config for no-console
- Add a name to each source
- Add default tags to each source
- Deduplicate bookmarks (if more than one source has the same bookmark, it is added with duplicates)
38 changes: 34 additions & 4 deletions demo/demo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import "../src/components/views/sh-settings";
import "../src/components/components/layout-vsplit";
import { BookmarkSource } from "../src/types";
import { FakeBrowser } from "./fake-browser";
import { Settings } from "../src/model/settings";
import { SettingsBridge } from "../src/components/views/sh-settings";
import { SettingsBridge } from "../src/core/settings";

let settingsElementV1 = document.getElementById("SettingsV1") as SettingsBridge;
let settingsElementV2 = document.getElementById("SettingsV2") as SettingsBridge;
Expand All @@ -24,12 +26,40 @@ settingsElementV1.settings = JSON.stringify({
});

let bookmarksElement = document.getElementById("schmackhaft");

// We can't use the default settings bridge here, because this only works in a
// browser-extension execution context.
let settings = new Settings(
["https://raw.githubusercontent.com/exhuma/dotfiles/master/bookmarks.json"],
true,
2
[
{
type: BookmarkSource.HTTP,
settings: {
url: "https://raw.githubusercontent.com/exhuma/dotfiles/master/bookmarks.json",
},
},
{
type: BookmarkSource.HTTP,
settings: {
url: "https://raw.githubusercontent.com/exhuma/schmackhaft/e6439061eedd24c50e00e8b2374ec50d376bc6e5/docs/examples/external-file.json",
},
},
{
type: BookmarkSource.BROWSER,
settings: {},
},
{
type: BookmarkSource.EXTENSION_STORAGE,
settings: {},
},
],
3
);
bookmarksElement.settings = settings.toJson();
bookmarksElement?.addEventListener("settingsChanged", (event) => {
console.log("Settings Changed to:");
console.log(JSON.parse(event.detail["settings"]));
});
bookmarksElement.injections = { getBrowser: async () => new FakeBrowser() };

/**
* Ensure only the div related to the clicked link is visible
Expand Down
Loading

0 comments on commit ed99242

Please sign in to comment.