mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
feat: upload maskable icon for PWA
This commit is contained in:
@@ -29,7 +29,8 @@
|
||||
"favicon.upload": "Upload",
|
||||
"touch-icon": "Homescreen/Touch Icon",
|
||||
"touch-icon.upload": "Upload",
|
||||
"touch-icon.help": "Recommended size and format: 192x192, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.",
|
||||
"touch-icon.help": "Recommended size and format: 512x512, PNG format only. If no touch icon is specified, NodeBB will fall back to using the favicon.",
|
||||
"maskable-icon.help": "Recommended size and format: 512x512, PNG format only. If no maskable icon is specified, NodeBB will fall back to the Touch Icon",
|
||||
"outgoing-links": "Outgoing Links",
|
||||
"outgoing-links.warning-page": "Use Outgoing Links Warning Page",
|
||||
"search-default-sort-by": "Search default sort by",
|
||||
|
||||
@@ -2606,7 +2606,40 @@ paths:
|
||||
description: The filename
|
||||
url:
|
||||
type: string
|
||||
description: URL of the uploaded image for use client-side
|
||||
description: URL of the uploaded logo for the Homescreen/Touch Icon to enable PWA
|
||||
/api/admin/uploadMaskableIcon:
|
||||
post:
|
||||
tags:
|
||||
- admin
|
||||
summary: Upload Maskable Icon
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
files:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: binary
|
||||
required:
|
||||
- files
|
||||
responses:
|
||||
"200":
|
||||
description: "Image uploaded"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The filename
|
||||
url:
|
||||
type: string
|
||||
description: URL of the uploaded logo for the Maskable Icon entry for PWA / A2HS
|
||||
/api/admin/uploadlogo:
|
||||
post:
|
||||
tags:
|
||||
|
||||
@@ -14,6 +14,9 @@ define('admin/settings/general', ['admin/settings'], function () {
|
||||
$('button[data-action="removeTouchIcon"]').on('click', function () {
|
||||
$('input[data-field="brand:touchIcon"]').val('');
|
||||
});
|
||||
$('button[data-action="removeMaskableIcon"]').on('click', function () {
|
||||
$('input[data-field="brand:maskableIcon"]').val('');
|
||||
});
|
||||
$('button[data-action="removeOgImage"]').on('click', function () {
|
||||
$('input[data-field="removeOgImage"]').val('');
|
||||
});
|
||||
|
||||
@@ -166,6 +166,23 @@ uploadsController.uploadTouchIcon = async function (req, res, next) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
uploadsController.uploadMaskableIcon = async function (req, res, next) {
|
||||
const uploadedFile = req.files.files[0];
|
||||
const allowedTypes = ['image/png'];
|
||||
|
||||
if (validateUpload(res, uploadedFile, allowedTypes)) {
|
||||
try {
|
||||
const imageObj = await file.saveFileToLocal('maskableicon-orig.png', 'system', uploadedFile.path);
|
||||
res.json([{ name: uploadedFile.name, url: imageObj.url }]);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
} finally {
|
||||
file.delete(uploadedFile.path);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
uploadsController.uploadLogo = async function (req, res, next) {
|
||||
await upload('site-logo', req, res, next);
|
||||
};
|
||||
|
||||
@@ -294,6 +294,22 @@ Controllers.manifest = function (req, res, next) {
|
||||
density: 10.0,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (meta.config['brand:maskableIcon']) {
|
||||
manifest.icons.push({
|
||||
src: nconf.get('relative_path') + '/assets/uploads/system/maskableicon-orig.png',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
});
|
||||
} else if (meta.config['brand:touchIcon']) {
|
||||
manifest.icons.push({
|
||||
src: nconf.get('relative_path') + '/assets/uploads/system/touchicon-orig.png',
|
||||
type: 'image/png',
|
||||
purpose: 'maskable',
|
||||
});
|
||||
}
|
||||
|
||||
plugins.fireHook('filter:manifest.build', { req: req, res: res, manifest: manifest }, function (err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
|
||||
@@ -79,6 +79,7 @@ function apiRoutes(router, middleware, controllers) {
|
||||
router.post('/api/admin/category/uploadpicture', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadCategoryPicture));
|
||||
router.post('/api/admin/uploadfavicon', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFavicon));
|
||||
router.post('/api/admin/uploadTouchIcon', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadTouchIcon));
|
||||
router.post('/api/admin/uploadMaskableIcon', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadMaskableIcon));
|
||||
router.post('/api/admin/uploadlogo', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadLogo));
|
||||
router.post('/api/admin/uploadOgImage', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadOgImage));
|
||||
router.post('/api/admin/upload/file', middlewares, helpers.tryRoute(controllers.admin.uploads.uploadFile));
|
||||
|
||||
@@ -117,6 +117,19 @@
|
||||
[[admin/settings/general:touch-icon.help]]
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input id="maskableIconUrl" type="text" class="form-control" data-field="brand:maskableIcon" data-action="upload" data-target="maskableIconUrl" data-route="{config.relative_path}/api/admin/uploadMaskableIcon" readonly />
|
||||
<span class="input-group-btn">
|
||||
<input data-action="upload" data-target="maskableIconUrl" data-route="{config.relative_path}/api/admin/uploadMaskableIcon" type="button" class="btn btn-default" value="[[admin/settings/general:touch-icon.upload]]"></input>
|
||||
<button data-action="removeMaskableIcon" type="button" class="btn btn-default btn-danger"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
<p class="help-block">
|
||||
[[admin/settings/general:maskable-icon.help]]
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user