mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-02 23:28:39 +08:00
dev: add icon_size query for get-launch-apps
This commit is contained in:
parent
f14e1fefcf
commit
df10a7c332
@ -22,6 +22,41 @@ const router = express.Router();
|
|||||||
const auth = require('../middleware/auth.js');
|
const auth = require('../middleware/auth.js');
|
||||||
const { get_app } = require('../helpers.js');
|
const { get_app } = require('../helpers.js');
|
||||||
const { DB_READ } = require('../services/database/consts.js');
|
const { DB_READ } = require('../services/database/consts.js');
|
||||||
|
const { stream_to_buffer } = require('../util/streamutil.js');
|
||||||
|
|
||||||
|
const get_apps = async ({ specifiers }) => {
|
||||||
|
return await Promise.all(specifiers.map(async (specifier) => {
|
||||||
|
return await get_app(specifier);
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const iconify_apps = async (context, { apps, size }) => {
|
||||||
|
return await Promise.all(apps.map(async app => {
|
||||||
|
const data_url = app.icon;
|
||||||
|
if ( ! data_url ) return app;
|
||||||
|
|
||||||
|
const metadata = data_url.split(',')[0];
|
||||||
|
const input_mime = metadata.split(';')[0].split(':')[1];
|
||||||
|
|
||||||
|
// svg icons will be sent as-is
|
||||||
|
if (input_mime === 'image/svg+xml') {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
const svc_appIcon = context.services.get('app-icon');
|
||||||
|
const { stream, mime } = await svc_appIcon.get_icon_stream({
|
||||||
|
app_icon: app.icon,
|
||||||
|
app_uid: app.uid ?? app.uuid,
|
||||||
|
size: size,
|
||||||
|
});
|
||||||
|
|
||||||
|
const buffer = await stream_to_buffer(stream);
|
||||||
|
const resp_data_url = `data:image/png;base64,${buffer.toString('base64')}`;
|
||||||
|
|
||||||
|
app.icon = resp_data_url;
|
||||||
|
return app;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------//
|
// -----------------------------------------------------------------------//
|
||||||
// GET /get-launch-apps
|
// GET /get-launch-apps
|
||||||
@ -29,10 +64,22 @@ const { DB_READ } = require('../services/database/consts.js');
|
|||||||
module.exports = async (req, res) => {
|
module.exports = async (req, res) => {
|
||||||
let result = {};
|
let result = {};
|
||||||
|
|
||||||
|
// Verify query params
|
||||||
|
if ( req.query.icon_size ) {
|
||||||
|
const ALLOWED_SIZES = ['16', '32', '64', '128', '256', '512'];
|
||||||
|
|
||||||
|
if ( ! ALLOWED_SIZES.includes(req.query.icon_size) ) {
|
||||||
|
res.status(400).send({ error: 'Invalid icon_size' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------//
|
// -----------------------------------------------------------------------//
|
||||||
// Recommended apps
|
// Recommended apps
|
||||||
// -----------------------------------------------------------------------//
|
// -----------------------------------------------------------------------//
|
||||||
result.recommended = kv.get('global:recommended-apps');
|
const recommended_cache_key = 'global:recommended-apps' + (
|
||||||
|
req.query.icon_size ? `:icon-size:${req.query.icon_size}` : ''
|
||||||
|
);
|
||||||
|
result.recommended = kv.get(recommended_cache_key);
|
||||||
if ( ! result.recommended ) {
|
if ( ! result.recommended ) {
|
||||||
let app_names = new Set([
|
let app_names = new Set([
|
||||||
'app-center',
|
'app-center',
|
||||||
@ -62,12 +109,10 @@ module.exports = async (req, res) => {
|
|||||||
|
|
||||||
// Prepare each app for returning to user by only returning the necessary fields
|
// Prepare each app for returning to user by only returning the necessary fields
|
||||||
// and adding them to the retobj array
|
// and adding them to the retobj array
|
||||||
result.recommended = [];
|
result.recommended = (await get_apps({
|
||||||
for ( const name of app_names ) {
|
specifiers: Array.from(app_names).map(name => ({ name }))
|
||||||
const app = await get_app({ name });
|
})).filter(app => !! app).map(app => {
|
||||||
if ( ! app ) continue;
|
return {
|
||||||
|
|
||||||
result.recommended.push({
|
|
||||||
uuid: app.uid,
|
uuid: app.uid,
|
||||||
name: app.name,
|
name: app.name,
|
||||||
title: app.title,
|
title: app.title,
|
||||||
@ -75,10 +120,18 @@ module.exports = async (req, res) => {
|
|||||||
godmode: app.godmode,
|
godmode: app.godmode,
|
||||||
maximize_on_start: app.maximize_on_start,
|
maximize_on_start: app.maximize_on_start,
|
||||||
index_url: app.index_url,
|
index_url: app.index_url,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Iconify apps
|
||||||
|
if ( req.query.icon_size ) {
|
||||||
|
result.recommended = await iconify_apps({ services: req.services }, {
|
||||||
|
apps: result.recommended,
|
||||||
|
size: req.query.icon_size,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
kv.set('global:recommended-apps', result.recommended);
|
kv.set(recommended_cache_key, result.recommended);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------//
|
// -----------------------------------------------------------------------//
|
||||||
@ -122,5 +175,13 @@ module.exports = async (req, res) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iconify apps
|
||||||
|
if ( req.query.icon_size ) {
|
||||||
|
result.recent = await iconify_apps({ services: req.services }, {
|
||||||
|
apps: result.recent,
|
||||||
|
size: req.query.icon_size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return res.send(result);
|
return res.send(result);
|
||||||
};
|
};
|
||||||
|
@ -124,6 +124,7 @@ describe('GET /launch-apps', () => {
|
|||||||
// First call
|
// First call
|
||||||
{
|
{
|
||||||
const { get_launch_apps, req_mock, res_mock, spies } = get_mock_context();
|
const { get_launch_apps, req_mock, res_mock, spies } = get_mock_context();
|
||||||
|
req_mock.query = {};
|
||||||
await get_launch_apps(req_mock, res_mock);
|
await get_launch_apps(req_mock, res_mock);
|
||||||
|
|
||||||
expect(res_mock.send.calledOnce).to.equal(true, 'res.send should be called once');
|
expect(res_mock.send.calledOnce).to.equal(true, 'res.send should be called once');
|
||||||
@ -177,6 +178,7 @@ describe('GET /launch-apps', () => {
|
|||||||
// Second call
|
// Second call
|
||||||
{
|
{
|
||||||
const { get_launch_apps, req_mock, res_mock, spies } = get_mock_context();
|
const { get_launch_apps, req_mock, res_mock, spies } = get_mock_context();
|
||||||
|
req_mock.query = {};
|
||||||
await get_launch_apps(req_mock, res_mock);
|
await get_launch_apps(req_mock, res_mock);
|
||||||
|
|
||||||
expect(res_mock.send.calledOnce).to.equal(true, 'res.send should be called once');
|
expect(res_mock.send.calledOnce).to.equal(true, 'res.send should be called once');
|
||||||
|
@ -62,20 +62,21 @@ class AppIconService extends BaseService {
|
|||||||
}).attach(app);
|
}).attach(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
async get_icon_stream ({ app_uid, size }) {
|
async get_icon_stream ({ app_icon, app_uid, size }) {
|
||||||
// Get icon file node
|
// Get icon file node
|
||||||
const dir_app_icons = await this.get_app_icons();
|
const dir_app_icons = await this.get_app_icons();
|
||||||
|
console.log('APP UID', app_uid);
|
||||||
const node = await dir_app_icons.getChild(`${app_uid}-${size}.png`);
|
const node = await dir_app_icons.getChild(`${app_uid}-${size}.png`);
|
||||||
if ( ! await node.exists() ) {
|
if ( ! await node.exists() ) {
|
||||||
// Use database-stored icon as a fallback
|
// Use database-stored icon as a fallback
|
||||||
|
app_icon = app_icon ?? await (async () => {
|
||||||
const app = await get_app({ uid: app_uid });
|
const app = await get_app({ uid: app_uid });
|
||||||
if ( ! app.icon ) {
|
return app.icon ?? DEFAULT_APP_ICON;
|
||||||
app.icon = DEFAULT_APP_ICON;
|
})()
|
||||||
}
|
const [metadata, base64] = app_icon.split(',');
|
||||||
const [metadata, app_icon] = app.icon.split(',');
|
|
||||||
console.log('METADATA', metadata);
|
console.log('METADATA', metadata);
|
||||||
const mime = metadata.split(';')[0].split(':')[1];
|
const mime = metadata.split(';')[0].split(':')[1];
|
||||||
const img = Buffer.from(app_icon, 'base64');
|
const img = Buffer.from(base64, 'base64');
|
||||||
return {
|
return {
|
||||||
mime,
|
mime,
|
||||||
stream: buffer_to_stream(img),
|
stream: buffer_to_stream(img),
|
||||||
|
Loading…
Reference in New Issue
Block a user