Skip to content
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

Initial Implementation #1

Closed
dlongley opened this issue Jun 18, 2020 · 11 comments
Closed

Initial Implementation #1

dlongley opened this issue Jun 18, 2020 · 11 comments
Assignees
Labels
Priority 1 Critical

Comments

@dlongley
Copy link
Member

This module should:

  • Be isomorphic.
  • Provide a function for directly fetching the /manifest.json file from a domain. When called from a browser, this may potentially fail because of CORS. If a CORS error occurs, then this function should fetch the file via a proxy service if one is given in the options.
  • Provide this function: https://gist.github.com/dlongley/1169a9e8de20ef69f8aa2f311b9a5f51 ... and consider adding an input option for preferred dark mode/light mode. This option could also be potentially computed (if no option is requested by the caller) when in a browser by programmatically running a CSS selector.
  • Provide a function for obtaining an icon for an origin -- which, internally, should use the above function via a web app manifest or, if one cannot be found, it should fall back to fetching favicon.ico -- and, if this is not found, it should return a default provided to the function by the caller.
  • Perhaps provide a function that will return back an auto-generated web app manifest when one can't be found that uses favicon.ico, etc. -- this is up to the discretion of the implementer to determine if this sort of abstraction is helpful.
  • Other helpful utilities related to web app manifests.

Another module may be needed to provide an express middleware for proxying manifest.json requests; it should not be this module as that code isn't needed by clients.

@mattcollier mattcollier added the Priority 1 Critical label Jun 18, 2020
@mattcollier
Copy link

As for the proxy, there's this thing: https://github.com/digitalbazaar/bedrock-http-proxy/tree/initial/lib

Which afaik is not being used. So it can be made to do whatever. Including using some popular express middleware for the proxy bit.

@JoshDunnDev JoshDunnDev self-assigned this Jun 18, 2020
@dlongley
Copy link
Member Author

dlongley commented Jun 18, 2020

I don't think that proxy code is sufficient -- we're doing quite a bit more with the current manifest.json proxy here:

https://github.com/digitalbazaar/authorization.io/blob/master/lib/http.js

The above is also intentionally more restrained in what it can do. So we either need to add features to bedrock-http-proxy -- or do something else.

@JoshDunnDev
Copy link
Contributor

JoshDunnDev commented Jun 29, 2020

@dlongley Elaboration on questions from office hours.

Currently the function that will be called is getManifestWithIcon({origin, size}).
This function will return:

{ 
  manifest: {...}, 
  icon: {...} 
}

First of all I want to make sure that this is the intention of a function that would be called and if so I have further questions.

  1. Dark/Light Mode
    I am not sure how this is supposed to work and looking at existing manifest examples from w3.org(https://www.w3.org/TR/appmanifest/#example-2-typical-manifest), I don't see anything related to this. Would there be different types of icons in the icons array that would be for light and dark modes? It seems by default there is a particular mode that the logo would work best with. The problem with this is that a user could select dark mode which the icon does not look well in. Here are some options:

    1. We use the background_color or theme_color to determine a luminance value that will tell us which version the icons provided work best on. We display the icon in the appropriate mode (light or dark) and then use a fallback icon (font-awesome?) in the case of the other mode.
    2. We put a small background area around the icon (square or circle) with a padding of 10px (size dependent on UI) that matches the background_color in the manifest. This is used regardless of the mode and would always ensure that the logo would correctly show up. (This is probably the best option)
    3. We change the color of the display interface to use the background_color or theme_color provided in the manifest.json. This would change the color of a large portion of our interface (such as CHAPI window) which is probably not ideal.
    4. We could possibly use prefers-color-scheme media feature which would potentially allow us to get a light mode version or dark mode version of an icon. Example of media usage in manifest: https://www.w3.org/TR/appmanifest/#the-display-mode-media-feature. This is a very specific use case where manifest would have to include all this info. We may be able to check for this first and then fallback to a more generic method if it does not.
    5. We could use the proposed color_scheme here: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/ImageResource-color_scheme/explainer.md#api-proposal. This seems like the best method to use the correct version of the icon based on if a user is in light or dark mode.
  2. Fallback Icons
    When are these to be used? My assumption is that we would use fallback icons when a manifest does not exist, however I did have some questions around this. Will there be cases where a manifest exists but it does not have any icons? I currently have fallbacks happening only if a manifest does not exist, so I need some clarification on this.
    Also, I need further details on what the default fallback icon should be. I assume we might use a font-awesome icon or something like that. Currently the returned icon object is as follows icon: { x: <size>, y: <size>, src: <url> } }. I have it change to icon: { src: <url> } } when we fallback to a favicon. However, if we are to use a font-awesome icon as a default fallback, it won't have a url. Should I change the structure of the icon object to have type: icon/favicon/default to help determine the difference so the front-end can easily receive the src the correct way? With a font-awesome icon, the src would be src: 'fas fa-icon' instead of a url. Is this acceptable or should this be done in a different way?

  3. Auto-generated Manifest
    I am a but confused on how we plan to auto-generate a manifest if one does not exist. What data would be required for this manifest? Even a simple manifest(https://www.w3.org/TR/appmanifest/#example-1-very-simple-manifest) still includes a name, description and icons. How would we get the name and description to generate this?
    I assume we will somehow scrape meta data which could be used to fill in some data into an auto-generated manifest but I am unsure of the best way to do this. Can we use some libraries that help with this scraping?

@JoshDunnDev
Copy link
Contributor

Added potential options above for dark/light mode.

@dlongley
Copy link
Member Author

  1. Dark/Light Mode

We would just use color_scheme as proposed here. The caller of the method to select an icon would indicate whether they want light or dark and we'd just do a best match using color_scheme (if present) first, then icon sizes.

https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/ImageResource-color_scheme/explainer.md#api-proposal

  1. Fallback Icons
    When are these to be used? My assumption is that we would use fallback icons when a manifest does not exist, however I did have some questions around this. Will there be cases where a manifest exists but it does not have any icons? I currently have fallbacks happening only if a manifest does not exist, so I need some clarification on this.

Fallback icons are needed when either the manifest does not exist or the manifest does not list icons. Both scenarios are possible.

Also, I need further details on what the default fallback icon should be. I assume we might use a font-awesome icon or something like that.

We don't need to do that here (another layer handles default icons) -- the only fallback we use is the favicon.ico file.

  1. Auto-generated Manifest
    I am a but confused on how we plan to auto-generate a manifest if one does not exist. What data would be required for this manifest? Even a simple manifest(https://www.w3.org/TR/appmanifest/#example-1-very-simple-manifest) still includes a name, description and icons. How would we get the name and description to generate this?

We don't need to worry about this here either, I don't think. We'll let another layer handle it. But, the answer to the questions here is that we'd just use the only information available (the origin) to provide defaults. So, the default name of the application would be the domain (example.com), for example. Let's see if we end up needing a "default manifest" method at this layer or not -- and if we do, it will be very simplistic (no data scraping, etc.).

I assume we will somehow scrape meta data which could be used to fill in some data into an auto-generated manifest but I am unsure of the best way to do this. Can we use some libraries that help with this scraping?

No, we don't need to do this here in the first iteration.

@JoshDunnDev
Copy link
Contributor

JoshDunnDev commented Nov 11, 2020

@dlongley So in a case where the manifest does not have icons, we would fallback to a favicon.ico correct? What if that website does not have a favicon.ico file? What would the fallback be in that case? Would we just return the following: {manifest: {...}, icon: null} and then let another layer handle a default for null?

@dmitrizagidulin
Copy link

If a CORS error occurs, then this function should fetch the file via a proxy service if one is given in the options.

Btw, in the browser, it's not possible for Javascript code to detect that a CORS error has occurred (the browser basically suppresses it silently). We may need to do some sort of timeout mechanism to catch it.

@dlongley
Copy link
Member Author

@dmitrizagidulin,

Btw, in the browser, it's not possible for Javascript code to detect that a CORS error has occurred (the browser basically suppresses it silently). We may need to do some sort of timeout mechanism to catch it.

I didn't mean for my comment to be that prescriptive. If the attempt to get the manifest.json via the client fails, we should try should start moving to fallback options. I do believe, however, that we may be able to differentiate between a "Network Error" and a 404. If so, the manifest fetching could work like this:

  1. Try to fetch manifest.json directly via the client (requires CORS).
  2. If it fails due to a Network Error, try to fetch the manifest.json via the proxy.
  3. If either of the above fail, return manifest not found.

If we can't make such a distinction then we'd just do this:

  1. Try to fetch manifest.json directly via the client (requires CORS).
  2. If it fails for any reason, try to fetch the manifest.json via the proxy.
  3. If either of the above fail, return manifest not found.

@dlongley
Copy link
Member Author

@JoshDunnDev,

@dlongley So in a case where the manifest does not have icons, we would fallback to a favicon.ico correct?

Yes.

What if that website does not have a favicon.ico file? What would the fallback be in that case? Would we just return the following: {manifest: {...}, icon: null} and then let another layer handle a default for null?

Yes, that's one option (though perhaps undefined is better). But let's also give the caller an option to pass in defaultIcon and, if they do, use that for icon.

@dlongley
Copy link
Member Author

@JoshDunnDev,

I think a goal for this library should be to provide functions that do one thing well: get the manifest directly (over CORS), get the manifest via proxy, find the best icon given some params, etc. And then also provide functions that will combine those functions to give a resilient result that supports defaults when all else fails (if those defaults are provided by the user).

So, someone using this library can make the individual calls directly if they want to -- or they can call the helper(s) that will do the above "fallback" steps to give you something to work with that may use your defaults if necessary.

@dmitrizagidulin dmitrizagidulin mentioned this issue Feb 19, 2021
@dlongley
Copy link
Member Author

Closing per 1.0 release. We can make whatever changes are needed as required -- without keeping this perma issue open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority 1 Critical
Projects
None yet
Development

No branches or pull requests

4 participants