Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
c0sc0s authored Apr 19, 2024
2 parents 449c07b + ba8db96 commit aa3ccb6
Show file tree
Hide file tree
Showing 17 changed files with 413 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export class AISubItemList extends WithDisposable(LitElement) {
display: flex;
flex-direction: column;
box-sizing: border-box;
position: absolute;
padding: 8px;
min-width: 240px;
max-height: 320px;
Expand Down
14 changes: 12 additions & 2 deletions packages/blocks/src/_common/components/ai-item/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,18 @@ abstract class BaseAIError extends Error {
}

export enum AIErrorType {
Unauthorized = 'Unauthorized',
PaymentRequired = 'PaymentRequired',
GeneralNetworkError = 'GeneralNetworkError',
}

// todo: move to presets
export class UnauthorizedError extends BaseAIError {
readonly type = AIErrorType.Unauthorized;
constructor() {
super('Unauthorized');
}
}

// user has used up the quota
export class PaymentRequiredError extends BaseAIError {
readonly type = AIErrorType.PaymentRequired;
Expand All @@ -51,4 +58,7 @@ export class GeneralNetworkError extends BaseAIError {
}
}

export type AIError = PaymentRequiredError | GeneralNetworkError;
export type AIError =
| UnauthorizedError
| PaymentRequiredError
| GeneralNetworkError;
7 changes: 6 additions & 1 deletion packages/blocks/src/attachment-block/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ async function getAttachmentBlob(model: AttachmentBlockModel) {
}

const doc = model.doc;
const blob = await doc.blob.get(sourceId);
let blob = await doc.blob.get(sourceId);

if (blob) {
blob = new Blob([blob], { type: model.type });
}

return blob;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class AIPanelAnswer extends WithDisposable(LitElement) {
box-sizing: border-box;
flex-direction: column;
gap: 8px;
padding: 12px 8px;
padding: 12px 0;
}
.answer {
Expand All @@ -39,7 +39,7 @@ export class AIPanelAnswer extends WithDisposable(LitElement) {
gap: 4px;
align-self: stretch;
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
padding: 0 8px;
padding: 0 12px;
}
.answer-head {
Expand Down Expand Up @@ -76,15 +76,14 @@ export class AIPanelAnswer extends WithDisposable(LitElement) {
height: 22px;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 0 8px;
padding: 0 12px;
gap: 4px;
color: var(--affine-text-secondary-color);
.text {
display: flex;
align-items: flex-start;
gap: 10px;
flex: 1 0 0;
/* light/xs */
Expand All @@ -97,6 +96,7 @@ export class AIPanelAnswer extends WithDisposable(LitElement) {
.right {
display: flex;
align-items: center;
padding-right: 8px;
.copy,
.copied {
Expand Down Expand Up @@ -124,9 +124,18 @@ export class AIPanelAnswer extends WithDisposable(LitElement) {
gap: 4px;
}
.response-list-container ai-item-list {
/* set item style outside ai-item */
.response-list-container,
.action-list-container {
padding: 0 8px;
}
/* set item style outside ai-item */
.response-list-container ai-item-list,
.action-list-container ai-item-list {
--item-padding: 4px;
}
.response-list-container ai-item-list {
--item-icon-color: var(--affine-icon-secondary);
--item-icon-hover-color: var(--affine-icon-color);
}
Expand Down Expand Up @@ -172,16 +181,16 @@ export class AIPanelAnswer extends WithDisposable(LitElement) {
${this.config.responses.length > 0
? html`
<ai-panel-divider></ai-panel-divider>
<div class="response-list-container">
${this.config.responses.map(
(group, index) => html`
${index !== 0
? html`<ai-panel-divider></ai-panel-divider>`
: nothing}
${this.config.responses.map(
(group, index) => html`
${index !== 0
? html`<ai-panel-divider></ai-panel-divider>`
: nothing}
<div class="response-list-container">
<ai-item-list .groups=${[group]}></ai-item-list>
`
)}
</div>
</div>
`
)}
`
: nothing}
${this.config.responses.length > 0 && this.config.actions.length > 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from '../../../../../_common/components/index.js';

export interface AIPanelErrorConfig {
login: () => void;
upgrade: () => void;
responses: AIItemConfig[];
error?: AIError;
Expand Down Expand Up @@ -70,7 +71,7 @@ export class AIPanelError extends WithDisposable(LitElement) {
}
}
}
.upgrade {
.action-button {
display: flex;
padding: 4px 12px;
justify-content: center;
Expand All @@ -92,7 +93,7 @@ export class AIPanelError extends WithDisposable(LitElement) {
line-height: 20px; /* 166.667% */
}
}
.upgrade:hover {
.action-button:hover {
background: var(--affine-hover-color, rgba(0, 0, 0, 0.04));
}
}
Expand All @@ -106,6 +107,19 @@ export class AIPanelError extends WithDisposable(LitElement) {
const errorTemplate = choose(
this.config.error?.type,
[
[
AIErrorType.Unauthorized,
() =>
html`<div class="answer-tip">
<div class="top">Answer</div>
<div class="bottom">
You need to login to AFFiNE Cloud to continue using AFFiNE AI.
</div>
<div @click=${this.config.login} class="action-button">
<div class="content">Login</div>
</div>
</div>`,
],
[
AIErrorType.PaymentRequired,
() => html`
Expand All @@ -115,7 +129,7 @@ export class AIPanelError extends WithDisposable(LitElement) {
You’ve reached the current usage cap for GPT-4. You can
subscribe AFFiNE AI to continue AI experience!
</div>
<div @click=${this.config.upgrade} class="upgrade">
<div @click=${this.config.upgrade} class="action-button">
<div class="content">Upgrade</div>
</div>
</div>
Expand Down
15 changes: 15 additions & 0 deletions packages/presets/src/ai/_common/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,18 @@ export const ArrowUpIcon = html`<svg
fill-opacity="0.6"
/>
</svg> `;

export const ErrorTipIcon = html`<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7.99984 3.16699C5.33046 3.16699 3.1665 5.33095 3.1665 8.00033C3.1665 10.6697 5.33046 12.8337 7.99984 12.8337C10.6692 12.8337 12.8332 10.6697 12.8332 8.00033C12.8332 5.33095 10.6692 3.16699 7.99984 3.16699ZM2.1665 8.00033C2.1665 4.77866 4.77818 2.16699 7.99984 2.16699C11.2215 2.16699 13.8332 4.77866 13.8332 8.00033C13.8332 11.222 11.2215 13.8337 7.99984 13.8337C4.77818 13.8337 2.1665 11.222 2.1665 8.00033ZM7.99984 5.12996C8.27598 5.12996 8.49984 5.35381 8.49984 5.62996V8.00033C8.49984 8.27647 8.27598 8.50033 7.99984 8.50033C7.72369 8.50033 7.49984 8.27647 7.49984 8.00033V5.62996C7.49984 5.35381 7.72369 5.12996 7.99984 5.12996ZM7.49984 10.3707C7.49984 10.0946 7.72369 9.8707 7.99984 9.8707H8.00576C8.28191 9.8707 8.50576 10.0946 8.50576 10.3707C8.50576 10.6468 8.28191 10.8707 8.00576 10.8707H7.99984C7.72369 10.8707 7.49984 10.6468 7.49984 10.3707Z"
fill="#EB4335"
/>
</svg>`;
7 changes: 6 additions & 1 deletion packages/presets/src/ai/ai-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export function buildTextResponseConfig(panel: AffineAIPanelWidget) {
name: '',
items: [
{
name: 'Continue in chat',
name: 'Continue with AI',
icon: ChatWithAIIcon,
handler: () => {
AIProvider.slots.requestContinueInChat.emit({
Expand Down Expand Up @@ -139,6 +139,11 @@ export function buildAIPanelConfig(
errorStateConfig: {
upgrade: () => {
AIProvider.slots.requestUpgradePlan.emit({ host: panel.host });
panel.hide();
},
login: () => {
AIProvider.slots.requestLogin.emit({ host: panel.host });
panel.hide();
},
responses: [],
},
Expand Down
25 changes: 17 additions & 8 deletions packages/presets/src/ai/chat-panel/actions/action-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ export class ActionWrapper extends WithDisposable(ShadowlessElement) {
gap: 18px;
height: 22px;
margin-bottom: 12px;
}
.action-name div:last-child {
margin-left: auto;
cursor: pointer;
div:last-child {
cursor: pointer;
display: flex;
align-items: center;
flex: 1;
div:last-child svg {
margin-left: auto;
}
}
}
.answer-prompt {
Expand Down Expand Up @@ -56,11 +62,14 @@ export class ActionWrapper extends WithDisposable(ShadowlessElement) {
const originalText = item.messages[1].content;
return html`<style></style>
<slot></slot>
<div class="action-name">
<div
class="action-name"
@click=${() => (this.promptShow = !this.promptShow)}
>
${ActionIcon}
<div>${item.action}</div>
<div @click=${() => (this.promptShow = !this.promptShow)}>
${this.promptShow ? ArrowUpIcon : ArrowDownIcon}
<div>
<div>${item.action}</div>
<div>${this.promptShow ? ArrowUpIcon : ArrowDownIcon}</div>
</div>
</div>
${this.promptShow
Expand Down
66 changes: 66 additions & 0 deletions packages/presets/src/ai/chat-panel/actions/chat-text.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import './action-wrapper.js';

import type { EditorHost } from '@blocksuite/block-std';
import { ShadowlessElement, WithDisposable } from '@blocksuite/block-std';
import { css, html, nothing } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { repeat } from 'lit/directives/repeat.js';

import { createTextRenderer } from '../../messages/text.js';
@customElement('chat-text')
export class ChatText extends WithDisposable(ShadowlessElement) {
static override styles = css`
.images-container {
display: flex;
gap: 12px;
}
.image-container {
border-radius: 4px;
width: 155px;
height: 129px;
overflow: hidden;
position: relative;
display: flex;
justify-content: center;
align-items: center;
img {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
}
}
`;
@property({ attribute: false })
host!: EditorHost;

@property({ attribute: false })
blobs?: Blob[];

@property({ attribute: false })
text!: string;

protected override render() {
const { blobs, text } = this;
return html`${blobs
? html`<div class="images-container">
${repeat(
blobs,
blob => blob,
blob => {
return html`<div class="image-container">
<img src="${URL.createObjectURL(blob)}" />
</div>`;
}
)}
</div>`
: nothing}${createTextRenderer(this.host)(text)}`;
}
}

declare global {
interface HTMLElementTagNameMap {
'chat-text': ChatText;
}
}
Loading

0 comments on commit aa3ccb6

Please sign in to comment.