Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions docs/live-folders-specs.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Remote APIs can return any JSON, but the Live Folder must provide a mapping conf
{
"type": "rest",
"url": "https://api.example.com/posts",
"params": {},
"mapping": {
"items": "data.posts",
"id": "id",
Expand All @@ -103,10 +104,47 @@ Remote APIs can return any JSON, but the Live Folder must provide a mapping conf
}
```

`params` (optional): Object for URL template substitution (`{key}` → `params.key`) and query parameters (unused keys appended as `?key=value`).

### Installation of REST API Live Folder

These schemas would be stored inside a marketplace on Zen's web platform, allowing users to easily discover and integrate new REST API Live Folders into their workspace.

If the user wants to create a new REST API Live Folder, they can do so by providing the necessary schema and configuration through the marketplace interface. This will enable them to customize the folder's behavior and data mapping according to their specific needs.

If it's a custom API and the schema is not publicly available, users can still create a Live Folder by defining their own mapping configuration. This allows them to integrate with proprietary APIs while adhering to Zen's Live Folder standards. This mapping configuration will be fetched via `https://example.com/zen-live-folder.schema.json`.

---

## Example Configurations

### Gitea

Uses the [Gitea Issues API](https://docs.gitea.com/api/#tag/issue). Replace `gitea.example.com`, `owner`, and `repo` with your Gitea instance, org/user, and repository. Use `type: "issues"` or `type: "pulls"` for issues vs pull requests. For private repos, add `"Authorization": "token YOUR_TOKEN"` to `headers`; otherwise use `"headers": {}` to rely on session cookies when logged in.

**Issues:**

```json
{
"url": "https://gitea.example.com/api/v1/repos/{owner}/{repo}/issues",
"params": {
"owner": "my-org",
"repo": "my-project",
"state": "open",
"type": "issues"
},
"label": "Gitea Issues",
"icon": "favicon",
"headers": {},
"mapping": {
"items": "",
"id": "id",
"title": "title",
"url": "html_url",
"subtitle": "user.login"
},
"maxItems": 50
}
```

**Pull requests:** change `params.type` to `"pulls"` and the label to `"Gitea Pull Requests"`.
20 changes: 20 additions & 0 deletions locales/en-US/browser/browser/zen-live-folders.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,23 @@ zen-live-folder-github-option-repo-list-note =

zen-live-folders-promotion-title = Live Folder Created!
zen-live-folders-promotion-description = Latest content from your RSS feeds or GitHub pull requests will appear here automatically.

zen-live-folder-rest-custom =
.label = Custom REST API…

zen-live-folder-rest-dialog-title = Create Custom REST Live Folder
zen-live-folder-rest-dialog-edit-title = Edit REST Live Folder
zen-live-folder-rest-dialog-save = Save
zen-live-folder-rest-dialog-config = Configuration (JSON)
zen-live-folder-rest-dialog-hint = Include: url, params (optional, for {placeholder} substitution and query string), label, icon (optional, use "favicon"), headers, mapping
zen-live-folder-rest-dialog-create = Create
zen-live-folder-rest-option-headers =
.label = Edit headers

zen-live-folder-rest-option-edit-config =
.label = Edit configuration…
zen-live-folder-rest-prompt-headers = Enter HTTP headers as JSON (e.g. {"Authorization": "Bearer token"}):
zen-live-folder-rest-dialog-cancel = Cancel
zen-live-folder-rest-invalid-json = Invalid mapping JSON.
zen-live-folder-rest-invalid-url = Invalid or unsupported URL.
zen-live-folder-rest-invalid-headers = Invalid headers JSON.
21 changes: 21 additions & 0 deletions src/browser/base/content/zen-panels/popups.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

<menupopup id="zenCreateNewPopup">
<menu data-l10n-id="zen-panel-ui-live-folder-create" id="zen-panel-ui-live-folder-create">
<menupopup>
<menuitem
data-l10n-id="zen-live-folder-github-pull-requests"
command="cmd_zenNewLiveFolder"
image="chrome://browser/skin/zen-icons/selectable/logo-github.svg" />
<menuitem
data-l10n-id="zen-live-folder-github-issues"
command="cmd_zenNewLiveFolder"
image="chrome://browser/skin/zen-icons/selectable/logo-github.svg" />
<menuitem
data-l10n-id="zen-live-folder-type-rss"
command="cmd_zenNewLiveFolder"
image="chrome://browser/skin/zen-icons/selectable/logo-rss.svg"/>
<menuitem
data-l10n-id="zen-live-folder-rest-custom"
command="cmd_zenNewLiveFolder"
image="chrome://browser/skin/zen-icons/selectable/code.svg"/>
</menupopup>
</menu>
<menuseparator/>
<menuitem data-l10n-id="zen-panel-ui-workspaces-create" command="cmd_zenOpenWorkspaceCreation" image="chrome://browser/skin/zen-icons/duplicate-tab.svg" />
<menuitem data-l10n-id="zen-panel-ui-folder-create" command="cmd_zenOpenFolderCreation" image="chrome://browser/skin/zen-icons/folder.svg" />
<menuseparator/>
Expand Down
93 changes: 93 additions & 0 deletions src/zen/common/styles/zen-panels/dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,96 @@
transform: translateY(-10%);
}
}

.zen-rest-live-folder-dialog .zen-rest-dialog-title {
margin: 0 0 16px;
font-size: 1.25em;
}

.zen-rest-live-folder-dialog .zen-rest-dialog-hint {
margin: 8px 0 0;
font-size: 0.9em;
color: var(--input-placeholder-color, light-dark(#8f8f9d, #737373));
}

.zen-rest-live-folder-dialog {
padding: 20px;
min-width: 400px;
max-width: 90vw;
background: var(--arrowpanel-background, light-dark(#fff, #1c1b22));
color: var(--panel-color, light-dark(#15141b, #fbfbfe));
border-radius: 12px;
border: 1px solid var(--panel-border-color, light-dark(#cfcfd8, #43434a));
box-shadow: var(--panel-shadow, 0 4px 16px rgba(0, 0, 0, 0.2));
}

.zen-rest-live-folder-dialog::backdrop {
background: rgba(0, 0, 0, 0.4);
}

.zen-rest-live-folder-dialog label {
display: block;
margin-block-end: 4px;
font-weight: 500;
color: inherit;
}

.zen-rest-live-folder-dialog input,
.zen-rest-live-folder-dialog textarea {
display: block;
width: 100%;
margin-block-end: 16px;
padding: 8px 12px;
box-sizing: border-box;
background: var(--input-bgcolor, light-dark(#fff, #2b2a33));
color: var(--input-color, light-dark(#15141b, #fbfbfe));
border: 1px solid var(--input-border-color, light-dark(#8f8f9d, #52525e));
border-radius: 6px;
font: inherit;
}

.zen-rest-live-folder-dialog input::placeholder,
.zen-rest-live-folder-dialog textarea::placeholder {
color: var(--input-placeholder-color, light-dark(#8f8f9d, #737373));
}

.zen-rest-live-folder-dialog textarea {
font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, monospace;
font-size: 13px;
min-height: 120px;
resize: vertical;
}

.zen-rest-dialog-buttons {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-block-start: 16px;
}

.zen-rest-dialog-create {
padding: 8px 16px;
cursor: pointer;
background: var(--zen-colors-primary, #0060df);
color: #fff;
border: none;
border-radius: 6px;
font-weight: 500;
}

.zen-rest-dialog-create:hover {
background: var(--zen-colors-primary-hover, #0250bb);
}

.zen-rest-dialog-cancel {
padding: 8px 16px;
cursor: pointer;
background: transparent;
color: var(--panel-color, inherit);
border: 1px solid var(--input-border-color, light-dark(#8f8f9d, #52525e));
border-radius: 6px;
}

.zen-rest-dialog-cancel:hover {
background: var(--input-bgcolor, light-dark(rgba(12, 12, 13, 0.07), rgba(255, 255, 255, 0.08)));
}
10 changes: 7 additions & 3 deletions src/zen/folders/ZenFolders.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
document.getElementById("context_moveTabToGroup").before(contextMenuItems);
const contextMenuItemsToolbar = window.MozXULElement.parseXULToFragment(
`<menuitem id="zen-context-menu-new-folder-toolbar" data-l10n-id="zen-toolbar-context-new-folder"/>
<menu data-l10n-id="zen-panel-ui-live-folder-create" id="zen-panel-ui-live-folder-create">
<menu data-l10n-id="zen-panel-ui-live-folder-create" id="zen-toolbar-context-live-folder-create">
<menupopup>
<menuitem
data-l10n-id="zen-live-folder-github-pull-requests"
Expand All @@ -90,6 +90,10 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
data-l10n-id="zen-live-folder-type-rss"
command="cmd_zenNewLiveFolder"
image="chrome://browser/skin/zen-icons/selectable/logo-rss.svg"/>
<menuitem
data-l10n-id="zen-live-folder-rest-custom"
command="cmd_zenNewLiveFolder"
image="chrome://browser/skin/zen-icons/selectable/code.svg"/>
</menupopup>
</menu>`
);
Expand All @@ -98,7 +102,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
.after(contextMenuItemsToolbar);

const folderActionsMenu = document.getElementById("zenFolderActions");
folderActionsMenu.addEventListener("popupshowing", event => {
folderActionsMenu.addEventListener("popupshowing", async event => {
const target = event.explicitOriginalTarget;
let folder;
if (gBrowser.isTabGroupLabel(target)) {
Expand All @@ -117,7 +121,7 @@ class nsZenFolders extends nsZenDOMOperatedFeature {
return;
}
this.#lastFolderContextMenu = folder;
gZenLiveFoldersUI.buildContextMenu(folder);
await gZenLiveFoldersUI.buildContextMenu(folder);

const newSubfolderItem = document.getElementById(
"context_zenFolderNewSubfolder"
Expand Down
1 change: 0 additions & 1 deletion src/zen/live-folders/LiveFoldersComponents.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

category browser-window-delayed-startup resource:///modules/zen/ZenLiveFoldersManager.sys.mjs ZenLiveFoldersManager.init
category browser-quit-application-granted resource:///modules/zen/ZenLiveFoldersManager.sys.mjs ZenLiveFoldersManager.uninit
Loading