-
Notifications
You must be signed in to change notification settings - Fork 26
Feature/zone icons #695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Feature/zone icons #695
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| { | ||
| "defaultIconId": "default", | ||
| "icons": [ | ||
| { "id": "firstFloor", "fileName": "first-floor.svg" }, | ||
| { "id": "groundFloor", "fileName": "ground-floor.svg" }, | ||
| { "id": "officeBuildings", "fileName": "office-buildings.svg" }, | ||
| { "id": "singleFloor", "fileName": "single-floor.svg" }, | ||
| { "id": "topFloor", "fileName": "top-floor.svg" }, | ||
| { "id": "default", "fileName": "zone.svg" }, | ||
| { "id": "home", "fileName": "home.svg" }, | ||
| { "id": "floor", "fileName": "floor.svg" }, | ||
| { "id": "basement", "fileName": "basement.svg" }, | ||
| { "id": "attic", "fileName": "attic.svg" }, | ||
| { "id": "roofSolar", "fileName": "roof-solar-panels.svg" }, | ||
| { "id": "garage", "fileName": "garage.svg" }, | ||
| { "id": "pool", "fileName": "pool.svg" }, | ||
| { "id": "garden", "fileName": "garden.svg" }, | ||
| { "id": "gardenShed", "fileName": "garden-shed.svg" }, | ||
| { "id": "terrace", "fileName": "terrace.svg" }, | ||
| { "id": "carport", "fileName": "carport.svg" }, | ||
| { "id": "hallway", "fileName": "hallway.svg" }, | ||
| { "id": "livingRoom", "fileName": "living-room.svg" }, | ||
| { "id": "kitchen", "fileName": "kitchen.svg" }, | ||
| { "id": "diningRoom", "fileName": "dining-room.svg" }, | ||
| { "id": "bedroomSingle", "fileName": "bedroom.svg" }, | ||
| { "id": "bedroomDouble", "fileName": "master-bedroom.svg" }, | ||
| { "id": "bedroomKids", "fileName": "kinder-room.svg" }, | ||
| { "id": "bathroom", "fileName": "bathroom.svg" }, | ||
| { "id": "wardrobe", "fileName": "wardrobe.svg" }, | ||
| { "id": "office", "fileName": "office.svg" }, | ||
| { "id": "gym", "fileName": "gym.svg" }, | ||
| { "id": "toilet", "fileName": "toilet.svg" }, | ||
| { "id": "entrance", "fileName": "entrance-front-door.svg" }, | ||
| { "id": "studyRoom", "fileName": "study-room.svg" }, | ||
| { "id": "gameRoom", "fileName": "game-room.svg" }, | ||
| { "id": "utilitiesRoom", "fileName": "utilities-room.svg" }, | ||
| { "id": "recreationRoom", "fileName": "recreation-room.svg" }, | ||
| { "id": "tipi", "fileName": "tipi-tent.svg" }, | ||
| { "id": "doorClosed", "fileName": "door-closed.svg" }, | ||
| { "id": "lounge", "fileName": "lounge-chair.svg" }, | ||
| { "id": "fuseBox", "fileName": "lightning-bolt.svg" }, | ||
| { "id": "laundryRoom", "fileName": "laundry-basket.svg" }, | ||
| { "id": "phone", "fileName": "phone.svg" }, | ||
| { "id": "coffeeMachine", "fileName": "coffee-machine.svg" }, | ||
| { "id": "drinks", "fileName": "drinks.svg" }, | ||
| { "id": "pantry", "fileName": "pantry.svg" }, | ||
| { "id": "suitcase", "fileName": "suitcase.svg" }, | ||
| { "id": "door", "fileName": "door.svg" }, | ||
| { "id": "toothbrush", "fileName": "toothbrush.svg" }, | ||
| { "id": "sink", "fileName": "sink.svg" } | ||
| ], | ||
| "legacyIcons": [ | ||
| { "id": "bed", "targetId": "bedroomDouble" }, | ||
| { "id": "bedroom", "targetId": "bedroomSingle" }, | ||
| { "id": "books", "targetId": "studyRoom" }, | ||
| { "id": "entranceFrontDoor", "targetId": "entrance" }, | ||
| { "id": "hallwayDoor", "targetId": "hallwayDoor", "fileName": "hallway-door.svg" }, | ||
| { "id": "kinderRoom", "targetId": "bedroomKids" }, | ||
| { "id": "living", "targetId": "livingRoom" }, | ||
| { "id": "masterBedroom", "targetId": "bedroomDouble" }, | ||
| { "id": "roof", "targetId": "attic" }, | ||
| { "id": "roofSolarPanels", "targetId": "roofSolar" }, | ||
| { "id": "shower", "targetId": "bathroom" }, | ||
| { "id": "stairs-down", "targetId": "basement" }, | ||
| { "id": "stairs-up", "targetId": "floor" }, | ||
| { "id": "tipiTent", "targetId": "tipi" } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| 'use strict'; | ||
|
|
||
| const { join } = require('../../helpers'); | ||
|
|
||
| /** @typedef {{ id: string, fileName: string }} ZoneIconManifestIcon */ | ||
| /** @typedef {{ id: string, targetId: string, fileName?: string }} ZoneIconManifestLegacyIcon */ | ||
| /** @typedef {{ defaultIconId: string, icons: ZoneIconManifestIcon[], legacyIcons: ZoneIconManifestLegacyIcon[] }} ZoneIconManifest */ | ||
| /** @typedef {{ id: string, fileName: string, path?: string }} ZoneIconDescriptor */ | ||
|
|
||
| /** @type {ZoneIconManifest} */ | ||
| const ICONS_MANIFEST = require('../../assets/zone/icons.json'); | ||
|
|
||
| const ICONS_PATH_SEGMENTS = [__dirname, '..', '..', 'assets', 'zone', 'icons']; | ||
| const DEFAULT_ICON_ID = ICONS_MANIFEST.defaultIconId; | ||
| const ACTIVE_ICONS = ICONS_MANIFEST.icons.reduce((obj, icon) => { | ||
| obj[icon.id] = icon.fileName; | ||
| return obj; | ||
| }, {}); | ||
| const LEGACY_ICONS = ICONS_MANIFEST.legacyIcons.reduce((obj, icon) => { | ||
| obj[icon.id] = { | ||
| id: icon.targetId, | ||
| fileName: icon.fileName, | ||
| }; | ||
| return obj; | ||
| }, {}); | ||
|
|
||
| /** @type {ZoneIconDescriptor[] | undefined} */ | ||
| let iconsCache; | ||
|
|
||
| class Zone { | ||
|
|
||
| /** | ||
| * @returns {ZoneIconDescriptor[]} | ||
| */ | ||
| static getIcons() { | ||
| if (iconsCache) return iconsCache; | ||
|
|
||
| iconsCache = ICONS_MANIFEST.icons.map(({ id, fileName }) => Zone._createIconDescriptor({ | ||
| id, | ||
| fileName, | ||
| })); | ||
|
|
||
| return iconsCache; | ||
| } | ||
|
|
||
| /** | ||
| * @param {string | null | undefined} icon | ||
| * @returns {ZoneIconDescriptor} | ||
| */ | ||
| static resolveIcon(icon) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot is this the best name for the function?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kept the name |
||
| const legacyIcon = typeof icon === 'string' ? LEGACY_ICONS[icon] : undefined; | ||
| const id = legacyIcon ? legacyIcon.id : icon; | ||
| let fileName = legacyIcon ? legacyIcon.fileName : undefined; | ||
|
|
||
| if (!fileName && typeof id === 'string') { | ||
| fileName = ACTIVE_ICONS[id]; | ||
| } | ||
|
|
||
| if (!fileName) { | ||
| return Zone._createIconDescriptor({ | ||
| id: DEFAULT_ICON_ID, | ||
| fileName: ACTIVE_ICONS[DEFAULT_ICON_ID], | ||
| }); | ||
| } | ||
|
|
||
| return Zone._createIconDescriptor({ | ||
| id, | ||
| fileName, | ||
| }); | ||
| } | ||
|
|
||
| static _createIconDescriptor({ | ||
| id, | ||
| fileName, | ||
| }) { | ||
| const descriptor = { | ||
|
Comment on lines
+72
to
+76
|
||
| id, | ||
| fileName, | ||
| }; | ||
|
|
||
| if (typeof join === 'function') { | ||
| descriptor.path = join(...ICONS_PATH_SEGMENTS, fileName); | ||
| } | ||
|
|
||
| return descriptor; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| module.exports = Zone; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| 'use strict'; | ||
|
|
||
| const assert = require('assert'); | ||
| const fs = require('fs'); | ||
|
|
||
| const HomeyLib = require('..'); | ||
|
|
||
| describe('Zone icons', function() { | ||
| it('returns active zone icons', function() { | ||
| const icons = HomeyLib.getZoneIcons(); | ||
|
|
||
| assert.strictEqual(icons.length, 47); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer to check |
||
| assert.strictEqual(icons[0].id, 'firstFloor'); | ||
| assert.strictEqual(icons[0].fileName, 'first-floor.svg'); | ||
| assert.strictEqual(icons.some(icon => icon.id === 'hallwayDoor'), false); | ||
|
|
||
| for (const icon of icons) { | ||
| assert.strictEqual(typeof icon.id, 'string'); | ||
| assert.strictEqual(typeof icon.fileName, 'string'); | ||
| assert.strictEqual(typeof icon.path, 'string'); | ||
| assert.strictEqual(fs.existsSync(icon.path), true); | ||
| } | ||
| }); | ||
|
|
||
| it('resolves active, legacy, and unknown zone icons', function() { | ||
| assert.strictEqual(HomeyLib.resolveZoneIcon('default').fileName, 'zone.svg'); | ||
| assert.strictEqual(HomeyLib.resolveZoneIcon('bed').id, 'bedroomDouble'); | ||
| assert.strictEqual(HomeyLib.resolveZoneIcon('hallwayDoor').fileName, 'hallway-door.svg'); | ||
| assert.strictEqual(HomeyLib.resolveZoneIcon('unknown').id, 'default'); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The svg file names in both Sketch as in this file should use
-not_There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in commit 74a9333: all zone SVG filenames and manifest references now use hyphens instead of underscores.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HarwinBorger we cannot just change these file paths, that is a breaking change for consumers of this library. I don't think that's worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed with @HarwinBorger privately on Slack, I agree that the naming is currently inconsistent. However, I also agree with @nozols that changing this would be a breaking change and is out of scope for this PR.
If we want to make the naming more consistent, we should first inventory which consumers rely on the current naming and check whether we can change this safely in separate PRs.
@HarwinBorger could you revert your changes for this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added these icons like two weeks ago so I doubt anyone uses them at this point.
Just bump a major version :)