capacitor icon indicating copy to clipboard operation
capacitor copied to clipboard

feat: Support loading from alternate path

Open imhoffd opened this issue 5 years ago • 10 comments

At runtime, we should support the use case of loading a file other than /index.html. For example: __app.html or en-US/index.html. This could also be a configuration option, but we should be able to override it at runtime to allow for use cases such as this: https://github.com/ionic-team/capacitor/discussions/3905

see https://github.com/ionic-team/capacitor/pull/3405 depends on https://github.com/ionic-team/capacitor/issues/3913

imhoffd avatar Dec 08 '20 01:12 imhoffd

I'd like to share another usecase, currently I'm building a Capacitor app with Svelte and Routify, and for SSR purposes the default entrypoint is __app.html. Currently my workaround for building the Capacitor app both locally and in CI is to have a separate build step for the web app which copies dist/__app.html to dist/index.html prior to executing npx cap copy. If this can be configured, it would resolve the separate jobs needed to make this work.

rraihansaputra avatar Dec 11 '20 03:12 rraihansaputra

Dear @imhoffd

Any luck when this could be resolved.

We now architecting an application that will use Angular built-in i18n for multi-lingual app. and with using Angular built-in i18n there would be a separate build for each language. We will use Capacitor as a hybrid mobile solution, but Capacitor copy the application from www directory, in my case there will be folder for each language. So how to handle this in Capacitor, and is it possible to change the URL in runtime as the user change the language.

sabahallah avatar Jul 16 '22 13:07 sabahallah

Any news here? we would like to use angular i18n and we have to decide how to proceed. Thanks!

meriturva avatar Sep 19 '22 19:09 meriturva

There is currently no way to do native translations (that allow a user to only install for example the english version of your app in your app bundle. Capacitor has no easy configuration for this. You have to do this manually and it is a lot of work..).

You do however have access in your web app to https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages, which allows you to determine the devices preferred language.

UltraCakeBakery avatar Sep 28 '22 22:09 UltraCakeBakery

Thanks @UltraCakeBakery for your feedback.

My idea is to pack capacitor with all language folders produced by ng build and add an index.html file on the root folder. The root index file has just to check the device's preferred language and redirects to the correct folder.

What do you think?

meriturva avatar Sep 29 '22 15:09 meriturva

Thanks @UltraCakeBakery for your feedback.

My idea is to pack capacitor with all language folders produced by ng build and add an index.html file on the root folder. The root index file has just to check the device's preferred language and redirects to the correct folder.

What do you think?

That'll work fine I think. It is all local so redirects won't hurt performance too much.

UltraCakeBakery avatar Sep 29 '22 16:09 UltraCakeBakery

Thanks @UltraCakeBakery for your feedback.

My idea is to pack capacitor with all language folders produced by ng build and add an index.html file on the root folder. The root index file has just to check the device's preferred language and redirects to the correct folder.

What do you think?

This work well. I prepared this html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <script type="text/javascript">
      // If true, you should set localStorage[storageKey] in your app.
      const saveLocale = true;
      const storageKey = 'locale';
      const defaultLocale = 'ja';
      const localeMap = {
        ja: ['ja', 'ja-JP'],
        'en-us': ['en', 'en-US'],
      };

      // Method
      const getBrowserLanguage = (navigator) => {
        if (!navigator) return null;
        if (navigator.languages && navigator.languages.length > 0) return navigator.languages[0];
        if (navigator.userLanguage) return navigator.userLanguage;
        return navigator.language;
      };
      const getToRoute = (locale) => {
        return Object.keys(localeMap).find((key) => {
          if (localeMap[key].map((l) => l.toLowerCase()).includes(locale)) return true;
        });
      };

      // Run redirect
      (() => {
        let locale = saveLocale === true ? localStorage.getItem(storageKey) : null;
        if (!locale) locale = getBrowserLanguage(window.navigator);
        if (saveLocale === true) localStorage.setItem(storageKey, locale);
        if (!locale) locale = defaultLocale;
        const route = getToRoute(locale.toLowerCase());
        console.log([new URL(window.location.href).origin, route, 'index.html'].join('/'));
        window.location.replace([new URL(window.location.href).origin, route, 'index.html'].join('/'));
      })();
    </script>
  </head>
</html>

Note: Capacitor require path/index.html. So subpath cannot be restored.

rdlabo avatar Oct 09 '22 09:10 rdlabo

Yes, it seems that setting server: url to ANYTHING (including the default, https://localhost/) prevents all localhost paths from working (Err Connection Refused). Would love to start somewhere else without losing the local server...

Erudition avatar Sep 18 '23 06:09 Erudition

Here's my current workaround, what do y'all think. Added a (p)npm script:

"capacitor:copy:after": "if [ $CAPACITOR_PLATFORM_NAME == 'web' ]; then echo leaving index in place for web. ; else echo replacing index with go-online... && mv android/app/src/main/assets/public/index.html android/app/src/main/assets/public/original.html && mv android/app/src/main/assets/public/go-online.html android/app/src/main/assets/public/index.html; fi"

Which moves the desired page to index.html for mobile platforms only. In my case, this lets me start at an external path (go-online is just a redirect) without losing the ability to navigate back to localhost.

Erudition avatar Sep 18 '23 07:09 Erudition