Skip to content

Commit

Permalink
feat: upload maskable icon for PWA
Browse files Browse the repository at this point in the history
  • Loading branch information
psychobunny committed Sep 29, 2020
1 parent bf3c1c0 commit 6478b32
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 3 deletions.
5 changes: 3 additions & 2 deletions public/language/en-GB/admin/settings/general.json
Expand Up @@ -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",
Expand All @@ -38,4 +39,4 @@
"theme-color": "Theme Color",
"background-color": "Background Color",
"background-color-help": "Color used for splash screen background when website is installed as a PWA"
}
}
35 changes: 34 additions & 1 deletion public/openapi/read.yaml
Expand Up @@ -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:
Expand Down
3 changes: 3 additions & 0 deletions public/src/admin/settings/general.js
Expand Up @@ -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('');
});
Expand Down
17 changes: 17 additions & 0 deletions src/controllers/admin/uploads.js
Expand Up @@ -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);
};
Expand Down
16 changes: 16 additions & 0 deletions src/controllers/index.js
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/routes/admin.js
Expand Up @@ -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));
Expand Down
13 changes: 13 additions & 0 deletions src/views/admin/settings/general.tpl
Expand Up @@ -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>

Expand Down

0 comments on commit 6478b32

Please sign in to comment.