From bae0dde83e410324b06662177b14061a77ffcf90 Mon Sep 17 00:00:00 2001 From: Sebastian Benz Date: Fri, 8 Nov 2024 21:17:51 +0100 Subject: [PATCH] Styles and config * Some CSS love with open props * Make summary configurable --- .../sidepanel/index.css | 56 +++++++++++++---- .../sidepanel/index.html | 33 +++++++++- .../sidepanel/index.js | 60 ++++++++++++------- 3 files changed, 113 insertions(+), 36 deletions(-) diff --git a/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.css b/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.css index 1b072eec30..e740e14c87 100644 --- a/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.css +++ b/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.css @@ -1,22 +1,52 @@ +@import 'https://unpkg.com/open-props'; + +@import 'https://unpkg.com/open-props/normalize.min.css'; +@import 'https://unpkg.com/open-props/buttons.min.css'; + :root { - --bg-secondary: #e6e2d9; - --bg-primary: #d4e7dd; - --bg-error: #f89696; + --font-size-00: 0.6rem; } + body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, - Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; - color: #1f1f1f; - background-color: #fffbff; - font-size: 16px; - padding: 8px; + margin: auto; + padding: var(--size-2); + font-size: var(--font-size-2); +} + +:where(ol, ul) { + padding: 0 var(--size-3); +} + +[hidden] { + display: none !important; +} + +fieldset > * { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--size-2); +} + +.card { + flex-basis: var(--size-content-1); + display: flex; + flex-direction: column; + gap: var(--size-2); + background: var(--surface-3); + border: 1px solid var(--surface-1); + padding: var(--size-4); + border-radius: var(--radius-3); + box-shadow: var(--shadow-2); + margin-bottom: var(--size-2); +} + +.card > h5 { + line-height: var(--font-lineheight-1); } .warning { - background: #ffc6c6; - padding: 16px; - border-radius: 8px; - margin: 16px 0; + background-color: var(--red-6); } .result { diff --git a/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.html b/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.html index 3b6a482ea7..63cad5d468 100644 --- a/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.html +++ b/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.html @@ -4,8 +4,37 @@ - -

Nothing to show...

+
+
+ Settings +
+ + +
+
+ + +
+
+ + +
+
+
+ +
Nothing to show...
diff --git a/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.js b/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.js index a9fc744147..f7ba9ab0ad 100644 --- a/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.js +++ b/functional-samples/ai.gemini-on-device-summarization/sidepanel/index.js @@ -10,6 +10,19 @@ let pageContent = ''; const summaryElement = document.body.querySelector('#summary'); const warningElement = document.body.querySelector('#warning'); +const summaryTypeSelect = document.querySelector('#type'); +const summaryFormatSelect = document.querySelector('#format'); +const summaryLengthSelect = document.querySelector('#length'); + +function onConfigChange() { + const oldContent = pageContent; + pageContent = ''; + onContentChange(oldContent); +} + +[summaryTypeSelect, summaryFormatSelect, summaryLengthSelect].forEach((e) => + e.addEventListener('change', onConfigChange) +); chrome.storage.session.get('pageContent', ({ pageContent }) => { onContentChange(pageContent); @@ -45,10 +58,17 @@ async function onContentChange(newContent) { async function generateSummary(text) { try { - let session = await createSummarizer((message, progress) => { - console.log(`${message} (${progress.loaded}/${progress.total})`); - }); - let summary = await session.summarize(text); + const session = await createSummarizer( + { + type: summaryTypeSelect.value, + format: summaryFormatSelect.value, + length: length.value + }, + (message, progress) => { + console.log(`${message} (${progress.loaded}/${progress.total})`); + } + ); + const summary = await session.summarize(text); session.destroy(); return summary; } catch (e) { @@ -58,28 +78,26 @@ async function generateSummary(text) { } } -async function createSummarizer() { +async function createSummarizer(config, downloadProgressCallback) { if (!window.ai || !window.ai.summarizer) { throw new Error('AI Summarization is not supported in this browser'); } const canSummarize = await window.ai.summarizer.capabilities(); - let summarizer; - if (canSummarize && canSummarize.available !== 'no') { - if (canSummarize.available === 'readily') { - // The summarizer can immediately be used. - summarizer = await window.ai.summarizer.create(); - } else { - // The summarizer can be used after the model download. - summarizer = await window.ai.summarizer.create(); - summarizer.addEventListener('downloadprogress', (e) => { - console.log('Downloading model', e.loaded, e.total); - }); - await summarizer.ready; - } - } else { - throw new Error(`AI Summarizer not available (${canSummarize.available})`); + if (canSummarize.available === 'no') { + throw new Error('AI Summarization is not supported'); + } + const summarizationSession = await window.ai.summarizer.create( + config, + downloadProgressCallback + ); + if (canSummarize.available === 'after-download') { + summarizationSession.addEventListener( + 'downloadprogress', + downloadProgressCallback + ); + await summarizationSession.ready; } - return summarizer; + return summarizationSession; } async function showSummary(text) {