Browse Source

Merge pull request #426 from HeyPuter/eric/service-scripts

refactor(gui): add service scripts
Eric Dubé 1 year ago
parent
commit
f4d41891d9

+ 6 - 5
packages/backend/src/services/PuterHomepageService.js

@@ -212,11 +212,6 @@ class PuterHomepageService extends BaseService {
                 ? manifest.js_paths.map(path => `<script type="module" src="${path}"></script>\n`)
                 : []).join('')
         }
-        ${
-            this.service_scripts
-                .map(path => `<script type="module" src="${path}"></script>\n`)
-                .join('')
-        }
         <!-- Load the GUI script -->
         <script ${ !bundled ? ' type="module"' : ''} src="${(!bundled && manifest?.index) || '/dist/gui.js'}"></script>
         <!-- Initialize GUI when document is loaded -->
@@ -229,6 +224,12 @@ class PuterHomepageService extends BaseService {
             });
         });
         </script>
+        <!-- Initialize Service Scripts -->
+        ${
+            this.service_scripts
+                .map(path => `<script type="module" src="${path}"></script>\n`)
+                .join('')
+        }
         <div id="templates" style="display: none;"></div>
     </body>
 

+ 3 - 16
src/UI/Settings/UIWindowSettings.js

@@ -18,27 +18,14 @@
  */
 
 import UIWindow from '../UIWindow.js'
-import AboutTab from './UITabAbout.js';
-import UsageTab from './UITabUsage.js';
-import AccountTab from './UITabAccount.js';
-import SecurityTab from './UITabSecurity.js';
-import PersonalizationTab from './UITabPersonalization.js';
-import LanguageTab from './UITabLanguage.js';
-import ClockTab from './UITabClock.js';
 
 async function UIWindowSettings(options){
     return new Promise(async (resolve) => {
         options = options ?? {};
 
-        const tabs = [
-            AboutTab,
-            UsageTab,
-            AccountTab,
-            SecurityTab,
-            PersonalizationTab,
-            LanguageTab,
-            ClockTab,
-        ];
+        const svc_settings = globalThis.services.get('settings');
+
+        const tabs = svc_settings.get_tabs();
 
         let h = '';
 

+ 17 - 0
src/index.js

@@ -16,6 +16,23 @@
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
+window.service_script_api_promise = (() => {
+    let resolve, reject;
+    const promise = new Promise((res, rej) => {
+        resolve = res;
+        reject = rej;
+    });
+    promise.resolve = resolve;
+    promise.reject = reject;
+    return promise;
+})();
+window.service_script = async fn => {
+    try {
+        await fn(await window.service_script_api_promise);
+    } catch (e) {
+        console.error('service_script(ERROR)', e);
+    }
+};
 
 window.puter_gui_enabled = true;
 /**

+ 26 - 1
src/initgui.js

@@ -39,28 +39,53 @@ import { BroadcastService } from './services/BroadcastService.js';
 import { ProcessService } from './services/ProcessService.js';
 import { PROCESS_RUNNING } from './definitions.js';
 import { LocaleService } from './services/LocaleService.js';
+import { SettingsService } from './services/SettingsService.js';
+import UIComponentWindow from './UI/UIComponentWindow.js';
 
 const launch_services = async function () {
+    // === Services Data Structures ===
     const services_l_ = [];
     const services_m_ = {};
     globalThis.services = {
         get: (name) => services_m_[name],
     };
-
     const register = (name, instance) => {
         services_l_.push([name, instance]);
         services_m_[name] = instance;
     }
 
+    // === Hooks for Service Scripts from Backend ===
+    const service_script_deferred = { services: [], on_ready: [] };
+    const service_script_api = {
+        register: (...a) => service_script_deferred.services.push(a),
+        on_ready: fn => service_script_deferred.on_ready.push(fn),
+        // Some files can't be imported by service scripts,
+        // so this hack makes that possible.
+        use: name => ({ UIWindow, UIComponentWindow })[name],
+    };
+    globalThis.service_script_api_promise.resolve(service_script_api);
+
+    // === Builtin Services ===
     register('broadcast', new BroadcastService());
     register('theme', new ThemeService());
     register('process', new ProcessService());
     register('locale', new LocaleService());
+    register('settings', new SettingsService());
+
+    // === Service-Script Services ===
+    for (const [name, script] of service_script_deferred.services) {
+        register(name, script);
+    }
 
     for (const [_, instance] of services_l_) {
         await instance.init();
     }
 
+    // === Service-Script Ready ===
+    for (const fn of service_script_deferred.on_ready) {
+        await fn();
+    }
+
     // Set init process status
     {
         const svc_process = globalThis.services.get('process');

+ 32 - 0
src/services/SettingsService.js

@@ -0,0 +1,32 @@
+import { Service } from "../definitions.js";
+
+import AboutTab from '../UI/Settings/UITabAbout.js';
+import UsageTab from '../UI/Settings/UITabUsage.js';
+import AccountTab from '../UI/Settings/UITabAccount.js';
+import SecurityTab from '../UI/Settings/UITabSecurity.js';
+import PersonalizationTab from '../UI/Settings/UITabPersonalization.js';
+import LanguageTag from '../UI/Settings/UITabLanguage.js';
+import ClockTab from '../UI/Settings/UITabClock.js';
+
+export class SettingsService extends Service {
+    #tabs = [];
+    async _init () {
+        ;[
+            AboutTab,
+            UsageTab,
+            AccountTab,
+            SecurityTab,
+            PersonalizationTab,
+            LanguageTag,
+            ClockTab,
+        ].forEach(tab => {
+            this.register_tab(tab);
+        });
+    }
+    get_tabs () {
+        return this.#tabs;
+    }
+    register_tab (tab) {
+        this.#tabs.push(tab);
+    }
+}