Skip to content
Closed
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
34 changes: 31 additions & 3 deletions blocklets/image-bin/CHANGELOG.md → CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
## 0.14.20 (2026-1-7)

- feat: change bundle method

## 0.14.19 (January 04, 2026)

- chore: update deps

## 0.14.18 (December 22, 2025)

- feat(uploader): add headless API for programmatic control

## 0.14.17 (December 20, 2025)

- feat: support app shell in dashboard

## 0.14.16 (December 17, 2025)

- fix(uploader): improve runtime path handling and EXIF removal logic

## 0.14.15 (December 15, 2025)

- chore: bump deps to latest

## 0.14.14 (December 05, 2025)

- fix: add prompt adapter for AI image generation

## 0.14.13 (November 28, 2025)

- chore: bump deps to latest
Expand Down Expand Up @@ -65,7 +93,7 @@

## 0.13.31 (September 30, 2025)

fix: enhance XSS filtering with recursive sanitization
- fix: enhance XSS filtering with recursive sanitization

## 0.13.30 (September 29, 2025)

Expand Down Expand Up @@ -98,7 +126,7 @@ fix: enhance XSS filtering with recursive sanitization

## 0.13.23 (September 05, 2025)

chore: bump deps to fix csrf token mismatch v2
- chore: bump deps to fix csrf token mismatch v2

## 0.13.22 (September 02, 2025)

Expand Down Expand Up @@ -209,7 +237,7 @@ chore: bump deps to fix csrf token mismatch v2

## 0.12.5 (June 24, 2025)

fix: fix image paste upload issue in Safari
- fix: fix image paste upload issue in Safari

## 0.12.4 (June 06, 2025)

Expand Down
3 changes: 2 additions & 1 deletion blocklets/image-bin/api/routes/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ router.post('/folders', user, ensureAdmin, async (req, res) => {
router.post('/image/generations', user, auth, async (req, res) => {
const { prompt, number = 1, model = 'dall-e-2', ...rest } = req.body;
const imageModel = new AIGNEHubImageModel({ model });
const result = await imageModel.invoke({ ...rest, prompt, n: parseInt(number, 10) });
const buildPrompt = `${config.env.preferences?.imagePromptTemplate || ''}\n ${prompt}`;
const result = await imageModel.invoke({ ...rest, prompt: buildPrompt, n: parseInt(number, 10) });
res.json(result);
});

Expand Down
28 changes: 27 additions & 1 deletion blocklets/image-bin/blocklet.prefs.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,34 @@
"default": "",
"required": false,
"shared": true
},
"imagePromptTemplate": {
"type": "string",
"title": "Image Prompt Template",
"x-decorator": "FormItem",
"x-component": "Input.TextArea",
"x-validator": [],
"x-component-props": {
"maxLength": null,
"style": {
"height": "400px"
}
},
"x-decorator-props": {
"size": "default",
"style": {
"height": "inherit"
}
},
"name": "imagePromptTemplate",
"x-designable-id": "1jvpoz5b038",
"x-index": 5,
"description": "An Image Prompt Template ensures the AI always generates an image, not text.",
"default": "You are an advanced image generation model. Your task is to produce a **single high-quality image** strictly based on the user's request. You **must output only image data** (no text, no descriptions, no metadata, no explanations). Image Generation Requirements: 1. **Output Type**: * Return an **image only**, never text. * If you would normally describe or explain something, **do not** — instead, directly generate the visual result. 2. **Style Handling**: * Use the style explicitly requested by the user. * If the user does not specify a style, infer the most visually appropriate style from their description (e.g., realistic, illustration, minimalist, futuristic, cinematic, etc.). 3. **Composition & Quality**: * Create a coherent, visually appealing composition. * Include appropriate details, lighting, and visual clarity. * If the user’s description is incomplete or vague, reasonably fill in missing visual details to ensure the final image looks complete and aesthetically balanced. 4. **Technical Specifications**: * Resolution: High-quality output * Follow the user’s content instructions exactly while maintaining strong visual fidelity. 5. **Safety**: * Ensure the generated content complies with safety policies. * Do not generate harmful, sensitive, or restricted material. 6. **Fallback Rules**: * Under no circumstances should you return text in place of an image. * If the instruction seems ambiguous, interpret it visually rather than returning or explaining text. * Always prioritize producing an actual image output. User request:",
"required": false,
"shared": true
}
},
"x-designable-id": "wx9pw6rs358"
"x-designable-id": "oazpa2gvism"
}
}
25 changes: 14 additions & 11 deletions blocklets/image-bin/blocklet.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: image-bin
version: 0.14.13
version: 0.14.20
title: Media Kit
description: Self-hosted media management that replaces expensive cloud services
while keeping you in complete control of your digital assets.
description: >-
Self-hosted media management that replaces expensive cloud services while
keeping you in complete control of your digital assets.
keywords:
- blocklet
- react
Expand All @@ -29,7 +30,7 @@ interfaces:
- type: web
name: publicUrl
path: /
prefix: "*"
prefix: '*'
port: BLOCKLET_PORT
protocol: http
cacheable:
Expand All @@ -49,19 +50,20 @@ interfaces:
- avatar
allowSwitchProfile: true
blockUnauthorized: false
proxyBehavior: service
community: https://community.arcblock.io
documentation: https://developer.blocklet.io
homepage: https://store.blocklet.dev
license: ""
license: ''
payment:
price: []
share: []
timeout:
start: 60
requirements:
server: ">=1.6.29"
os: "*"
cpu: "*"
server: '>=1.6.29'
os: '*'
cpu: '*'
scripts:
preStart: node api/hooks/pre-start.js
preConfig: node api/hooks/pre-config.js
Expand All @@ -70,19 +72,19 @@ environments:
- name: CDN_HOST
description: Use CDN Host for image load speed
required: false
default: ""
default: ''
secure: false
shared: true
- name: UNSPLASH_KEY
description: The Unsplash API key, you can get on https://unsplash.com/developers
required: false
default: ""
default: ''
secure: false
shared: true
- name: UNSPLASH_SECRET
description: The Unsplash API secret, you can get on https://unsplash.com/developers
required: false
default: ""
default: ''
secure: true
shared: false
capabilities:
Expand Down Expand Up @@ -116,3 +118,4 @@ resource:
types:
- type: imgpack
description: A collection of media assets that can be served by the Media Kit
egress: true
24 changes: 12 additions & 12 deletions blocklets/image-bin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "image-bin",
"version": "0.14.13",
"version": "0.14.20",
"private": true,
"scripts": {
"dev": "blocklet dev",
Expand Down Expand Up @@ -41,22 +41,22 @@
]
},
"dependencies": {
"@aigne/aigne-hub": "^0.10.11-beta.1",
"@arcblock/did": "^1.27.12",
"@arcblock/did-connect-react": "^3.2.11",
"@arcblock/ux": "^3.2.11",
"@blocklet/constant": "^1.17.3",
"@blocklet/embed": "^0.3.3",
"@blocklet/js-sdk": "^1.17.3",
"@blocklet/logger": "^1.17.3",
"@blocklet/sdk": "^1.17.3",
"@aigne/aigne-hub": "^0.10.16-beta.13",
"@arcblock/did": "^1.27.16",
"@arcblock/did-connect-react": "^3.3.9",
"@arcblock/ux": "^3.3.9",
"@blocklet/constant": "^1.17.7",
"@blocklet/embed": "^0.3.5",
"@blocklet/js-sdk": "^1.17.7",
"@blocklet/logger": "^1.17.7",
"@blocklet/sdk": "^1.17.7",
"@blocklet/uploader": "workspace:^",
"@blocklet/uploader-server": "workspace:^",
"@blocklet/xss": "workspace:^",
"@iconify/react": "^5.0.2",
"@mui/icons-material": "^7.1.2",
"@mui/material": "^7.1.2",
"@ocap/client": "^1.27.12",
"@ocap/client": "^1.27.16",
"compression": "^1.7.5",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
Expand All @@ -80,7 +80,7 @@
},
"devDependencies": {
"@arcblock/eslint-config": "^0.3.3",
"@blocklet/ui-react": "^3.2.11",
"@blocklet/ui-react": "^3.3.9",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@vitejs/plugin-react": "^4.6.0",
Expand Down
1 change: 0 additions & 1 deletion blocklets/image-bin/src/components/history.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ export default function Uploads() {
style={{
height: '100%',
overflowY: 'auto',
padding: '24px',
}}>
{!!tabs.length && (
<Tabs
Expand Down
18 changes: 5 additions & 13 deletions blocklets/image-bin/src/components/layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import Header from '@blocklet/ui-react/lib/Header';
import Container from '@mui/material/Container';
import Footer from '@blocklet/ui-react/lib/Footer';
import { useMemo } from 'react';
import { joinURL } from 'ufo';

import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import Uploader, { UploaderProviderWrapper } from './uploader';
import { UploaderProviderWrapper } from './uploader';
// import Exporter from './exporter';
import { useUploadContext } from '../contexts/upload';
import { useSessionContext } from '../contexts/session';
import { hasAdminPermission, hasMediaKitAccessPermission } from '../libs/utils';

export default function Layout({ title = window.blocklet.appName }) {
const { tab } = useUploadContext();
const { session } = useSessionContext();
const { pathname } = window.location;
const navigate = useNavigate();
const hadLogin = !!session?.user;
const { t } = useLocaleContext();
Expand All @@ -28,10 +28,6 @@ export default function Layout({ title = window.blocklet.appName }) {

const adminPermissionInSingleTenant = hasAdminPermission(session?.user);

if (hadLogin && tab === 'bucket') {
addons.push(<Uploader key="uploader-addon" />);
}

const hasPermission =
hadLogin &&
(window?.blocklet?.tenantMode === 'multiple' ||
Expand All @@ -51,8 +47,7 @@ export default function Layout({ title = window.blocklet.appName }) {
/>
<Container
sx={{
padding: '0px !important',
my: '-24px !important',
paddingTop: '24px',
height: 'calc(100vh - 64px - 68px + 46px)',
overflowY: 'hidden',
}}>
Expand Down Expand Up @@ -82,6 +77,7 @@ export default function Layout({ title = window.blocklet.appName }) {
<DashWrapper
id="media-kit-layout"
dense
appPath={pathname.endsWith('/admin') ? joinURL(pathname, 'images') : pathname}
title={title}
headerAddons={(exists) => {
return [addons, ...exists];
Expand Down Expand Up @@ -130,10 +126,6 @@ const StyledDashboard = styled(Dashboard)`

.dashboard-content {
max-width: 1680px;
padding: 0 !important;
& > div {
padding: 0 !important;
}
}

// footer
Expand Down
3 changes: 3 additions & 0 deletions blocklets/image-bin/src/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ export default flatten({
copyDownloadSuccess: 'Copy Download Link Success',
copySuccess: 'Copy URL Success',
},
nav: {
imagesDesc: 'View, organize, and manage all project images, videos, and resources in one place.',
},
});
3 changes: 3 additions & 0 deletions blocklets/image-bin/src/locales/ja.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ export default flatten({
copyDownloadSuccess: 'ダウンロードリンクのコピーに成功しました',
copySuccess: 'URLのコピーに成功しました',
},
nav: {
imagesDesc: 'プロジェクトの画像、ビデオ、およびリソースを1か所で表示、整理、管理します。',
},
});
3 changes: 3 additions & 0 deletions blocklets/image-bin/src/locales/zh-tw.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ export default flatten({
copyDownloadSuccess: '複製下載連結成功',
copySuccess: '複製連結成功',
},
nav: {
imagesDesc: '查看、組織和管理所有項目圖片、視頻和資源。',
},
});
3 changes: 3 additions & 0 deletions blocklets/image-bin/src/locales/zh.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,7 @@ export default flatten({
copyDownloadSuccess: '复制下载链接成功',
copySuccess: '复制链接成功',
},
nav: {
imagesDesc: '查看、组织和管理所有项目图片、视频和资源。',
},
});
21 changes: 20 additions & 1 deletion blocklets/image-bin/src/pages/images/index.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
/* eslint-disable jsx-a11y/label-has-associated-control */
import { useEffect } from 'react';
import styled from '@emotion/styled';
import { useAppInfo } from '@blocklet/ui-react/lib/Dashboard';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';

import { useSessionContext } from '../../contexts/session';
import { useUploadContext } from '../../contexts/upload';
import Uploader from '../../components/uploader';
import UploadHistory from '../../components/history';

function ImageList() {
const { t } = useLocaleContext();
const { session } = useSessionContext();
const { tab } = useUploadContext();
const { updateAppInfo } = useAppInfo();
const hasLoggedIn = !!session?.user;

useEffect(() => {
updateAppInfo({
description: t('nav.imagesDesc'),
actions: hasLoggedIn && tab === 'bucket' ? <Uploader key="uploader-addon" /> : null,
});
}, [tab, updateAppInfo, hasLoggedIn, t]);

return (
<Div>
<section id="image-list" className="history">
Expand All @@ -14,7 +33,7 @@ function ImageList() {
}

const Div = styled.div`
padding: 24px 0;
padding: 0 0 24px;
`;

export default ImageList;
2 changes: 1 addition & 1 deletion blocklets/image-bin/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.14.13
0.14.19
Loading