diff --git a/src/gresource.xml b/src/gresource.xml
index a110bc4e..bfd3dbe6 100644
--- a/src/gresource.xml
+++ b/src/gresource.xml
@@ -62,6 +62,7 @@
foliate-js/vendor/pdfjs/pdf.worker.js
opds/opds.html
opds/opds.js
+ opds/widgets.js
reader/reader.html
reader/reader.js
reader/markup.js
diff --git a/src/library.js b/src/library.js
index 71f6a66c..8152d1d1 100644
--- a/src/library.js
+++ b/src/library.js
@@ -561,25 +561,32 @@ export const Library = GObject.registerClass({
}
showCatalog(url) {
this._main_stack.visible_child = this._catalog_toolbar_view
- this._catalog_toolbar_view.content ??= utils.connect(new WebView({
- settings: new WebKit.Settings({
- enable_write_console_messages_to_stdout: true,
- enable_developer_extras: true,
- enable_back_forward_navigation_gestures: false,
- enable_hyperlink_auditing: false,
- enable_html5_database: false,
- enable_html5_local_storage: false,
- disable_web_security: true,
- }),
- }), {
- 'context-menu': () => false,
- 'load-changed': (webView, event) => {
- if (event === WebKit.LoadEvent.FINISHED) {
- webView.run(`globalThis.uiText = ${JSON.stringify(uiText)}`)
- .catch(e => console.error(e))
- }
- },
- })
+ if (!this._catalog_toolbar_view.content) {
+ const webView = new WebView({
+ settings: new WebKit.Settings({
+ enable_write_console_messages_to_stdout: true,
+ enable_developer_extras: true,
+ enable_back_forward_navigation_gestures: false,
+ enable_hyperlink_auditing: false,
+ enable_html5_database: false,
+ enable_html5_local_storage: false,
+ disable_web_security: true,
+ }),
+ })
+ const initFormatMediaType = webView.provide('formatMediaType', type =>
+ Gio.content_type_get_description(type))
+ utils.connect(webView, {
+ 'context-menu': () => false,
+ 'load-changed': (webView, event) => {
+ if (event === WebKit.LoadEvent.FINISHED) {
+ webView.run(`globalThis.uiText = ${JSON.stringify(uiText)}`)
+ .catch(e => console.error(e))
+ initFormatMediaType()
+ }
+ },
+ })
+ this._catalog_toolbar_view.content = webView
+ }
const webView = this._catalog_toolbar_view.content
webView.loadURI(`foliate-opds:///opds/opds.html?url=${encodeURIComponent(url)}`)
.catch(e => console.error(e))
diff --git a/src/opds/opds.html b/src/opds/opds.html
index 0a4b9441..f7b45587 100644
--- a/src/opds/opds.html
+++ b/src/opds/opds.html
@@ -5,6 +5,16 @@
:root {
font-size: 11pt;
font-family: system-ui;
+ --shade: rgba(0, 0, 0, .1);
+ --raised: rgba(0, 0, 0, .05);
+ --pressed: rgba(0, 0, 0, .15);
+}
+@media (prefers-color-scheme: dark) {
+ :root {
+ --shade: rgba(255, 255, 255, .1);
+ --raised: rgba(255, 255, 255, .05);
+ --pressed: rgba(255, 255, 255, .15);
+ }
}
hgroup {
margin-bottom: 24px;
@@ -55,17 +65,76 @@
display: block;
max-width: 42em;
}
-button {
+button, foliate-menubutton::part(button) {
padding: 9px 18px;
font-weight: 700;
- min-width: min(100%, 8em);
+ border-radius: 6px;
+ border: 0;
+ background: var(--shade);
}
-opds-pub-full [slot="actions"] {
+button:hover, foliate-menubutton::part(button):hover {
+ background: var(--raised);
+}
+button:active, foliate-menubutton::part(button):active {
+ background: var(--pressed);
+}
+opds-pub-full > [slot="actions"] {
display: flex;
flex-wrap: wrap;
gap: 9px;
width: 100%;
}
+opds-pub-full > [slot="actions"] > * {
+ min-width: min(100%, 8em);
+}
+.split-button {
+ display: flex;
+}
+.split-button button {
+ border-start-end-radius: 0;
+ border-end-end-radius: 0;
+}
+.split-button foliate-menubutton::part(button) {
+ padding: 9px;
+ border-start-start-radius: 0;
+ border-end-start-radius: 0;
+ border-inline-start: 1px solid color-mix(in hsl, currentColor, transparent 85%);;
+}
+foliate-menubutton {
+ display: flex;
+}
+foliate-menu {
+ position: absolute;
+ inset-block-start: 100%;
+ inset-inline-end: 0;
+ display: flex;
+ flex-direction: column;
+ width: max-content;
+ background: canvas;
+ border-radius: 9px;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.03),
+ 0 1px 3px 1px rgba(0, 0, 0, 0.07),
+ 0 2px 6px 2px rgba(0, 0, 0, 0.03);
+ visibility: hidden;
+ padding: 6px;
+}
+foliate-menu:not([hidden]) {
+ visibility: visible;
+}
+button[role="menuitem"] {
+ border: 0;
+ text-align: start;
+ font: menu;
+ background: none;
+ border-radius: 6px;
+ padding: 9px;
+}
+button[role="menuitem"]:hover {
+ background: var(--raised);
+}
+button[role="menuitem"]:active {
+ background: var(--pressed);
+}